Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/jmx/snmp/BerDecoder.java
38924 views
1
/*
2
* Copyright (c) 1997, 2007, 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
27
package com.sun.jmx.snmp;
28
29
30
31
32
/**
33
* The <CODE>BerDecoder</CODE> class is used for decoding
34
* BER-encoded data.
35
*
36
* A <CODE>BerDecoder</CODE> needs to be set up with the byte string containing
37
* the encoding. It maintains a current position in the byte string.
38
*
39
* Methods allows to fetch integer, string, OID, etc., from the current
40
* position. After a fetch the current position is moved forward.
41
*
42
* A fetch throws a <CODE>BerException</CODE> if the encoding is not of the
43
* expected type.
44
*
45
* <p><b>This API is a Sun Microsystems internal API and is subject
46
* to change without notice.</b></p>
47
*
48
* @since 1.5
49
*/
50
51
public class BerDecoder {
52
53
/**
54
* Constructs a new decoder and attaches it to the specified byte string.
55
*
56
* @param b The byte string containing the encoded data.
57
*/
58
59
public BerDecoder(byte b[]) {
60
bytes = b ;
61
reset() ;
62
}
63
64
public void reset() {
65
next = 0 ;
66
stackTop = 0 ;
67
}
68
69
/**
70
* Fetch an integer.
71
*
72
* @return The decoded integer.
73
*
74
* @exception BerException Current position does not point to an integer.
75
*/
76
77
public int fetchInteger() throws BerException {
78
return fetchInteger(IntegerTag) ;
79
}
80
81
82
/**
83
* Fetch an integer with the specified tag.
84
*
85
* @param tag The expected tag.
86
*
87
* @return The decoded integer.
88
*
89
* @exception BerException Current position does not point to an integer
90
* or the tag is not the expected one.
91
*/
92
93
public int fetchInteger(int tag) throws BerException {
94
int result = 0 ;
95
final int backup = next ;
96
try {
97
if (fetchTag() != tag) {
98
throw new BerException() ;
99
}
100
result = fetchIntegerValue() ;
101
}
102
catch(BerException e) {
103
next = backup ;
104
throw e ;
105
}
106
107
return result ;
108
}
109
110
111
112
/**
113
* Fetch an integer and return a long value.
114
*
115
* @return The decoded integer.
116
*
117
* @exception BerException Current position does not point to an integer.
118
*/
119
120
public long fetchIntegerAsLong() throws BerException {
121
return fetchIntegerAsLong(IntegerTag) ;
122
}
123
124
125
/**
126
* Fetch an integer with the specified tag and return a long value.
127
*
128
* @param tag The expected tag.
129
*
130
* @return The decoded integer.
131
*
132
* @exception BerException Current position does not point to an integer
133
* or the tag is not the expected one.
134
*/
135
136
public long fetchIntegerAsLong(int tag) throws BerException {
137
long result = 0 ;
138
final int backup = next ;
139
try {
140
if (fetchTag() != tag) {
141
throw new BerException() ;
142
}
143
result = fetchIntegerValueAsLong() ;
144
}
145
catch(BerException e) {
146
next = backup ;
147
throw e ;
148
}
149
150
return result ;
151
}
152
153
154
155
/**
156
* Fetch an octet string.
157
*
158
* @return The decoded string.
159
*
160
* @exception BerException Current position does not point to an octet string.
161
*/
162
163
public byte[] fetchOctetString() throws BerException {
164
return fetchOctetString(OctetStringTag) ;
165
}
166
167
168
/**
169
* Fetch an octet string with a specified tag.
170
*
171
* @param tag The expected tag.
172
*
173
* @return The decoded string.
174
*
175
* @exception BerException Current position does not point to an octet string
176
* or the tag is not the expected one.
177
*/
178
179
public byte[] fetchOctetString(int tag) throws BerException {
180
byte[] result = null ;
181
final int backup = next ;
182
try {
183
if (fetchTag() != tag) {
184
throw new BerException() ;
185
}
186
result = fetchStringValue() ;
187
}
188
catch(BerException e) {
189
next = backup ;
190
throw e ;
191
}
192
193
return result ;
194
}
195
196
197
/**
198
* Fetch an object identifier.
199
*
200
* @return The decoded object identifier as an array of long.
201
*/
202
203
public long[] fetchOid() throws BerException {
204
return fetchOid(OidTag) ;
205
}
206
207
208
/**
209
* Fetch an object identifier with a specified tag.
210
*
211
* @param tag The expected tag.
212
*
213
* @return The decoded object identifier as an array of long.
214
*
215
* @exception BerException Current position does not point to an oid
216
* or the tag is not the expected one.
217
*/
218
219
public long[] fetchOid(int tag) throws BerException {
220
long[] result = null ;
221
final int backup = next ;
222
try {
223
if (fetchTag() != tag) {
224
throw new BerException() ;
225
}
226
result = fetchOidValue() ;
227
}
228
catch(BerException e) {
229
next = backup ;
230
throw e ;
231
}
232
233
return result ;
234
}
235
236
237
/**
238
* Fetch a <CODE>NULL</CODE> value.
239
*
240
* @exception BerException Current position does not point to <CODE>NULL</CODE> value.
241
*/
242
243
public void fetchNull() throws BerException {
244
fetchNull(NullTag) ;
245
}
246
247
248
/**
249
* Fetch a <CODE>NULL</CODE> value with a specified tag.
250
*
251
* @param tag The expected tag.
252
*
253
* @exception BerException Current position does not point to
254
* <CODE>NULL</CODE> value or the tag is not the expected one.
255
*/
256
257
public void fetchNull(int tag) throws BerException {
258
final int backup = next ;
259
try {
260
if (fetchTag() != tag) {
261
throw new BerException() ;
262
}
263
final int length = fetchLength();
264
if (length != 0) throw new BerException();
265
}
266
catch(BerException e) {
267
next = backup ;
268
throw e ;
269
}
270
}
271
272
273
274
/**
275
* Fetch an <CODE>ANY</CODE> value. In fact, this method does not decode anything
276
* it simply returns the next TLV as an array of bytes.
277
*
278
* @return The TLV as a byte array.
279
*
280
* @exception BerException The next TLV is really badly encoded...
281
*/
282
283
public byte[] fetchAny() throws BerException {
284
byte[] result = null ;
285
final int backup = next ;
286
try {
287
final int tag = fetchTag() ;
288
final int contentLength = fetchLength() ;
289
if (contentLength < 0) throw new BerException() ;
290
final int tlvLength = next + contentLength - backup ;
291
if (contentLength > (bytes.length - next))
292
throw new IndexOutOfBoundsException("Decoded length exceeds buffer");
293
final byte[] data = new byte[tlvLength] ;
294
java.lang.System.arraycopy(bytes,backup,data,0,tlvLength);
295
// for (int i = 0 ; i < tlvLength ; i++) {
296
// data[i] = bytes[backup + i] ;
297
// }
298
next = next + contentLength ;
299
result = data;
300
}
301
catch(IndexOutOfBoundsException e) {
302
next = backup ;
303
throw new BerException() ;
304
}
305
// catch(Error e) {
306
// debug("fetchAny: Error decoding BER: " + e);
307
// throw e;
308
// }
309
310
return result ;
311
}
312
313
314
/**
315
* Fetch an <CODE>ANY</CODE> value with a specific tag.
316
*
317
* @param tag The expected tag.
318
*
319
* @return The TLV as a byte array.
320
*
321
* @exception BerException The next TLV is really badly encoded...
322
*/
323
324
public byte[] fetchAny(int tag) throws BerException {
325
if (getTag() != tag) {
326
throw new BerException() ;
327
}
328
return fetchAny() ;
329
}
330
331
332
333
/**
334
* Fetch a sequence header.
335
* The decoder computes the end position of the sequence and push it
336
* on its stack.
337
*
338
* @exception BerException Current position does not point to a sequence header.
339
*/
340
341
public void openSequence() throws BerException {
342
openSequence(SequenceTag) ;
343
}
344
345
346
/**
347
* Fetch a sequence header with a specific tag.
348
*
349
* @param tag The expected tag.
350
*
351
* @exception BerException Current position does not point to a sequence header
352
* or the tag is not the expected one.
353
*/
354
355
public void openSequence(int tag) throws BerException {
356
final int backup = next ;
357
try {
358
if (fetchTag() != tag) {
359
throw new BerException() ;
360
}
361
final int l = fetchLength() ;
362
if (l < 0) throw new BerException();
363
if (l > (bytes.length - next)) throw new BerException();
364
stackBuf[stackTop++] = next + l ;
365
}
366
catch(BerException e) {
367
next = backup ;
368
throw e ;
369
}
370
}
371
372
373
/**
374
* Close a sequence.
375
* The decode pull the stack and verifies that the current position
376
* matches with the calculated end of the sequence. If not it throws
377
* an exception.
378
*
379
* @exception BerException The sequence is not expected to finish here.
380
*/
381
382
public void closeSequence() throws BerException {
383
if (stackBuf[stackTop - 1] == next) {
384
stackTop-- ;
385
}
386
else {
387
throw new BerException() ;
388
}
389
}
390
391
392
/**
393
* Return <CODE>true</CODE> if the end of the current sequence is not reached.
394
* When this method returns <CODE>false</CODE>, <CODE>closeSequence</CODE> can (and must) be
395
* invoked.
396
*
397
* @return <CODE>true</CODE> if there is still some data in the sequence.
398
*/
399
400
public boolean cannotCloseSequence() {
401
return (next < stackBuf[stackTop - 1]) ;
402
}
403
404
405
/**
406
* Get the tag of the data at the current position.
407
* Current position is unchanged.
408
*
409
* @return The next tag.
410
*/
411
412
public int getTag() throws BerException {
413
int result = 0 ;
414
final int backup = next ;
415
try {
416
result = fetchTag() ;
417
}
418
finally {
419
next = backup ;
420
}
421
422
return result ;
423
}
424
425
426
427
public String toString() {
428
final StringBuffer result = new StringBuffer(bytes.length * 2) ;
429
for (int i = 0 ; i < bytes.length ; i++) {
430
final int b = (bytes[i] > 0) ? bytes[i] : bytes[i] + 256 ;
431
if (i == next) {
432
result.append("(") ;
433
}
434
result.append(Character.forDigit(b / 16, 16)) ;
435
result.append(Character.forDigit(b % 16, 16)) ;
436
if (i == next) {
437
result.append(")") ;
438
}
439
}
440
if (bytes.length == next) {
441
result.append("()") ;
442
}
443
444
return new String(result) ;
445
}
446
447
448
//
449
// Some standard tags
450
//
451
public final static int BooleanTag = 1 ;
452
public final static int IntegerTag = 2 ;
453
public final static int OctetStringTag = 4 ;
454
public final static int NullTag = 5 ;
455
public final static int OidTag = 6 ;
456
public final static int SequenceTag = 0x30 ;
457
458
459
460
461
////////////////////////// PRIVATE ///////////////////////////////
462
463
464
465
/**
466
* Fetch a tag and move the current position forward.
467
*
468
* @return The tag
469
*/
470
471
private final int fetchTag() throws BerException {
472
int result = 0 ;
473
final int backup = next ;
474
475
try {
476
final byte b0 = bytes[next++] ;
477
result = (b0 >= 0) ? b0 : b0 + 256 ;
478
if ((result & 31) == 31) {
479
while ((bytes[next] & 128) != 0) {
480
result = result << 7 ;
481
result = result | (bytes[next++] & 127);
482
}
483
}
484
}
485
catch(IndexOutOfBoundsException e) {
486
next = backup ;
487
throw new BerException() ;
488
}
489
490
return result ;
491
}
492
493
494
/**
495
* Fetch a length and move the current position forward.
496
*
497
* @return The length
498
*/
499
500
private final int fetchLength() throws BerException {
501
int result = 0 ;
502
final int backup = next ;
503
504
try {
505
final byte b0 = bytes[next++] ;
506
if (b0 >= 0) {
507
result = b0 ;
508
}
509
else {
510
for (int c = 128 + b0 ; c > 0 ; c--) {
511
final byte bX = bytes[next++] ;
512
result = result << 8 ;
513
result = result | ((bX >= 0) ? bX : bX+256) ;
514
}
515
}
516
}
517
catch(IndexOutOfBoundsException e) {
518
next = backup ;
519
throw new BerException() ;
520
}
521
522
return result ;
523
}
524
525
526
/**
527
* Fetch an integer value and move the current position forward.
528
*
529
* @return The integer
530
*/
531
532
private int fetchIntegerValue() throws BerException {
533
int result = 0 ;
534
final int backup = next ;
535
536
try {
537
final int length = fetchLength() ;
538
if (length <= 0) throw new BerException() ;
539
if (length > (bytes.length - next)) throw
540
new IndexOutOfBoundsException("Decoded length exceeds buffer");
541
final int end = next + length ;
542
result = bytes[next++] ;
543
while (next < end) {
544
final byte b = bytes[next++] ;
545
if (b < 0) {
546
result = (result << 8) | (256 + b) ;
547
}
548
else {
549
result = (result << 8) | b ;
550
}
551
}
552
}
553
catch(BerException e) {
554
next = backup ;
555
throw e ;
556
}
557
catch(IndexOutOfBoundsException e) {
558
next = backup ;
559
throw new BerException() ;
560
}
561
catch(ArithmeticException e) {
562
next = backup ;
563
throw new BerException() ;
564
}
565
return result ;
566
}
567
568
569
/**
570
* Fetch an integer value and return a long value.
571
* FIX ME: someday we could have only on fetchIntegerValue() which always
572
* returns a long value.
573
*
574
* @return The integer
575
*/
576
577
private final long fetchIntegerValueAsLong() throws BerException {
578
long result = 0 ;
579
final int backup = next ;
580
581
try {
582
final int length = fetchLength() ;
583
if (length <= 0) throw new BerException() ;
584
if (length > (bytes.length - next)) throw
585
new IndexOutOfBoundsException("Decoded length exceeds buffer");
586
587
final int end = next + length ;
588
result = bytes[next++] ;
589
while (next < end) {
590
final byte b = bytes[next++] ;
591
if (b < 0) {
592
result = (result << 8) | (256 + b) ;
593
}
594
else {
595
result = (result << 8) | b ;
596
}
597
}
598
}
599
catch(BerException e) {
600
next = backup ;
601
throw e ;
602
}
603
catch(IndexOutOfBoundsException e) {
604
next = backup ;
605
throw new BerException() ;
606
}
607
catch(ArithmeticException e) {
608
next = backup ;
609
throw new BerException() ;
610
}
611
return result ;
612
}
613
614
615
/**
616
* Fetch a byte string and move the current position forward.
617
*
618
* @return The byte string
619
*/
620
621
private byte[] fetchStringValue() throws BerException {
622
byte[] result = null ;
623
final int backup = next ;
624
625
try {
626
final int length = fetchLength() ;
627
if (length < 0) throw new BerException() ;
628
if (length > (bytes.length - next))
629
throw new IndexOutOfBoundsException("Decoded length exceeds buffer");
630
final byte data[] = new byte[length] ;
631
java.lang.System.arraycopy(bytes,next,data,0,length);
632
next += length;
633
// int i = 0 ;
634
// while (i < length) {
635
// result[i++] = bytes[next++] ;
636
// }
637
result = data;
638
}
639
catch(BerException e) {
640
next = backup ;
641
throw e ;
642
}
643
catch(IndexOutOfBoundsException e) {
644
next = backup ;
645
throw new BerException() ;
646
}
647
catch(ArithmeticException e) {
648
next = backup ;
649
throw new BerException() ;
650
}
651
// catch(Error e) {
652
// debug("fetchStringValue: Error decoding BER: " + e);
653
// throw e;
654
// }
655
656
return result ;
657
}
658
659
660
661
/**
662
* Fetch an oid and move the current position forward.
663
*
664
* @return The oid
665
*/
666
667
private final long[] fetchOidValue() throws BerException {
668
long[] result = null ;
669
final int backup = next ;
670
671
try {
672
final int length = fetchLength() ;
673
if (length <= 0) throw new BerException() ;
674
if (length > (bytes.length - next))
675
throw new IndexOutOfBoundsException("Decoded length exceeds buffer");
676
// Count how many bytes have their 8th bit to 0
677
// -> this gives the number of components in the oid
678
int subidCount = 2 ;
679
for (int i = 1 ; i < length ; i++) {
680
if ((bytes[next + i] & 0x80) == 0) {
681
subidCount++ ;
682
}
683
}
684
final int datalen = subidCount;
685
final long[] data = new long[datalen];
686
final byte b0 = bytes[next++] ;
687
688
// bugId 4641746
689
// The 8th bit of the first byte should always be set to 0
690
if (b0 < 0) throw new BerException();
691
692
// bugId 4641746
693
// The first sub Id cannot be greater than 2
694
final long lb0 = b0 / 40 ;
695
if (lb0 > 2) throw new BerException();
696
697
final long lb1 = b0 % 40;
698
data[0] = lb0 ;
699
data[1] = lb1 ;
700
int i = 2 ;
701
while (i < datalen) {
702
long subid = 0 ;
703
byte b = bytes[next++] ;
704
while ((b & 0x80) != 0) {
705
subid = (subid << 7) | (b & 0x7f) ;
706
// bugId 4654674
707
if (subid < 0) throw new BerException();
708
b = bytes[next++] ;
709
}
710
subid = (subid << 7) | b ;
711
// bugId 4654674
712
if (subid < 0) throw new BerException();
713
data[i++] = subid ;
714
}
715
result = data;
716
}
717
catch(BerException e) {
718
next = backup ;
719
throw e ;
720
}
721
catch(IndexOutOfBoundsException e) {
722
next = backup ;
723
throw new BerException() ;
724
}
725
// catch(Error e) {
726
// debug("fetchOidValue: Error decoding BER: " + e);
727
// throw e;
728
// }
729
730
return result ;
731
}
732
733
// private static final void debug(String str) {
734
// System.out.println(str);
735
// }
736
737
//
738
// This is the byte array containing the encoding.
739
//
740
private final byte bytes[];
741
742
//
743
// This is the current location. It is the next byte
744
// to be decoded. It's an index in bytes[].
745
//
746
private int next = 0 ;
747
748
//
749
// This is the stack where end of sequences are kept.
750
// A value is computed and pushed in it each time openSequence()
751
// is invoked.
752
// A value is pulled and checked each time closeSequence() is called.
753
//
754
private final int stackBuf[] = new int[200] ;
755
private int stackTop = 0 ;
756
757
}
758
759