1 /* dn.c - routines for dealing with distinguished names */
4 * The functions normalize_unicode(), get_hexpair(), write_hex_pair(),
5 * get_next_byte(), get_next_char(), get_ber_length(),
6 * ber_parse_primitive_string(), ber_parse_string(), String_normalize(),
7 * DirectoryString_normalize(), PrintableString_normalize(),
8 * IA5String_normalize(), ber_parse_primitive_bitstring(),
9 * ber_parse_bitstring(), getNext8bits(), bitString_normalize(), match_oid(),
10 * match_key(), get_validated_av_in_dn(), get_validated_rdn_in_dn(),
11 * and get_validated_dn() in this file were developed at the National Institute
12 * of Standards and Technology by employees of the Federal Government in the
13 * course of their official duties. Pursuant to title 17 Section 105 of the
14 * United States Code the code in these functions is not subject to copyright
15 * protection and is in the public domain. The copyright for all other code in
16 * this file is as specified below.
19 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
20 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
28 #include <ac/socket.h>
29 #include <ac/string.h>
43 #define INQUOTEDVALUE 7
45 #define INBERENCODEDVALUE 9
49 typedef int (*av_normalize_type)(char **, char **, int *, int, int, int, unsigned long *);
51 #define PRINTABLE_STRING 1
53 #define TELETEX_STRING 3
55 #define UNIVERSAL_STRING 5
57 #define DIRECTORY_STRING 7
59 /* unnormalized_unicode contains a string of ucs4 encoded unicode characters of length
60 * len. Place in *d a normalized UTF8 encoded version of unnormalized_unicode. If firstchar is
61 * true, then the first character output by uccanoncomp is the first character of the
62 * attribute value. If successful, return 1 and advance *d to the end of the UTF8 encoded string.
63 * Otherwise, return 0.
66 normalize_unicode(unsigned long *unnormalized_unicode, int len, char **d, int *av_length) {
67 unsigned long *normalized_unicode;
68 int i, normalized_len, char_len;
72 i = uccanondecomp(unnormalized_unicode, len, &normalized_unicode, &normalized_len);
73 if ( (i == -1) || (normalized_unicode == NULL) )
75 normalized_len = uccanoncomp(normalized_unicode, normalized_len);
77 char_len = ldap_ucs4_to_utf8(normalized_unicode[0], *d);
80 for(i=1; i < normalized_len; i++) {
81 char_len = ldap_ucs4_to_utf8(normalized_unicode[i], *d);
83 if ( RDN_NEEDSESCAPE( tmp ) || RDN_SPECIAL( tmp ) ) {
88 } else if ( ASCII_WHITESPACE( tmp ) && ASCII_SPACE( *(*d - 1) ) ) {
89 /* There should not be two consequtive space characters in the
90 * normalized string. */
96 *av_length += normalized_len;
98 ch_free(normalized_unicode);
104 /* The next two bytes in the string beginning at *sec should be
105 * a pair of hexadecimal characters. If they are, the value of that
106 * hexpair is placed in *out and 1 is returned. Otherwise, 0 is returned.
109 get_hexpair(char **src, unsigned char *out)
115 if ( !ASCII_XDIGIT(ch) ) {
119 if ( ASCII_DIGIT(ch) ) {
121 } else if ( ch >= 'A' && ch <= 'F' ) {
122 *out = ch - 'A' + 10;
124 *out = ch - 'a' + 10;
131 if ( !ASCII_XDIGIT(ch) ) {
137 if ( ASCII_DIGIT(ch) ) {
139 } else if ( ch >= 'A' && ch <= 'F' ) {
140 *out += ch - 'A' + 10;
142 *out += ch - 'a' + 10;
151 /* output in as a hexadecimal pair to the string pointed to be *d and advance *d to the end
155 write_hex_pair(char **d, unsigned char in) {
156 unsigned char upper_nibble, lower_nibble;
158 upper_nibble = (in & 0xF0) >> 4;
159 lower_nibble = in & 0x0F;
161 if (upper_nibble < 10)
162 **d = upper_nibble + '0';
164 **d = upper_nibble - 10 + 'A';
168 if (lower_nibble < 10)
169 **d = lower_nibble + '0';
171 **d = lower_nibble - 10 + 'A';
177 /* The string beginning at *src represents a octet.
178 * The octet is either represented by a single byte or
179 * a '\' followed by a 2-byte hexpair or a single byte.
180 * Place the octet in *out, increment *src to the beginning
181 * of the next character. If the representation of the octet
182 * began with a '\' then *is_escaped is set to 1. Otherwise,
183 * *is_escaped is set to 0. If the string beginning at *src
184 * does not represent a well formed octet, then 0 is returned.
185 * Otherwise 1 is returned.
188 get_next_byte(char **src, unsigned char *out, int *is_escaped)
191 unsigned char s1, s2;
211 if ( !ASCII_XDIGIT( s1 ) ) {
216 if ( get_hexpair(src, &s2) ) {
226 /* If the string beginning at *src is a well formed UTF8 character,
227 * then the value of that character is placed in *out and 1 is returned.
228 * If the string is not a well formed UTF8 character, 0 is returned.
229 * If the character is an ASCII character, and its representation began
230 * with a '\', then *is_escaped is set to 1. Otherwise *is_escaped is set to 0.
231 * When the function returns, *src points to the first byte after the character.
234 get_next_char(char **src, unsigned long int *out, int *is_escaped)
238 unsigned long int ch;
240 static unsigned char mask[] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
242 res = get_next_byte( src, &tmp, is_escaped );
249 if ( ( res == 0 ) || ( tmp < 128 ) ) {
253 /* This is a UTF8 encoded, non-ASCII character */
254 len = ldap_utf8_charlen( &tmp );
259 ch = tmp & mask[len];
261 for(i=1; i < len; i++) {
262 res = get_next_byte( src, &tmp, is_escaped );
263 if ( ( res == 0) || ( ( tmp & 0xc0 ) != 0x80 ) ) return 0;
275 /* The string beginning at *s should be an ASCII-hex encoding of BER encoded
276 * length data. If so, place the length in *length, add the length of the
277 * length encoding to *encoded_length, advance *s to next byte after the end
278 * of the length encoding, and return 1. Otherwise, return 0.
283 unsigned int *encoded_length,
284 unsigned long int *length
288 unsigned char ch, ch2;
290 res = get_hexpair(s, &ch);
294 *encoded_length += 1;
296 if ( (ch & 0x80) == 0) {
297 /* Bit 8 is 0, so this byte gives the length */
300 /* This byte specifies the number of remaining length octets */
304 /* This assumes that length can hold up to a 32-bit
305 * integer and that bit strings will always be shorter
313 *length = *length << 8;
315 res = get_hexpair(s, &ch2);
319 *encoded_length += 1;
320 *length = *length | ch2;
330 /* The string beginning at *s should be an ASCII-hex encoding of a BER
331 * encoded string of type string_type (minus the "tag" octet) in which the
332 * encoding is primitive, definite length. If it is, write a UTF8 encoding
333 * of the string, according to RFC 2253, to *d, advance *s to one byte after
334 * the end of the BER encoded string, advance *d to one byte after the UTF8
335 * encoded string, add to *encoded_length the length of the BER encoding, add
336 * to *av_length the number of UTF8 characters written to *d, set *firstchar
337 * to 0 if any characters are written to *d, and return 1. Otherwise, return
338 * 0. If make_uppercase is 1, write all of the characters in uppercase. If
339 * not, write the characters as they occur in the BER encoding. If
340 * normalize is 1, remove all leading and trailing whitespace, and
341 * compress all whitespace between words to a single space. If not, transfer
342 * whitespace from the BER encoding to the UTF8 encoding unchanged.
345 ber_parse_primitive_string(
352 unsigned int *encoded_length,
354 unsigned long *unnormalized_unicode,
355 int *unnormalized_unicode_len
360 unsigned long int uch;
361 unsigned long int length;
364 static unsigned char mask[] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
366 res = get_ber_length(s, encoded_length, &length);
371 /* read in next character */
372 if (string_type == PRINTABLE_STRING) {
373 /* each character is one byte */
374 res = get_hexpair(s, &ch);
378 *encoded_length += 1;
381 if ( !SLAP_PRINTABLE(ch) )
386 } else if (string_type == IA5_STRING) {
387 /* each character is one byte */
388 res = get_hexpair(s, &ch);
392 *encoded_length += 1;
400 } else if (string_type == TELETEX_STRING) {
401 /* This code is not correct. Each character is one byte.
402 * However, the enocodings need to be transliterated to
405 res = get_hexpair(s, &ch);
409 *encoded_length += 1;
414 } else if (string_type == BMP_STRING) {
415 /* This is a 2-byte unicode character */
421 for(i=0; i < 2; i++) {
422 res = get_hexpair(s, &ch);
430 *encoded_length += 2;
432 } else if (string_type == UNIVERSAL_STRING) {
433 /* This is a 4-byte unicode character */
439 for(i=0; i < 4; i++) {
440 res = get_hexpair(s, &ch);
448 *encoded_length += 4;
450 } else if (string_type == UTF8_STRING) {
451 res = get_hexpair(s, &ch);
455 *encoded_length += 1;
458 /* Not sure what to do here */
462 len = ldap_utf8_charlen( &ch );
463 if ( ( len == 0) || ( length < len ) )
466 uch = ch & mask[len];
468 for(i=1; i < len; i++) {
469 res = get_hexpair(s, &ch);
470 if ( ( res == 0) || ( ( ch & 0xc0 ) != 0x80 ) ) return 0;
472 *encoded_length += 1;
481 /* Unknown string type */
485 /* Now add character to *d */
488 if (make_uppercase) {
489 uch = uctoupper( uch );
492 if ( (uch < 128) && (*unnormalized_unicode_len > 0) ) {
493 res = normalize_unicode(unnormalized_unicode, *unnormalized_unicode_len, d, av_length);
496 *unnormalized_unicode_len = 0;
499 if ( !normalize || !ASCII_WHITESPACE(uch) ) {
500 if ( (*firstchar) && ASCII_SPACE(uch) ) {
509 if ( normalize && (uch > 127) ) {
510 if (*unnormalized_unicode_len == 0) {
511 /* The previous output character must be ASCII
512 * and it should be normalized.
515 unnormalized_unicode[0] = **d;
516 *unnormalized_unicode_len = 1;
519 unnormalized_unicode[*unnormalized_unicode_len] = uch;
520 *unnormalized_unicode_len += 1;
522 len = ldap_ucs4_to_utf8( uch, *d );
524 if ( RDN_NEEDSESCAPE( tmp ) || RDN_SPECIAL( tmp ) ) {
529 } else if ( (*firstchar) && ( uch == '#' ) ) {
541 } else if ( !(*firstchar) && !ASCII_SPACE( *(*d - 1) ) ) {
547 /* Not sure what to do here either */
551 if (make_uppercase) {
552 uch = TOUPPER( uch );
555 if ( !normalize || !ASCII_WHITESPACE(uch) ) {
556 if ( (*firstchar) && ASCII_SPACE(uch) ) {
564 if ( RDN_NEEDSESCAPE( uch ) || RDN_SPECIAL( uch ) ) {
567 } else if ( (*firstchar) && ( uch == '#' ) ) {
576 } else if ( !(*firstchar) && !ASCII_SPACE( *(*d - 1) ) ) {
588 /* The string beginning at *s should be an ASCII-hex encoding of a BER
589 * encoded string of type string_type. If it is, write a UTF8 encoding
590 * of the string, according to RFC 2253, to *d, advance *s to one byte after
591 * the end of the BER encoded string, advance *d to one byte after the UTF8
592 * encoded string, add to *encoded_length the length of the BER encoding, add
593 * to *av_length the number of UTF8 characters written to *d, set *firstchar
594 * to 0 if any characters are written to *d, and return 1. Otherwise, return
595 * 0. If make_uppercase is 1, write all of the characters in uppercase. If
596 * not, write the characters as they occur in the BER encoding. If
597 * normalize is 1, remove all leading and trailing whitespace, and
598 * compress all whitespace between words to a single space. If not, transfer
599 * whitespace from the BER encoding to the UTF8 encoding unchanged.
609 unsigned int *encoded_length,
611 unsigned long *unnormalized_unicode,
612 int *unnormalized_unicode_len
616 unsigned char ch, tag, encoding_method;
618 unsigned long int length;
619 unsigned int component_encoded_length;
621 res = get_hexpair(s, &ch);
631 ber_string_type = UTF8_STRING;
633 ber_string_type = PRINTABLE_STRING;
635 ber_string_type = TELETEX_STRING;
637 ber_string_type = IA5_STRING;
639 ber_string_type = UNIVERSAL_STRING;
641 ber_string_type = BMP_STRING;
643 /* Unknown string type or not a string type */
647 /* Check that this is an acceptable string type */
648 if ( ber_string_type == string_type ) {
650 } else if ( ( string_type == DIRECTORY_STRING ) &&
651 ( ( ber_string_type == PRINTABLE_STRING ) ||
652 ( ber_string_type == TELETEX_STRING ) ||
653 ( ber_string_type == BMP_STRING ) ||
654 ( ber_string_type == UNIVERSAL_STRING ) ||
655 ( ber_string_type == UTF8_STRING ) ) ) {
658 /* Bad string type */
662 /* Bit 5 specifies the encoding method */
663 encoding_method = ch & 0x20;
665 if (encoding_method == 0) {
666 /* Primitive, definite-length encoding */
667 res = ber_parse_primitive_string(s, d, av_length, make_uppercase, normalize, ber_string_type, encoded_length, firstchar, unnormalized_unicode, unnormalized_unicode_len);
671 /* Constructed encoding */
673 res = get_hexpair(s, &ch);
678 /* Constructed, indefinite-length */
679 *encoded_length += 1;
682 res = ber_parse_string(s, d, av_length, make_uppercase, normalize, ber_string_type, &component_encoded_length, firstchar, unnormalized_unicode, unnormalized_unicode_len);
686 *encoded_length += component_encoded_length;
688 /* Must end in "0000" */
689 res = get_hexpair(s, &ch);
694 res = get_hexpair(s, &ch);
695 if ( (res == 0) || (ch != 0) )
698 *encoded_length += 2;
704 /* Constructed, definite-length */
706 res = get_ber_length(s, encoded_length, &length);
711 res = ber_parse_string(s, d, av_length, make_uppercase, normalize, ber_string_type, &component_encoded_length, firstchar, unnormalized_unicode, unnormalized_unicode_len);
712 if ( (res == 0) || (component_encoded_length > length) )
715 length -= component_encoded_length;
716 *encoded_length += component_encoded_length;
723 /* The string beginning at *s should be a string of type string_type encoded
724 * as described in RFC 2253. If it is, write a UTF8 encoding
725 * of the string, according to RFC 2253, to *d, advance *s to one byte after
726 * the end of the BER encoded string, advance *d to one byte after the UTF8
727 * encoded string, set *av_length the number of UTF8 characters written to *d,
728 * and return 1. Otherwise, return 0. If make_uppercase is 1, write all of the
729 * characters in uppercase. If not, write the characters as they occur. If
730 * normalize is 1, remove all leading and trailing whitespace, and
731 * compress all whitespace between words to a single space. If not, transfer
732 * whitespace from the BER encoding to the UTF8 encoding unchanged.
733 * representation specifies whether the string is encoding as ASCII-hex BER,
734 * within quotation marks, or as a plain string.
745 unsigned long *unnormalized_unicode
750 int first_dstchar = 0;
752 unsigned long int tmp;
755 unsigned int encoded_length;
756 int unnormalized_unicode_len = 0;
761 switch ( representation ) {
765 if ( representation == INQUOTEDVALUE ) {
773 if (unnormalized_unicode_len > 0) {
774 res = normalize_unicode(unnormalized_unicode, unnormalized_unicode_len, d, av_length);
778 *av_length -= (*d - lastchar);
779 if ( !normalize && ( ASCII_SPACE(*(lastchar - 1)) ) ) {
780 /* a space at the end of the string must be escaped */
781 *(lastchar - 1) = '\\';
788 if (representation == INQUOTEDVALUE) {
789 /* Missing end quote */
793 } else if ( representation == INVALUE && RDN_SEPARATOR( **s ) ) {
794 if (unnormalized_unicode_len > 0) {
795 res = normalize_unicode(unnormalized_unicode, unnormalized_unicode_len, d, av_length);
799 *av_length -= (*d - lastchar);
800 if ( !normalize && ( ASCII_SPACE(*(lastchar - 1)) ) ) {
801 /* a space at the end of the string must be escaped */
802 *(lastchar - 1) = '\\';
809 } else if ( representation == INQUOTEDVALUE && **s == '"' ) {
810 if (unnormalized_unicode_len > 0) {
811 res = normalize_unicode(unnormalized_unicode, unnormalized_unicode_len, d, av_length);
815 *av_length -= (*d - lastchar);
816 if ( !normalize && ( ASCII_SPACE(*(lastchar - 1)) ) ) {
817 /* a space at the end of the string must be escaped */
818 *(lastchar - 1) = '\\';
827 if ( !normalize && !ASCII_SPACE( **s ) )
830 res = get_next_char( s, &tmp, &is_escaped );
834 if ( string_type == PRINTABLE_STRING ) {
835 if ( !SLAP_PRINTABLE(tmp) )
837 } else if (string_type == IA5_STRING ) {
838 if ( !SLAP_IA5(tmp) )
842 if ( !ASCII_WHITESPACE( tmp ) )
845 if ( (tmp < 128) && (unnormalized_unicode_len > 0) ) {
846 res = normalize_unicode(unnormalized_unicode, unnormalized_unicode_len, d, av_length);
849 unnormalized_unicode_len = 0;
853 if ( RDN_NEEDSESCAPE( tmp ) ||
854 RDN_SPECIAL( tmp ) ) {
855 if ( ( representation == INVALUE ) && !is_escaped ) {
856 /* This character should have been escaped according to
857 * RFC 2253, but was not */
860 /* This must be an ASCII character */
868 } else if ( tmp == 0 ) {
869 strncpy(*d, "\\00", 3);
874 } else if ( !first_dstchar && (tmp == '#') ) {
882 } else if ( !normalize && !ASCII_SPACE( tmp ) ) {
884 if (make_uppercase) {
885 tmp = uctoupper( tmp );
887 len = ldap_ucs4_to_utf8( tmp, *d );
890 if (make_uppercase) {
891 **d = TOUPPER( tmp );
900 } else if ( !ASCII_WHITESPACE( tmp ) ) {
902 if (make_uppercase) {
903 tmp = uctoupper( tmp );
905 if ( normalize && (tmp > 127) ) {
906 if ( (unnormalized_unicode_len == 0) && first_dstchar ) {
907 /* The previous output character must be ASCII
908 * and it should be normalized.
911 unnormalized_unicode[unnormalized_unicode_len++] = **d;
914 unnormalized_unicode[unnormalized_unicode_len++] = tmp;
916 len = ldap_ucs4_to_utf8( tmp, *d );
921 if (make_uppercase) {
922 **d = TOUPPER( tmp );
931 } else if ( !firstchar && ( !normalize || !ASCII_SPACE( *(*d - 1) ) ) ) {
932 if ( !first_dstchar ) {
945 if ( !normalize && ( is_escaped || representation == INQUOTEDVALUE ) )
952 case INBERENCODEDVALUE:
953 /* Skip over the '#' */
958 res = ber_parse_string(s, d, av_length, make_uppercase, normalize, string_type, &encoded_length, &firstchar, unnormalized_unicode, &unnormalized_unicode_len);
962 if (unnormalized_unicode_len > 0) {
963 res = normalize_unicode(unnormalized_unicode, unnormalized_unicode_len, d, av_length);
966 } else if ( ASCII_SPACE( *(*d - 1) ) ) {
982 /* Something must be wrong, representation shouldn't
983 * have any other value.
993 /* Normalize a directory string */
995 DirectoryString_normalize(
1002 unsigned long *unnormalized_unicode
1005 return String_normalize(s, d, av_length, make_uppercase, normalize, representation, DIRECTORY_STRING, unnormalized_unicode);
1009 /* Normalize a printable string */
1011 PrintableString_normalize(
1018 unsigned long *unnormalized_unicode
1021 return String_normalize(s, d, av_length, make_uppercase, normalize, representation, PRINTABLE_STRING, unnormalized_unicode);
1025 /* Normalize an IA5 string */
1027 IA5String_normalize(
1034 unsigned long *unnormalized_unicode
1037 return String_normalize(s, d, av_length, make_uppercase, normalize, representation, IA5_STRING, unnormalized_unicode);
1042 /* The string beginning at *s represents an ASCII-hex encoding of a BER
1043 * encoded bitstring, where the encoding is primitive, definite-length.
1044 * If the string is properly encoded, place the string in *d, advance *s
1045 * and *d, add the number of bits in the string to *av_length, add
1046 * the length of the BER encoding to *encoded_length, and return 1. Otherwise,
1050 ber_parse_primitive_bitstring(
1054 unsigned int *encoded_length
1059 unsigned long int length;
1060 unsigned char unused;
1063 static unsigned char mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
1065 res = get_ber_length(s, encoded_length, &length);
1070 /* There must be a least one byte containing the number of
1076 /* get number of unused bits */
1077 res = get_hexpair(s, &unused);
1078 if ( ( res == 0 ) || ( unused > 7 ) )
1081 if ( (length == 0) && (unused != 0) ) {
1082 /* If there are no content bits, there can be no unused bits */
1086 *encoded_length += 1;
1089 while( length > 1 ) {
1090 res = get_hexpair(s, &ch);
1094 *encoded_length += 1;
1097 for(bit_pos = 7; bit_pos >= 0; bit_pos--) {
1098 if ( (ch & mask[bit_pos]) == 0 ) {
1109 res = get_hexpair(s, &ch);
1113 *encoded_length += 1;
1115 for(bit_pos = 7; bit_pos >= unused; bit_pos--) {
1116 if ( (ch & mask[bit_pos]) == 0 ) {
1130 /* The string beginning at *s represents an ASCII-hex encoding of a BER
1131 * encoded bitstring. If the string is properly encoded, place the string
1132 * in *d, advance *s and *d, add the number of bits in the string to
1133 * *av_length, add the length of the BER encoding to *encoded_length, and
1134 * return 1. Otherwise, return 0.
1137 ber_parse_bitstring(
1141 unsigned int *encoded_length
1146 unsigned long int length;
1147 unsigned int component_encoded_length;
1149 res = get_hexpair(s, &ch);
1153 *encoded_length = 1;
1156 /* Primitive, definite-length encoding */
1157 res = ber_parse_primitive_bitstring(s, d, av_length, encoded_length);
1160 } else if ( ch == '\x23' ) {
1161 /* Constructed encoding */
1163 res = get_hexpair(s, &ch);
1168 /* Constructed, indefinite-length */
1169 *encoded_length += 1;
1172 res = ber_parse_bitstring(s, d, av_length, &component_encoded_length);
1176 *encoded_length += component_encoded_length;
1178 /* Must end in "0000" */
1179 res = get_hexpair(s, &ch);
1184 res = get_hexpair(s, &ch);
1185 if ( (res == 0) || (ch != 0) )
1188 *encoded_length += 2;
1194 /* Constructed, definite-length */
1196 res = get_ber_length(s, encoded_length, &length);
1200 while (length > 0) {
1201 res = ber_parse_bitstring(s, d, av_length, &component_encoded_length);
1202 if ( (res == 0) || (component_encoded_length > length) )
1205 length -= component_encoded_length;
1206 *encoded_length += component_encoded_length;
1210 /* Not a valid bitstring */
1216 /* *s is a pointer to a string of zero or more 0's and 1's. Return a binary encoding of the next 8 bits of *s and advance
1217 * *s to the end of the parsed sub-string. If the string is less than 8-bytes long, pad the binary encoding with 0's.
1219 static unsigned char
1224 static unsigned char mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
1226 unsigned char output;
1231 while ( ( pos > 0 ) && ( ( **s == '0' ) || ( **s == '1' ) ) ) {
1235 output = output | mask[pos];
1245 /* The string beginning at *s represents a bitstring encoded according to
1246 * RFC 2253. If the string is properly encoded, place the string
1247 * in *d, advance *s and *d, place the length of the string representation of
1248 * the bitstring in *av_length, and return 1. Otherwise, return 0.
1249 * representation specifies whether the string is encoding as ASCII-hex BER,
1250 * within quotation marks, or as a plain string.
1252 * According to RFC 2252, the string representation for
1253 * bit strings is described by the following BNF:
1255 * bitstring = "'" *binary-digit "'B"
1257 * binary-digit = "0" / "1"
1260 bitString_normalize(
1267 unsigned long *unnormalized_unicode /* not used in this function */
1273 unsigned int encoded_length;
1276 unsigned char unused_bits;
1277 unsigned char byte1, byte2, temp;
1278 char *src, *start_of_output;
1281 start_of_output = *d;
1283 switch ( representation ) {
1287 if ( representation == INQUOTEDVALUE ) {
1288 /* Skip over quotation mark */
1292 /* First non-space character must be a "'" */
1293 res = get_next_byte(s, &ch, &is_escaped);
1294 if ( (res == 0) || (ch != '\'') )
1301 /* Next should be a sequence of 0's and 1's followed by a "'" */
1302 res = get_next_byte(s, &ch, &is_escaped);
1306 while ( ( ch == '0' ) || ( ch == '1' ) ) {
1311 res = get_next_byte(s, &ch, &is_escaped);
1323 /* The last character should be a 'B' */
1324 res = get_next_byte(s, &ch, &is_escaped);
1325 if ( (res == 0) || ( TOUPPER(ch) != 'B' ) )
1332 if ( representation == INQUOTEDVALUE ) {
1340 case INBERENCODEDVALUE:
1341 /* Skip over the '#' */
1350 ber_parse_bitstring(s, d, av_length, &encoded_length);
1363 /* Something must be wrong, representation shouldn't
1364 * have any other value.
1370 if ( !normalize && (representation != INBERENCODEDVALUE) )
1375 unused_bits = *av_length % 8;
1376 if ( unused_bits == 0 ) {
1377 DER_length = (*av_length / 8) + 1;
1379 DER_length = (*av_length / 8) + 2;
1380 unused_bits = 8 - unused_bits;
1383 *d = start_of_output;
1384 src = start_of_output + 1;
1387 byte1 = getNext8bits( &src );
1389 byte2 = getNext8bits( &src );
1398 /* Insert length into string */
1399 if (DER_length < 128) {
1401 write_hex_pair(d, temp);
1402 *av_length = 7 + 2 * DER_length;
1403 } else if (DER_length < 256) {
1409 write_hex_pair(d, temp);
1410 *av_length = 9 + 2 * DER_length;
1411 } else if (DER_length < 65536) {
1416 temp = (DER_length >> 8) & 0xFF;
1417 write_hex_pair(d, temp);
1418 temp = DER_length & 0xFF;
1419 write_hex_pair(d, temp);
1420 *av_length = 11 + 2 * DER_length;
1421 } else if (DER_length < 16777216) {
1426 temp = (DER_length >> 16) & 0xFF;
1427 write_hex_pair(d, temp);
1428 temp = (DER_length >> 8) & 0xFF;
1429 write_hex_pair(d, temp);
1430 temp = DER_length & 0xFF;
1431 write_hex_pair(d, temp);
1432 *av_length = 13 + 2 * DER_length;
1434 /* NOTE: I am assuming that the length will always fit in 4 octets */
1439 temp = (DER_length >> 24) & 0xFF;
1440 write_hex_pair(d, temp);
1441 temp = (DER_length >> 16) & 0xFF;
1442 write_hex_pair(d, temp);
1443 temp = (DER_length >> 8) & 0xFF;
1444 write_hex_pair(d, temp);
1445 temp = DER_length & 0xFF;
1446 write_hex_pair(d, temp);
1447 *av_length = 15 + 2 * DER_length;
1450 /* Insert number of unused bits into string */
1451 write_hex_pair(d, unused_bits);
1454 write_hex_pair(d, byte1);
1456 write_hex_pair(d, byte2);
1458 if (DER_length > 3) {
1461 while (DER_length > 0) {
1462 byte1 = getNext8bits( &src );
1463 write_hex_pair(d, byte1);
1473 * match_oid - determine if the OID represented by the string beginning
1474 * at *src and of length len is a known attribute type. If so, copy the
1475 * string representation to *dst and return a pointer to the normalization
1476 * function for the attribute value. If the attribute type places an
1477 * upper bound on the length of the attribute value, make *ub that
1478 * upper bound, otherwise set *ub to -1.
1479 * If the OID is unknown, copy the OID to *dst and return NULL.
1481 static av_normalize_type
1482 match_oid(char **src, char **dst, int *ub, int len, int make_uppercase)
1486 av_normalize_type normalize_function = NULL;
1492 if (strncmp(*src, "2.5.4.6", len) == 0) {
1497 normalize_function = PrintableString_normalize;
1498 } else if (strncmp(*src, "2.5.4.3", len) == 0) {
1500 strncpy(*dst, "cn", 2);
1503 normalize_function = DirectoryString_normalize;
1504 } else if (strncmp(*src, "2.5.4.8", len) == 0) {
1505 /* State or Province Name */
1506 strncpy(*dst, "st", 2);
1509 normalize_function = DirectoryString_normalize;
1510 } else if (strncmp(*src, "2.5.4.7", len) == 0) {
1515 normalize_function = DirectoryString_normalize;
1516 } else if (strncmp(*src, "2.5.4.5", len) == 0) {
1518 strncpy(*dst, "snu", 3);
1521 normalize_function = PrintableString_normalize;
1522 } else if (strncmp(*src, "2.5.4.4", len) == 0) {
1524 strncpy(*dst, "sn", 2);
1527 normalize_function = DirectoryString_normalize;
1528 } else if (strncmp(*src, "2.5.4.9", len) == 0) {
1529 /* street address */
1530 strncpy(*dst, "street", 6);
1533 normalize_function = DirectoryString_normalize;
1535 /* Unknown attributeType */
1536 strncpy(*dst, *src, len);
1539 normalize_function = NULL;
1544 if (strncmp(*src, "2.5.4.10", len) == 0) {
1549 normalize_function = DirectoryString_normalize;
1550 } else if (strncmp(*src, "2.5.4.11", len) == 0) {
1551 /* Organizational Unit */
1552 strncpy(*dst, "ou", 2);
1555 normalize_function = DirectoryString_normalize;
1556 } else if (strncmp(*src, "2.5.4.12", len) == 0) {
1558 strncpy(*dst, "title", 5);
1561 normalize_function = DirectoryString_normalize;
1562 } else if (strncmp(*src, "2.5.4.42", len) == 0) {
1564 strncpy(*dst, "givenName", 9);
1567 normalize_function = DirectoryString_normalize;
1568 } else if (strncmp(*src, "2.5.4.43", len) == 0) {
1570 strncpy(*dst, "initials", 8);
1573 normalize_function = DirectoryString_normalize;
1574 } else if (strncmp(*src, "2.5.4.44", len) == 0) {
1575 /* generationQualifier */
1576 strncpy(*dst, "generationQualifier", 19);
1579 normalize_function = DirectoryString_normalize;
1580 } else if (strncmp(*src, "2.5.4.45", len) == 0) {
1581 /* uniqueIdentifier */
1582 strncpy(*dst, "uniqueIdentifier", 16);
1585 normalize_function = bitString_normalize;
1586 } else if (strncmp(*src, "2.5.4.46", len) == 0) {
1588 strncpy(*dst, "dnQualifier", 11);
1591 normalize_function = PrintableString_normalize;
1592 } else if (strncmp(*src, "2.5.4.65", len) == 0) {
1594 strncpy(*dst, "Pseudonym", 9);
1597 normalize_function = DirectoryString_normalize;
1599 /* Unknown attributeType */
1600 strncpy(*dst, *src, len);
1603 normalize_function = NULL;
1608 if (strncmp(*src, "1.2.840.113549.1.9.1", len) == 0) {
1613 normalize_function = IA5String_normalize;
1615 /* Unknown attributeType */
1616 strncpy(*dst, *src, len);
1619 normalize_function = NULL;
1624 if (strncmp(*src, "0.2.262.1.10.7.20", len) == 0) {
1625 /* name distinguisher */
1626 strncpy(*dst, "nameDistinguisher", 17);
1629 normalize_function = DirectoryString_normalize;
1631 /* Unknown attributeType */
1632 strncpy(*dst, *src, len);
1635 normalize_function = NULL;
1640 if (strncmp(*src, "0.9.2342.19200300.100.1.1", len) == 0) {
1642 strncpy(*dst, "uid", 3);
1645 normalize_function = DirectoryString_normalize;
1647 /* Unknown attributeType */
1648 strncpy(*dst, *src, len);
1651 normalize_function = NULL;
1656 if (strncmp(*src, "0.9.2342.19200300.100.1.25", len) == 0) {
1657 /* domainComponent */
1658 strncpy(*dst, "dc", 2);
1661 normalize_function = IA5String_normalize;
1663 /* Unknown attributeType */
1664 strncpy(*dst, *src, len);
1667 normalize_function = NULL;
1672 /* Unknown attributeType */
1673 strncpy(*dst, *src, len);
1676 normalize_function = NULL;
1680 if (make_uppercase) {
1681 for(i=0; i < dst_len; i++) {
1682 **dst = TOUPPER( **dst );
1689 return normalize_function;
1694 * match_key - determine if the attribute type represented by the string
1695 * beginning at *src and of length len is a known attribute type. If so,
1696 * copy the string representation to *dst and return a pointer to the
1697 * normalization function for the attribute value. If the attribute type
1698 * places an upper bound on the length of the attribute value, make *ub that
1699 * upper bound, otherwise set *ub to -1.
1700 * If the attribute type is unknown, copy the string representation of the
1701 * attribute type to *dst and return NULL.
1703 static av_normalize_type
1704 match_key(char **src, char **dst, int *ub, int len, int make_uppercase)
1708 av_normalize_type normalize_function = NULL;
1714 if (strncasecmp(*src, "C", len) == 0) {
1719 normalize_function = PrintableString_normalize;
1720 } else if (strncasecmp(*src, "O", len) == 0) {
1725 normalize_function = DirectoryString_normalize;
1726 } else if (strncasecmp(*src, "T", len) == 0) {
1728 strncpy(*dst, "title", 5);
1731 normalize_function = DirectoryString_normalize;
1732 } else if (strncasecmp(*src, "S", len) == 0) {
1733 /* state or province */
1734 strncpy(*dst, "st", 2);
1737 normalize_function = DirectoryString_normalize;
1738 } else if (strncasecmp(*src, "L", len) == 0) {
1743 normalize_function = DirectoryString_normalize;
1744 } else if (strncasecmp(*src, "E", len) == 0) {
1749 normalize_function = IA5String_normalize;
1751 /* Unknown attributeType */
1752 strncpy(*dst, *src, len);
1755 normalize_function = NULL;
1760 if (strncasecmp(*src, "CN", len) == 0) {
1762 strncpy(*dst, "cn", 2);
1765 normalize_function = DirectoryString_normalize;
1766 } else if (strncasecmp(*src, "OU", len) == 0) {
1767 /* organizational unit */
1768 strncpy(*dst, "ou", 2);
1771 normalize_function = DirectoryString_normalize;
1772 } else if (strncasecmp(*src, "DC", len) == 0) {
1773 /* domainComponent */
1774 strncpy(*dst, "dc", 2);
1777 normalize_function = IA5String_normalize;
1778 } else if (strncasecmp(*src, "SN", len) == 0) {
1780 strncpy(*dst, "sn", 2);
1783 normalize_function = DirectoryString_normalize;
1784 } else if (strncasecmp(*src, "ST", len) == 0) {
1785 /* state or province */
1786 strncpy(*dst, "st", 2);
1789 normalize_function = DirectoryString_normalize;
1791 /* Unknown attributeType */
1792 strncpy(*dst, *src, len);
1795 normalize_function = NULL;
1800 if (strncasecmp(*src, "SNU", len) == 0) {
1802 strncpy(*dst, "snu", 3);
1805 normalize_function = PrintableString_normalize;
1806 } else if (strncasecmp(*src, "UID", len) == 0) {
1808 strncpy(*dst, "uid", 3);
1811 normalize_function = DirectoryString_normalize;
1813 /* Unknown attributeType */
1814 strncpy(*dst, *src, len);
1817 normalize_function = NULL;
1822 if (strncasecmp(*src, "TITLE", len) == 0) {
1824 strncpy(*dst, "title", 5);
1827 normalize_function = DirectoryString_normalize;
1828 } else if (strncasecmp(*src, "STATE", len) == 0) {
1829 /* state or province */
1830 strncpy(*dst, "st", 2);
1833 normalize_function = DirectoryString_normalize;
1835 /* Unknown attributeType */
1836 strncpy(*dst, *src, len);
1839 normalize_function = NULL;
1844 if (strncasecmp(*src, "USERID", len) == 0) {
1846 strncpy(*dst, "uid", 3);
1849 normalize_function = DirectoryString_normalize;
1850 } else if (strncasecmp(*src, "STREET", len) == 0) {
1851 /* street address */
1852 strncpy(*dst, "street", 6);
1855 normalize_function = DirectoryString_normalize;
1857 /* Unknown attributeType */
1858 strncpy(*dst, *src, len);
1861 normalize_function = NULL;
1866 if (strncasecmp(*src, "SURNAME", len) == 0) {
1868 strncpy(*dst, "sn", 2);
1871 normalize_function = DirectoryString_normalize;
1873 /* Unknown attributeType */
1874 strncpy(*dst, *src, len);
1877 normalize_function = NULL;
1882 if (strncasecmp(*src, "INITIALS", len) == 0) {
1884 strncpy(*dst, "initials", 8);
1887 normalize_function = DirectoryString_normalize;
1888 } else if (strncasecmp(*src, "PROVINCE", len) == 0) {
1889 /* state or province */
1890 strncpy(*dst, "st", 2);
1893 normalize_function = DirectoryString_normalize;
1895 /* Unknown attributeType */
1896 strncpy(*dst, *src, len);
1899 normalize_function = NULL;
1904 if (strncasecmp(*src, "GIVENNAME", len) == 0) {
1906 strncpy(*dst, "givenName", 9);
1909 normalize_function = DirectoryString_normalize;
1910 } else if (strncasecmp(*src, "PSEUDONYM", len) == 0) {
1912 strncpy(*dst, "Pseudonym", 9);
1915 normalize_function = DirectoryString_normalize;
1917 /* Unknown attributeType */
1918 strncpy(*dst, *src, len);
1921 normalize_function = NULL;
1926 if (strncasecmp(*src, "COMMONNAME", len) == 0) {
1928 strncpy(*dst, "cn", 2);
1931 normalize_function = DirectoryString_normalize;
1933 /* Unknown attributeType */
1934 strncpy(*dst, *src, len);
1937 normalize_function = NULL;
1942 if (strncasecmp(*src, "DNQUALIFIER", len) == 0) {
1943 /* Distinguished Name Quailifier */
1944 strncpy(*dst, "dnQualifier", 11);
1947 normalize_function = DirectoryString_normalize;
1948 } else if (strncasecmp(*src, "COUNTRYNAME", len) == 0) {
1953 normalize_function = PrintableString_normalize;
1955 /* Unknown attributeType */
1956 strncpy(*dst, *src, len);
1959 normalize_function = NULL;
1964 if (strncasecmp(*src, "SERIALNUMBER", len) == 0) {
1966 strncpy(*dst, "snu", 3);
1969 normalize_function = PrintableString_normalize;
1970 } else if (strncasecmp(*src, "LOCALITYNAME", len) == 0) {
1975 normalize_function = DirectoryString_normalize;
1976 } else if (strncasecmp(*src, "EMAILADDRESS", len) == 0) {
1981 normalize_function = IA5String_normalize;
1983 /* Unknown attributeType */
1984 strncpy(*dst, *src, len);
1987 normalize_function = NULL;
1992 if (strncasecmp(*src, "STREETADDRESS", len) == 0) {
1993 /* street address */
1994 strncpy(*dst, "street", 6);
1997 normalize_function = DirectoryString_normalize;
1999 /* Unknown attributeType */
2000 strncpy(*dst, *src, len);
2003 normalize_function = NULL;
2008 if (strncasecmp(*src, "DOMAINCOMPONENT", len) == 0) {
2009 /* domainComponent */
2010 strncpy(*dst, "dc", 2);
2013 normalize_function = IA5String_normalize;
2015 /* Unknown attributeType */
2016 strncpy(*dst, *src, len);
2019 normalize_function = NULL;
2024 if (strncasecmp(*src, "UNIQUEIDENTIFIER", len) == 0) {
2025 /* uniqueIdentifier */
2026 strncpy(*dst, "uniqueIdentifier", 16);
2029 normalize_function = bitString_normalize;
2030 } else if (strncasecmp(*src, "ORGANIZATIONNAME", len) == 0) {
2035 normalize_function = DirectoryString_normalize;
2037 /* Unknown attributeType */
2038 strncpy(*dst, *src, len);
2041 normalize_function = NULL;
2046 if (strncasecmp(*src, "NAMEDISTINGUISHER", len) == 0) {
2047 /* name distinguisher */
2048 strncpy(*dst, "nameDistinguisher", 17);
2051 normalize_function = DirectoryString_normalize;
2053 /* Unknown attributeType */
2054 strncpy(*dst, *src, len);
2057 normalize_function = NULL;
2062 if (strncasecmp(*src, "GENERATIONQUALIFIER", len) == 0) {
2063 /* Distinguished Name Quailifier */
2064 strncpy(*dst, "generationQualifier", 19);
2067 normalize_function = DirectoryString_normalize;
2068 } else if (strncasecmp(*src, "STATEORPROVINCENAME", len) == 0) {
2069 /* state or province */
2070 strncpy(*dst, "st", 2);
2073 normalize_function = DirectoryString_normalize;
2075 /* Unknown attributeType */
2076 strncpy(*dst, *src, len);
2079 normalize_function = NULL;
2085 if (strncasecmp(*src, "ORGANIZATIONALUNITNAME", len) == 0) {
2086 /* organizational unit */
2087 strncpy(*dst, "ou", 2);
2090 normalize_function = DirectoryString_normalize;
2092 /* Unknown attributeType */
2093 strncpy(*dst, *src, len);
2096 normalize_function = NULL;
2101 /* Unknown attributeType */
2102 strncpy(*dst, *src, len);
2105 normalize_function = NULL;
2109 if (make_uppercase) {
2110 for(i=0; i < dst_len; i++) {
2111 **dst = TOUPPER( **dst );
2118 return normalize_function;
2123 get_validated_av_in_dn(char **s, char **d, int make_uppercase, int normalize, unsigned long *unnormalized_unicode) {
2125 int status, av_ub, len, av_length;
2126 av_normalize_type av_normalize;
2128 /* First skip over any leading spaces */
2129 while ( ASCII_SPACE( **s ) )
2132 /* Next get the attribute type */
2133 if ( OID_LEADCHAR(**s) ) {
2135 while ( *i != '\0' && OID_CHAR(*i) )
2141 av_normalize = match_oid(s, d, &av_ub, len, make_uppercase);
2142 } else if ( DESC_LEADCHAR(**s) ) {
2143 if ( TOUPPER ( **s ) == 'O' &&
2144 TOUPPER ( *(*s+1) ) == 'I' &&
2145 TOUPPER ( *(*s+2) ) == 'D' &&
2148 if ( !OID_LEADCHAR(**s) )
2152 while ( *i != '\0' && OID_CHAR(*i) )
2158 av_normalize = match_oid(s, d, &av_ub, len, make_uppercase);
2161 while ( *i != '\0' && DESC_CHAR(*i) )
2167 av_normalize = match_key(s, d, &av_ub, len, make_uppercase);
2174 /* Next should be the equal sign */
2176 while ( (**s != '=') && (**s != '\0') ) {
2177 if ( !ASCII_SPACE(**s) )
2190 while ( ASCII_SPACE(**s) )
2193 /* The final part is the attribute value */
2195 if (av_normalize == NULL) {
2197 av_normalize = DirectoryString_normalize;
2199 status = (*av_normalize)(s, d, &av_length, make_uppercase, normalize, INQUOTEDVALUE, unnormalized_unicode);
2202 if ( ( av_ub != -1 ) && ( av_length > av_ub ) ) {
2203 /* attribute value too long */
2206 } else if ( **s == '#' ) {
2207 if (av_normalize == NULL) {
2208 /* Unknown attribute type. Since we don't know its string representation,
2209 * just leave it as a BER encoded value.
2214 while ( ASCII_XDIGIT(**s) ) {
2220 /* The length must be odd, since there must be an even number of
2221 * hexadecimal charaters after the '#'.
2223 if ( (av_length & 1) == 0)
2226 status = (*av_normalize)(s, d, &av_length, make_uppercase, normalize, INBERENCODEDVALUE, unnormalized_unicode);
2229 if ( ( av_ub != -1 ) && ( av_length > av_ub ) ) {
2230 /* attribute value too long */
2235 if (av_normalize == NULL) {
2237 av_normalize = DirectoryString_normalize;
2239 status = (*av_normalize)(s, d, &av_length, make_uppercase, normalize, INVALUE, unnormalized_unicode);
2242 if ( ( av_ub != -1 ) && ( av_length > av_ub ) ) {
2243 /* attribute value too long */
2251 /* The string *s is a distinguished name encoded according to RFC 2253.
2252 * If the first RDN in *s is properly encoded, place in *d a normalized
2253 * version of the first RDN in *s, advance *d to the end of the normalized
2254 * RDN, advance *s to the end of the input string, and return 1.
2255 * If *s is not properly encoded, return 0.
2258 get_validated_rdn_in_dn(char **s, char **d, int make_uppercase, int normalize, unsigned long *unnormalized_unicode) {
2259 char *av_pair[1001]; /* Assume there are less than 1000 attribute value pairs per RDN */
2260 int av_pair_len[1001];
2261 char *temp, *work_space;
2262 int i, j, num_av_pairs, status, state, len;
2264 /* An RDN is a set of 1 or more attribute/value pairs. Get the first AV pair */
2266 status = get_validated_av_in_dn(s, d, make_uppercase, normalize, unnormalized_unicode);
2272 state = B4SEPARATOR;
2274 while ( ASCII_SPACE( **s ) ) {
2279 /* This RDN contains only 1 attribute value pair */
2283 /* Since RDNs with more than one attribute value pair are
2284 * rare, the above code was optimized for the case of an
2285 * RDN with only one AV pair. This RDN, however, contains
2286 * two or more AV pairs and they must be sorted to ensure
2287 * consistency when performing matches. The ordering does
2288 * not matter as long as it is consistent.
2291 /* Create temporary space to hold the AV pairs before sorting */
2294 /* Compute the length of the first AV pair */
2295 av_pair_len[0] = *d - av_pair[0];
2297 work_space = (char *)ch_malloc(4 * strlen( *s ) + av_pair_len[0] + 1000);
2299 /* Move *d back so that the whole RDN can be written in the proper order */
2302 av_pair[0] = work_space;
2303 bcopy(*d, av_pair[0], av_pair_len[0]+1);
2305 av_pair[1] = av_pair[0] + av_pair_len[0] + 1;
2306 while ( (num_av_pairs < 1000) && (**s != ',') && (**s != ';') && (**s != '\0') ) {
2308 ch_free(work_space);
2313 temp = av_pair[num_av_pairs];
2314 status = get_validated_av_in_dn(s, &temp, make_uppercase, normalize, unnormalized_unicode);
2316 ch_free(work_space);
2319 av_pair_len[num_av_pairs] = temp - av_pair[num_av_pairs];
2323 av_pair[num_av_pairs] = temp;
2325 while ( ASCII_SPACE(**s) )
2329 if (num_av_pairs == 1000) {
2330 ch_free(work_space);
2335 /* Sort the AV pairs. Since the number of AV pairs in an RDN should always
2336 * be very small, bubblesort is used.
2338 for(i = 0; i < num_av_pairs; i++) {
2339 for(j = 1; j < num_av_pairs; j++) {
2340 if (strcasecmp(av_pair[j-1], av_pair[j]) > 0) {
2341 temp = av_pair[j-1];
2342 av_pair[j-1] = av_pair[j];
2345 len = av_pair_len[j-1];
2346 av_pair_len[j-1] = av_pair_len[j];
2347 av_pair_len[j] = len;
2353 /* place the AV pairs in *d, separated by commas */
2354 for(i=0; i < num_av_pairs; i++) {
2355 bcopy(av_pair[i], *d, av_pair_len[i]);
2356 *d += av_pair_len[i];
2362 ch_free(work_space);
2367 /* The string dn is a distinguished name encoded according to RFC 2253.
2368 * If dn is properly encoded, return a normalized version of the string.
2369 * If not, return NULL. If make_uppercase is 0, do not change the case of
2370 * characters in attribute values, otherwise make all characters in attribute
2371 * values uppercase. If normalize is 0, do not compress whitespace
2372 * within attribute values, otherwise remove any leading and trailing
2373 * whitespace characters from attribute values and replace any strings of
2374 * whitespace characters between "words" with a single space character.
2377 get_validated_dn( char *dn, int make_uppercase, int normalize)
2379 char *ret_val, *s, *d;
2380 unsigned long *unnormalized_unicode;
2381 int dn_len, status, state;
2385 dn_len = strlen(dn);
2386 d = ret_val = (char *)ch_malloc(4 * dn_len + 1);
2389 /* Create temporary workspace to hold unicode characters before
2390 * they have been normalized.
2393 unnormalized_unicode = (unsigned long *)ch_malloc(dn_len * sizeof(unsigned long));
2395 unnormalized_unicode = NULL;
2397 /* A DN consists of a sequence of 0 or more RDNs */
2399 while ( ret_val != NULL && *s != '\0' ) {
2400 if ( ASCII_SPACE( *s ) ) {
2402 } else if ( (state == B4SEPARATOR) && ( (*s == ',') || (*s == ';') ) ) {
2407 status = get_validated_rdn_in_dn(&s, &d, make_uppercase, normalize, unnormalized_unicode);
2409 /* not a valid RDN */
2413 state = B4SEPARATOR;
2417 if (state == B4VALUE) {
2418 /* not a valid DN */
2428 * dn_validate - validate and compress dn. the dn is
2429 * compressed in place are returned if valid.
2433 dn_validate( char *dn_in )
2438 len = strlen(dn_in);
2441 dn_out = get_validated_dn(dn_in, 0, 0);
2442 if (dn_out == NULL) {
2444 } else if (strlen(dn_out) <= len) {
2445 strcpy(dn_in, dn_out);
2456 * dn_normalize - put dn into a canonical form suitable for storing
2457 * in a hash database. this involves normalizing the case as well as
2458 * the format. the dn is normalized in place as well as returned if valid.
2462 dn_normalize( char *dn )
2470 dn_out = get_validated_dn(dn, 1, 1);
2471 if (dn_out == NULL) {
2473 } else if (strlen(dn_out) <= len) {
2485 * dn_parent - return a copy of the dn of dn's parent
2501 while(*dn != '\0' && ASCII_SPACE(*dn)) {
2509 if ( be != NULL && be_issuffix( be, dn ) ) {
2514 * assume it is an X.500-style name, which looks like
2515 * foo=bar,sha=baz,...
2519 for ( s = dn; *s; s++ ) {
2533 } else if ( DN_SEPARATOR( *s ) ) {
2534 return ch_strdup( &s[1] );
2539 return ch_strdup( "" );
2549 if( dn_in == NULL ) {
2553 while(*dn_in && ASCII_SPACE(*dn_in)) {
2557 if( *dn_in == '\0' ) {
2561 if ( be != NULL && be_issuffix( be, dn_in ) ) {
2565 dn = ch_strdup( dn_in );
2569 for ( s = dn; *s; s++ ) {
2583 } else if ( DN_SEPARATOR( *s ) ) {
2595 * return a charray of all subtrees to which the DN resides in
2601 char *child, *parent;
2602 char **subtree = NULL;
2604 child = ch_strdup( dn );
2607 charray_add( &subtree, child );
2609 parent = dn_parent( be, child );
2614 } while ( child != NULL );
2621 * dn_issuffix - tells whether suffix is a suffix of dn. both dn
2622 * and suffix must be normalized.
2631 int dnlen, suffixlen;
2637 suffixlen = strlen( suffix );
2638 dnlen = strlen( dn );
2640 if ( suffixlen > dnlen ) {
2644 return( strcmp( dn + dnlen - suffixlen, suffix ) == 0 );
2648 * get_next_substring(), rdn_attr_type(), rdn_attr_value(), and
2651 * Copyright 1999, Juan C. Gomez, All rights reserved.
2652 * This software is not subject to any license of Silicon Graphics
2653 * Inc. or Purdue University.
2655 * Redistribution and use in source and binary forms are permitted
2656 * without restriction or fee of any kind as long as this notice
2661 /* get_next_substring:
2663 * Gets next substring in s, using d (or the end of the string '\0') as a
2664 * string delimiter, and places it in a duplicated memory space. Leading
2665 * spaces are ignored. String s **must** be null-terminated.
2669 get_next_substring( const char * s, char d )
2674 r = str = ch_malloc( strlen(s) + 1 );
2676 /* Skip leading spaces */
2678 while ( *s && ASCII_SPACE(*s) ) {
2684 while ( *s && (*s != d) ) {
2686 /* Don't stop when you see trailing spaces may be a multi-word
2687 * string, i.e. name=John Doe!
2703 * Given a string (i.e. an rdn) of the form:
2704 * "attribute_type = attribute_value"
2705 * this function returns the type of an attribute, that is the
2706 * string "attribute_type" which is placed in newly allocated
2707 * memory. The returned string will be null-terminated.
2710 char * rdn_attr_type( const char * s )
2712 return get_next_substring( s, '=' );
2718 * Given a string (i.e. an rdn) of the form:
2719 * "attribute_type = attribute_value"
2720 * this function returns "attribute_type" which is placed in newly allocated
2721 * memory. The returned string will be null-terminated and may contain
2722 * spaces (i.e. "John Doe\0").
2726 rdn_attr_value( const char * rdn )
2731 if ( (str = strchr( rdn, '=' )) != NULL ) {
2732 return get_next_substring(++str, '\0');
2742 * Given a string (i.e. an rdn) of the form:
2743 * "attribute_type=attribute_value[+attribute_type=attribute_value[...]]"
2744 * this function stores the types of the attributes in ptypes, that is the
2745 * array of strings "attribute_type" which is placed in newly allocated
2746 * memory, and the values of the attributes in pvalues, that is the
2747 * array of strings "attribute_value" which is placed in newly allocated
2748 * memory. Returns 0 on success, -1 on failure.
2750 * note: got part of the code from dn_validate
2754 rdn_attrs( const char * rdn_in, char ***ptypes, char ***pvalues)
2762 * explode the rdn in parts
2764 parts = ldap_explode_rdn( rdn_in, 0 );
2766 if ( parts == NULL ) {
2770 for ( p = parts; p[0]; p++ ) {
2773 /* split each rdn part in type value */
2774 s = strchr( p[0], '=' );
2776 charray_free( *ptypes );
2777 charray_free( *pvalues );
2778 charray_free( parts );
2782 /* type should be fine */
2783 charray_add_n( ptypes, p[0], ( s-p[0] ) );
2785 /* value needs to be unescaped
2786 * (maybe this should be moved to ldap_explode_rdn?) */
2787 for ( e = d = s + 1; e[0]; e++ ) {
2793 charray_add( pvalues, s + 1 );
2797 charray_free( parts );
2805 * 1 if rdn is a legal rdn;
2806 * 0 otherwise (including a sequence of rdns)
2808 * note: got it from dn_rdn; it should be rewritten
2809 * according to dn_validate
2812 rdn_validate( const char * rdn )
2816 if ( rdn == NULL ) {
2820 if ( strchr( rdn, '=' ) == NULL ) {
2824 while ( *rdn && ASCII_SPACE( *rdn ) ) {
2828 if( *rdn == '\0' ) {
2834 for ( ; *rdn; rdn++ ) {
2835 if ( *rdn == '\\' ) {
2842 if ( *rdn == '"' ) {
2846 if ( *rdn == '"' ) {
2848 } else if ( DN_SEPARATOR( *rdn ) ) {
2860 * Used by ldbm/bdb2_back_modrdn to create the new dn of entries being
2863 * new_dn = parent (p_dn) + separator(s) + rdn (newrdn) + null.
2867 build_new_dn( char ** new_dn,
2870 const char * newrdn )
2873 if ( p_dn == NULL ) {
2874 *new_dn = ch_strdup( newrdn );
2878 *new_dn = (char *) ch_malloc( strlen( p_dn ) + strlen( newrdn ) + 3 );
2880 strcpy( *new_dn, newrdn );
2881 strcat( *new_dn, "," );
2882 strcat( *new_dn, p_dn );