Source Code Cross Referenced for BER.java in  » Net » snmp4j » org » snmp4j » asn1 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » snmp4j » org.snmp4j.asn1 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*_############################################################################
002:          _## 
003:          _##  SNMP4J - BER.java  
004:          _## 
005:          _##  Copyright (C) 2003-2008  Frank Fock and Jochen Katz (SNMP4J.org)
006:          _##  
007:          _##  Licensed under the Apache License, Version 2.0 (the "License");
008:          _##  you may not use this file except in compliance with the License.
009:          _##  You may obtain a copy of the License at
010:          _##  
011:          _##      http://www.apache.org/licenses/LICENSE-2.0
012:          _##  
013:          _##  Unless required by applicable law or agreed to in writing, software
014:          _##  distributed under the License is distributed on an "AS IS" BASIS,
015:          _##  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016:          _##  See the License for the specific language governing permissions and
017:          _##  limitations under the License.
018:          _##  
019:          _##########################################################################*/
020:
021:        package org.snmp4j.asn1;
022:
023:        import java.io.OutputStream;
024:        import java.io.IOException;
025:
026:        /**
027:         * The BER class provides utility methods for the BER encoding and decoding.
028:         *
029:         * @author Jochen Katz & Frank Fock
030:         * @version 1.7.4
031:         */
032:        public class BER {
033:
034:            public static final byte ASN_BOOLEAN = 0x01;
035:            public static final byte ASN_INTEGER = 0x02;
036:            public static final byte ASN_BIT_STR = 0x03;
037:            public static final byte ASN_OCTET_STR = 0x04;
038:            public static final byte ASN_NULL = 0x05;
039:            public static final byte ASN_OBJECT_ID = 0x06;
040:            public static final byte ASN_SEQUENCE = 0x10;
041:            public static final byte ASN_SET = 0x11;
042:            public static final byte ASN_UNIVERSAL = 0x00;
043:            public static final byte ASN_APPLICATION = 0x40;
044:            public static final byte ASN_CONTEXT = (byte) 0x80;
045:            public static final byte ASN_PRIVATE = (byte) 0xC0;
046:            public static final byte ASN_PRIMITIVE = (byte) 0x00;
047:            public static final byte ASN_CONSTRUCTOR = (byte) 0x20;
048:
049:            public static final byte ASN_LONG_LEN = (byte) 0x80;
050:            public static final byte ASN_EXTENSION_ID = (byte) 0x1F;
051:            public static final byte ASN_BIT8 = (byte) 0x80;
052:
053:            public static final byte INTEGER = ASN_UNIVERSAL | 0x02;
054:            public static final byte INTEGER32 = ASN_UNIVERSAL | 0x02;
055:            public static final byte BITSTRING = ASN_UNIVERSAL | 0x03;
056:            public static final byte OCTETSTRING = ASN_UNIVERSAL | 0x04;
057:            public static final byte NULL = ASN_UNIVERSAL | 0x05;
058:            public static final byte OID = ASN_UNIVERSAL | 0x06;
059:            public static final byte SEQUENCE = ASN_CONSTRUCTOR | 0x10;
060:
061:            public static final byte IPADDRESS = ASN_APPLICATION | 0x00;
062:            public static final byte COUNTER = ASN_APPLICATION | 0x01;
063:            public static final byte COUNTER32 = ASN_APPLICATION | 0x01;
064:            public static final byte GAUGE = ASN_APPLICATION | 0x02;
065:            public static final byte GAUGE32 = ASN_APPLICATION | 0x02;
066:            public static final byte TIMETICKS = ASN_APPLICATION | 0x03;
067:            public static final byte OPAQUE = ASN_APPLICATION | 0x04;
068:            public static final byte COUNTER64 = ASN_APPLICATION | 0x06;
069:
070:            public static final int NOSUCHOBJECT = 0x80;
071:            public static final int NOSUCHINSTANCE = 0x81;
072:            public static final int ENDOFMIBVIEW = 0x82;
073:
074:            private static final int LENMASK = 0x0ff;
075:            public static final int MAX_OID_LENGTH = 127;
076:
077:            private static boolean checkSequenceLength = true;
078:            private static boolean checkValueLength = true;
079:
080:            /**
081:             * The <code>MutableByte</code> class serves for exchanging type information
082:             * from the various decode* methods.
083:             *
084:             * @author Frank Fock
085:             * @version 1.0
086:             */
087:            public static class MutableByte {
088:                byte value = 0;
089:
090:                public MutableByte() {
091:                }
092:
093:                public MutableByte(byte value) {
094:                    setValue(value);
095:                }
096:
097:                public void setValue(byte value) {
098:                    this .value = value;
099:                }
100:
101:                public byte getValue() {
102:                    return value;
103:                }
104:            }
105:
106:            /**
107:             * Encodes an ASN.1 header for an object with the ID and
108:             * length specified.
109:             * @param os
110:             *    an <code>OutputStream</code> to which the header is encoded.
111:             * @param type
112:             *    the type of the ASN.1 object. Must be < 30, i.e. no extension octets.
113:             * @param length
114:             *    the length of the object. The maximum length is 0xFFFFFFFF;
115:             * @throws IOException
116:             */
117:            public static final void encodeHeader(OutputStream os, int type,
118:                    int length) throws IOException {
119:                os.write(type);
120:                encodeLength(os, length);
121:            }
122:
123:            /**
124:             * Encodes an ASN.1 header for an object with the ID and
125:             * length specified with a fixed length of the encoded length as supplied.
126:             * @param os
127:             *    an <code>OutputStream</code> to which the header is encoded.
128:             * @param type
129:             *    the type of the ASN.1 object. Must be < 30, i.e. no extension octets.
130:             * @param length
131:             *    the length of the object. The maximum length is 0xFFFFFFFF;
132:             * @param numBytesLength
133:             *    the number of bytes used to encode the length of the length.
134:             * @throws IOException
135:             */
136:            public static final void encodeHeader(OutputStream os, int type,
137:                    int length, int numBytesLength) throws IOException {
138:                os.write(type);
139:                encodeLength(os, length, numBytesLength);
140:            }
141:
142:            /**
143:             * Compute the space needed to encode the length.
144:             *
145:             * @param length
146:             *    Length to encode
147:             * @return
148:             *    the count of bytes needed to encode the value <code>length</code>
149:             */
150:            public static final int getBERLengthOfLength(int length) {
151:                if (length < 0) {
152:                    return 5;
153:                } else if (length < 0x80) {
154:                    return 1;
155:                } else if (length <= 0xFF) {
156:                    return 2;
157:                } else if (length <= 0xFFFF) { /* 0xFF < length <= 0xFFFF */
158:                    return 3;
159:                } else if (length <= 0xFFFFFF) { /* 0xFFFF < length <= 0xFFFFFF */
160:                    return 4;
161:                }
162:                return 5;
163:            }
164:
165:            /**
166:             * Encodes the length of an ASN.1 object.
167:             * @param os
168:             *   an <code>OutputStream</code> to which the length is encoded.
169:             * @param length
170:             *    the length of the object. The maximum length is 0xFFFFFFFF;
171:             * @throws IOException
172:             */
173:            public static final void encodeLength(OutputStream os, int length)
174:                    throws IOException {
175:                if (length < 0) {
176:                    os.write(0x04 | ASN_LONG_LEN);
177:                    os.write((length >> 24) & 0xFF);
178:                    os.write((length >> 16) & 0xFF);
179:                    os.write((length >> 8) & 0xFF);
180:                    os.write(length & 0xFF);
181:                } else if (length < 0x80) {
182:                    os.write(length);
183:                } else if (length <= 0xFF) {
184:                    os.write((0x01 | ASN_LONG_LEN));
185:                    os.write(length);
186:                } else if (length <= 0xFFFF) { /* 0xFF < length <= 0xFFFF */
187:                    os.write(0x02 | ASN_LONG_LEN);
188:                    os.write((length >> 8) & 0xFF);
189:                    os.write(length & 0xFF);
190:                } else if (length <= 0xFFFFFF) { /* 0xFFFF < length <= 0xFFFFFF */
191:                    os.write(0x03 | ASN_LONG_LEN);
192:                    os.write((length >> 16) & 0xFF);
193:                    os.write((length >> 8) & 0xFF);
194:                    os.write(length & 0xFF);
195:                } else {
196:                    os.write(0x04 | ASN_LONG_LEN);
197:                    os.write((length >> 24) & 0xFF);
198:                    os.write((length >> 16) & 0xFF);
199:                    os.write((length >> 8) & 0xFF);
200:                    os.write(length & 0xFF);
201:                }
202:            }
203:
204:            /**
205:             * Encodes the length of an ASN.1 object.
206:             * @param os
207:             *   an <code>OutputStream</code> to which the length is encoded.
208:             * @param length
209:             *    the length of the object. The maximum length is 0xFFFFFFFF;
210:             * @param numLengthBytes
211:             *    the number of bytes to be used to encode the length using the long
212:             *    form.
213:             * @throws IOException
214:             */
215:            public static final void encodeLength(OutputStream os, int length,
216:                    int numLengthBytes) throws IOException {
217:                os.write((numLengthBytes | ASN_LONG_LEN));
218:                for (int i = (numLengthBytes - 1) * 8; i >= 0; i -= 8) {
219:                    os.write(((length >> i) & 0xFF));
220:                }
221:            }
222:
223:            /**
224:             * Encode a signed integer.
225:             * @param os
226:             *    an <code>OutputStream</code> to which the length is encoded.
227:             * @param type
228:             *    the tag type for the integer (typically 0x02)
229:             * @param value
230:             *    the integer value to encode.
231:             * @throws IOException
232:             */
233:            public static final void encodeInteger(OutputStream os, byte type,
234:                    int value) throws IOException {
235:                int integer = value;
236:                int mask;
237:                int intsize = 4;
238:
239:                /*
240:                 * Truncate "unnecessary" bytes off of the most significant end of this
241:                 * 2's complement integer.  There should be no sequence of 9
242:                 * consecutive 1's or 0's at the most significant end of the
243:                 * integer.
244:                 */
245:                mask = 0x1FF << ((8 * 3) - 1);
246:                /* mask is 0xFF800000 on a big-endian machine */
247:                while ((((integer & mask) == 0) || ((integer & mask) == mask))
248:                        && intsize > 1) {
249:                    intsize--;
250:                    integer <<= 8;
251:                }
252:                encodeHeader(os, type, intsize);
253:                mask = 0xFF << (8 * 3);
254:                /* mask is 0xFF000000 on a big-endian machine */
255:                while ((intsize--) > 0) {
256:                    os.write(((integer & mask) >> (8 * 3)));
257:                    integer <<= 8;
258:                }
259:            }
260:
261:            /**
262:             * Encode an unsigned integer.
263:             * ASN.1 integer ::= 0x02 asnlength byte {byte}*
264:             * @param os
265:             *    an <code>OutputStream</code> to which the length is encoded.
266:             * @param type
267:             *    the tag type for the integer (typically 0x02)
268:             * @param value
269:             *    the integer value to encode.
270:             * @throws IOException
271:             */
272:            public static final void encodeUnsignedInteger(OutputStream os,
273:                    byte type, long value) throws IOException {
274:                // figure out the len
275:                int len = 1;
276:                if (((value >> 24) & LENMASK) != 0) {
277:                    len = 4;
278:                } else if (((value >> 16) & LENMASK) != 0) {
279:                    len = 3;
280:                } else if (((value >> 8) & LENMASK) != 0) {
281:                    len = 2;
282:                }
283:                // check for 5 byte len where first byte will be
284:                // a null
285:                if (((value >> (8 * (len - 1))) & 0x080) != 0) {
286:                    len++;
287:                }
288:
289:                // build up the header
290:                encodeHeader(os, type, len); // length of BER encoded item
291:
292:                // special case, add a null byte for len of 5
293:                if (len == 5) {
294:                    os.write(0);
295:                    for (int x = 1; x < len; x++) {
296:                        os.write((int) (value >> (8 * (4 - x) & LENMASK)));
297:                    }
298:                } else {
299:                    for (int x = 0; x < len; x++) {
300:                        os
301:                                .write((int) (value >> (8 * ((len - 1) - x) & LENMASK)));
302:                    }
303:                }
304:            }
305:
306:            /**
307:             * Encode an ASN.1 octet string filled with the supplied input string.
308:             * @param os
309:             *    an <code>OutputStream</code> to which the length is encoded.
310:             * @param type
311:             *    the tag type for the integer (typically 0x02)
312:             * @param string
313:             *    the <code>byte</code> array containing the octet string value.
314:             * @throws IOException
315:             */
316:            public static final void encodeString(OutputStream os, byte type,
317:                    byte[] string) throws IOException {
318:                /*
319:                 * ASN.1 octet string ::= primstring | cmpdstring
320:                 * primstring ::= 0x04 asnlength byte {byte}*
321:                 * cmpdstring ::= 0x24 asnlength string {string}*
322:                 * This code will never send a compound string.
323:                 */
324:                encodeHeader(os, type, string.length);
325:                // fixed
326:                os.write(string);
327:            }
328:
329:            /**
330:             * Encode an ASN.1 header for a sequence with the ID and length specified.
331:             * This only works on data types < 30, i.e. no extension octets.
332:             * The maximum length is 0xFFFF;
333:             *
334:             * @param os
335:             *    an <code>OutputStream</code> to which the length is encoded.
336:             * @param type
337:             *    the tag type for the integer (typically 0x02)
338:             * @param length
339:             *    the length of the sequence to encode.
340:             * @throws IOException
341:             */
342:            public static final void encodeSequence(OutputStream os, byte type,
343:                    int length) throws IOException {
344:                os.write(type);
345:                encodeLength(os, length);
346:            }
347:
348:            /**
349:             * Gets the payload length in bytes of the BER encoded OID value.
350:             * @param value
351:             *    an array of unsigned integer values representing an object identifier.
352:             * @return
353:             *    the BER encoded length of the OID without header and length.
354:             */
355:            public static final int getOIDLength(int[] value) {
356:                int length = 1; // for first 2 subids
357:                for (int i = 2; i < value.length; i++) {
358:                    long v = value[i] & 0xFFFFFFFFL;
359:                    if (v < 0x80) { //  7 bits long subid
360:                        length += 1;
361:                    } else if (v < 0x4000) { // 14 bits long subid
362:                        length += 2;
363:                    } else if (v < 0x200000) { // 21 bits long subid
364:                        length += 3;
365:                    } else if (v < 0x10000000) { // 28 bits long subid
366:                        length += 4;
367:                    } else { // 32 bits long subid
368:                        length += 5;
369:                    }
370:                }
371:                return length;
372:            }
373:
374:            /**
375:             * Encode an ASN.1 oid filled with the supplied oid value.
376:             *
377:             * @param os
378:             *    an <code>OutputStream</code> to which the length is encoded.
379:             * @param type
380:             *    the tag type for the integer (typically 0x06)
381:             * @param oid
382:             *    the <code>int</code> array containing the OID value.
383:             * @throws IOException
384:             */
385:            public static final void encodeOID(OutputStream os, byte type,
386:                    int[] oid) throws IOException {
387:                /*
388:                 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
389:                 * subidentifier ::= {leadingbyte}* lastbyte
390:                 * leadingbyte ::= 1 7bitvalue
391:                 * lastbyte ::= 0 7bitvalue
392:                 */
393:                encodeHeader(os, type, getOIDLength(oid));
394:
395:                int encodedLength = oid.length;
396:                int rpos = 0;
397:
398:                if (oid.length < 2) {
399:                    os.write(0);
400:                    encodedLength = 0;
401:                } else {
402:                    os.write(((oid[1] + (oid[0] * 40)) & 0xFF));
403:                    encodedLength -= 2;
404:                    rpos = 2;
405:                }
406:
407:                while (encodedLength-- > 0) {
408:                    long subid = (oid[rpos++] & 0xFFFFFFFFL);
409:                    if (subid < 127) {
410:                        os.write((int) subid & 0xFF);
411:                    } else {
412:                        long mask = 0x7F; /* handle subid == 0 case */
413:                        long bits = 0;
414:
415:                        /* testmask *MUST* !!!! be of an unsigned type */
416:                        for (long testmask = 0x7F, testbits = 0; testmask != 0; testmask <<= 7, testbits += 7) {
417:                            if ((subid & testmask) > 0) { /* if any bits set */
418:                                mask = testmask;
419:                                bits = testbits;
420:                            }
421:                        }
422:                        /* mask can't be zero here */
423:                        for (; mask != 0x7F; mask >>= 7, bits -= 7) {
424:                            /* fix a mask that got truncated above */
425:                            if (mask == 0x1E00000) {
426:                                mask = 0xFE00000;
427:                            }
428:                            os
429:                                    .write((int) (((subid & mask) >> bits) | ASN_BIT8));
430:                        }
431:                        os.write((int) (subid & mask));
432:                    }
433:                }
434:            }
435:
436:            public static final void encodeUnsignedInt64(OutputStream os,
437:                    byte type, long value) throws IOException {
438:                int len;
439:                /*
440:                 * Truncate "unnecessary" bytes off of the most significant end of this
441:                 * 2's complement integer.  There should be no sequence of 9
442:                 * consecutive 1's or 0's at the most significant end of the
443:                 * integer.
444:                 */
445:                for (len = 8; len > 1; len--) {
446:                    if (((value >> (8 * (len - 1))) & 0xFF) != 0) {
447:                        break;
448:                    }
449:                }
450:                if (((value >> (8 * (len - 1))) & 0x080) != 0) {
451:                    len++;
452:                }
453:                encodeHeader(os, type, len);
454:                if (len == 9) {
455:                    os.write(0);
456:                    len--;
457:                }
458:                for (int x = 0; x < len; x++) {
459:                    os.write((int) (value >> (8 * ((len - 1) - x) & LENMASK)));
460:                }
461:            }
462:
463:            /**
464:             * Decodes a ASN.1 length.
465:             * @param is
466:             *    an <code>InputStream</code>
467:             * @return
468:             *    the decoded length.
469:             * @throws IOException
470:             */
471:            public static final int decodeLength(BERInputStream is)
472:                    throws IOException {
473:                return decodeLength(is, true);
474:            }
475:
476:            /**
477:             * Decodes a ASN.1 length.
478:             * @param is
479:             *    an <code>InputStream</code>
480:             * @param checkLength
481:             *    if <code>false</code> length check is always suppressed.
482:             * @return
483:             *    the decoded length.
484:             * @throws IOException
485:             */
486:            public static final int decodeLength(BERInputStream is,
487:                    boolean checkLength) throws IOException {
488:                int length = 0;
489:                int lengthbyte = is.read();
490:
491:                if ((lengthbyte & ASN_LONG_LEN) > 0) {
492:                    lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */
493:                    if (lengthbyte == 0) {
494:                        throw new IOException(
495:                                "Indefinite lengths are not supported");
496:                    }
497:                    if (lengthbyte > 4) {
498:                        throw new IOException(
499:                                "Data length > 4 bytes are not supported!");
500:                    }
501:                    for (int i = 0; i < lengthbyte; i++) {
502:                        int l = is.read() & 0xFF;
503:                        length |= (l << (8 * ((lengthbyte - 1) - i)));
504:                    }
505:                    if (length < 0) {
506:                        throw new IOException(
507:                                "SNMP does not support data lengths > 2^31");
508:                    }
509:                } else { /* short asnlength */
510:                    length = lengthbyte & 0xFF;
511:                }
512:                /**
513:                 * If activated we do a length check here: length > is.available() -> throw
514:                 * exception
515:                 */
516:                if (checkLength) {
517:                    checkLength(is, length);
518:                }
519:                return length;
520:            }
521:
522:            /**
523:             * Decodes an ASN.1 header for an object with the ID and
524:             * length specified.
525:             *  On entry, datalength is input as the number of valid bytes following
526:             *   "data".  On exit, it is returned as the number of valid bytes
527:             *   in this object following the id and length.
528:             *
529:             *  This only works on data types < 30, i.e. no extension octets.
530:             *  The maximum length is 0xFFFF;
531:             *
532:             * @param is
533:             *   the BERInputStream to decode.
534:             * @param type
535:             *   returns the type of the object at the current position in the input
536:             *   stream.
537:             * @param checkLength
538:             *    if <code>false</code> length check is always suppressed.
539:             * @return
540:             *   the decoded length of the object.
541:             * @throws IOException
542:             */
543:            public static final int decodeHeader(BERInputStream is,
544:                    MutableByte type, boolean checkLength) throws IOException {
545:                /* this only works on data types < 30, i.e. no extension octets */
546:                byte t = (byte) is.read();
547:                if ((t & ASN_EXTENSION_ID) == ASN_EXTENSION_ID) {
548:                    throw new IOException("Cannot process extension IDs"
549:                            + getPositionMessage(is));
550:                }
551:                type.setValue(t);
552:                return decodeLength(is, checkLength);
553:            }
554:
555:            /**
556:             * Decodes an ASN.1 header for an object with the ID and
557:             * length specified.
558:             *  On entry, datalength is input as the number of valid bytes following
559:             *   "data".  On exit, it is returned as the number of valid bytes
560:             *   in this object following the id and length.
561:             *
562:             *  This only works on data types < 30, i.e. no extension octets.
563:             *  The maximum length is 0xFFFF;
564:             *
565:             * @param is
566:             *   the BERInputStream to decode.
567:             * @param type
568:             *   returns the type of the object at the current position in the input
569:             *   stream.
570:             * @return
571:             *   the decoded length of the object.
572:             * @throws IOException
573:             */
574:            public static final int decodeHeader(BERInputStream is,
575:                    MutableByte type) throws IOException {
576:                return decodeHeader(is, type, true);
577:            }
578:
579:            public static final int decodeInteger(BERInputStream is,
580:                    MutableByte type) throws IOException {
581:                int length;
582:                int value = 0;
583:
584:                type.setValue((byte) is.read());
585:
586:                if ((type.value != 0x02) && (type.value != 0x43)
587:                        && (type.value != 0x41)) {
588:                    throw new IOException("Wrong ASN.1 type. Not an integer: "
589:                            + type.value + getPositionMessage(is));
590:                }
591:                length = decodeLength(is);
592:                if (length > 4) {
593:                    throw new IOException(
594:                            "Length greater than 32bit are not supported "
595:                                    + " for integers: "
596:                                    + getPositionMessage(is));
597:                }
598:                int b = is.read() & 0xFF;
599:                if ((b & 0x80) > 0) {
600:                    value = -1; /* integer is negative */
601:                }
602:                while (length-- > 0) {
603:                    value = (value << 8) | b;
604:                    if (length > 0) {
605:                        b = is.read();
606:                    }
607:                }
608:                return value;
609:            }
610:
611:            private static String getPositionMessage(BERInputStream is) {
612:                return " at position " + is.getPosition();
613:            }
614:
615:            public static final long decodeUnsignedInteger(BERInputStream is,
616:                    MutableByte type) throws IOException {
617:                int length;
618:                long value = 0;
619:
620:                // get the type
621:                type.setValue((byte) is.read());
622:                if ((type.value != 0x02) && (type.value != 0x43)
623:                        && (type.value != 0x41) && (type.value != 0x42)
624:                        && (type.value != 0x47)) {
625:                    throw new IOException(
626:                            "Wrong ASN.1 type. Not an unsigned integer: "
627:                                    + type.value + getPositionMessage(is));
628:                }
629:                // pick up the len
630:                length = decodeLength(is);
631:
632:                // check for legal uint size
633:                int b = is.read();
634:                if ((length > 5) || ((length > 4) && (b != 0x00))) {
635:                    throw new IOException(
636:                            "Only 32bit unsigned integers are supported"
637:                                    + getPositionMessage(is));
638:                }
639:
640:                // check for leading  0 octet
641:                if (b == 0x00) {
642:                    if (length > 1) {
643:                        b = is.read();
644:                    }
645:                    length--;
646:                }
647:
648:                // calculate the value
649:                for (int i = 0; i < length; i++) {
650:                    value = (value << 8) | (b & 0xFF);
651:                    if (i + 1 < length) {
652:                        b = is.read();
653:                    }
654:                }
655:                return value;
656:            }
657:
658:            public static final byte[] decodeString(BERInputStream is,
659:                    MutableByte type) throws IOException {
660:                /*
661:                 * ASN.1 octet string ::= primstring | cmpdstring
662:                 * primstring ::= 0x04 asnlength byte {byte}*
663:                 * cmpdstring ::= 0x24 asnlength string {string}*
664:                 * ipaddress  ::= 0x40 4 byte byte byte byte
665:                 */
666:                // get the type
667:                type.setValue((byte) is.read());
668:                if ((type.value != BER.OCTETSTRING) && (type.value != 0x24)
669:                        && (type.value != BER.IPADDRESS)
670:                        && (type.value != BER.OPAQUE)
671:                        && (type.value != BER.BITSTRING)
672:                        && (type.value != 0x45)) {
673:                    throw new IOException("Wrong ASN.1 type. Not a string: "
674:                            + type.value + getPositionMessage(is));
675:                }
676:                int length = decodeLength(is);
677:
678:                byte[] value = new byte[length];
679:                int pos = 0;
680:
681:                while ((pos < length) && (is.available() > 0)) {
682:                    int read = is.read(value);
683:                    if (read > 0) {
684:                        pos += read;
685:                    } else if (read < 0) {
686:                        throw new IOException("Wrong string length " + read
687:                                + " < " + length);
688:                    }
689:                }
690:                return value;
691:            }
692:
693:            public static final int[] decodeOID(BERInputStream is,
694:                    MutableByte type) throws IOException {
695:                /*
696:                 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
697:                 * subidentifier ::= {leadingbyte}* lastbyte
698:                 * leadingbyte ::= 1 7bitvalue
699:                 * lastbyte ::= 0 7bitvalue
700:                 */
701:                int subidentifier;
702:                int length;
703:
704:                // get the type
705:                type.setValue((byte) is.read());
706:                if (type.value != 0x06) {
707:                    throw new IOException("Wrong type. Not an OID: "
708:                            + type.value + getPositionMessage(is));
709:                }
710:                length = decodeLength(is);
711:
712:                int[] oid = new int[length + 2];
713:                /* Handle invalid object identifier encodings of the form 06 00 robustly */
714:                if (length == 0) {
715:                    oid[0] = oid[1] = 0;
716:                }
717:                int pos = 1;
718:                while (length > 0) {
719:                    subidentifier = 0;
720:                    int b;
721:                    do { /* shift and add in low order 7 bits */
722:                        int next = is.read();
723:                        if (next < 0) {
724:                            throw new IOException(
725:                                    "Unexpected end of input stream"
726:                                            + getPositionMessage(is));
727:                        }
728:                        b = next & 0xFF;
729:                        subidentifier = (subidentifier << 7) + (b & ~ASN_BIT8);
730:                        length--;
731:                    } while ((length > 0) && ((b & ASN_BIT8) != 0)); /* last byte has high bit clear */
732:                    oid[pos++] = subidentifier;
733:                }
734:
735:                /*
736:                 * The first two subidentifiers are encoded into the first component
737:                 * with the value (X * 40) + Y, where:
738:                 *	X is the value of the first subidentifier.
739:                 *  Y is the value of the second subidentifier.
740:                 */
741:                subidentifier = oid[1];
742:                if (subidentifier == 0x2B) {
743:                    oid[0] = 1;
744:                    oid[1] = 3;
745:                } else {
746:                    oid[1] = (subidentifier % 40);
747:                    oid[0] = ((subidentifier - oid[1]) / 40);
748:                }
749:                if (pos < 2) {
750:                    pos = 2;
751:                }
752:                int[] value = new int[pos];
753:                System.arraycopy(oid, 0, value, 0, pos);
754:                return value;
755:            }
756:
757:            public static final void decodeNull(BERInputStream is,
758:                    MutableByte type) throws IOException {
759:                // get the type
760:                type.setValue((byte) (is.read() & 0xFF));
761:                if ((type.value != (byte) 0x05) && (type.value != (byte) 0x80)
762:                        && (type.value != (byte) 0x81)
763:                        && (type.value != (byte) 0x82)) {
764:                    throw new IOException("Wrong ASN.1 type. Is not null: "
765:                            + type.value + getPositionMessage(is));
766:                }
767:                int length = decodeLength(is);
768:                if (length != 0) {
769:                    throw new IOException(
770:                            "Invalid Null encoding, length is not zero: "
771:                                    + length + getPositionMessage(is));
772:                }
773:            }
774:
775:            public static final long decodeUnsignedInt64(BERInputStream is,
776:                    MutableByte type) throws IOException {
777:                // get the type
778:                type.setValue((byte) is.read());
779:                if ((type.value != 0x02) && (type.value != 0x46)) {
780:                    throw new IOException("Wrong type. Not an integer 64: "
781:                            + type.value + getPositionMessage(is));
782:                }
783:                int length = decodeLength(is);
784:                int b = is.read() & 0xFF;
785:                if (length > 9) {
786:                    throw new IOException(
787:                            "Invalid 64bit unsigned integer length: " + length
788:                                    + getPositionMessage(is));
789:                }
790:                // check for leading  0 octet
791:                if (b == 0x00) {
792:                    if (length > 1) {
793:                        b = is.read();
794:                    }
795:                    length--;
796:                }
797:                long value = 0;
798:                // calculate the value
799:                for (int i = 0; i < length; i++) {
800:                    value = (value << 8) | (b & 0xFF);
801:                    if (i + 1 < length) {
802:                        b = is.read();
803:                    }
804:                }
805:                return value;
806:            }
807:
808:            /**
809:             * Gets the SEQUENCE length checking mode.
810:             * @return
811:             *    <code>true</code> if the length of a parsed SEQUENCE should be checked
812:             *    against the real length of the objects parsed.
813:             */
814:            public static boolean isCheckSequenceLength() {
815:                return checkSequenceLength;
816:            }
817:
818:            /**
819:             * Sets the application wide SEQUENCE length checking mode.
820:             * @param checkSequenceLen
821:             *    specifies whether he length of a parsed SEQUENCE should be checked
822:             *    against the real length of the objects parsed.
823:             */
824:            public static void setCheckSequenceLength(boolean checkSequenceLen) {
825:                checkSequenceLength = checkSequenceLen;
826:            }
827:
828:            public static void checkSequenceLength(int expectedLength,
829:                    BERSerializable sequence) throws IOException {
830:                if ((isCheckSequenceLength())
831:                        && (expectedLength != sequence.getBERPayloadLength())) {
832:                    throw new IOException(
833:                            "The actual length of the SEQUENCE object "
834:                                    + sequence.getClass().getName() + " is "
835:                                    + sequence.getBERPayloadLength() + ", but "
836:                                    + expectedLength + " was expected");
837:                }
838:            }
839:
840:            public static void checkSequenceLength(int expectedLength,
841:                    int actualLength, BERSerializable sequence)
842:                    throws IOException {
843:                if ((isCheckSequenceLength())
844:                        && (expectedLength != actualLength)) {
845:                    throw new IOException(
846:                            "The actual length of the SEQUENCE object "
847:                                    + sequence.getClass().getName() + " is "
848:                                    + actualLength + ", but " + expectedLength
849:                                    + " was expected");
850:                }
851:            }
852:
853:            /**
854:             * Checks whether the length of that was encoded is also available from the
855:             * stream.
856:             *
857:             * @param is InputStream
858:             * @param length int
859:             * @throws IOException
860:             *    if the bytes that are given in length cannot be read from the input
861:             *    stream (without blocking).
862:             */
863:            private static void checkLength(BERInputStream is, int length)
864:                    throws IOException {
865:                if (!checkValueLength) {
866:                    return;
867:                }
868:                if ((length < 0) || (length > is.getAvailableBytes())) {
869:                    throw new IOException("The encoded length " + length
870:                            + " exceeds the number of bytes left in input"
871:                            + getPositionMessage(is) + " which actually is "
872:                            + is.getAvailableBytes());
873:                }
874:            }
875:
876:            public boolean isCheckValueLength() {
877:                return checkValueLength;
878:            }
879:
880:            public void setCheckValueLength(boolean checkValueLength) {
881:                BER.checkValueLength = checkValueLength;
882:            }
883:
884:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.