2 * Copyright (c) 1990 Regents of the University of Michigan.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of Michigan at Ann Arbor. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
18 #include <ac/socket.h>
19 #include <ac/string.h>
21 #include <quipu/commonarg.h>
22 #include <quipu/attrvalue.h>
23 #include <quipu/ds_error.h>
24 #include <quipu/ds_search.h>
25 #include <quipu/dap2.h>
26 #include <quipu/dua.h>
29 #include "../../libraries/liblber/lber-int.h" /* get struct berelement */
33 short ldap_photo_syntax;
34 short ldap_jpeg_syntax;
35 short ldap_jpeg_nonfile_syntax;
36 short ldap_audio_syntax;
38 short ldap_postaladdress_syntax;
39 short ldap_acl_syntax;
40 short ldap_mtai_syntax;
41 short ldap_rts_cred_syntax;
42 short ldap_rtl_syntax;
43 short ldap_mailbox_syntax;
44 short ldap_caseignorelist_syntax;
45 short ldap_caseexactstring_syntax;
46 short ldap_certif_syntax;
47 short ldap_iattr_syntax;
48 short ldap_telex_syntax;
49 short ldap_octetstring_syntax;
50 short ldap_deliverymethod_syntax;
51 short ldap_facsimileTelephoneNumber_syntax;
52 short ldap_presentationAddress_syntax;
53 short ldap_teletexTerminalIdentifier_syntax;
54 short ldap_searchGuide_syntax;
55 short ldap_dLSubmitPermission_syntax;
57 static void de_t61( char *s, int t61mark );
58 static int syntax_is_string( short syntax );
60 static get_one_syntax( char *attrib, int required )
62 oid_table_attr *p, *name2attr();
64 if ( (p = name2attr( attrib )) != (oid_table_attr *) 0 )
65 return( p->oa_syntax );
70 Debug( LDAP_DEBUG_ANY, "name2attr (%s) failed - exiting\n", attrib,
79 oid_table_attr *name2attr();
81 Debug( LDAP_DEBUG_TRACE, "get_syntaxes\n", 0, 0, 0 );
83 ldap_photo_syntax = get_one_syntax( "photo", 0 );
84 ldap_jpeg_syntax = get_one_syntax( "jpegPhoto", 0 );
85 ldap_jpeg_nonfile_syntax = str2syntax( "jpeg" );
86 ldap_audio_syntax = get_one_syntax( "audio", 0 );
87 ldap_postaladdress_syntax = get_one_syntax( "postaladdress", 0 );
88 ldap_dn_syntax = get_one_syntax( "aliasedObjectName", 1 );
89 ldap_acl_syntax = get_one_syntax( "acl", 0 );
90 ldap_mtai_syntax = get_one_syntax( "mTAInfo", 0 );
91 ldap_rts_cred_syntax= get_one_syntax( "initiatingRTSCredentials", 0 );
92 ldap_rtl_syntax= get_one_syntax( "routingTreeList", 0 );
93 ldap_mailbox_syntax = get_one_syntax( "otherMailbox", 0 );
94 ldap_caseignorelist_syntax = str2syntax( "CaseIgnoreList" );
95 ldap_caseexactstring_syntax = str2syntax( "caseexactstring" );
96 ldap_octetstring_syntax = str2syntax( "OctetString" );
97 ldap_deliverymethod_syntax = str2syntax( "DeliveryMethod" );
98 ldap_iattr_syntax = get_one_syntax( "inheritedAttribute", 0 );
99 ldap_certif_syntax = get_one_syntax( "userCertificate", 0 );
100 ldap_telex_syntax = get_one_syntax( "telexNumber", 0 );
101 ldap_facsimileTelephoneNumber_syntax =
102 get_one_syntax( "facsimileTelephoneNumber", 0 );
103 ldap_presentationAddress_syntax =
104 get_one_syntax( "presentationAddress", 0 );
105 ldap_teletexTerminalIdentifier_syntax =
106 get_one_syntax( "teletexTerminalIdentifier", 0 );
107 ldap_searchGuide_syntax = get_one_syntax( "searchGuide", 0 );
108 ldap_dLSubmitPermission_syntax =
109 get_one_syntax( "mhsDLSubmitPermissions", 0 );
111 certif_init(); /* initialize certificate syntax handler */
115 * From RFC 1779 "A String Representation of Distinguished Names"
117 * Key Attribute (X.520 keys)
118 * ------------------------------
121 * ST StateOrProvinceName
123 * OU OrganizationalUnitName
125 * STREET StreetAddress
128 * Table 1: Standardised Keywords
130 * There is an escape mechanism from the normal user oriented form, so
131 * that this syntax may be used to print any valid distinguished name.
133 * 1. Attributes types are represented in a (big-endian) dotted
134 * notation. (e.g., OID.2.6.53).
137 static void attr_key_rfc1779 (
139 char *key /* return key, caller allocated */
144 x = attr2name_aux ( at );
148 } else if ( isdigit ( *x ) ) {
149 sprintf ( key, "OID.%s", x );
151 } else if (strcasecmp(x,"commonName")==0) {
153 } else if (strcasecmp(x,"localityName")==0) {
155 } else if (strcasecmp(x,"stateOrProvinceName")==0) {
157 } else if (strcasecmp(x,"organizationName")==0) {
159 } else if (strcasecmp(x,"organizationalUnitName")==0) {
161 } else if (strcasecmp(x,"countryName")==0) {
163 } else if (strcasecmp(x,"streetAddress")==0) {
170 #define SEPARATOR(c) (c == ',' || c == ';')
171 #define SPACE(c) (c == ' ' || c == '\n')
184 void ldap_dn_print();
190 if ( dn->dn_parent != NULLDN ) {
191 dn_print_real( ps, dn->dn_parent, format );
192 ps_print( ps, ", " );
195 if ( (rps = ps_alloc( str_open )) == NULLPS )
197 if ( str_setup( rps, NULLCP, 0, 0 ) == NOTOK )
201 for ( rdn = dn->dn_rdn; rdn != NULLRDN; rdn = rdn->rdn_next ) {
205 ps_print( ps, " + " );
207 attr_key_rfc1779 ( rdn->rdn_at, key );
209 ps_print ( ps, key );
212 if ( rdn->rdn_at->oa_syntax == ldap_dn_syntax ) {
213 dn_print_real( rps, (DN) rdn->rdn_av.av_struct,
216 value = rps->ps_base;
218 AttrV_print( rps, &rdn->rdn_av, EDBOUT );
220 if ( rps->ps_ptr - rps->ps_base >= 5 &&
221 strncmp( rps->ps_base, "{ASN}", 5 ) == 0 ) {
223 SAFEMEMCPY( rps->ps_base + 1, rps->ps_base + 5,
224 rps->ps_ptr - rps->ps_base - 4 );
226 value = rps->ps_base;
231 * ,+="\\\n all go in quotes. " and \\ need to
232 * be preceeded by \\.
235 if ( strpbrk( value, ",+=\"\\\n" ) != NULL || SPACE( value[0] )
236 || SPACE( value[max( strlen(value) - 1, (size_t) 0 )] ) ) {
240 ps_print( ps, "\"" );
243 for ( p = value; *p != '\0'; p++ ) {
244 if ( *p == '"' || *p == '\\' ) {
248 if ( specialcount > 0 ) {
249 tmp = smalloc( strlen( value ) + specialcount
251 for ( p = value, t = tmp; *p != '\0'; p++ ) {
265 ps_print( ps, value );
268 ps_print( ps, "\"" );
270 ps_print( ps, value );
273 rps->ps_ptr = rps->ps_base;
285 DN base, /* if non-NULL, subsitute '*' for base (for CLDAP) */
292 Debug( LDAP_DEBUG_TRACE, "ldap_dn_print\n", 0, 0, 0 );
295 if ( base != NULLDN && dn != NULL ) {
296 for ( tmpdn = dn; base != NULLDN && tmpdn != NULLDN;
297 base = base->dn_parent, tmpdn = tmpdn->dn_parent ) {
298 if ( dn_comp_cmp( base, tmpdn ) == NOTOK ) {
302 if (( addstar = ( base == NULLDN && tmpdn != NULL ))) {
307 dn_print_real( ps, dn, format );
309 ps_print( ps, ", *" );
317 DN base /* if non-NULL, subsitute '*' for base (for CLDAP) */
323 Debug( LDAP_DEBUG_TRACE, "encode_dn\n", 0, 0, 0 );
325 if ( (ps = ps_alloc( str_open )) == NULLPS )
327 if ( str_setup( ps, NULLCP, 0, 0 ) == NOTOK )
330 ldap_dn_print( ps, dn, base, EDBOUT );
333 rc = ber_printf( ber, "s", ps->ps_base );
340 static put_jpeg_value( BerElement *ber, AttributeValue av )
345 Debug( LDAP_DEBUG_TRACE, "put_jpeg_value\n", 0, 0, 0 );
347 if (av->av_syntax == AV_FILE)
348 pe = (PE) (((struct file_syntax *) av->av_struct)->
351 pe = (PE) av->av_struct;
353 Debug( LDAP_DEBUG_ARGS,
354 "put_jpeg_value: pe_class %x, pe_form %x, pe_id %x\n",
355 pe->pe_class, pe->pe_form, pe->pe_id );
357 if ( (pe->pe_class != PE_CLASS_UNIV && pe->pe_class != PE_CLASS_CONT)
358 || pe->pe_form != PE_FORM_PRIM || pe->pe_id != PE_PRIM_OCTS ) {
359 Debug( LDAP_DEBUG_ANY, "put_jpeg_value: unknown type\n", 0,
364 if ( pe_pullup( pe ) == NOTOK ) {
365 Debug( LDAP_DEBUG_ANY, "put_jpeg_value: cannot pullup\n", 0,
370 len = ps_get_abs( pe );
372 Debug( LDAP_DEBUG_ARGS, "put_jeg_value: ber_printf %d bytes\n",
374 if ( ber_printf( ber, "o", (char *) pe->pe_prim, len ) == -1 ) {
375 Debug( LDAP_DEBUG_ANY, "put_jpeg_value: ber_printf failed\n",
383 static put_audio_value( BerElement *ber, AttributeValue av )
389 Debug( LDAP_DEBUG_TRACE, "put_audio_value\n", 0, 0, 0 );
391 qb = (struct qbuf *) (((struct file_syntax *)
392 av->av_struct)->fs_attr->av_struct);
395 for ( p = qb->qb_forw; p != qb; p = p->qb_forw ) {
399 if ( (buf = (char *) malloc( len )) == NULL )
403 for ( p = qb->qb_forw; p != qb; p = p->qb_forw ) {
404 SAFEMEMCPY( buf + len, p->qb_data, p->qb_len );
408 Debug( LDAP_DEBUG_ARGS, "put_audio_value: ber_printf %d bytes\n",
411 if ( (rc = ber_printf( ber, "o", buf, len )) == -1 )
412 Debug( LDAP_DEBUG_ANY, "put_audio_value: ber_printf failed\n",
420 static put_photo_value( BerElement *ber, AttributeValue av )
425 char *faxparamset = "\000\300\000\000";
428 Debug( LDAP_DEBUG_TRACE, "put_photo_value\n", 0, 0, 0 );
430 pe = (PE) (((struct file_syntax *) av->av_struct)->fs_attr->av_struct);
432 /* old bit string-like format - only handle this for now */
433 if ( pe->pe_class == PE_CLASS_UNIV && pe->pe_form == PE_FORM_PRIM
434 && pe->pe_id == PE_PRIM_BITS ) {
435 len = ps_get_abs( pe );
436 Debug( LDAP_DEBUG_ARGS, "put_photo_val: ber_printf %d bytes\n",
438 if (( phber = der_alloc()) == NULLBER ) {
439 Debug( LDAP_DEBUG_ANY, "der_alloc failed\n", 0, 0, 0 );
442 if ( ber_printf( phber, "t{[tB]{B}}", 0xA3, 0x81, faxparamset,
443 31, (char *)pe->pe_prim, len * 8 ) == -1 ) {
444 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
445 ber_free( phber, 1 );
448 if ( ber_printf( ber, "o", phber->ber_buf, phber->ber_ptr
449 - phber->ber_buf ) == -1 ) {
450 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
451 ber_free( phber, 1 );
454 ber_free( phber, 1 );
457 * try just writing this into a PS and sending it along
459 ps_len_strategy = PS_LEN_LONG;
460 if ( (ps = ps_alloc( str_open )) == NULLPS )
462 if ( str_setup( ps, NULLCP, 0, 0 ) == NOTOK ||
463 pe2ps( ps, pe ) == NOTOK ) {
468 len = ps->ps_ptr - ps->ps_base;
469 Debug( LDAP_DEBUG_ARGS, "put_photo_val: ber_printf %d bytes\n",
471 if ( ber_printf( ber, "o", (char *) ps->ps_base, len ) == -1 ) {
472 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
492 Debug( LDAP_DEBUG_TRACE, "put_values\n", 0, 0, 0 );
494 for ( av = vals; av != NULLAV; av = av->avseq_next ) {
495 if ( syntax == ldap_jpeg_syntax ||
496 syntax == ldap_jpeg_nonfile_syntax ) {
497 if ( put_jpeg_value( ber, &av->avseq_av ) == -1 )
499 } else if ( syntax == ldap_photo_syntax ) {
500 if ( put_photo_value( ber, &av->avseq_av ) == -1 )
502 } else if ( syntax == ldap_audio_syntax ) {
503 if ( put_audio_value( ber, &av->avseq_av ) == -1 )
505 } else if ( syntax == ldap_dn_syntax ) {
506 if ( encode_dn( ber, (DN) av->avseq_av.av_struct,
509 } else if ( syntax > AV_WRITE_FILE ) {
510 struct file_syntax *fsyntax;
512 fsyntax = (struct file_syntax *) av->avseq_av.av_struct;
514 ps->ps_ptr = ps->ps_base;
515 AttrV_print( ps, fsyntax->fs_attr, EDBOUT );
518 if ( ber_printf( ber, "o", ps->ps_base,
519 ps->ps_ptr - ps->ps_base ) == -1 )
522 ps->ps_ptr = ps->ps_base;
523 AttrV_print( ps, &av->avseq_av, EDBOUT );
525 de_t61( ps->ps_base, 0 );
527 if ( syntax_is_string( av->avseq_av.av_syntax ) &&
528 *ps->ps_base == '\0' ) {
530 * If this is a zero-length string, make it
531 * a single blank (this is gross, but it works
532 * around a dsap library bug).
534 Debug( LDAP_DEBUG_ANY,
535 "put_values: replaced zero-length string with single blank\n", 0, 0, 0 );
538 strvalue = ps->ps_base;
540 if ( ber_printf( ber, "s", strvalue ) == -1 )
549 encode_attrs( BerElement *ber, Attr_Sequence as )
553 extern int ldap_compat;
556 Debug( LDAP_DEBUG_TRACE, "encode_attrs\n", 0, 0, 0 );
558 if ( (ps = ps_alloc( str_open )) == NULLPS )
560 if ( str_setup( ps, NULLCP, 0, 0 ) == NOTOK )
564 if ( ber_printf( ber, "t{", ldap_compat == 20 ? OLD_LBER_SEQUENCE :
565 LBER_SEQUENCE ) == -1 ) {
567 if ( ber_printf( ber, "{" ) == -1 ) {
573 while ( as != NULLATTR ) {
574 ps->ps_ptr = ps->ps_base;
575 AttrT_print( ps, as->attr_type, EDBOUT );
579 if ( ber_printf( ber, "t{st[", ldap_compat == 20 ?
580 OLD_LBER_SEQUENCE : LBER_SEQUENCE, ps->ps_base,
581 ldap_compat == 20 ? OLD_LBER_SET : LBER_SET ) == -1 ) {
583 if ( ber_printf( ber, "{s[", ps->ps_base ) == -1 ) {
589 put_values( ber, ps, as->attr_type->oa_syntax, as->attr_value );
591 if ( ber_printf( ber, "]}" ) == -1 ) {
600 if ( ber_printf( ber, "}" ) == -1 )
607 trim_trailing_spaces( char *s )
621 DN ldap_str2dn( char *str )
624 RDN rdn, newrdn, tmprdn;
627 char *type, *value, *savestr;
630 Debug( LDAP_DEBUG_TRACE, "ldap_str2dn\n", 0, 0, 0 );
632 savestr = str = strdup( str );
642 while ( *str == ' ' || *str == '\n' )
645 while ( *str != '\0' && *str != '=' )
647 if ( *str == '\0' ) {
649 Debug( LDAP_DEBUG_ARGS, "no =\n", 0, 0, 0 );
653 if ( strncmp( type, "OID.", 4 ) == 0 )
665 /* break or return out */
666 while ( state != ENDVALUE ) {
669 if ( state == BEGINVALUE ) {
672 } else if ( state == INQUOTE ) {
677 Debug( LDAP_DEBUG_ARGS,
678 "quote state %d\n", state,
687 if ( state == INVALUE ) {
689 } else if ( state == INQUOTE ) {
693 Debug( LDAP_DEBUG_ARGS,
694 "comma state %d\n", state,
702 if ( state == BEGINVALUE ) {
719 if ( state == BEGINVALUE )
726 while ( SPACE( *str ) )
733 if ( SEPARATOR( *str ) )
739 trim_trailing_spaces( type );
740 if ( (at = str2AttrT( type )) == NULLAttrT ) {
743 Debug( LDAP_DEBUG_ARGS, "bad type (%s)\n",
745 return( NULLDN ); /* LDAP_UNDEFINED_TYPE */
748 if ( (av = ldap_str2AttrV( value, at->oa_syntax ))
752 Debug( LDAP_DEBUG_ARGS, "bad val\n", 0, 0, 0 );
753 return( NULLDN ); /* LDAP_INVALID_SYNTAX */
756 newrdn = rdn_comp_new( at, av );
758 /* add it to the list */
759 for ( tmprdn = rdn; tmprdn != NULLRDN &&
760 tmprdn->rdn_next != NULLRDN;
761 tmprdn = tmprdn->rdn_next )
763 if ( tmprdn != NULLRDN )
764 tmprdn->rdn_next = newrdn;
769 } while ( morerdncomps );
772 dn = dn_comp_new( rdn );
773 dn->dn_parent = save;
774 } while ( str != NULL && *str != '\0' );
777 Debug( LDAP_DEBUG_TRACE, "ldap_str2dn OK\n", 0, 0, 0 );
784 static void de_t61( char *s, int t61mark )
792 if ( strncasecmp( s, T61, T61LEN) == 0 ) {
810 /* reverse solidus character itself */
817 else if ( c >= 'A' && c <= 'F' )
819 else if ( c >= 'a' && c <= 'f' )
829 else if ( c >= 'A' && c <= 'F' )
831 else if ( c >= 'a' && c <= 'f' )
853 bv_asn2pe( struct berval *bv )
858 if (( ps = ps_alloc(str_open)) == NULLPS || str_setup( ps, bv->bv_val,
859 bv->bv_len, 0 ) == NOTOK ) {
860 Debug( LDAP_DEBUG_TRACE, "bv_asn2pe: ps_alloc failed\n",
866 if ( ps->ps_errno != PS_ERR_NONE ) {
867 Debug( LDAP_DEBUG_TRACE, "bv_asn2pe: ps2pe failed %s\n",
868 ps_error(ps->ps_errno), 0, 0 );
869 if ( pe != NULLPE ) {
880 bv_octet2AttrV( struct berval *bv )
885 if ( av == NULLAttrV ) {
889 if (( av->av_struct = (caddr_t) str2prim( bv->bv_val, bv->bv_len,
890 PE_CLASS_UNIV, PE_PRIM_OCTS )) == NULL ) {
901 bv_asn2AttrV( struct berval *bv )
906 if ( av == NULLAttrV ) {
910 if (( av->av_struct = (caddr_t) bv_asn2pe( bv )) == NULL ) {
921 ldap_strdn2AttrV( char *dnstr )
926 if (( dn = ldap_str2dn( dnstr )) == NULL ) {
931 if ( av == NULLAttrV ) {
936 av->av_struct = (caddr_t)dn;
937 av->av_syntax = ldap_dn_syntax;
942 ldap_str2rdn( char *rdnstr )
947 if ( (dn = ldap_str2dn( rdnstr )) == NULL ) {
951 if ( (rdn = rdn_cpy( dn->dn_rdn )) == NULL ) {
961 ldap_str_at2AttrV( char *str, AttributeType type )
964 AttributeValue str_at2AttrV();
966 Debug( LDAP_DEBUG_TRACE, "ldap_str_at2AttrV str (%s) type (%s)\n", str,
967 type->oa_ot.ot_name, 0 );
969 if ( type->oa_syntax == ldap_rts_cred_syntax ||
970 type->oa_syntax == ldap_mtai_syntax ||
971 type->oa_syntax == ldap_acl_syntax ||
972 type->oa_syntax == ldap_mailbox_syntax ||
973 type->oa_syntax == ldap_caseignorelist_syntax ||
974 type->oa_syntax == ldap_certif_syntax ||
975 type->oa_syntax == ldap_iattr_syntax ||
976 type->oa_syntax == ldap_telex_syntax ||
977 type->oa_syntax == ldap_deliverymethod_syntax ||
978 type->oa_syntax == ldap_facsimileTelephoneNumber_syntax ||
979 type->oa_syntax == ldap_presentationAddress_syntax ||
980 type->oa_syntax == ldap_teletexTerminalIdentifier_syntax ||
981 type->oa_syntax == ldap_searchGuide_syntax ||
982 type->oa_syntax == ldap_dLSubmitPermission_syntax ||
983 type->oa_syntax == ldap_rtl_syntax ) {
986 res = (char *) malloc( max( 2 * strlen( str ), (size_t) 10 ) );
989 for ( s = str; *s; s++ ) {
997 sprintf( r, "\\%02x", *s & 0xff );
1008 Debug( LDAP_DEBUG_TRACE, "ldap_str_at2AttrV returning (%s)\n", res,
1011 return( str_at2AttrV( res, type ) );
1015 ldap_str2AttrV( char *value, short syntax )
1017 if ( syntax == ldap_dn_syntax ) {
1018 return( ldap_strdn2AttrV( value ) );
1020 return( str2AttrV( value, syntax ) );
1026 syntax_is_string( short syntax )
1029 * this code depends on the order and nunber of strings that are in
1030 * the ISODE file lib/syntax/x500/string.c
1032 return ( syntax >= ldap_caseexactstring_syntax &&
1033 syntax <= ldap_caseexactstring_syntax + 8 );