]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/compiler/core/val-parser.c
Security-28.tar.gz
[apple/security.git] / SecuritySNACCRuntime / compiler / core / val-parser.c
1 /*
2 * compiler/core/val_parser.c
3 * given a string with txt ASN.1 value notation, the length of
4 * the string and the ASN.1 type the value notion defines a value
5 * for, return a Value that contains the internal version
6 *
7 *
8 * currently limited to parsing OBJECT IDENTIFIERs.
9 * should be easy to extend for other values as needed
10 *
11 * Copyright (C) 1991, 1992 Michael Sample
12 * and the University of British Columbia
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/compiler/core/val-parser.c,v 1.1 2001/06/20 21:27:59 dmitch Exp $
20 * $Log: val-parser.c,v $
21 * Revision 1.1 2001/06/20 21:27:59 dmitch
22 * Adding missing snacc compiler files.
23 *
24 * Revision 1.1.1.1 1999/03/16 18:06:53 aram
25 * Originals from SMIME Free Library.
26 *
27 * Revision 1.4 1997/10/10 13:43:16 wan
28 * Corrected bug in generic table decoder wrt. indefinite length elements
29 * Corrected compiler access to freed memory (bug reported by Markku Savela)
30 * Broke asnwish.c into two pieces so that one can build ones on wish
31 * Added beredit tool (based on asnwish, allowes to edit BER messages)
32 *
33 * Revision 1.3 1995/07/25 19:41:46 rj
34 * changed `_' to `-' in file names.
35 *
36 * Revision 1.2 1994/09/01 00:47:33 rj
37 * snacc_config.h removed; val_parser.h includet.
38 *
39 * Revision 1.1 1994/08/28 09:49:44 rj
40 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
41 *
42 */
43
44
45
46 #include <ctype.h> /* for isalpha, isdigit etc macros */
47 #include <stdio.h>
48
49 #include "asn-incl.h"
50 #include "asn1module.h"
51 #include "mem.h"
52 #include "snacc-util.h"
53 #include "oid.h" /* arcname->number mapping */
54 #include "val-parser.h"
55
56 /*
57 * a bunch of macros for 'standard' parse routines
58 */
59 #define P_LOCALS\
60 char *startStr
61
62 #define SAVE_POS()\
63 startStr = *vStr;
64
65 #define RESTORE_POS()\
66 *vStr = startStr;
67
68 #define AT_EOF()\
69 (*vStr == eof)
70
71 #define FAIL()\
72 {\
73 if (*vStr > farthestPosG)\
74 farthestPosG = *vStr;\
75 RESTORE_POS();\
76 return FALSE;\
77 }
78
79 #define SUCCEED()\
80 return TRUE;
81
82 #define FATAL_ERR()\
83 parseValuesErrG = 1;
84
85 /*
86 * a couple macros for errmsg generation
87 */
88 #define PRINT_ERR_LOC(m, vd)\
89 fprintf (stderr,"file \"%s\", line %d (or near): ", m->asn1SrcFileName, valLineNoG);
90
91
92 #define PRINT_VAL(vd)\
93 PrintValueDef (stderr, vd);
94
95 /*
96 * globals
97 */
98 static ValueDefList *newValsG;
99 static int parseValuesErrG;
100 static unsigned long valLineNoG;
101 static char *farthestPosG;
102
103 /*
104 * prototypes for non-exported routines
105 */
106 char *StripComments PROTO ((char *asn1Str, int len));
107 Value *ParseValue PROTO ((ModuleList *mods, Module *m, ValueDef *vd, Type *t, char *valueNotation, int len));
108
109 Value *ParseValueInternal PROTO ((ModuleList *mods, Module *m, ValueDef *vd, Type *t, char **valueNotation, char *eof));
110
111 int ParseOidValue PROTO ((ModuleList *mods, Module *m, ValueDef *vd, Type *t, char **valueNotation, char *eof, Value **result));
112
113 void SkipWht PROTO ((char **vStr, char *eof));
114 int ParseIdentifier PROTO ((char **valueNotation, char *eof, char **result));
115 int ParseNum PROTO ((char **valueNotation, char *eof, char **result));
116 void AddNewValueDef PROTO ((ValueDefList *vdl, char *name, Value *value));
117
118
119
120 /*
121 * returns 0 if no parse errors occurred
122 * otherwise returns non-zero
123 */
124 int
125 ParseValues PARAMS ((mods, m),
126 ModuleList *mods _AND_
127 Module *m)
128 {
129 ValueDef *v;
130 Value *pv;
131
132 newValsG = AsnListNew (sizeof (void*));
133
134 FOR_EACH_LIST_ELMT (v, m->valueDefs)
135 {
136 if (v->value->basicValue->choiceId == BASICVALUE_VALUENOTATION)
137 {
138 valLineNoG = v->value->lineNo;
139 pv = ParseValue (mods, m, v, v->value->type, v->value->basicValue->a.valueNotation->octs, v->value->basicValue->a.valueNotation->octetLen);
140
141 /* replace value notation value with parsed version */
142 if (pv != NULL)
143 {
144 pv->lineNo = v->value->lineNo;
145 pv->type = v->value->type;
146 Free (v->value->basicValue->a.valueNotation->octs);
147 Free (v->value->basicValue->a.valueNotation);
148 Free (v->value->basicValue);
149 Free (v->value);
150 v->value = pv;
151 }
152 }
153 }
154
155 /*
156 * should traverse type structures for default values etc
157 * that need parsing
158 */
159
160 /* add any new value defs */
161 m->valueDefs = AsnListConcat (m->valueDefs, newValsG);
162 Free (newValsG);
163
164 return parseValuesErrG;
165
166 } /* ParseValues */
167
168
169
170 /*
171 * returns the Value that resuls from parsing the given
172 * value notation string
173 */
174 Value*
175 ParseValue PARAMS ((mods, m, vd, t, valueNotationStr, vnLen),
176 ModuleList *mods _AND_
177 Module *m _AND_
178 ValueDef *vd _AND_
179 Type *t _AND_
180 char *valueNotationStr _AND_
181 int vnLen)
182 {
183 char *vStr;
184 char *vStrOrig;
185 int vStrLen;
186 Value *retVal;
187
188 /* make copy of value notation with ASN.1 comments zapped */
189 vStrOrig = vStr = StripComments (valueNotationStr, vnLen);
190 vStrLen = strlen (vStr);
191
192 retVal = ParseValueInternal (mods, m, vd, t, &vStr, (vStr + vStrLen));
193
194 /* use original since parsing has changed vStr */
195 free (vStrOrig);
196
197 return retVal;
198 }
199
200 /*
201 * vStr is a handle to a commentless ASN.1 value string,
202 * eof is a char * to character after the last valid character
203 * in vStr. vStr will be advanced to the current parse location.
204 */
205 Value*
206 ParseValueInternal PARAMS ((mods, m, vd, t, vStr, eof),
207 ModuleList *mods _AND_
208 Module *m _AND_
209 ValueDef *vd _AND_
210 Type *t _AND_
211 char **vStr _AND_
212 char *eof)
213 {
214 Type *dT;
215 Value *retVal;
216 int parseResult = FALSE;
217
218 dT = ParanoidGetType (t); /* skip type refs to get defining type */
219
220 if (dT == NULL)
221 return NULL;
222
223 retVal = NULL;
224
225 switch (dT->basicType->choiceId)
226 {
227 case BASICTYPE_SEQUENCE:
228 case BASICTYPE_SET:
229 case BASICTYPE_CHOICE:
230 case BASICTYPE_SEQUENCEOF:
231 case BASICTYPE_SETOF:
232 /* don't do constructed types yet */
233 break;
234
235
236 case BASICTYPE_SELECTION:
237 case BASICTYPE_COMPONENTSOF:
238 case BASICTYPE_ANYDEFINEDBY:
239 case BASICTYPE_UNKNOWN:
240 case BASICTYPE_ANY:
241 /* don't do weird types */
242 break;
243
244
245 /*
246 * The following simple types will need to be filled in
247 * when the constructed types are parsed.
248 * (ie ParseValueInternal becomes recursive)
249 * (currenly all simple types not in {}'s are parsed
250 * in the main yacc parser.)
251 */
252
253 case BASICTYPE_BOOLEAN:
254 break;
255
256 case BASICTYPE_INTEGER:
257 case BASICTYPE_ENUMERATED:
258 break;
259
260 case BASICTYPE_REAL:
261 break;
262
263 case BASICTYPE_BITSTRING:
264 break;
265
266 case BASICTYPE_NULL:
267 break;
268
269 case BASICTYPE_OCTETSTRING:
270 break;
271
272
273 /* assume all macro values in {}'s are OID values */
274 case BASICTYPE_OID:
275 case BASICTYPE_MACROTYPE:
276 parseResult = ParseOidValue (mods, m, vd, t, vStr, eof, &retVal);
277 if (!parseResult)
278 FATAL_ERR();
279 break;
280
281
282 default:
283 break;
284 }
285
286 if (parseResult)
287 return retVal;
288 else
289 return NULL;
290
291 } /* ParseValueInternal */
292
293
294 /*
295 * Strips ASN.1 comments from the given string.
296 * returns a null terminated malloc'd copy without the comments
297 */
298 char*
299 StripComments PARAMS ((s, len),
300 char *s _AND_
301 int len)
302 {
303 char *cpy;
304 int sIndex, cpyIndex;
305 int inComment;
306
307 cpy = (char*)Malloc (len +1);
308 cpyIndex = 0;
309 for (sIndex = 0; sIndex < len; )
310 {
311 if ((s[sIndex] == '-') &&
312 ((sIndex+1) < len) && (s[sIndex+1]== '-'))
313 {
314 /* eat comment body */
315 for (sIndex += 2; sIndex < len; )
316 {
317 if ((s[sIndex] == '-') &&
318 ((sIndex+1) < len) && (s[sIndex+1]== '-'))
319 {
320 sIndex += 2;
321 break; /* exit for */
322 }
323 else if (s[sIndex] == '\n')
324 {
325 sIndex++;
326 break; /* exit for */
327 }
328 else
329 sIndex++;
330 }
331 }
332 else /* not in or start of comment */
333 cpy[cpyIndex++] = s[sIndex++];
334 }
335
336 cpy[cpyIndex] == '\0'; /* add NULL terminator */
337 return cpy;
338 } /* StripComments */
339
340
341
342
343 /*
344 * Returns TRUE if successfully parsed an OID
345 * otherwise returns FALSE. Puts the resulting OID Value in
346 * result if successful.
347 * The result Value's type is BASICVALUE_LINKEDOID
348 *
349 * Pseudo reg expr of the expected oid format:
350 * "{"
351 * (oid_val_ref)?
352 *(defined_oid_elmt_name | digit+ | int_or_enum_val_ref |name"(" digit")")*
353 * "}"
354 *
355 * Does not attempt to link/lookup referenced values
356 *
357 * eg
358 * for { ccitt foo (1) bar bell (bunt) 2 }
359 *
360 * ccitt
361 * arcnum is set to number from oid table (oid.c)
362 * foo (1)
363 * - arcnum set to 1
364 * - sets up a new integer value def "foo"
365 * defined as 1 *CHANGED -see changes*
366 * - makes oid valueref a value ref to foo (doesn't link it tho)
367 * bar
368 * - makes oid valueref a value ref to bar (doesn't link it tho)
369 * bell (bunt)
370 * - sets up a new integer value def "bell" defined
371 * as a val ref to "bunt" *CHANGED -see changes*
372 * - makes oid valueref a value ref to bell (doesn't link it tho)
373 * 2
374 * -arc num is set to 2
375 *
376 * CHANGES:
377 * 93/05/03 - named arcs such as foo (1) or bell (bunt) handling
378 * changed. The names (foo and bell) are now ignored
379 * and *do not* define new integer values.
380 * The old way led to problems of defining some values
381 * more than once. E.g. in X.500 the { .. ds (5) }
382 * arc name is used everywhere - "ds INTEGER ::= 5"
383 * was defined multiple times as a result.
384 * Then the snacc error checker halted the compilation
385 * since the integer value "ds" was mulitply defined.
386 *
387 */
388 int
389 ParseOidValue PARAMS ((mods, m, vd, t, vStr, eof, result),
390 ModuleList *mods _AND_
391 Module *m _AND_
392 ValueDef *vd _AND_
393 Type *t _AND_
394 char **vStr _AND_
395 char *eof _AND_
396 Value **result)
397 {
398 Value *newVal;
399 Type *newType;
400 Value *oidVal;
401 OID *parsedOid;
402 OID **nextOid;
403 char *id;
404 char *id2;
405 char *id3;
406 char *num;
407 int arcNum;
408 int namedNumVal;
409 P_LOCALS;
410
411
412 SAVE_POS();
413
414 if (AT_EOF())
415 {
416 PRINT_ERR_LOC (m, vd);
417 fprintf (stderr,"ERROR - expecting more data in OBJECT IDENTIFER value\n");
418 FAIL();
419 }
420
421 SkipWht (vStr, eof);
422
423 if (**vStr != '{')
424 {
425 PRINT_ERR_LOC (m, vd);
426 fprintf (stderr,"ERROR - OBJECT IDENTIFER values must begin with an \"{\".\n");
427 FAIL();
428 }
429 else
430 (*vStr)++; /* skip opening { */
431
432 SkipWht (vStr, eof);
433
434 parsedOid = NULL;
435 nextOid = &parsedOid;
436
437 while (**vStr != '}')
438 {
439 if (ParseIdentifier (vStr, eof, &id))
440 {
441 /*
442 * check for named number ident (num) or ident (valref)
443 * make a new value def with the name ident if is name
444 * and number form
445 */
446 SkipWht (vStr, eof);
447 if (**vStr == '(')
448 {
449
450 (*vStr)++; /* skip opening ( */
451 SkipWht (vStr, eof);
452
453 arcNum = NULL_OID_ARCNUM;
454 /*
455 * ident (num)/ident (valref) yields a new value definition
456 * ident. The oid then refences this new value def.
457 */
458
459 /*
460 * first case check if of form
461 * { ... ident (valref) ... }
462 */
463 if (ParseIdentifier (vStr, eof, &id2))
464 {
465 id3 = NULL;
466 /* check if modname.val format */
467 if (**vStr == '.')
468 {
469 (*vStr)++;
470 if (!ParseIdentifier (vStr, eof, &id3))
471 {
472 PRINT_ERR_LOC (m, vd);
473 fprintf (stderr,"ERROR - missing a module name after the \"%s.\" value reference", id2);
474 FAIL();
475 }
476 }
477
478 /* grab closing ) */
479 SkipWht (vStr, eof);
480 if (**vStr == ')')
481 (*vStr)++;
482 else
483 {
484 PRINT_ERR_LOC (m, vd);
485 fprintf (stderr,"ERROR - missing a closing \")\", after the \"%s\" value reference.\n", id2);
486 FAIL();
487 }
488
489 if (id3 != NULL) /* modname.val format */
490 {
491 SetupValue (&newVal, BASICVALUE_IMPORTVALUEREF,valLineNoG);
492 newVal->basicValue->a.importValueRef =
493 (ValueRef*)Malloc (sizeof (ValueRef));
494 newVal->basicValue->a.importValueRef->valueName = id2;
495 newVal->basicValue->a.importValueRef->moduleName = id3;
496
497 AddPrivateImportElmt (m, id2, id3, valLineNoG);
498
499 }
500 else
501 {
502 SetupValue (&newVal, BASICVALUE_LOCALVALUEREF,valLineNoG);
503 newVal->basicValue->a.localValueRef =
504 (ValueRef*)Malloc (sizeof (ValueRef));
505 newVal->basicValue->a.localValueRef->valueName = id2;
506 }
507
508 }
509 /* check this form { ... ident (2)...}*/
510 else if (ParseNum (vStr, eof, &num))
511 {
512 /* grab closing ) */
513 SkipWht (vStr, eof);
514 if (**vStr == ')')
515 (*vStr)++;
516 else
517 {
518 PRINT_ERR_LOC (m, vd);
519 fprintf (stderr,"ERROR - missing a closing \")\" after the \"%s (%s\".\n", id2, num);
520 Free (num);
521 FAIL();
522 }
523 arcNum = atoi (num);
524 Free (num);
525 newVal = NULL;
526 }
527 else /* neither an ident or num after the "(" */
528 {
529 PRINT_ERR_LOC (m, vd);
530 fprintf (stderr,"ERROR - expecting either a value reference or number after the \"(\".\n");
531 FAIL();
532 }
533
534 *nextOid = (OID*) Malloc (sizeof (OID));
535 (*nextOid)->valueRef = newVal;
536 (*nextOid)->arcNum = arcNum;
537 nextOid = &(*nextOid)->next;
538
539 } /* end of ident (num) and ident (ident) form */
540
541 else /* value ref: { ... ident .... } */
542 {
543 *nextOid = (OID*) Malloc (sizeof (OID));
544 (*nextOid)->arcNum = NULL_OID_ARCNUM;
545
546 /*
547 * check if special defined oid elmt name
548 * like joint-iso-ccitt, iso, standard etc.
549 */
550
551 arcNum = OidArcNameToNum (id);
552 if (arcNum != -1)
553 {
554 (*nextOid)->arcNum = arcNum;
555 }
556 else /* value reference */
557 {
558 SetupValue (&newVal, BASICVALUE_LOCALVALUEREF,valLineNoG);
559 newVal->basicValue->a.localValueRef =
560 (ValueRef*)Malloc (sizeof (ValueRef));
561 newVal->basicValue->a.localValueRef->valueName = id;
562
563 (*nextOid)->valueRef = newVal;
564 }
565 nextOid = &(*nextOid)->next;
566 }
567 }
568 else if (ParseNum (vStr, eof, &num)) /* { .. 2 .. } */
569 {
570 *nextOid = (OID*) Malloc (sizeof (OID));
571 (*nextOid)->arcNum = atoi (num);
572 nextOid = &(*nextOid)->next;
573 Free (num);
574 }
575 else
576 {
577 PRINT_ERR_LOC (m, vd);
578 fprintf (stderr,"ERROR - bady formed arc number\n");
579 FAIL();
580 }
581
582 SkipWht (vStr, eof);
583 }
584
585 (*vStr)++; /* move over closing } */
586
587 SetupValue (&oidVal, BASICVALUE_LINKEDOID, valLineNoG);
588 oidVal->basicValue->a.linkedOid = parsedOid;
589 *result = oidVal;
590 SUCCEED();
591 }
592
593
594 void
595 SkipWht PARAMS ((vStr, eof),
596 char **vStr _AND_
597 char *eof)
598 {
599 while (!AT_EOF())
600 switch (**vStr)
601 {
602 case '\n': /* newline */
603 case '\f': /* form feed ?*/
604 case '\v': /* vertical tab ?*/
605 case '\r': valLineNoG++; /* carriage return */
606 case '\t': /* tab */
607 case ' ': /* space */
608 case '\007': /* bell? */
609 case '\b': /* back spc */
610 (*vStr)++;
611 break;
612
613 default:
614 return;
615 }
616 }
617
618
619 /*
620 * advances the vStr over ASN.1 identifier, returns a copy
621 * in result, and returns TRUE. otherwise returns FALSE
622 *
623 * ASN.1 identifier is: lowercase letter followed by a
624 * string of letters (upper and lower case allowed), digtits, or single
625 * hyphens. last char cannot be a hyphen.
626 */
627 int
628 ParseIdentifier PARAMS ((vStr, eof, result),
629 char **vStr _AND_
630 char *eof _AND_
631 char **result)
632 {
633 char *start;
634 int len;
635 P_LOCALS;
636
637 SAVE_POS();
638
639 if (AT_EOF())
640 FAIL();
641
642 start = *vStr;
643 if (!islower (**vStr))
644 FAIL();
645
646 (*vStr)++;
647
648 while (!AT_EOF())
649 {
650 /* allow letters, digits and single hyphens */
651 if ((isalpha (**vStr)) || isdigit (**vStr) ||
652 ((**vStr == '-') && !(*(*vStr - 1) == '-')))
653 (*vStr)++;
654 else
655 break; /* exit for loop */
656
657 }
658
659 /* don't allow hyphens on the end */
660 if (*(*vStr - 1) == '-')
661 (*vStr)--;
662
663 len = *vStr - start;
664 *result = Malloc (len +1);
665 strncpy (*result, start, len);
666 (*result)[len] = '\0'; /* null terminate */
667
668 SUCCEED();
669 } /* ParseIdentifier */
670
671
672
673 /*
674 * advances the vStr over ASN.1 number, returns a
675 * null terminated ascii copy of the number
676 * in result, and returns TRUE. otherwise returns FALSE
677 */
678 int
679 ParseNum PARAMS ((vStr, eof, result),
680 char **vStr _AND_
681 char *eof _AND_
682 char **result)
683 {
684 P_LOCALS;
685 char *start;
686 int len;
687
688 SAVE_POS();
689
690 if (AT_EOF())
691 FAIL();
692
693 start = *vStr;
694
695 while (!AT_EOF())
696 {
697 if (isdigit (**vStr))
698 (*vStr)++;
699 else
700 break; /* exit for loop */
701 }
702 len = *vStr - start;
703
704 if (len == 0)
705 FAIL();
706
707 *result = Malloc (len +1);
708 strncpy (*result, start, len);
709 (*result)[len] = '\0'; /* null terminate */
710
711 SUCCEED();
712 } /* ParseNum */
713
714 /*
715 * adds a new value def to the vdl. Used
716 * when parsing oid's that defined arc values
717 * eg { 1 2 foo (3) } --> defined foo INTEGER ::= 3
718 * (should be foo INTEGER (0..MAX) ::= 3)
719 */
720 void
721 AddNewValueDef PARAMS ((vdl, name, value),
722 ValueDefList *vdl _AND_
723 char *name _AND_
724 Value *value)
725 {
726 ValueDef *vd;
727 ValueDef **tmpVd;
728
729 vd = (ValueDef*)Malloc (sizeof (ValueDef));
730 vd->definedName = name;
731 vd->value = value;
732 tmpVd = (ValueDef**)AsnListAppend (vdl);
733 *tmpVd = vd;
734 } /* AddNewValueDef */