xref: /titanic_51/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ldap.c (revision 733a5356058ae0150a67d61f0ad8e5260d2acae3)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2000-2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/time.h>
36 #include <sys/stat.h>
37 #include <sys/uio.h>
38 #include <unistd.h>
39 #include <signal.h>
40 #include <errno.h>
41 #include <stdlib.h>
42 #include <sys/wait.h>
43 #include <sys/socket.h>
44 #include <sys/sockio.h>
45 #include <net/if.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>
51 #include "snoop.h"
52 
53 #ifndef MIN
54 #define	MIN(a, b) ((a) < (b) ? (a) : (b))
55 #endif
56 
57 extern char *src_name;
58 extern char *dst_name;
59 #define	MAX_CTX  (10)
60 #define	LINE_LEN (255)
61 #define	BUF_SIZE (16000)
62 static int ldap = 0;	/* flag to control initialization */
63 struct ctx {
64 	int src;
65 	int dst;
66 	char *src_name;
67 	char *dst_name;
68 };
69 char *osibuff = NULL;
70 int osilen = 0;
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.  */
75 char bb[LINE_LEN];
76 
77 int gi_osibuf[MAX_CTX];
78 int otyp[MAX_CTX];
79 int olen[MAX_CTX];
80 int level[MAX_CTX];
81 
82 void decode_ldap(char *buf, int len);
83 
84 #define	X unsigned char
85 typedef	X * A;
86 #define	INT(a) ((int)(a))
87 #define	SCRUB (void) strcat(scrbuffer, bb);
88 
89 static X	hex;	/* input hex octet */
90 static A	*PTRaclass;	/* application tag table pointer */
91 
92 /*
93 **----------------------------------------------**
94 **		ASN.1 Message Printing Macros			**
95 **----------------------------------------------**
96 */
97 
98 #define	asnshw1(a)				{(void)sprintf(bb, a); SCRUB }
99 #define	asnshw2(a, b)			{(void)sprintf(bb, a, b); SCRUB }
100 #define	asnshw3(a, b, c)		{(void)sprintf(bb, a, b, c); SCRUB }
101 #define	asnshw4(a, b, c, d)		{(void)sprintf(bb, a, b, c, d); SCRUB }
102 #define	asnshw5(a, b, c, d, e)	{(void)sprintf(bb, a, b, c, d, e); SCRUB }
103 
104 /*
105 **--------------------------------------**
106 **		Local Types And Variables		**
107 **--------------------------------------**
108 */
109 
110 /*
111 ** object identifier oid to name mapping description type
112 */
113 
114 typedef struct {
115 	A	oidname;		/* object identifier string name */
116 	X	oidcode[16];	/* object identifier hexa code */
117 }	oidelmT;
118 typedef oidelmT *oidelmTp;
119 
120 /*
121 **------------------------------------------**
122 **	snoop's entry point to ldap decoding	**
123 **------------------------------------------**
124 */
125 
126 void
127 interpret_ldap(flags, data, fraglen, src, dst)
128 int flags;
129 char *data;
130 int fraglen;
131 int src;
132 int dst;
133 {
134 
135 	if (!ldap) {
136 		init_ldap();
137 		ldap = 1;
138 	}
139 
140 	(void) decode_ldap(data, fraglen);
141 
142 	if (flags & F_DTAIL) {
143 		/* i.e. when snoop is run with -v (verbose) */
144 		show_header("LDAP:  ",
145 		"Lightweight Directory Access Protocol Header", fraglen);
146 		show_space();
147 		printf("%s", scrbuffer);
148 	}
149 
150 	if (flags & F_SUM) {
151 	/* i.e. when snoop is run with -V (summary) */
152 		(void) strcpy(data, "");
153 
154 		if (strlen(operation) != 0) {
155 			(void) strcat(data, " ");
156 			(void) strncat(data, operation, 30);
157 			(void) strcpy(operation, "");
158 		}
159 
160 		if (strlen(resultcode) != 0) {
161 			(void) strcat(data, " ");
162 			(void) strncat(data, resultcode, 30);
163 			(void) strcpy(resultcode, "");
164 		}
165 
166 		if (dst == 389) {
167 			(void) sprintf(get_sum_line(),
168 				"LDAP C port=%d%s", src, data);
169 		}
170 		if (src == 389) {
171 			(void) sprintf(get_sum_line(),
172 				"LDAP R port=%d%s", dst, data);
173 		}
174 	}
175 
176 	(void) strcpy(scrbuffer, "");
177 }
178 
179 /*
180 **--------------------------------------------------------------**
181 **	known object identifiers: customize to add your own oids	**
182 **--------------------------------------------------------------**
183 */
184 
185 static oidelmT OidTab[] = {
186 /*
187 **	X.500 Standardized Attribute Types
188 */
189 {(A)"ObjectClass",				{ 0x03, 0x55, 0x04, 0x00 }},
190 {(A)"AliasObjectName",			{ 0x03, 0x55, 0x04, 0x01 }},
191 {(A)"KnowledgeInfo",			{ 0x03, 0x55, 0x04, 0x02 }},
192 {(A)"CommonName",				{ 0x03, 0x55, 0x04, 0x03 }},
193 {(A)"Surname",					{ 0x03, 0x55, 0x04, 0x04 }},
194 {(A)"SerialNumber",				{ 0x03, 0x55, 0x04, 0x05 }},
195 {(A)"CountryName",				{ 0x03, 0x55, 0x04, 0x06 }},
196 {(A)"LocalityName",				{ 0x03, 0x55, 0x04, 0x07 }},
197 {(A)"StateOrProvinceName",		{ 0x03, 0x55, 0x04, 0x08 }},
198 {(A)"StreetAddress",			{ 0x03, 0x55, 0x04, 0x09 }},
199 {(A)"OrganizationName",			{ 0x03, 0x55, 0x04, 0x0a }},
200 {(A)"OrganizationUnitName",		{ 0x03, 0x55, 0x04, 0x0b }},
201 {(A)"Title",					{ 0x03, 0x55, 0x04, 0x0c }},
202 {(A)"Description",				{ 0x03, 0x55, 0x04, 0x0d }},
203 {(A)"SearchGuide",				{ 0x03, 0x55, 0x04, 0x0e }},
204 {(A)"BusinessCategory",			{ 0x03, 0x55, 0x04, 0x0f }},
205 {(A)"PostalAddress",			{ 0x03, 0x55, 0x04, 0x10 }},
206 {(A)"PostalCode",				{ 0x03, 0x55, 0x04, 0x11 }},
207 {(A)"PostOfficeBox",			{ 0x03, 0x55, 0x04, 0x12 }},
208 {(A)"PhysicalDeliveryOffice",	{ 0x03, 0x55, 0x04, 0x13 }},
209 {(A)"TelephoneNUmber",			{ 0x03, 0x55, 0x04, 0x14 }},
210 {(A)"TelexNumber",				{ 0x03, 0x55, 0x04, 0x15 }},
211 {(A)"TeletexTerminalId",		{ 0x03, 0x55, 0x04, 0x16 }},
212 {(A)"FaxTelephoneNumber",		{ 0x03, 0x55, 0x04, 0x17 }},
213 {(A)"X121Address",				{ 0x03, 0x55, 0x04, 0x18 }},
214 {(A)"IsdnAddress",				{ 0x03, 0x55, 0x04, 0x19 }},
215 {(A)"RegisteredAddress",		{ 0x03, 0x55, 0x04, 0x1a }},
216 {(A)"DestinationIndicator",		{ 0x03, 0x55, 0x04, 0x1b }},
217 {(A)"PreferDeliveryMethod",		{ 0x03, 0x55, 0x04, 0x1c }},
218 {(A)"PresentationAddress",		{ 0x03, 0x55, 0x04, 0x1d }},
219 {(A)"SupportedApplContext",		{ 0x03, 0x55, 0x04, 0x1e }},
220 {(A)"Member",					{ 0x03, 0x55, 0x04, 0x1f }},
221 {(A)"Owner",					{ 0x03, 0x55, 0x04, 0x20 }},
222 {(A)"RoleOccupant",				{ 0x03, 0x55, 0x04, 0x21 }},
223 {(A)"SeeAlso",					{ 0x03, 0x55, 0x04, 0x22 }},
224 {(A)"Password",					{ 0x03, 0x55, 0x04, 0x23 }},
225 {(A)"UserCertificate",			{ 0x03, 0x55, 0x04, 0x24 }},
226 {(A)"CaCertificate",			{ 0x03, 0x55, 0x04, 0x25 }},
227 {(A)"AuthorityRevList",			{ 0x03, 0x55, 0x04, 0x26 }},
228 {(A)"CertificateRevList",		{ 0x03, 0x55, 0x04, 0x27 }},
229 {(A)"CrossCertificatePair",		{ 0x03, 0x55, 0x04, 0x28 }},
230 
231 /*
232 **	X.500 Standardized Object Classes
233 */
234 {(A)"Top",					{ 0x03, 0x55, 0x06, 0x00 }},
235 {(A)"Alias",				{ 0x03, 0x55, 0x06, 0x01 }},
236 {(A)"Country",				{ 0x03, 0x55, 0x06, 0x02 }},
237 {(A)"Locality",				{ 0x03, 0x55, 0x06, 0x03 }},
238 {(A)"Organization",			{ 0x03, 0x55, 0x06, 0x04 }},
239 {(A)"OrganizationUnit",		{ 0x03, 0x55, 0x06, 0x05 }},
240 {(A)"Person",				{ 0x03, 0x55, 0x06, 0x06 }},
241 {(A)"OrganizationPersion",	{ 0x03, 0x55, 0x06, 0x07 }},
242 {(A)"OrganizationRole",		{ 0x03, 0x55, 0x06, 0x08 }},
243 {(A)"Group",				{ 0x03, 0x55, 0x06, 0x09 }},
244 {(A)"ResidentialPerson",	{ 0x03, 0x55, 0x06, 0x0A }},
245 {(A)"ApplicationProcess",	{ 0x03, 0x55, 0x06, 0x0B }},
246 {(A)"ApplicationEntity",	{ 0x03, 0x55, 0x06, 0x0C }},
247 {(A)"Dsa",					{ 0x03, 0x55, 0x06, 0x0D }},
248 {(A)"Device",				{ 0x03, 0x55, 0x06, 0x0E }},
249 {(A)"StrongAuthenticUser",	{ 0x03, 0x55, 0x06, 0x0F }},
250 {(A)"CaAuthority",			{ 0x03, 0x55, 0x06, 0x10 }},
251 
252 /*
253 **	ACSE Protocol Object Identifiers
254 */
255 {(A)"Asn1BER-TS",		{ 0x02, 0x51, 0x01 }},
256 {(A)"Private-TS",		{ 0x06, 0x2b, 0xce, 0x06, 0x01, 0x04, 0x06 }},
257 {(A)"ACSE-AS",			{ 0x04, 0x52, 0x01, 0x00, 0x01 }},
258 
259 /*
260 **	Directory Protocol Oids
261 */
262 {(A)"DirAccess-AC",			{ 0x03, 0x55, 0x03, 0x01 }},
263 {(A)"DirSystem-AC",			{ 0x03, 0x55, 0x03, 0x02 }},
264 
265 {(A)"DirAccess-AS",			{ 0x03, 0x55, 0x09, 0x01 }},
266 {(A)"DirSystem-AS",			{ 0x03, 0x55, 0x09, 0x02 }},
267 
268 /*
269 **	and add your private object identifiers here ...
270 */
271 };
272 
273 #define	OIDNB (sizeof (OidTab) / sizeof (oidelmT))	/* total oid nb */
274 
275 /*
276 **	asn.1 tag class definition
277 */
278 
279 static A class[] = {	/* tag class */
280 	(A)"UNIV ",
281 	(A)"APPL ",
282 	(A)"CTXs ",
283 	(A)"PRIV "
284 };
285 
286 /*
287 **	universal tag definition
288 */
289 
290 static A uclass[] = {	/* universal tag assignment */
291 (A)"EndOfContents",			/* 0  */
292 (A)"Boolean",				/* 1  */
293 (A)"Integer",				/* 2  */
294 (A)"BitString",				/* 3  */
295 (A)"OctetString",			/* 4  */
296 (A)"Null",					/* 5  */
297 (A)"Oid",					/* 6  */
298 (A)"ObjDescriptor",			/* 7  */
299 (A)"External",				/* 8  */
300 (A)"Real",					/* 9  */
301 (A)"Enumerated",			/* 10 */
302 (A)"Reserved",				/* 11 */
303 (A)"Reserved",				/* 12 */
304 (A)"Reserved",				/* 13 */
305 (A)"Reserved",				/* 14 */
306 (A)"Reserved",				/* 15 */
307 (A)"Sequence",				/* 16 */
308 (A)"Set",					/* 17 */
309 (A)"NumericString",			/* 18 */
310 (A)"PrintableString",		/* 19 */
311 (A)"T.61String",			/* 20 */
312 (A)"VideotexString",		/* 21 */
313 (A)"IA5String",				/* 22 */
314 (A)"UTCTime",				/* 23 */
315 (A)"GeneralizedTime",		/* 24 */
316 (A)"GraphicString",			/* 25 */
317 (A)"VisibleString",			/* 26 */
318 (A)"GeneralString",			/* 27 */
319 (A)"Reserved",				/* 28 */
320 (A)"Reserved",				/* 29 */
321 (A)"Reserved",				/* 30 */
322 (A)"Reserved" 				/* 31 */
323 };
324 
325 static A MHSaclass[] = {	/* mhs application tag assignment */
326 (A)"Bind Request",		/* 0 */
327 (A)"Bind Response",
328 (A)"Unbind Request",
329 (A)"Search Request",
330 (A)"Search ResEntry",
331 (A)"Search ResDone",	/* 5 */
332 (A)"Modify Request",
333 (A)"Modify Response",
334 (A)"Add Request",
335 (A)"Add Response",		/* 9 */
336 (A)"Del Request",
337 (A)"Del Response",
338 (A)"ModDN Request",
339 (A)"ModDN Response",
340 (A)"Compare Request",	/* 14 */
341 (A)"Compare Response",
342 (A)"Abandon Request",
343 (A)"",					/* 17 */
344 (A)"",					/* 18 */
345 (A)"Search ResRef",		/* 19 */
346 (A)"",					/* 20 */
347 (A)"",					/* 21 */
348 (A)"",					/* 22 */
349 (A)"Extended Request",
350 (A)"Extended Response",
351 (A)"",					/* 25 */
352 (A)"",					/* 26 */
353 (A)"",					/* 27 */
354 (A)"",					/* 28 */
355 (A)"",					/* 29 */
356 (A)"",					/* 30 */
357 (A)"" 					/* 31 */
358 };
359 
360 
361 static A DFTaclass[] = {	/* Default Application Tag Assignment */
362 (A)"",				/* 0  */
363 (A)"",				/* 1  */
364 (A)"",				/* 2  */
365 (A)"",				/* 3  */
366 (A)"",				/* 4  */
367 (A)"",				/* 5  */
368 (A)"",				/* 6  */
369 (A)"",				/* 7  */
370 (A)"",				/* 8  */
371 (A)"",				/* 9  */
372 (A)"",				/* 10 */
373 (A)"",				/* 11 */
374 (A)"",				/* 12 */
375 (A)"",				/* 13 */
376 (A)"",				/* 14 */
377 (A)"",				/* 15 */
378 (A)"",				/* 16 */
379 (A)"",				/* 17 */
380 (A)"",				/* 18 */
381 (A)"",				/* 19 */
382 (A)"",				/* 20 */
383 (A)"",				/* 21 */
384 (A)"",				/* 22 */
385 (A)"",				/* 23 */
386 (A)"",				/* 24 */
387 (A)"",				/* 25 */
388 (A)"",				/* 26 */
389 (A)"",				/* 27 */
390 (A)"",				/* 28 */
391 (A)"",				/* 29 */
392 (A)"",				/* 30 */
393 (A)"" 				/* 31 */
394 };
395 
396 typedef struct asndefS {
397 char *name;
398 int type;
399 int application;
400 int nbson;
401 struct {
402 	char *sonname;
403 	struct asndefS *sondef;
404 	long tag;
405 	} son[50];
406 } asndefT, * asndefTp;
407 
408 #define	SEQUENCE		0x0002
409 #define	SEQUENCEOF		0x0003
410 #define	SET				0x0004
411 #define	PRINTABLE		0x0008
412 #define	ENUM			0x0010
413 #define	BITSTRING		0x0020
414 #define	EXTENSION		0x0040
415 #define	CONTENTTYPE		0x0080
416 #define	CONTENT			0x0100
417 #define	CHOICE			0x0200
418 
419 static asndefT RTSpasswd = { "RTS Authentification data", SET,  -1, 2, {
420 			{"MTA Name", 0, 0},
421 			{"MTA Password", 0, 1}}};
422 static asndefT RTSudata = { "RTS User data", SET,  -1, 1, {
423 			{0, &RTSpasswd, 1}}};
424 
425 static asndefT baseObject = {"Base Object", PRINTABLE, -1, 0, {0}};
426 
427 static asndefT scope = {"Scope", ENUM, -1, 3, {
428 			{"BaseObject", 0, 0},
429 			{"singleLevel", 0, 1},
430 			{"wholeSubtree", 0, 2}}};
431 
432 static asndefT derefAliases = {"DerefAliases", ENUM, -1, 4, {
433 			{"neverDerefAliases", 0, 0},
434 			{"derefInSearching", 0, 1},
435 			{"derefFindingBaseObj", 0, 2},
436 			{"derefAlways", 0, 3}}};
437 
438 static asndefT filter;
439 static asndefT and = {"And", SET, -1, 1, {
440 			{0, &filter, -1}}};
441 static asndefT or = {"Or", SET, -1, 1, {
442 			{0, &filter, -1}}};
443 static asndefT not = {"Not", SET, -1, 1, {
444 			{0, &filter, -1}}};
445 static asndefT equalityMatch = {"Equality Match", SEQUENCE, -1, 2, {
446 			{"Attr Descr", 0, -1},
447 			{"Value", 0, -1}}};
448 static asndefT substrings = {"Substring", SEQUENCE, -1, 2, {
449 			{"Type", 0, -1},
450 			{"Substrings (initial)", 0, 0},
451 			{"Substrings (any)", 0, 1},
452 			{"Substring (final)", 0, 2}}};
453 static asndefT greaterOrEqual = {"Greater Or Equal", SEQUENCE, -1, 2, {
454 			{"Attr Descr", 0, -1},
455 			{"Value", 0, -1}}};
456 static asndefT lessOrEqual = {"Less Or Equal", SEQUENCE, -1, 2, {
457 			{"Attr Descr", 0, -1},
458 			{"Value", 0, -1}}};
459 static asndefT approxMatch = {"Approx Match", SEQUENCE, -1, 2, {
460 			{"Attr Descr", 0, -1},
461 			{"Value", 0, -1}}};
462 static asndefT extensibleMatch = {"Extensible Match", SEQUENCE, -1, 4, {
463 			{"MatchingRule", 0, 1},
464 			{"Type", 0, 2},
465 			{"MatchValue", 0, 3},
466 			{"dnAttributes", 0, 4}}};
467 
468 static asndefT filter = {"Filter", CHOICE, -1, 10, {
469 			{0, &and, 0},
470 			{0, &or, 1},
471 			{0, &not, 2},
472 			{0, &equalityMatch, 3},
473 			{0, &substrings, 4},
474 			{0, &greaterOrEqual, 5},
475 			{0, &lessOrEqual, 6},
476 			{"Filter: Present", 0, 7},
477 			{0, &approxMatch, 8},
478 			{0, &extensibleMatch, 9}}};
479 
480 static asndefT attributedescription = \
481 			{"Attribute Description", PRINTABLE, -1, 0, {0}};
482 static asndefT attributes = {"Attribute List", SEQUENCEOF, -1, 1, {
483 			{0, &attributedescription, -1}}};
484 
485 static asndefT searchRequest = {"Operation", SEQUENCE, 3, 8, {
486 			{0, &baseObject, -1},
487 			{0, &scope, -1},
488 			{0, &derefAliases, -1},
489 			{"SizeLimit", 0, -1},
490 			{"TimeLimit", 0, -1},
491 			{"TypesOnly", 0, -1},
492 			{0, &filter, -1},
493 			{0, &attributes, -1}}};
494 
495 static asndefT objectName = {"Object Name", PRINTABLE, -1, 0, {0}};
496 
497 static asndefT ldapEntry = {"Entry", PRINTABLE, -1, 0, {0}};
498 static asndefT relativeLdapEntry = \
499 			{"Relative LDAP Entry", PRINTABLE, -1, 0, {0}};
500 static asndefT newSuperior = {"New Superior", PRINTABLE, -1, 0, {0}};
501 
502 static asndefT vals = {"Vals", SET, -1, 1, {
503 			{"Value", 0, -1}}};
504 
505 static asndefT attribute = {"Attribute", SEQUENCE, -1, 2, {
506 			{"Type", 0, -1},
507 			{0, &vals, -1}}};
508 
509 static asndefT partialAttributes = {"Partial Attributes", SEQUENCEOF, -1, 1, {
510 			{0, &attribute, -1}}};
511 
512 static asndefT searchResEntry = {"Operation", SEQUENCE, 4, 2, {
513 			{0, &objectName, -1},
514 			{0, &partialAttributes, -1}}};
515 
516 static asndefT authChoice = {"Authentication Choice", CHOICE, -1, 2, {
517 			{"Authentication: Simple", 0, 0},
518 			{"Authentication: SASL", 0, 3}}};
519 
520 static asndefT bindRequest = {"Operation", SEQUENCE, 0, 3, {
521 			{"Version", 0, -1},
522 			{0, &objectName, -1},
523 			{0, &authChoice, -1}}};
524 
525 static asndefT resultCode = {"Result Code", ENUM, -1, 39, {
526 			{"Success", 0, 0},
527 			{"Operation Error", 0, 1},
528 			{"Protocol Error", 0, 2},
529 			{"Time Limit Exceeded", 0, 3},
530 			{"Size Limit Exceeded", 0, 4},
531 			{"Compare False", 0, 5},
532 			{"Compare True", 0, 6},
533 			{"Auth Method Not supported", 0, 7},
534 			{"Strong Auth Required", 0, 8},
535 			{"Referral", 0, 10},
536 			{"Admin Limit Exceeded", 0, 11},
537 			{"Unavailable Critical Extension", 0, 12},
538 			{"Confidentiality required", 0, 13},
539 			{"SASL Bind In Progress", 0, 14},
540 			{"No Such Attribute", 0, 16},
541 			{"Undefined Attribute Type", 0, 17},
542 			{"Inappropriate Matching", 0, 18},
543 			{"Constraint violation", 0, 19},
544 			{"Attribute or Value Exists", 0, 20},
545 			{"Invalid Attribute Syntax", 0, 21},
546 			{"No Such Object", 0, 32},
547 			{"Alias Problem", 0, 33},
548 			{"Invalid DN Syntax", 0, 34},
549 			{"Alias Dereferencing Problem", 0, 36},
550 			{"Inappropriate Authentication", 0, 48},
551 			{"Invalid Credentials", 0, 49},
552 			{"Insufficient Access Rights", 0, 50},
553 			{"Busy", 0, 51},
554 			{"Unavailable", 0, 52},
555 			{"Unwilling To Perform", 0, 53},
556 			{"Loop Detect", 0, 54},
557 			{"Naming Violation", 0, 64},
558 			{"ObjectClass violation", 0, 65},
559 			{"Not Allowed On Non Leaf", 0, 66},
560 			{"Not Allowed On RDN", 0, 67},
561 			{"Entry Already Exists", 0, 68},
562 			{"ObjectClass Mods Prohibited", 0, 69},
563 			{"Affects Multiple DSAs", 0, 71},
564 			{"Other", 0, 80}}};
565 
566 
567 static asndefT referral = {"Referral", SEQUENCEOF, -1, 1, {
568 			{"LDAP URL", 0, -1}}};
569 
570 static asndefT ldapResult = {"LDAP Result", SEQUENCE, -1, 4, {
571 			{0, &resultCode, -1},
572 			{"Matched DN", 0, -1},
573 			{"Error Message", 0, -1},
574 			{0, &referral, 3}}};
575 
576 static asndefT bindResponse = {"Operation", SEQUENCE, 1, 5, {
577 			{0, &resultCode, -1},
578 			{"Matched DN", 0, -1},
579 			{"Error Message", 0, -1},
580 			{0, &referral, 3},
581 			{"SASL Credentials", 0, 7}}};
582 
583 static asndefT unbindRequest = {"Operation", SEQUENCE, 2, 0, {0}};
584 
585 static asndefT searchResDone = {"Operation", SEQUENCE, 5, 4, {
586 			{0, &resultCode, -1},
587 			{"Matched DN", 0, -1},
588 			{"Error Message", 0, -1},
589 			{0, &referral, 3}}};
590 
591 static asndefT seqModOperation = {"Operation", ENUM, -1, 4, {
592 			{"Add", 0, 0},
593 			{"Delete", 0, 1},
594 			{"Replace", 0, 2}}};
595 
596 static asndefT seqModModification = {"Modification", SEQUENCE, -1, 1, {
597 			{0, &attribute, -1}}};
598 
599 static asndefT seqModification = {"", SEQUENCE, -1, 2, {
600 		    {0, &seqModOperation, -1},
601 			{0, &seqModModification, -1}}};
602 
603 static asndefT modification = {"Modification", SEQUENCEOF, -1, 1, {
604 			{0, &seqModification, -1}}};
605 
606 static asndefT modifyRequest = {"Operation", SEQUENCE, 6, 2, {
607 			{0, &objectName, -1},
608 			{0, &modification, -1}}};
609 
610 static asndefT modifyResponse = {"Operation", SEQUENCE, 7, 4, {
611 			{0, &resultCode, -1},
612 			{"Matched DN", 0, -1},
613 			{"Error Message", 0, -1},
614 			{0, &referral, 3}}};
615 
616 static asndefT addAttributes = {"Attributes", SEQUENCEOF, -1, 1, {
617 			{0, &attribute, -1}}};
618 
619 static asndefT addRequest = {"Operation", SEQUENCE, 8, 2, {
620 			{0, &ldapEntry, -1},
621 			{0, &addAttributes, -1}}};
622 
623 static asndefT addResponse = {"Operation", SEQUENCE, 9, 4, {
624 			{0, &resultCode, -1},
625 			{"Matched DN", 0, -1},
626 			{"Error Message", 0, -1},
627 			{0, &referral, 3}}};
628 
629 static asndefT delRequest = {"Operation", SEQUENCE, 10, 1, {
630 			{0, &ldapEntry, -1}}};
631 
632 static asndefT delResponse = {"Operation", SEQUENCE, 11, 4, {
633 			{0, &resultCode, -1},
634 			{"Matched DN", 0, -1},
635 			{"Error Message", 0, -1},
636 			{0, &referral, 3}}};
637 
638 static asndefT modifyDNRequest = {"Operation", SEQUENCE, 12, 4, {
639 			{0, &ldapEntry, -1},
640 			{0, &relativeLdapEntry, -1},
641 			{"Delete Old RDN", 0, -1},
642 			{0, &newSuperior, 0}}};
643 
644 static asndefT modifyDNResponse = {"Operation", SEQUENCE, 13, 4, {
645 			{0, &resultCode, -1},
646 			{"Matched DN", 0, -1},
647 			{"Error Message", 0, -1},
648 			{0, &referral, 3}}};
649 
650 static asndefT ava = {"Ava", SEQUENCE, -1, 2, {
651 			{"Attr Descr", 0, -1},
652 			{"Value", 0, -1}}};
653 
654 static asndefT compareRequest = {"Operation", SEQUENCE, 14, 2, {
655 			{0, &ldapEntry, -1},
656 			{0, &ava, 0}}};
657 
658 static asndefT compareResponse = {"Operation", SEQUENCE, 15, 4, {
659 			{0, &resultCode, -1},
660 			{"Matched DN", 0, -1},
661 			{"Error Message", 0, -1},
662 			{0, &referral, 3}}};
663 
664 static asndefT abandonRequest = {"Operation", SEQUENCE, 16, 1, {
665 		    {"Message ID", 0, -1}}};
666 
667 static asndefT searchResRef =  {"Operation", SEQUENCEOF, 19, 1, {
668 			{"LDAP URL", 0, -1}}};
669 
670 static asndefT extendedRequest = {"Operation", SEQUENCE, 14, 2, {
671 			{"Request Name", 0, 0},
672 			{"Request Value", 0, 1}}};
673 
674 static asndefT extendedResponse = {"Operation", SEQUENCE, 24, 6, {
675 			{0, &resultCode, -1},
676 			{"Matched DN", 0, -1},
677 			{"Error Message", 0, -1},
678 			{0, &referral, 3},
679 			{"Response Name", 0, 10},
680 			{"Response", 0, 11}}};
681 
682 static asndefT protocolOp = {"Protocol Op", CHOICE, -1, 20, {
683 			{0, &bindRequest, 0},
684 			{0, &bindResponse, 1},
685 			{0, &unbindRequest, 2},
686 			{0, &searchRequest, 3},
687 			{0, &searchResEntry, 4},
688 			{0, &searchResDone, 5},
689 			{0, &modifyRequest, 6},
690 			{0, &modifyResponse, 7},
691 			{0, &addRequest, 8},
692 			{0, &addResponse, 9},
693 			{0, &delRequest, 10},
694 			{0, &delResponse, 11},
695 			{0, &modifyDNRequest, 12},
696 			{0, &modifyDNResponse, 13},
697 			{0, &compareRequest, 14},
698 			{0, &compareResponse, 15},
699 			{0, &abandonRequest, 16},
700 			{0, &searchResRef, 19},
701 			{0, &extendedRequest, 23},
702 			{0, &extendedResponse, 24}}};
703 
704 static asndefT control = {"Control", SEQUENCE, -1, 3, {
705 			{"LDAP OID", 0, -1},
706 			{"Criticality", 0, -1},
707 			{"Control value", 0, -1}}};
708 
709 static asndefT controls = {"Controls List", SEQUENCEOF, -1, 1, {
710 	{0, &control, -1}}};
711 
712 static asndefT LDAPMessage = { "LDAPMessage", SEQUENCE, -1, 3, {
713 			{"Message ID", 0, -1},
714 			{0, &protocolOp, -1},
715 			{0, &controls, 0}}};
716 
717 static asndefT MPDU = { "MPDU", SET,  -1, 1,
718 			{{0, &LDAPMessage, 0}}};
719 
720 static int mytype[] = {
721 0,			/* EndOfContents	*/
722 0,			/* Boolean			*/
723 0,			/* Integer			*/
724 BITSTRING,	/* BitString		*/
725 0,			/* OctetString		*/
726 0,			/* Null				*/
727 0,			/* Oid				*/
728 0,			/* ObjDescriptor	*/
729 0,			/* External			*/
730 0,			/* Real				*/
731 ENUM,		/* Enumerated		*/
732 0,			/* Reserved			*/
733 0,			/* Reserved			*/
734 0,			/* Reserved			*/
735 0,			/* Reserved			*/
736 0,			/* Reserved			*/
737 SEQUENCE,	/* Sequence			*/
738 SET,		/* Set				*/
739 0,			/* NumericString	*/
740 0,			/* PrintableString	*/
741 0,			/* T.61String		*/
742 0,			/* VideotexString	*/
743 0,			/* IA5String		*/
744 0,			/* UTCTime			*/
745 0,			/* GeneralizedTime	*/
746 0,			/* GraphicString	*/
747 0,			/* VisibleString	*/
748 0,			/* GeneralString	*/
749 0,			/* Reserved			*/
750 0,			/* Reserved			*/
751 0,			/* Reserved			*/
752 0,			/* Reserved			*/
753 };
754 
755 /*
756 **----------------------------------------------**
757 **	find object identifier in known oid table	**
758 **----------------------------------------------**
759 */
760 static oidmap(oid, olg)
761 A	oid;	/* oid hexa string */
762 int	olg;	/* oid length */
763 {
764 	register int ix, goon;
765 	register A oidptr, tabptr, tabend;
766 
767 /* returns (oid table size) if not found */
768 
769 	for (ix = 0; ix < OIDNB; ix++) {
770 		oidptr = oid; tabptr = (&(OidTab[ix].oidcode[0]));
771 		if (olg == INT(*tabptr++)) {
772 			for (tabend = tabptr + olg, goon = 1;
773 				(goon) && (tabptr < tabend); ) {
774 				if (*tabptr++ != *oidptr++) goon = 0;
775 			}
776 			if (goon)
777 				return (ix);
778 		}
779 	}
780 	return (OIDNB);
781 }
782 
783 /*
784 **------------------------------------------------------**
785 **read an hexacode and convert it into ascii		**
786 **------------------------------------------------------**
787 */
788 
789 static int getnext(int ctxnum)
790 {
791 	static X c[3]; /* c[0-3] will contain ascii values on exit */
792 	hex = 0;
793 	if (gi_osibuf[ctxnum] == osilen)
794 		return (-1);
795 	hex = osibuff[gi_osibuf[ctxnum]++];
796 	(void) sprintf((char *)c, "%02x", (hex&0x00FF));
797 	return (0);
798 }
799 
800 /*
801 **------------------------------------------------------**
802 ** Skip everything that is not an LDAPMessage		**
803 **------------------------------------------------------**
804 */
805 static char *skipjunk(len, pdu)
806 int len;
807 char *pdu;
808 {
809 	int tag;
810 	char *buf = pdu;
811 	int offset = 0;
812 	while (len > 0) {
813 		/* size minumum for a sequence + integer = 5 */
814 		/* LDAPMessage::= SEQUENCE  */
815 		if ((len > 5) && (buf[0] == 0x30)) {
816 			tag = buf[1]&0x00ff;
817 			if (tag < 0x80) {
818 				/* length is one one octet */
819 				offset = 1;
820 			} else {
821 				/* length is multiple octet.  */
822 				offset = 1+ tag&0x007f;
823 			}
824 			/* Make sure we don't read past the end */
825 			/* of the buffer */
826 			if (len - (1+offset) > 0) {
827 				/* skip after the length */
828 				tag = buf[1+offset]&0x00ff;
829 				if (tag == 0x02) { /* INTEGER */
830 					/* looks like a valid PDU */
831 					return (buf);
832 				}
833 			}
834 		}
835 		len --;
836 		buf++;
837 	}
838 	return (buf);
839 }
840 /*
841 **----------------------------------------------------------**
842 **	main routine: decode a TLV; to be called recursively	**
843 **----------------------------------------------------------**
844 */
845 #define	GETNEXT(a) (void)getnext(a);
846 static int decpdu(pdulen, ASNDESC, ctxnum)
847 int	pdulen;	/* current pdu's length */
848 asndefTp ASNDESC;
849 int ctxnum;
850 {
851 	X		scrlin[99];	/* screen line */
852 	X		oidstr[80];	/* oid hexa string */
853 	int		slen;	/* screen line length */
854 	int		stlv;	/* sub-tlv length */
855 	int		oix;	/* oid table index */
856 	int		effnb;	/* effectively traced octet nb */
857 	int		i, j;
858 	int		ai = -2;
859 	asndefTp SASNDESC = 0;
860 	asndefTp TMPDESC = 0;
861 	asndefTp GR_TMPDESC = 0;
862 	int tmpai = 0;
863 	int gr_tmpai = 0;
864 	int dontprint = 0;
865 	int already = 0;
866 	static int rlen = 0;	/* tlv's real length */
867 
868 	++level[ctxnum];	/* level indicator */
869 	effnb = 0;
870 
871 	/*
872 	** Decode the current TLV segment
873 	*/
874 	while (pdulen > 1) {
875 
876 		if (getnext(ctxnum)) {
877 			break;
878 		}
879 		if (strlen(scrbuffer)) asnshw2("%s  ", "LDAP:");
880 		/* screen printing according to level indicator */
881 		for (i = 1; i < level[ctxnum]; ++i) asnshw1("   ");
882 
883 		/* get tag */
884 		otyp[ctxnum] = INT(hex); /* single octet type only */
885 		--pdulen;
886 		++effnb;
887 
888 		/* get length */
889 		GETNEXT(ctxnum);
890 		olen[ctxnum] = INT(hex);	/* tlv length */
891 		--pdulen;
892 		++effnb;
893 
894 		/* Continuing decoding of current TLV... */
895 		/*
896 		** Snoop's lower layers do not allow us
897 		** to know the true length for
898 		** datastream protocols like LDAP.
899 		*/
900 
901 		/* if length is less than 128, we */
902 		/* already have the real TLV length. */
903 		if (olen[ctxnum] < 128) {	/* short length form */
904 			rlen = olen[ctxnum];
905 		} else {		/* long and any form length */
906 		/* else we do more getnext()'s */
907 			for (rlen = 0, olen[ctxnum] &= 0x0F;
908 			(olen[ctxnum]) && (pdulen > 0);
909 			--olen[ctxnum], --pdulen, ++effnb) {
910 				GETNEXT(ctxnum);
911 				rlen = (rlen << 8) | INT(hex);
912 			}
913 			if (!rlen) {
914 				pdulen = 0x7fffffff;
915 			}
916 		}
917 
918 		/*
919 		** print the tag class and number
920 		*/
921 		i = otyp[ctxnum]&0x1F;
922 		switch (otyp[ctxnum] >> 6) {	/* class */
923 		case 0:	/* universal */
924 			if (ASNDESC && i != 0) {
925 				int dobreak = 0;
926 				switch (ASNDESC->type) {
927 				case CONTENT:
928 					SASNDESC = ASNDESC;
929 					break;
930 				case SET:
931 					for (ai = 0;
932 						ai < ASNDESC->nbson && i < 32 &&
933 						ASNDESC->son[ai].sondef &&
934 					/*
935 					** For this test SEQUENCE & SEQUENCE OF
936 					** are same, so suppress the last bit
937 					*/
938 						(ASNDESC->son[ai].sondef
939 							->type&0xFE)
940 						!= mytype[i]; ++ai);
941 					if (ai < ASNDESC->nbson) {
942 						SASNDESC =
943 							ASNDESC->son[ai].sondef;
944 						if (ASNDESC->son[ai].sonname) {
945 							if (ASNDESC-> \
946 				son[ai].sondef && ASNDESC->son[ai].sondef->name)
947 							{
948 							asnshw2 \
949 				("%s	", "LDAP:");
950 								asnshw4 \
951 				(" %c[%s %s]",
952 				((otyp[ctxnum]&0x20)?'*':' '), \
953 				ASNDESC->son[ai].sonname, \
954 				ASNDESC->son[ai].sondef->name);
955 							} else {
956 								asnshw2 \
957 							("%s	", "");
958 								asnshw3 \
959 							(" %c[%s]", \
960 				((otyp[ctxnum]&0x20)?'*':' '),
961 				ASNDESC->son[ai].sonname);
962 							} /* end if */
963 							dobreak = 1;
964 						} else if
965 				(ASNDESC->son[ai].sondef &&
966 				ASNDESC->son[ai].sondef->name) {
967 							asnshw2 \
968 					("%s	", "LDAP:");
969 							asnshw3 \
970 				(" %c[%s]", ((otyp[ctxnum]&0x20)?'*':' '),
971 				ASNDESC->son[ai].sondef->name);
972 							dobreak = 1;
973 						} /* end if */
974 					} /* end if */
975 						break;
976 				case CHOICE:
977 					if (GR_TMPDESC) {
978 						ASNDESC = TMPDESC;
979 						TMPDESC = GR_TMPDESC;
980 						GR_TMPDESC = 0;
981 					} else if (TMPDESC) {
982 						ASNDESC = TMPDESC;
983 						TMPDESC = 0;
984 					}
985 					if (gr_tmpai) {
986 						ai = tmpai;
987 						tmpai = gr_tmpai;
988 						gr_tmpai = 0;
989 					} else if (tmpai) {
990 						ai = tmpai;
991 						tmpai = 0;
992 					}
993 					break;
994 
995 				case SEQUENCE:
996 					if (ai == -2) {
997 						ai = 0;
998 					} else {
999 						do {
1000 							ai++;
1001 						} while \
1002 			(ai < ASNDESC->nbson && i < 32 && mytype[i] && \
1003 			ASNDESC->son[ai].sondef &&
1004 					/*
1005 					** For this test SEQUENCE & SEQUENCE OF
1006 					** are the same, so suppress last bit
1007 					*/
1008 			(ASNDESC->son[ai].sondef->type&0xFE) != mytype[i]);
1009 					} /* end if */
1010 					if (ai < ASNDESC->nbson) {
1011 						SASNDESC = \
1012 						ASNDESC->son[ai].sondef;
1013 						if (ASNDESC->son[ai].sonname) {
1014 							if \
1015 			(ASNDESC->son[ai].sondef &&
1016 			ASNDESC->son[ai].sondef->name) {
1017 								asnshw4 \
1018 			(" %c[%s %s]", ((otyp[ctxnum]&0x20)?'*':' '),
1019 			ASNDESC->son[ai].sonname,
1020 			ASNDESC->son[ai].sondef->name);
1021 							} else {
1022 								asnshw3 \
1023 			(" %c[%s]", ((otyp[ctxnum]&0x20)?'*':' '),
1024 			ASNDESC->son[ai].sonname);
1025 							} /* end if */
1026 							dobreak = 1;
1027 						} else if \
1028 			(ASNDESC->son[ai].sondef &&
1029 			ASNDESC->son[ai].sondef->name) {
1030 								asnshw3 \
1031 			(" %c[%s]", ((otyp[ctxnum]&0x20)?'*':' '),
1032 			ASNDESC->son[ai].sondef->name);
1033 							dobreak = 1;
1034 						} /* end if */
1035 					} /* end if */
1036 					break;
1037 				case SEQUENCEOF:
1038 					ai = 0;
1039 					SASNDESC = ASNDESC->son[ai].sondef;
1040 					if (ASNDESC->son[ai].sonname) {
1041 						if (ASNDESC->son[ai].sondef && \
1042 			ASNDESC->son[ai].sondef->name) {
1043 								asnshw4 \
1044 			(" %c[%s %s]", ((otyp[ctxnum]&0x20)?'*':' '),
1045 			ASNDESC->son[ai].sonname,
1046 			ASNDESC->son[ai].sondef->name);
1047 						} else {
1048 							asnshw3 \
1049 			(" %c[%s]", ((otyp[ctxnum]&0x20)?'*':' '),
1050 			ASNDESC->son[ai].sonname);
1051 						} /* end if */
1052 						dobreak = 1;
1053 					} else if \
1054 			(ASNDESC->son[ai].sondef &&
1055 			ASNDESC->son[ai].sondef->name) {
1056 							asnshw3 \
1057 			(" %c[%s]", ((otyp[ctxnum]&0x20)?'*':' '),
1058 			ASNDESC->son[ai].sondef->name);
1059 						dobreak = 1;
1060 					} /* end if */
1061 				} /* end switch */
1062 				if (dobreak) {
1063 					break;
1064 				} /* end if */
1065 			} /* end if */
1066 			if (uclass[i]) {
1067 				asnshw3 \
1068 			(" %c[%s]", ((otyp[ctxnum]&0x20)?'*':' '), uclass[i]);
1069 			} else {
1070 				asnshw4 \
1071 			(" %c[%s%d]", ((otyp[ctxnum]&0x20)?'*':' '),
1072 			class[0], i);
1073 			}
1074 			break;
1075 		case 1:		/* application */
1076 
1077 		if (ASNDESC) {
1078 
1079 				for (ai = 0; ai < ASNDESC->nbson; ++ai) {
1080 					int i2 = 0;
1081 
1082 					if \
1083 			(ASNDESC->son[ai].sondef &&
1084 			ASNDESC->son[ai].sondef->type == CHOICE) {
1085 						while \
1086 			(i2 < ASNDESC->son[ai].sondef->nbson &&
1087 			ASNDESC->son[ai].sondef->son[i2].sondef && \
1088 	ASNDESC->son[ai].sondef->son[i2].sondef->application != i) {
1089 							i2++;
1090 							continue;
1091 						}
1092 						if \
1093 			(i2 == ASNDESC->son[ai].sondef->nbson) {
1094 							ai = ASNDESC->nbson;
1095 							break;
1096 						}
1097 			if (TMPDESC) {
1098 				GR_TMPDESC = TMPDESC;
1099 				gr_tmpai = tmpai;
1100 			}
1101 					TMPDESC = ASNDESC;
1102 					ASNDESC = ASNDESC->son[ai].sondef;
1103 					tmpai = ai;
1104 					ai = i2;
1105 					}
1106 
1107 					if (ASNDESC->son[ai].sondef && \
1108 			ASNDESC->son[ai].sondef->application == i) {
1109 						SASNDESC = \
1110 			ASNDESC->son[ai].sondef;
1111 						if (ASNDESC->son[ai].sonname) {
1112 							if \
1113 			(ASNDESC->son[ai].sondef->name) {
1114 								asnshw3 \
1115 			(" %s %s", ASNDESC->son[ai].sonname,
1116 			ASNDESC->son[ai].sondef->name);
1117 							} else {
1118 								asnshw2 \
1119 			(" %s", ASNDESC->son[ai].sonname);
1120 							} /* end if */
1121 						} else if \
1122 			(ASNDESC->son[ai].sondef->name) {
1123 							asnshw2 \
1124 			(" %s", ASNDESC->son[ai].sondef->name);
1125 						} /* end if */
1126 						break;
1127 					} /* end if */
1128 				} /* end for */
1129 				if (ai >= ASNDESC->nbson) {
1130 					ai = -1;	/* not found */
1131 				} /* end if */
1132 			} /* end if */
1133 			if (PTRaclass[i]) {
1134 				asnshw5 \
1135 			(" %c[%s%d: %s]", ((otyp[ctxnum]&0x20)?'*':' '),
1136 			class[1], i, PTRaclass[i]);
1137 				(void) strcpy(operation, (char *)PTRaclass[i]);
1138 			} else {
1139 				asnshw4 \
1140 			(" %c[%s%d]", ((otyp[ctxnum]&0x20)?'*':' '), \
1141 			class[1], i);
1142 			}
1143 			break;
1144 
1145 		case 2:		/* context-specific */
1146 
1147 			if (TMPDESC) {
1148 				ASNDESC = TMPDESC;
1149 				TMPDESC = GR_TMPDESC;
1150 				already = 1;
1151 			}
1152 			if (ASNDESC) {
1153 
1154 				for (ai = 0; ai < ASNDESC->nbson; ++ai) {
1155 					if \
1156 			(!already && ASNDESC->son[ai].sondef &&
1157 			ASNDESC->son[ai].sondef->type == CHOICE) {
1158 						int i2 = 0;
1159 						while \
1160 			(i2 < ASNDESC->son[ai].sondef->nbson &&
1161 			ASNDESC->son[ai].sondef->son[i2].tag != i) {
1162 							i2++;
1163 							continue;
1164 						}
1165 						if (i2 == \
1166 			ASNDESC->son[ai].sondef->nbson) {
1167 							ai = ASNDESC->nbson;
1168 							break;
1169 						}
1170 						if (TMPDESC) {
1171 							GR_TMPDESC = TMPDESC;
1172 							gr_tmpai = tmpai;
1173 						}
1174 						TMPDESC = ASNDESC;
1175 						ASNDESC = \
1176 			ASNDESC->son[ai].sondef;
1177 						tmpai = ai;
1178 						ai = i2;
1179 					}
1180 
1181 					if \
1182 			(ASNDESC->son[ai].tag == i) {
1183 						SASNDESC = \
1184 			ASNDESC->son[ai].sondef;
1185 						if (ASNDESC->son[ai].sonname) {
1186 							if \
1187 			(ASNDESC->son[ai].sondef &&
1188 			ASNDESC->son[ai].sondef->name) {
1189 								asnshw3 \
1190 			(" %s %s", ASNDESC->son[ai].sonname,
1191 			ASNDESC->son[ai].sondef->name);
1192 							} else {
1193 								asnshw2 \
1194 			(" %s", ASNDESC->son[ai].sonname);
1195 							} /* end if */
1196 						} else if \
1197 			(ASNDESC->son[ai].sondef &&
1198 			ASNDESC->son[ai].sondef->name) {
1199 							asnshw2 \
1200 			(" %s", ASNDESC->son[ai].sondef->name);
1201 						} /* end if */
1202 						break;
1203 					} /* end if */
1204 				} /* end for */
1205 				if (ai >= ASNDESC->nbson) {
1206 					ai = -1;	/* not found */
1207 				} /* end if */
1208 			} /* end if */
1209 			asnshw3 \
1210 			(" %c[%d]", ((otyp[ctxnum]&0x20)?'*':' '), i);
1211 			break;
1212 
1213 		case 3:		/* private */
1214 			asnshw4 \
1215 			(" %c[%s%d]", ((otyp[ctxnum]&0x20)?'*':' '), \
1216 			class[3], i);
1217 		} /* esac: tag */
1218 
1219 		/*
1220 		** print the length - as a debug tool only.
1221 		*/
1222 		/* asnshw2(" Length=%d ",rlen); */
1223 		asnshw1("\n");
1224 		if (rlen > pdulen) {
1225 			asnshw1("*** Decode length error,");
1226 			asnshw2(" PDU length = %d ***\n", pdulen);
1227 			rlen = pdulen;
1228 		}
1229 
1230 		/*
1231 		** recursive interpretation of the value if constructor
1232 		*/
1233 		if (otyp[ctxnum]&0x20) {		/* constructor */
1234 
1235 			stlv = decpdu((rlen?rlen:pdulen), \
1236 			ASNDESC && ai != -1 ?(ai == -2 ? ASNDESC:
1237 			ASNDESC->son[ai].sondef):0, ctxnum);
1238 			/* recursive decoding */
1239 			pdulen -= stlv;
1240 			effnb += stlv;
1241 		} else if (otyp[ctxnum] == 0x06) {
1242 			/*
1243 			** interpretation of the object identifier
1244 			*/
1245 			for (j = 0; (rlen) && (pdulen > 0); \
1246 			--rlen, --pdulen, ++effnb) {
1247 				GETNEXT(ctxnum);
1248 				oidstr[j++] = hex;
1249 			}
1250 
1251 			/* interpret the object identifier */
1252 			oidstr[j++] = '\0';
1253 			oix = oidmap(oidstr, j-1);
1254 			asnshw1("\n");
1255 			if (oix >= 0 && oix < OIDNB) {	/* recognized obj id */
1256 				asnshw2("%s\n", OidTab[oix].oidname);
1257 			} else {
1258 				asnshw1("Unknown Oid\n");
1259 			}
1260 		} else {
1261 			/*
1262 			** interpretation of other primitive tags
1263 			*/
1264 			if (!otyp[ctxnum] && !rlen) {
1265 			/* end of contents: any form length */
1266 				pdulen = 0;
1267 			} else {
1268 				X   hexstr[5];
1269 				int k = 0;
1270 				int klen = rlen;
1271 				if (SASNDESC && SASNDESC->type == CONTENT && \
1272 			SASNDESC->nbson && SASNDESC->son[0].sondef) {
1273 					(void)
1274 			decpdu(rlen, SASNDESC->son[0].sondef, ctxnum);
1275 				} else {
1276 					if (rlen < 200) {
1277 					for (j = 0, slen = 0; \
1278 			(rlen) && (pdulen > 0);
1279 					--rlen, --pdulen, ++effnb)
1280 					{
1281 						if (!slen) {
1282 						    (void) \
1283 			strcpy((char *)scrlin, "LDAP:  "); j += 7;
1284 						    for \
1285 			(i = 0; i < level[ctxnum]; ++i) {
1286 							scrlin[j++] = ' ';
1287 							scrlin[j++] = ' ';
1288 							scrlin[j++] = ' ';
1289 							scrlin[j++] = ' ';
1290 						    }
1291 						}
1292 
1293 						GETNEXT(ctxnum);
1294 						if (k < 5) {
1295 							hexstr[k++] = hex;
1296 						} /* end if */
1297 						if (!isprint(hex)) {
1298 							hex = '_';
1299 							dontprint = 1;
1300 						}
1301 						scrlin[j++] = hex;
1302 						if ((slen += 2) >= \
1303 			(72 - (level[ctxnum] * 3))) {
1304 							slen = 0;
1305 							scrlin[j] = 0;
1306 							if (!dontprint) {
1307 								asnshw2 \
1308 			("%s\n", scrlin);
1309 							}
1310 							j = 0;
1311 						}
1312 					} /* rof: primitive values */
1313 					if (slen) {
1314 						scrlin[j] = 0;
1315 						if (!dontprint) {
1316 							asnshw2("%s\n", scrlin);
1317 						}
1318 					}
1319 					dontprint = 0;
1320 				} else {
1321 					asnshw2("%s  ", "LDAP:");
1322 				    for (i = 0; i < level[ctxnum]; ++i) {
1323 						asnshw1("   ");
1324 						scrlin[j++] = ' ';
1325 						scrlin[j++] = ' ';
1326 						scrlin[j++] = ' ';
1327 					}
1328 
1329 				    for (j = 0; (rlen) && (pdulen > 0); \
1330 			--rlen, --pdulen, ++effnb) {
1331 						GETNEXT(ctxnum);
1332 						if (k < 5) {
1333 							hexstr[k++] = hex;
1334 						}
1335 					}
1336 				    (void) strcpy \
1337 			((char *)scrlin, \
1338 			"*** NOT PRINTED - Too long value ***");
1339 						asnshw2("%s\n", scrlin);
1340 					}
1341 
1342 					if \
1343 			(SASNDESC && SASNDESC->type == BITSTRING &&\
1344 			klen <= 5) {
1345 						unsigned long bitstr = 0;
1346 						for (i = 1; i < 5; ++i) {
1347 							bitstr = \
1348 			((bitstr) << 8) + ((i < klen)?hexstr[i]:0);
1349 						} /* end for */
1350 						for \
1351 			(i = 0; i < SASNDESC->nbson; ++i) {
1352 							if ((bitstr & \
1353 			((unsigned long)SASNDESC->son[i].sondef)) ==
1354 			((unsigned long)SASNDESC->son[i].tag)) {
1355 								if \
1356 			(SASNDESC->son[i].sonname) {
1357 								int k;
1358 								asnshw2 \
1359 			("%s  ", "LDAP:");
1360 								for \
1361 			(k = 0; k < level[ctxnum]; ++k) {
1362 								asnshw1("   ");
1363 								}
1364 								asnshw2 \
1365 			("%s", SASNDESC->son[i].sonname);
1366 								} /* end if */
1367 							} /* end if */
1368 						} /* end for */
1369 					} /* end if */
1370 					if (SASNDESC && \
1371 			(SASNDESC->type == ENUM ||
1372 			SASNDESC->type == CONTENTTYPE) && klen <= 5) {
1373 						unsigned long value = 0;
1374 						for (i = 0; i < klen; ++i) {
1375 							value = \
1376 			((value) << 8) + hexstr[i];
1377 						} /* end for */
1378 						for \
1379 			(i = 0; i < SASNDESC->nbson; ++i) {
1380 							if \
1381 			(value == ((unsigned long)SASNDESC->son[i].tag)) {
1382 								if \
1383 			(SASNDESC->son[i].sonname) {
1384 									int k;
1385 								asnshw2 \
1386 			("%s  ", "LDAP:");
1387 									for \
1388 			(k = 0; k < level[ctxnum]; ++k) {
1389 								asnshw1("   ");
1390 									}
1391 								asnshw2 \
1392 			("%s\n", SASNDESC->son[i].sonname);
1393 									(void) \
1394 			strcpy(resultcode, SASNDESC->son[i].sonname);
1395 								} /* end if */
1396 								break;
1397 							} /* end if */
1398 						} /* end for */
1399 					} /* end if */
1400 
1401 				} /* end if */
1402 			} /* fi: constructor/obj-id/primitive */
1403 		} /* fi: tag analysis */
1404 	} /* elihw: len>1 */
1405 	--level[ctxnum];
1406 	return (effnb);
1407 }
1408 
1409 
1410 /* init_ldap initializes various buffers and variables */
1411 /* it is called one-time (in snoop_filter.c) only. */
1412 
1413 void
1414 init_ldap()
1415 {
1416 	int i;
1417 
1418 	for (i = 0; i < MAX_CTX; i++) {
1419 		gi_osibuf[i] = 0;
1420 		level[i] = 0;
1421 	}
1422 }
1423 static void
1424 ldapdump(char *data, int datalen)
1425 {
1426 	char *p;
1427 	ushort_t *p16 = (ushort_t *)data;
1428 	char *p8 = data;
1429 	int i, left, len;
1430 	int chunk = 16;  /* 16 bytes per line */
1431 
1432 	asnshw1("LDAP: Skipping until next full LDAPMessage\n");
1433 
1434 	for (p = data; p < data + datalen; p += chunk) {
1435 		asnshw2("LDAP:\t%4d: ", p - data);
1436 		left = (data + datalen) - p;
1437 		len = MIN(chunk, left);
1438 		for (i = 0; i < (len / 2); i++)
1439 			asnshw2("%04x ", ntohs(*p16++) & 0xffff);
1440 		if (len % 2) {
1441 			asnshw2("%02x   ", *((unsigned char *)p16));
1442 		}
1443 		for (i = 0; i < (chunk - left) / 2; i++)
1444 			asnshw1("     ");
1445 
1446 		asnshw1("   ");
1447 		for (i = 0; i < len; i++, p8++)
1448 			asnshw2("%c", isprint(*p8) ? *p8 : '.');
1449 		asnshw1("\n");
1450 	}
1451 
1452 	asnshw1("LDAP:\n");
1453 }
1454 
1455 /* decode_ldap is the entry point for the main decoding function */
1456 /* decpdu(). decode_ldap() is only called by interpret_ldap. */
1457 
1458 void
1459 decode_ldap(char *buf, int len)
1460 {
1461 	asndefTp ASNDESC = 0;
1462 	char *newbuf;
1463 	int skipped = 0;
1464 
1465 	PTRaclass = MHSaclass;
1466 	ASNDESC = &MPDU;
1467 
1468 
1469 	newbuf =  skipjunk(len, buf);
1470 	if (newbuf > buf) {
1471 		skipped = newbuf-buf;
1472 		ldapdump(buf, newbuf-buf);
1473 	}
1474 	buf = newbuf;
1475 	len = len-skipped;
1476 	osibuff = buf;	/* Undecoded buf is passed by interpret_ldap */
1477 	osilen = len;	/* length of tcp data is also passed */
1478 
1479 	(void) decpdu(len, ASNDESC, 0);
1480 	gi_osibuf[0] = 0;
1481 }
1482