Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.naming/share/classes/com/sun/jndi/ldap/BerDecoder.java
41161 views
1
/*
2
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package com.sun.jndi.ldap;
27
28
import java.io.UnsupportedEncodingException;
29
30
/**
31
* A BER decoder. Contains methods to parse a BER buffer.
32
*
33
* @author Jagane Sundar
34
* @author Vincent Ryan
35
*/
36
public final class BerDecoder extends Ber {
37
38
private int origOffset; // The start point in buf to decode
39
40
/**
41
* Creates a BER decoder that reads bytes from the specified buffer.
42
*/
43
public BerDecoder(byte buf[], int offset, int bufsize) {
44
45
this.buf = buf; // shared buffer, be careful to use this class
46
this.bufsize = bufsize;
47
this.origOffset = offset;
48
49
reset();
50
}
51
52
/**
53
* Resets this decode to start parsing from the initial offset
54
* (ie., same state as after calling the constructor).
55
*/
56
public void reset() {
57
offset = origOffset;
58
}
59
60
/**
61
* Returns the current parse position.
62
* It points to the byte that will be parsed next.
63
* Useful for parsing sequences.
64
*/
65
public int getParsePosition() {
66
return offset;
67
}
68
69
/**
70
* Parses a possibly variable length field.
71
*/
72
public int parseLength() throws DecodeException {
73
74
int lengthbyte = parseByte();
75
76
if ((lengthbyte & 0x80) == 0x80) {
77
78
lengthbyte &= 0x7f;
79
80
if (lengthbyte == 0) {
81
throw new DecodeException(
82
"Indefinite length not supported");
83
}
84
85
if (lengthbyte > 4) {
86
throw new DecodeException("encoding too long");
87
}
88
89
if (bufsize - offset < lengthbyte) {
90
throw new DecodeException("Insufficient data");
91
}
92
93
int retval = 0;
94
95
for( int i = 0; i < lengthbyte; i++) {
96
retval = (retval << 8) + (buf[offset++] & 0xff);
97
}
98
if (retval < 0) {
99
throw new DecodeException("Invalid length bytes");
100
}
101
return retval;
102
} else {
103
return lengthbyte;
104
}
105
}
106
107
/**
108
* Parses the next sequence in this BER buffer.
109
* @param rlen An array for returning size of the sequence in bytes. If null,
110
* the size is not returned.
111
* @return The sequence's tag.
112
*/
113
public int parseSeq(int rlen[]) throws DecodeException {
114
115
int seq = parseByte();
116
int len = parseLength();
117
if (rlen != null) {
118
rlen[0] = len;
119
}
120
return seq;
121
}
122
123
/**
124
* Used to skip bytes. Usually used when trying to recover from parse error.
125
* Don't need to be public right now?
126
* @param i The number of bytes to skip
127
*/
128
void seek(int i) throws DecodeException {
129
if (offset + i > bufsize || offset + i < 0) {
130
throw new DecodeException("array index out of bounds");
131
}
132
offset += i;
133
}
134
135
/**
136
* Parses the next byte in this BER buffer.
137
* @return The byte parsed.
138
*/
139
public int parseByte() throws DecodeException {
140
if (bufsize - offset < 1) {
141
throw new DecodeException("Insufficient data");
142
}
143
return buf[offset++] & 0xff;
144
}
145
146
147
/**
148
* Returns the next byte in this BER buffer without consuming it.
149
* @return The next byte.
150
*/
151
public int peekByte() throws DecodeException {
152
if (bufsize - offset < 1) {
153
throw new DecodeException("Insufficient data");
154
}
155
return buf[offset] & 0xff;
156
}
157
158
/**
159
* Parses an ASN_BOOLEAN tagged integer from this BER buffer.
160
* @return true if the tagged integer is 0; false otherwise.
161
*/
162
public boolean parseBoolean() throws DecodeException {
163
return ((parseIntWithTag(ASN_BOOLEAN) == 0x00) ? false : true);
164
}
165
166
/**
167
* Parses an ASN_ENUMERATED tagged integer from this BER buffer.
168
* @return The tag of enumeration.
169
*/
170
public int parseEnumeration() throws DecodeException {
171
return parseIntWithTag(ASN_ENUMERATED);
172
}
173
174
/**
175
* Parses an ASN_INTEGER tagged integer from this BER buffer.
176
* @return The value of the integer.
177
*/
178
public int parseInt() throws DecodeException {
179
return parseIntWithTag(ASN_INTEGER);
180
}
181
182
/**
183
* Parses an integer that's preceded by a tag.
184
*<blockquote><pre>
185
* BER integer ::= tag length byte {byte}*
186
*</pre></blockquote>
187
*/
188
private int parseIntWithTag(int tag) throws DecodeException {
189
if (parseByte() != tag) {
190
// Ber could have been reset;
191
String s;
192
if (offset > 0) {
193
s = Integer.toString(buf[offset - 1] & 0xff);
194
} else {
195
s = "Empty tag";
196
}
197
throw new DecodeException("Encountered ASN.1 tag " +
198
s + " (expected tag " + Integer.toString(tag) + ")");
199
}
200
201
int len = parseLength();
202
203
if (len > 4) {
204
throw new DecodeException("INTEGER too long");
205
} else if (len > bufsize - offset) {
206
throw new DecodeException("Insufficient data");
207
}
208
209
byte fb = buf[offset++];
210
int value = 0;
211
212
value = fb & 0x7F;
213
for( int i = 1 /* first byte already read */ ; i < len; i++) {
214
value <<= 8;
215
value |= (buf[offset++] & 0xff);
216
}
217
218
if ((fb & 0x80) == 0x80) {
219
value = -value;
220
}
221
222
return value;
223
}
224
225
/**
226
* Parses a string.
227
*/
228
public String parseString(boolean decodeUTF8) throws DecodeException {
229
return parseStringWithTag(ASN_SIMPLE_STRING, decodeUTF8, null);
230
}
231
232
/**
233
* Parses a string of a given tag from this BER buffer.
234
*<blockquote><pre>
235
*BER simple string ::= tag length {byte}*
236
*</pre></blockquote>
237
* @param rlen An array for holding the relative parsed offset; if null
238
* offset not set.
239
* @param decodeUTF8 If true, use UTF-8 when decoding the string; otherwise
240
* use ISO-Latin-1 (8859_1). Use true for LDAPv3; false for LDAPv2.
241
* @param tag The tag that precedes the string.
242
* @return The non-null parsed string.
243
*/
244
public String parseStringWithTag(int tag, boolean decodeUTF8, int rlen[])
245
throws DecodeException {
246
247
int st;
248
int origOffset = offset;
249
250
if ((st = parseByte()) != tag) {
251
throw new DecodeException("Encountered ASN.1 tag " +
252
Integer.toString((byte)st) + " (expected tag " + tag + ")");
253
}
254
255
int len = parseLength();
256
257
if (len > bufsize - offset) {
258
throw new DecodeException("Insufficient data");
259
}
260
261
String retstr;
262
if (len == 0) {
263
retstr = "";
264
} else {
265
byte[] buf2 = new byte[len];
266
267
System.arraycopy(buf, offset, buf2, 0, len);
268
if (decodeUTF8) {
269
try {
270
retstr = new String(buf2, "UTF8");
271
} catch (UnsupportedEncodingException e) {
272
throw new DecodeException("UTF8 not available on platform");
273
}
274
} else {
275
try {
276
retstr = new String(buf2, "8859_1");
277
} catch (UnsupportedEncodingException e) {
278
throw new DecodeException("8859_1 not available on platform");
279
}
280
}
281
offset += len;
282
}
283
284
if (rlen != null) {
285
rlen[0] = offset - origOffset;
286
}
287
288
return retstr;
289
}
290
291
/**
292
* Parses an octet string of a given type(tag) from this BER buffer.
293
* <blockquote><pre>
294
* BER Binary Data of type "tag" ::= tag length {byte}*
295
*</pre></blockquote>
296
*
297
* @param tag The tag to look for.
298
* @param rlen An array for returning the relative parsed position. If null,
299
* the relative parsed position is not returned.
300
* @return A non-null array containing the octet string.
301
* @throws DecodeException If the next byte in the BER buffer is not
302
* {@code tag}, or if length specified in the BER buffer exceeds the
303
* number of bytes left in the buffer.
304
*/
305
public byte[] parseOctetString(int tag, int rlen[]) throws DecodeException {
306
307
int origOffset = offset;
308
int st;
309
if ((st = parseByte()) != tag) {
310
311
throw new DecodeException("Encountered ASN.1 tag " +
312
Integer.toString(st) +
313
" (expected tag " + Integer.toString(tag) + ")");
314
}
315
316
int len = parseLength();
317
318
if (len > bufsize - offset) {
319
throw new DecodeException("Insufficient data");
320
}
321
322
byte retarr[] = new byte[len];
323
if (len > 0) {
324
System.arraycopy(buf, offset, retarr, 0, len);
325
offset += len;
326
}
327
328
if (rlen != null) {
329
rlen[0] = offset - origOffset;
330
}
331
332
return retarr;
333
}
334
335
/**
336
* Returns the number of unparsed bytes in this BER buffer.
337
*/
338
public int bytesLeft() {
339
return bufsize - offset;
340
}
341
}
342
343