4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
34 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
46 #include <netinet/in_systm.h>
47 #include <netinet/in.h>
48 #include <netinet/ip.h>
49 #include <netinet/if_ether.h>
50 #include <netinet/udp.h>
54 #define MIN(a, b) ((a) < (b) ? (a) : (b))
57 extern char *src_name
;
58 extern char *dst_name
;
60 #define LINE_LEN (255)
61 #define BUF_SIZE (16000)
62 static int ldap
= 0; /* flag to control initialization */
71 char scrbuffer
[BUF_SIZE
]; /* buffer to accumulate data until a */
72 /* complete LDAPmessage is received */
73 char resultcode
[LINE_LEN
]; /* These are used */
74 char operation
[LINE_LEN
]; /* by -V option. */
77 int gi_osibuf
[MAX_CTX
];
82 void decode_ldap(char *buf
, int len
);
84 #define X unsigned char
86 #define INT(a) ((int)(a))
87 #define SCRUB (void) strcat(scrbuffer, bb);
89 static X hex
; /* input hex octet */
90 static A
*PTRaclass
; /* application tag table pointer */
93 * ASN.1 Message Printing Macros
96 #define asnshw1(a) {(void)sprintf(bb, a); SCRUB }
97 #define asnshw2(a, b) {(void)sprintf(bb, a, b); SCRUB }
98 #define asnshw3(a, b, c) {(void)sprintf(bb, a, b, c); SCRUB }
99 #define asnshw4(a, b, c, d) {(void)sprintf(bb, a, b, c, d); SCRUB }
100 #define asnshw5(a, b, c, d, e) {(void)sprintf(bb, a, b, c, d, e); SCRUB }
103 * Local Types And Variables
107 * Object identifier oid to name mapping description type
111 A oidname
; /* object identifier string name */
112 X oidcode
[16]; /* object identifier hexa code */
114 typedef oidelmT
*oidelmTp
;
117 * Snoop's entry point to ldap decoding
121 interpret_ldap(flags
, data
, fraglen
, src
, dst
)
134 (void) decode_ldap(data
, fraglen
);
136 if (flags
& F_DTAIL
) {
137 /* i.e. when snoop is run with -v (verbose) */
138 show_header("LDAP: ",
139 "Lightweight Directory Access Protocol Header", fraglen
);
141 printf("%s", scrbuffer
);
145 /* i.e. when snoop is run with -V (summary) */
146 (void) strcpy(data
, "");
148 if (strlen(operation
) != 0) {
149 (void) strcat(data
, " ");
150 (void) strncat(data
, operation
, 30);
151 (void) strcpy(operation
, "");
154 if (strlen(resultcode
) != 0) {
155 (void) strcat(data
, " ");
156 (void) strncat(data
, resultcode
, 30);
157 (void) strcpy(resultcode
, "");
161 (void) sprintf(get_sum_line(),
162 "LDAP C port=%d%s", src
, data
);
165 (void) sprintf(get_sum_line(),
166 "LDAP R port=%d%s", dst
, data
);
170 (void) strcpy(scrbuffer
, "");
174 * Known object identifiers: customize to add your own oids
177 static oidelmT OidTab
[] = {
179 * X.500 Standardized Attribute Types
181 {(A
)"ObjectClass", { 0x03, 0x55, 0x04, 0x00 }},
182 {(A
)"AliasObjectName", { 0x03, 0x55, 0x04, 0x01 }},
183 {(A
)"KnowledgeInfo", { 0x03, 0x55, 0x04, 0x02 }},
184 {(A
)"CommonName", { 0x03, 0x55, 0x04, 0x03 }},
185 {(A
)"Surname", { 0x03, 0x55, 0x04, 0x04 }},
186 {(A
)"SerialNumber", { 0x03, 0x55, 0x04, 0x05 }},
187 {(A
)"CountryName", { 0x03, 0x55, 0x04, 0x06 }},
188 {(A
)"LocalityName", { 0x03, 0x55, 0x04, 0x07 }},
189 {(A
)"StateOrProvinceName", { 0x03, 0x55, 0x04, 0x08 }},
190 {(A
)"StreetAddress", { 0x03, 0x55, 0x04, 0x09 }},
191 {(A
)"OrganizationName", { 0x03, 0x55, 0x04, 0x0a }},
192 {(A
)"OrganizationUnitName", { 0x03, 0x55, 0x04, 0x0b }},
193 {(A
)"Title", { 0x03, 0x55, 0x04, 0x0c }},
194 {(A
)"Description", { 0x03, 0x55, 0x04, 0x0d }},
195 {(A
)"SearchGuide", { 0x03, 0x55, 0x04, 0x0e }},
196 {(A
)"BusinessCategory", { 0x03, 0x55, 0x04, 0x0f }},
197 {(A
)"PostalAddress", { 0x03, 0x55, 0x04, 0x10 }},
198 {(A
)"PostalCode", { 0x03, 0x55, 0x04, 0x11 }},
199 {(A
)"PostOfficeBox", { 0x03, 0x55, 0x04, 0x12 }},
200 {(A
)"PhysicalDeliveryOffice", { 0x03, 0x55, 0x04, 0x13 }},
201 {(A
)"TelephoneNUmber", { 0x03, 0x55, 0x04, 0x14 }},
202 {(A
)"TelexNumber", { 0x03, 0x55, 0x04, 0x15 }},
203 {(A
)"TeletexTerminalId", { 0x03, 0x55, 0x04, 0x16 }},
204 {(A
)"FaxTelephoneNumber", { 0x03, 0x55, 0x04, 0x17 }},
205 {(A
)"X121Address", { 0x03, 0x55, 0x04, 0x18 }},
206 {(A
)"IsdnAddress", { 0x03, 0x55, 0x04, 0x19 }},
207 {(A
)"RegisteredAddress", { 0x03, 0x55, 0x04, 0x1a }},
208 {(A
)"DestinationIndicator", { 0x03, 0x55, 0x04, 0x1b }},
209 {(A
)"PreferDeliveryMethod", { 0x03, 0x55, 0x04, 0x1c }},
210 {(A
)"PresentationAddress", { 0x03, 0x55, 0x04, 0x1d }},
211 {(A
)"SupportedApplContext", { 0x03, 0x55, 0x04, 0x1e }},
212 {(A
)"Member", { 0x03, 0x55, 0x04, 0x1f }},
213 {(A
)"Owner", { 0x03, 0x55, 0x04, 0x20 }},
214 {(A
)"RoleOccupant", { 0x03, 0x55, 0x04, 0x21 }},
215 {(A
)"SeeAlso", { 0x03, 0x55, 0x04, 0x22 }},
216 {(A
)"Password", { 0x03, 0x55, 0x04, 0x23 }},
217 {(A
)"UserCertificate", { 0x03, 0x55, 0x04, 0x24 }},
218 {(A
)"CaCertificate", { 0x03, 0x55, 0x04, 0x25 }},
219 {(A
)"AuthorityRevList", { 0x03, 0x55, 0x04, 0x26 }},
220 {(A
)"CertificateRevList", { 0x03, 0x55, 0x04, 0x27 }},
221 {(A
)"CrossCertificatePair", { 0x03, 0x55, 0x04, 0x28 }},
224 * X.500 Standardized Object Classes
226 {(A
)"Top", { 0x03, 0x55, 0x06, 0x00 }},
227 {(A
)"Alias", { 0x03, 0x55, 0x06, 0x01 }},
228 {(A
)"Country", { 0x03, 0x55, 0x06, 0x02 }},
229 {(A
)"Locality", { 0x03, 0x55, 0x06, 0x03 }},
230 {(A
)"Organization", { 0x03, 0x55, 0x06, 0x04 }},
231 {(A
)"OrganizationUnit", { 0x03, 0x55, 0x06, 0x05 }},
232 {(A
)"Person", { 0x03, 0x55, 0x06, 0x06 }},
233 {(A
)"OrganizationPersion", { 0x03, 0x55, 0x06, 0x07 }},
234 {(A
)"OrganizationRole", { 0x03, 0x55, 0x06, 0x08 }},
235 {(A
)"Group", { 0x03, 0x55, 0x06, 0x09 }},
236 {(A
)"ResidentialPerson", { 0x03, 0x55, 0x06, 0x0A }},
237 {(A
)"ApplicationProcess", { 0x03, 0x55, 0x06, 0x0B }},
238 {(A
)"ApplicationEntity", { 0x03, 0x55, 0x06, 0x0C }},
239 {(A
)"Dsa", { 0x03, 0x55, 0x06, 0x0D }},
240 {(A
)"Device", { 0x03, 0x55, 0x06, 0x0E }},
241 {(A
)"StrongAuthenticUser", { 0x03, 0x55, 0x06, 0x0F }},
242 {(A
)"CaAuthority", { 0x03, 0x55, 0x06, 0x10 }},
245 * ACSE Protocol Object Identifiers
247 {(A
)"Asn1BER-TS", { 0x02, 0x51, 0x01 }},
248 {(A
)"Private-TS", { 0x06, 0x2b, 0xce, 0x06, 0x01, 0x04, 0x06 }},
249 {(A
)"ACSE-AS", { 0x04, 0x52, 0x01, 0x00, 0x01 }},
252 * Directory Protocol Oids
254 {(A
)"DirAccess-AC", { 0x03, 0x55, 0x03, 0x01 }},
255 {(A
)"DirSystem-AC", { 0x03, 0x55, 0x03, 0x02 }},
257 {(A
)"DirAccess-AS", { 0x03, 0x55, 0x09, 0x01 }},
258 {(A
)"DirSystem-AS", { 0x03, 0x55, 0x09, 0x02 }},
261 * and add your private object identifiers here ...
265 #define OIDNB (sizeof (OidTab) / sizeof (oidelmT)) /* total oid nb */
268 * asn.1 tag class definition
271 static A
class[] = { /* tag class */
279 * universal tag definition
282 static A uclass
[] = { /* universal tag assignment */
283 (A
)"EndOfContents", /* 0 */
284 (A
)"Boolean", /* 1 */
285 (A
)"Integer", /* 2 */
286 (A
)"BitString", /* 3 */
287 (A
)"OctetString", /* 4 */
290 (A
)"ObjDescriptor", /* 7 */
291 (A
)"External", /* 8 */
293 (A
)"Enumerated", /* 10 */
294 (A
)"Reserved", /* 11 */
295 (A
)"Reserved", /* 12 */
296 (A
)"Reserved", /* 13 */
297 (A
)"Reserved", /* 14 */
298 (A
)"Reserved", /* 15 */
299 (A
)"Sequence", /* 16 */
301 (A
)"NumericString", /* 18 */
302 (A
)"PrintableString", /* 19 */
303 (A
)"T.61String", /* 20 */
304 (A
)"VideotexString", /* 21 */
305 (A
)"IA5String", /* 22 */
306 (A
)"UTCTime", /* 23 */
307 (A
)"GeneralizedTime", /* 24 */
308 (A
)"GraphicString", /* 25 */
309 (A
)"VisibleString", /* 26 */
310 (A
)"GeneralString", /* 27 */
311 (A
)"Reserved", /* 28 */
312 (A
)"Reserved", /* 29 */
313 (A
)"Reserved", /* 30 */
314 (A
)"Reserved" /* 31 */
317 static A MHSaclass
[] = { /* mhs application tag assignment */
318 (A
)"Bind Request", /* 0 */
322 (A
)"Search ResEntry",
323 (A
)"Search ResDone", /* 5 */
325 (A
)"Modify Response",
327 (A
)"Add Response", /* 9 */
332 (A
)"Compare Request", /* 14 */
333 (A
)"Compare Response",
334 (A
)"Abandon Request",
337 (A
)"Search ResRef", /* 19 */
341 (A
)"Extended Request",
342 (A
)"Extended Response",
353 static A DFTaclass
[] = { /* Default Application Tag Assignment */
388 typedef struct asndefS
{
395 struct asndefS
*sondef
;
398 } asndefT
, * asndefTp
;
400 #define SEQUENCE 0x0002
401 #define SEQUENCEOF 0x0003
403 #define PRINTABLE 0x0008
405 #define BITSTRING 0x0020
406 #define EXTENSION 0x0040
407 #define CONTENTTYPE 0x0080
408 #define CONTENT 0x0100
409 #define CHOICE 0x0200
411 static asndefT RTSpasswd
= { "RTS Authentification data", SET
, -1, 2, {
413 {"MTA Password", 0, 1}}};
414 static asndefT RTSudata
= { "RTS User data", SET
, -1, 1, {
415 {0, &RTSpasswd
, 1}}};
417 static asndefT baseObject
= {"Base Object", PRINTABLE
, -1, 0, {0}};
419 static asndefT scope
= {"Scope", ENUM
, -1, 3, {
420 {"BaseObject", 0, 0},
421 {"singleLevel", 0, 1},
422 {"wholeSubtree", 0, 2}}};
424 static asndefT derefAliases
= {"DerefAliases", ENUM
, -1, 4, {
425 {"neverDerefAliases", 0, 0},
426 {"derefInSearching", 0, 1},
427 {"derefFindingBaseObj", 0, 2},
428 {"derefAlways", 0, 3}}};
430 static asndefT filter
;
431 static asndefT
and = {"And", SET
, -1, 1, {
433 static asndefT
or = {"Or", SET
, -1, 1, {
435 static asndefT
not = {"Not", SET
, -1, 1, {
437 static asndefT equalityMatch
= {"Equality Match", SEQUENCE
, -1, 2, {
438 {"Attr Descr", 0, -1},
440 static asndefT substrings
= {"Substring", SEQUENCE
, -1, 2, {
442 {"Substrings (initial)", 0, 0},
443 {"Substrings (any)", 0, 1},
444 {"Substring (final)", 0, 2}}};
445 static asndefT greaterOrEqual
= {"Greater Or Equal", SEQUENCE
, -1, 2, {
446 {"Attr Descr", 0, -1},
448 static asndefT lessOrEqual
= {"Less Or Equal", SEQUENCE
, -1, 2, {
449 {"Attr Descr", 0, -1},
451 static asndefT approxMatch
= {"Approx Match", SEQUENCE
, -1, 2, {
452 {"Attr Descr", 0, -1},
454 static asndefT extensibleMatch
= {"Extensible Match", SEQUENCE
, -1, 4, {
455 {"MatchingRule", 0, 1},
457 {"MatchValue", 0, 3},
458 {"dnAttributes", 0, 4}}};
460 static asndefT filter
= {"Filter", CHOICE
, -1, 10, {
464 {0, &equalityMatch
, 3},
466 {0, &greaterOrEqual
, 5},
467 {0, &lessOrEqual
, 6},
468 {"Filter: Present", 0, 7},
469 {0, &approxMatch
, 8},
470 {0, &extensibleMatch
, 9}}};
472 static asndefT attributedescription
= \
473 {"Attribute Description", PRINTABLE
, -1, 0, {0}};
474 static asndefT attributes
= {"Attribute List", SEQUENCEOF
, -1, 1, {
475 {0, &attributedescription
, -1}}};
477 static asndefT searchRequest
= {"Operation", SEQUENCE
, 3, 8, {
478 {0, &baseObject
, -1},
480 {0, &derefAliases
, -1},
481 {"SizeLimit", 0, -1},
482 {"TimeLimit", 0, -1},
483 {"TypesOnly", 0, -1},
485 {0, &attributes
, -1}}};
487 static asndefT objectName
= {"Object Name", PRINTABLE
, -1, 0, {0}};
489 static asndefT ldapEntry
= {"Entry", PRINTABLE
, -1, 0, {0}};
490 static asndefT relativeLdapEntry
= \
491 {"Relative LDAP Entry", PRINTABLE
, -1, 0, {0}};
492 static asndefT newSuperior
= {"New Superior", PRINTABLE
, -1, 0, {0}};
494 static asndefT vals
= {"Vals", SET
, -1, 1, {
497 static asndefT attribute
= {"Attribute", SEQUENCE
, -1, 2, {
501 static asndefT partialAttributes
= {"Partial Attributes", SEQUENCEOF
, -1, 1, {
502 {0, &attribute
, -1}}};
504 static asndefT searchResEntry
= {"Operation", SEQUENCE
, 4, 2, {
505 {0, &objectName
, -1},
506 {0, &partialAttributes
, -1}}};
508 static asndefT authChoice
= {"Authentication Choice", CHOICE
, -1, 2, {
509 {"Authentication: Simple", 0, 0},
510 {"Authentication: SASL", 0, 3}}};
512 static asndefT bindRequest
= {"Operation", SEQUENCE
, 0, 3, {
514 {0, &objectName
, -1},
515 {0, &authChoice
, -1}}};
517 static asndefT resultCode
= {"Result Code", ENUM
, -1, 39, {
519 {"Operation Error", 0, 1},
520 {"Protocol Error", 0, 2},
521 {"Time Limit Exceeded", 0, 3},
522 {"Size Limit Exceeded", 0, 4},
523 {"Compare False", 0, 5},
524 {"Compare True", 0, 6},
525 {"Auth Method Not supported", 0, 7},
526 {"Strong Auth Required", 0, 8},
528 {"Admin Limit Exceeded", 0, 11},
529 {"Unavailable Critical Extension", 0, 12},
530 {"Confidentiality required", 0, 13},
531 {"SASL Bind In Progress", 0, 14},
532 {"No Such Attribute", 0, 16},
533 {"Undefined Attribute Type", 0, 17},
534 {"Inappropriate Matching", 0, 18},
535 {"Constraint violation", 0, 19},
536 {"Attribute or Value Exists", 0, 20},
537 {"Invalid Attribute Syntax", 0, 21},
538 {"No Such Object", 0, 32},
539 {"Alias Problem", 0, 33},
540 {"Invalid DN Syntax", 0, 34},
541 {"Alias Dereferencing Problem", 0, 36},
542 {"Inappropriate Authentication", 0, 48},
543 {"Invalid Credentials", 0, 49},
544 {"Insufficient Access Rights", 0, 50},
546 {"Unavailable", 0, 52},
547 {"Unwilling To Perform", 0, 53},
548 {"Loop Detect", 0, 54},
549 {"Naming Violation", 0, 64},
550 {"ObjectClass violation", 0, 65},
551 {"Not Allowed On Non Leaf", 0, 66},
552 {"Not Allowed On RDN", 0, 67},
553 {"Entry Already Exists", 0, 68},
554 {"ObjectClass Mods Prohibited", 0, 69},
555 {"Affects Multiple DSAs", 0, 71},
559 static asndefT referral
= {"Referral", SEQUENCEOF
, -1, 1, {
560 {"LDAP URL", 0, -1}}};
562 static asndefT ldapResult
= {"LDAP Result", SEQUENCE
, -1, 4, {
563 {0, &resultCode
, -1},
564 {"Matched DN", 0, -1},
565 {"Error Message", 0, -1},
568 static asndefT bindResponse
= {"Operation", SEQUENCE
, 1, 5, {
569 {0, &resultCode
, -1},
570 {"Matched DN", 0, -1},
571 {"Error Message", 0, -1},
573 {"SASL Credentials", 0, 7}}};
575 static asndefT unbindRequest
= {"Operation", SEQUENCE
, 2, 0, {0}};
577 static asndefT searchResDone
= {"Operation", SEQUENCE
, 5, 4, {
578 {0, &resultCode
, -1},
579 {"Matched DN", 0, -1},
580 {"Error Message", 0, -1},
583 static asndefT seqModOperation
= {"Operation", ENUM
, -1, 4, {
588 static asndefT seqModModification
= {"Modification", SEQUENCE
, -1, 1, {
589 {0, &attribute
, -1}}};
591 static asndefT seqModification
= {"", SEQUENCE
, -1, 2, {
592 {0, &seqModOperation
, -1},
593 {0, &seqModModification
, -1}}};
595 static asndefT modification
= {"Modification", SEQUENCEOF
, -1, 1, {
596 {0, &seqModification
, -1}}};
598 static asndefT modifyRequest
= {"Operation", SEQUENCE
, 6, 2, {
599 {0, &objectName
, -1},
600 {0, &modification
, -1}}};
602 static asndefT modifyResponse
= {"Operation", SEQUENCE
, 7, 4, {
603 {0, &resultCode
, -1},
604 {"Matched DN", 0, -1},
605 {"Error Message", 0, -1},
608 static asndefT addAttributes
= {"Attributes", SEQUENCEOF
, -1, 1, {
609 {0, &attribute
, -1}}};
611 static asndefT addRequest
= {"Operation", SEQUENCE
, 8, 2, {
613 {0, &addAttributes
, -1}}};
615 static asndefT addResponse
= {"Operation", SEQUENCE
, 9, 4, {
616 {0, &resultCode
, -1},
617 {"Matched DN", 0, -1},
618 {"Error Message", 0, -1},
621 static asndefT delRequest
= {"Operation", SEQUENCE
, 10, 1, {
622 {0, &ldapEntry
, -1}}};
624 static asndefT delResponse
= {"Operation", SEQUENCE
, 11, 4, {
625 {0, &resultCode
, -1},
626 {"Matched DN", 0, -1},
627 {"Error Message", 0, -1},
630 static asndefT modifyDNRequest
= {"Operation", SEQUENCE
, 12, 4, {
632 {0, &relativeLdapEntry
, -1},
633 {"Delete Old RDN", 0, -1},
634 {0, &newSuperior
, 0}}};
636 static asndefT modifyDNResponse
= {"Operation", SEQUENCE
, 13, 4, {
637 {0, &resultCode
, -1},
638 {"Matched DN", 0, -1},
639 {"Error Message", 0, -1},
642 static asndefT ava
= {"Ava", SEQUENCE
, -1, 2, {
643 {"Attr Descr", 0, -1},
646 static asndefT compareRequest
= {"Operation", SEQUENCE
, 14, 2, {
650 static asndefT compareResponse
= {"Operation", SEQUENCE
, 15, 4, {
651 {0, &resultCode
, -1},
652 {"Matched DN", 0, -1},
653 {"Error Message", 0, -1},
656 static asndefT abandonRequest
= {"Operation", SEQUENCE
, 16, 1, {
657 {"Message ID", 0, -1}}};
659 static asndefT searchResRef
= {"Operation", SEQUENCEOF
, 19, 1, {
660 {"LDAP URL", 0, -1}}};
662 static asndefT extendedRequest
= {"Operation", SEQUENCE
, 14, 2, {
663 {"Request Name", 0, 0},
664 {"Request Value", 0, 1}}};
666 static asndefT extendedResponse
= {"Operation", SEQUENCE
, 24, 6, {
667 {0, &resultCode
, -1},
668 {"Matched DN", 0, -1},
669 {"Error Message", 0, -1},
671 {"Response Name", 0, 10},
672 {"Response", 0, 11}}};
674 static asndefT protocolOp
= {"Protocol Op", CHOICE
, -1, 20, {
675 {0, &bindRequest
, 0},
676 {0, &bindResponse
, 1},
677 {0, &unbindRequest
, 2},
678 {0, &searchRequest
, 3},
679 {0, &searchResEntry
, 4},
680 {0, &searchResDone
, 5},
681 {0, &modifyRequest
, 6},
682 {0, &modifyResponse
, 7},
684 {0, &addResponse
, 9},
685 {0, &delRequest
, 10},
686 {0, &delResponse
, 11},
687 {0, &modifyDNRequest
, 12},
688 {0, &modifyDNResponse
, 13},
689 {0, &compareRequest
, 14},
690 {0, &compareResponse
, 15},
691 {0, &abandonRequest
, 16},
692 {0, &searchResRef
, 19},
693 {0, &extendedRequest
, 23},
694 {0, &extendedResponse
, 24}}};
696 static asndefT control
= {"Control", SEQUENCE
, -1, 3, {
698 {"Criticality", 0, -1},
699 {"Control value", 0, -1}}};
701 static asndefT controls
= {"Controls List", SEQUENCEOF
, -1, 1, {
704 static asndefT LDAPMessage
= { "LDAPMessage", SEQUENCE
, -1, 3, {
705 {"Message ID", 0, -1},
706 {0, &protocolOp
, -1},
709 static asndefT MPDU
= { "MPDU", SET
, -1, 1,
710 {{0, &LDAPMessage
, 0}}};
712 static int mytype
[] = {
713 0, /* EndOfContents */
716 BITSTRING
, /* BitString */
720 0, /* ObjDescriptor */
723 ENUM
, /* Enumerated */
729 SEQUENCE
, /* Sequence */
731 0, /* NumericString */
732 0, /* PrintableString */
734 0, /* VideotexString */
737 0, /* GeneralizedTime */
738 0, /* GraphicString */
739 0, /* VisibleString */
740 0, /* GeneralString */
748 * Find object identifier in known oid table
749 * A oid - oid hexa string
750 * int olg - oid length
753 oidmap(A oid
, int olg
)
755 register int ix
, goon
;
756 register A oidptr
, tabptr
, tabend
;
758 /* returns (oid table size) if not found */
760 for (ix
= 0; ix
< OIDNB
; ix
++) {
761 oidptr
= oid
; tabptr
= (&(OidTab
[ix
].oidcode
[0]));
762 if (olg
== INT(*tabptr
++)) {
763 tabend
= tabptr
+ olg
;
765 while (goon
!= 0 && tabptr
< tabend
) {
766 if (*tabptr
++ != *oidptr
++)
777 * Read an hexacode and convert it into ASCII
779 static int getnext(int ctxnum
)
781 static X c
[3]; /* c[0-3] will contain ascii values on exit */
783 if (gi_osibuf
[ctxnum
] == osilen
)
785 hex
= osibuff
[gi_osibuf
[ctxnum
]++];
786 (void) sprintf((char *)c
, "%02x", (hex
&0x00FF));
791 * Skip everything that is not an LDAPMessage
793 static char *skipjunk(len
, pdu
)
801 /* size minumum for a sequence + integer = 5 */
802 /* LDAPMessage::= SEQUENCE */
803 if ((len
> 5) && (buf
[0] == 0x30)) {
806 /* length is one one octet */
809 /* length is multiple octet. */
810 offset
= 1+ tag
&0x007f;
812 /* Make sure we don't read past the end */
814 if (len
- (1+offset
) > 0) {
815 /* skip after the length */
816 tag
= buf
[1+offset
]&0x00ff;
817 if (tag
== 0x02) { /* INTEGER */
818 /* looks like a valid PDU */
830 #define GETNEXT(a) (void)getnext(a);
833 * main routine: decode a TLV; to be called recursively
835 * pdulen: current pdu's length
838 decpdu(int pdulen
, asndefTp ASNDESC
, int ctxnum
)
840 X scrlin
[99]; /* screen line */
841 X oidstr
[80]; /* oid hexa string */
842 int slen
; /* screen line length */
843 int stlv
; /* sub-tlv length */
844 int oix
; /* oid table index */
845 int effnb
; /* effectively traced octet nb */
848 asndefTp SASNDESC
= 0;
849 asndefTp TMPDESC
= 0;
850 asndefTp GR_TMPDESC
= 0;
855 static int rlen
= 0; /* tlv's real length */
857 ++level
[ctxnum
]; /* level indicator */
861 * Decode the current TLV segment
865 if (getnext(ctxnum
)) {
868 if (strlen(scrbuffer
)) asnshw2("%s ", "LDAP:");
869 /* screen printing according to level indicator */
870 for (i
= 1; i
< level
[ctxnum
]; ++i
) asnshw1(" ");
873 otyp
[ctxnum
] = INT(hex
); /* single octet type only */
879 olen
[ctxnum
] = INT(hex
); /* tlv length */
883 /* Continuing decoding of current TLV... */
885 * Snoop's lower layers do not allow us
886 * to know the true length for
887 * datastream protocols like LDAP.
891 * if length is less than 128, we
892 * already have the real TLV length.
894 if (olen
[ctxnum
] < 128) { /* short length form */
896 } else { /* long and any form length */
897 /* else we do more getnext()'s */
898 for (rlen
= 0, olen
[ctxnum
] &= 0x0F;
899 (olen
[ctxnum
]) && (pdulen
> 0);
900 --olen
[ctxnum
], --pdulen
, ++effnb
) {
902 rlen
= (rlen
<< 8) | INT(hex
);
910 * print the tag class and number
912 i
= otyp
[ctxnum
]&0x1F;
913 switch (otyp
[ctxnum
] >> 6) { /* class */
914 case 0: /* universal */
915 if (ASNDESC
&& i
!= 0) {
917 switch (ASNDESC
->type
) {
923 ai
< ASNDESC
->nbson
&& i
< 32 &&
924 ASNDESC
->son
[ai
].sondef
&&
926 * For this test SEQUENCE & SEQUENCE OF
927 * are same, so suppress the last bit
929 (ASNDESC
->son
[ai
].sondef
932 if (ai
< ASNDESC
->nbson
) {
934 ASNDESC
->son
[ai
].sondef
;
935 if (ASNDESC
->son
[ai
].sonname
!= NULL
) {
937 if (ASNDESC
->son
[ai
].sondef
!= NULL
&&
938 ASNDESC
->son
[ai
].sondef
->name
!=
940 asnshw2("%s ", "LDAP:");
941 asnshw4(" %c[%s %s]",
942 ((otyp
[ctxnum
]&0x20)?'*':' '),
943 ASNDESC
->son
[ai
].sonname
,
944 ASNDESC
->son
[ai
].sondef
->name
);
948 ((otyp
[ctxnum
]&0x20)?'*':' '),
949 ASNDESC
->son
[ai
].sonname
);
954 } else if (ASNDESC
->son
[ai
].sondef
!=
956 ASNDESC
->son
[ai
].sondef
->name
!=
958 asnshw2("%s ", "LDAP:");
960 ((otyp
[ctxnum
]&0x20)?'*':' '),
961 ASNDESC
->son
[ai
].sondef
->name
);
969 TMPDESC
= GR_TMPDESC
;
971 } else if (TMPDESC
) {
992 (ai
< ASNDESC
->nbson
&& i
< 32 && mytype
[i
] && \
993 ASNDESC
->son
[ai
].sondef
&&
995 * For this test SEQUENCE & SEQUENCE OF
996 * are the same, so suppress last bit
998 (ASNDESC
->son
[ai
].sondef
->type
&0xFE) != mytype
[i
]);
1000 if (ai
< ASNDESC
->nbson
) {
1002 ASNDESC
->son
[ai
].sondef
;
1003 if (ASNDESC
->son
[ai
].sonname
) {
1005 (ASNDESC
->son
[ai
].sondef
&&
1006 ASNDESC
->son
[ai
].sondef
->name
) {
1008 (" %c[%s %s]", ((otyp
[ctxnum
]&0x20)?'*':' '),
1009 ASNDESC
->son
[ai
].sonname
,
1010 ASNDESC
->son
[ai
].sondef
->name
);
1013 (" %c[%s]", ((otyp
[ctxnum
]&0x20)?'*':' '),
1014 ASNDESC
->son
[ai
].sonname
);
1018 (ASNDESC
->son
[ai
].sondef
&&
1019 ASNDESC
->son
[ai
].sondef
->name
) {
1021 (" %c[%s]", ((otyp
[ctxnum
]&0x20)?'*':' '),
1022 ASNDESC
->son
[ai
].sondef
->name
);
1029 SASNDESC
= ASNDESC
->son
[ai
].sondef
;
1030 if (ASNDESC
->son
[ai
].sonname
) {
1031 if (ASNDESC
->son
[ai
].sondef
&& \
1032 ASNDESC
->son
[ai
].sondef
->name
) {
1034 (" %c[%s %s]", ((otyp
[ctxnum
]&0x20)?'*':' '),
1035 ASNDESC
->son
[ai
].sonname
,
1036 ASNDESC
->son
[ai
].sondef
->name
);
1039 (" %c[%s]", ((otyp
[ctxnum
]&0x20)?'*':' '),
1040 ASNDESC
->son
[ai
].sonname
);
1044 (ASNDESC
->son
[ai
].sondef
&&
1045 ASNDESC
->son
[ai
].sondef
->name
) {
1047 (" %c[%s]", ((otyp
[ctxnum
]&0x20)?'*':' '),
1048 ASNDESC
->son
[ai
].sondef
->name
);
1058 (" %c[%s]", ((otyp
[ctxnum
]&0x20)?'*':' '), uclass
[i
]);
1061 (" %c[%s%d]", ((otyp
[ctxnum
]&0x20)?'*':' '),
1065 case 1: /* application */
1069 for (ai
= 0; ai
< ASNDESC
->nbson
; ++ai
) {
1073 (ASNDESC
->son
[ai
].sondef
&&
1074 ASNDESC
->son
[ai
].sondef
->type
== CHOICE
) {
1076 (i2
< ASNDESC
->son
[ai
].sondef
->nbson
&&
1077 ASNDESC
->son
[ai
].sondef
->son
[i2
].sondef
&& \
1078 ASNDESC
->son
[ai
].sondef
->son
[i2
].sondef
->application
!= i
) {
1083 (i2
== ASNDESC
->son
[ai
].sondef
->nbson
) {
1084 ai
= ASNDESC
->nbson
;
1088 GR_TMPDESC
= TMPDESC
;
1092 ASNDESC
= ASNDESC
->son
[ai
].sondef
;
1097 if (ASNDESC
->son
[ai
].sondef
&& \
1098 ASNDESC
->son
[ai
].sondef
->application
== i
) {
1100 ASNDESC
->son
[ai
].sondef
;
1101 if (ASNDESC
->son
[ai
].sonname
) {
1103 (ASNDESC
->son
[ai
].sondef
->name
) {
1105 (" %s %s", ASNDESC
->son
[ai
].sonname
,
1106 ASNDESC
->son
[ai
].sondef
->name
);
1109 (" %s", ASNDESC
->son
[ai
].sonname
);
1112 (ASNDESC
->son
[ai
].sondef
->name
) {
1114 (" %s", ASNDESC
->son
[ai
].sondef
->name
);
1119 if (ai
>= ASNDESC
->nbson
) {
1120 ai
= -1; /* not found */
1125 (" %c[%s%d: %s]", ((otyp
[ctxnum
]&0x20)?'*':' '),
1126 class[1], i
, PTRaclass
[i
]);
1127 (void) strcpy(operation
, (char *)PTRaclass
[i
]);
1130 (" %c[%s%d]", ((otyp
[ctxnum
]&0x20)?'*':' '), \
1135 case 2: /* context-specific */
1139 TMPDESC
= GR_TMPDESC
;
1144 for (ai
= 0; ai
< ASNDESC
->nbson
; ++ai
) {
1146 (!already
&& ASNDESC
->son
[ai
].sondef
&&
1147 ASNDESC
->son
[ai
].sondef
->type
== CHOICE
) {
1150 (i2
< ASNDESC
->son
[ai
].sondef
->nbson
&&
1151 ASNDESC
->son
[ai
].sondef
->son
[i2
].tag
!= i
) {
1156 ASNDESC
->son
[ai
].sondef
->nbson
) {
1157 ai
= ASNDESC
->nbson
;
1161 GR_TMPDESC
= TMPDESC
;
1166 ASNDESC
->son
[ai
].sondef
;
1172 (ASNDESC
->son
[ai
].tag
== i
) {
1174 ASNDESC
->son
[ai
].sondef
;
1175 if (ASNDESC
->son
[ai
].sonname
) {
1177 (ASNDESC
->son
[ai
].sondef
&&
1178 ASNDESC
->son
[ai
].sondef
->name
) {
1180 (" %s %s", ASNDESC
->son
[ai
].sonname
,
1181 ASNDESC
->son
[ai
].sondef
->name
);
1184 (" %s", ASNDESC
->son
[ai
].sonname
);
1187 (ASNDESC
->son
[ai
].sondef
&&
1188 ASNDESC
->son
[ai
].sondef
->name
) {
1190 (" %s", ASNDESC
->son
[ai
].sondef
->name
);
1195 if (ai
>= ASNDESC
->nbson
) {
1196 ai
= -1; /* not found */
1200 (" %c[%d]", ((otyp
[ctxnum
]&0x20)?'*':' '), i
);
1203 case 3: /* private */
1205 (" %c[%s%d]", ((otyp
[ctxnum
]&0x20)?'*':' '), \
1210 * print the length - as a debug tool only.
1212 /* asnshw2(" Length=%d ",rlen); */
1214 if (rlen
> pdulen
) {
1215 asnshw1("*** Decode length error,");
1216 asnshw2(" PDU length = %d ***\n", pdulen
);
1221 * recursive interpretation of the value if constructor
1223 if (otyp
[ctxnum
]&0x20) { /* constructor */
1225 stlv
= decpdu((rlen
?rlen
:pdulen
), \
1226 ASNDESC
&& ai
!= -1 ?(ai
== -2 ? ASNDESC
:
1227 ASNDESC
->son
[ai
].sondef
):0, ctxnum
);
1228 /* recursive decoding */
1231 } else if (otyp
[ctxnum
] == 0x06) {
1233 * interpretation of the object identifier
1235 for (j
= 0; (rlen
) && (pdulen
> 0); \
1236 --rlen
, --pdulen
, ++effnb
) {
1241 /* interpret the object identifier */
1243 oix
= oidmap(oidstr
, j
-1);
1245 if (oix
>= 0 && oix
< OIDNB
) { /* recognized obj id */
1246 asnshw2("%s\n", OidTab
[oix
].oidname
);
1248 asnshw1("Unknown Oid\n");
1252 * interpretation of other primitive tags
1254 if (!otyp
[ctxnum
] && !rlen
) {
1255 /* end of contents: any form length */
1261 if (SASNDESC
&& SASNDESC
->type
== CONTENT
&& \
1262 SASNDESC
->nbson
&& SASNDESC
->son
[0].sondef
) {
1264 decpdu(rlen
, SASNDESC
->son
[0].sondef
, ctxnum
);
1267 for (j
= 0, slen
= 0; \
1268 (rlen
) && (pdulen
> 0);
1269 --rlen
, --pdulen
, ++effnb
) {
1272 strcpy((char *)scrlin
, "LDAP: "); j
+= 7;
1274 (i
= 0; i
< level
[ctxnum
]; ++i
) {
1286 if (!isprint(hex
)) {
1291 if ((slen
+= 2) >= \
1292 (72 - (level
[ctxnum
] * 3))) {
1301 } /* rof: primitive values */
1305 asnshw2("%s\n", scrlin
);
1310 asnshw2("%s ", "LDAP:");
1311 for (i
= 0; i
< level
[ctxnum
]; ++i
) {
1318 for (j
= 0; (rlen
) && (pdulen
> 0); \
1319 --rlen
, --pdulen
, ++effnb
) {
1327 "*** NOT PRINTED - Too long value ***");
1328 asnshw2("%s\n", scrlin
);
1332 (SASNDESC
&& SASNDESC
->type
== BITSTRING
&&\
1334 unsigned long bitstr
= 0;
1335 for (i
= 1; i
< 5; ++i
) {
1337 ((bitstr
) << 8) + ((i
< klen
)?hexstr
[i
]:0);
1340 (i
= 0; i
< SASNDESC
->nbson
; ++i
) {
1342 ((unsigned long)SASNDESC
->son
[i
].sondef
)) ==
1343 ((unsigned long)SASNDESC
->son
[i
].tag
)) {
1345 (SASNDESC
->son
[i
].sonname
) {
1350 (k
= 0; k
< level
[ctxnum
]; ++k
) {
1354 ("%s", SASNDESC
->son
[i
].sonname
);
1360 (SASNDESC
->type
== ENUM
||
1361 SASNDESC
->type
== CONTENTTYPE
) && klen
<= 5) {
1362 unsigned long value
= 0;
1363 for (i
= 0; i
< klen
; ++i
) {
1365 ((value
) << 8) + hexstr
[i
];
1368 (i
= 0; i
< SASNDESC
->nbson
; ++i
) {
1370 (value
== ((unsigned long)SASNDESC
->son
[i
].tag
)) {
1372 (SASNDESC
->son
[i
].sonname
) {
1377 (k
= 0; k
< level
[ctxnum
]; ++k
) {
1381 ("%s\n", SASNDESC
->son
[i
].sonname
);
1383 strcpy(resultcode
, SASNDESC
->son
[i
].sonname
);
1391 } /* fi: constructor/obj-id/primitive */
1392 } /* fi: tag analysis */
1393 } /* elihw: len>1 */
1399 /* init_ldap initializes various buffers and variables */
1400 /* it is called one-time (in snoop_filter.c) only. */
1407 for (i
= 0; i
< MAX_CTX
; i
++) {
1413 ldapdump(char *data
, int datalen
)
1416 ushort_t
*p16
= (ushort_t
*)data
;
1419 int chunk
= 16; /* 16 bytes per line */
1421 asnshw1("LDAP: Skipping until next full LDAPMessage\n");
1423 for (p
= data
; p
< data
+ datalen
; p
+= chunk
) {
1424 asnshw2("LDAP:\t%4d: ", p
- data
);
1425 left
= (data
+ datalen
) - p
;
1426 len
= MIN(chunk
, left
);
1427 for (i
= 0; i
< (len
/ 2); i
++)
1428 asnshw2("%04x ", ntohs(*p16
++) & 0xffff);
1430 asnshw2("%02x ", *((unsigned char *)p16
));
1432 for (i
= 0; i
< (chunk
- left
) / 2; i
++)
1436 for (i
= 0; i
< len
; i
++, p8
++)
1437 asnshw2("%c", isprint(*p8
) ? *p8
: '.');
1444 /* decode_ldap is the entry point for the main decoding function */
1445 /* decpdu(). decode_ldap() is only called by interpret_ldap. */
1448 decode_ldap(char *buf
, int len
)
1450 asndefTp ASNDESC
= 0;
1454 PTRaclass
= MHSaclass
;
1458 newbuf
= skipjunk(len
, buf
);
1460 skipped
= newbuf
-buf
;
1461 ldapdump(buf
, newbuf
-buf
);
1465 osibuff
= buf
; /* Undecoded buf is passed by interpret_ldap */
1466 osilen
= len
; /* length of tcp data is also passed */
1468 (void) decpdu(len
, ASNDESC
, 0);