3 * Copyright (c) 1990 Regents of the University of Michigan.
6 * Redistribution and use in source and binary forms are permitted
7 * provided that this notice is preserved and that due credit is given
8 * to the University of Michigan at Ann Arbor. The name of the University
9 * may not be used to endorse or promote products derived from this
10 * software without specific prior written permission. This software
11 * is provided ``as is'' without express or implied warranty.
19 #include <ac/socket.h>
20 #include <ac/string.h>
22 #include <quipu/commonarg.h>
23 #include <quipu/attrvalue.h>
24 #include <quipu/ds_error.h>
25 #include <quipu/ds_search.h>
26 #include <quipu/dap2.h>
27 #include <quipu/dua.h>
28 extern oid_table_attr *name2attr( char * );
29 /*extern AttributeValue str_at2AttrV( char *, IF_AttributeType * );*/
32 #include "../../libraries/liblber/lber-int.h" /* get struct berelement */
36 short ldap_photo_syntax;
37 short ldap_jpeg_syntax;
38 short ldap_jpeg_nonfile_syntax;
39 short ldap_audio_syntax;
41 short ldap_postaladdress_syntax;
42 short ldap_acl_syntax;
43 short ldap_mtai_syntax;
44 short ldap_rts_cred_syntax;
45 short ldap_rtl_syntax;
46 short ldap_mailbox_syntax;
47 short ldap_caseignorelist_syntax;
48 short ldap_caseexactstring_syntax;
49 short ldap_certif_syntax;
50 short ldap_iattr_syntax;
51 short ldap_telex_syntax;
52 short ldap_octetstring_syntax;
53 short ldap_deliverymethod_syntax;
54 short ldap_facsimileTelephoneNumber_syntax;
55 short ldap_presentationAddress_syntax;
56 short ldap_teletexTerminalIdentifier_syntax;
57 short ldap_searchGuide_syntax;
58 short ldap_dLSubmitPermission_syntax;
60 static void de_t61( char *s, int t61mark );
61 static int syntax_is_string( short syntax );
64 get_one_syntax( char *attrib, int required )
68 if ( (p = name2attr( attrib )) != (oid_table_attr *) 0 )
69 return( p->oa_syntax );
74 Debug( LDAP_DEBUG_ANY, "name2attr (%s) failed - exiting\n", attrib,
83 Debug( LDAP_DEBUG_TRACE, "get_syntaxes\n", 0, 0, 0 );
85 ldap_photo_syntax = get_one_syntax( "photo", 0 );
86 ldap_jpeg_syntax = get_one_syntax( "jpegPhoto", 0 );
87 ldap_jpeg_nonfile_syntax = str2syntax( "jpeg" );
88 ldap_audio_syntax = get_one_syntax( "audio", 0 );
89 ldap_postaladdress_syntax = get_one_syntax( "postaladdress", 0 );
90 ldap_dn_syntax = get_one_syntax( "aliasedObjectName", 1 );
91 ldap_acl_syntax = get_one_syntax( "acl", 0 );
92 ldap_mtai_syntax = get_one_syntax( "mTAInfo", 0 );
93 ldap_rts_cred_syntax= get_one_syntax( "initiatingRTSCredentials", 0 );
94 ldap_rtl_syntax= get_one_syntax( "routingTreeList", 0 );
95 ldap_mailbox_syntax = get_one_syntax( "otherMailbox", 0 );
96 ldap_caseignorelist_syntax = str2syntax( "CaseIgnoreList" );
97 ldap_caseexactstring_syntax = str2syntax( "caseexactstring" );
98 ldap_octetstring_syntax = str2syntax( "OctetString" );
99 ldap_deliverymethod_syntax = str2syntax( "DeliveryMethod" );
100 ldap_iattr_syntax = get_one_syntax( "inheritedAttribute", 0 );
101 ldap_certif_syntax = get_one_syntax( "userCertificate", 0 );
102 ldap_telex_syntax = get_one_syntax( "telexNumber", 0 );
103 ldap_facsimileTelephoneNumber_syntax =
104 get_one_syntax( "facsimileTelephoneNumber", 0 );
105 ldap_presentationAddress_syntax =
106 get_one_syntax( "presentationAddress", 0 );
107 ldap_teletexTerminalIdentifier_syntax =
108 get_one_syntax( "teletexTerminalIdentifier", 0 );
109 ldap_searchGuide_syntax = get_one_syntax( "searchGuide", 0 );
110 ldap_dLSubmitPermission_syntax =
111 get_one_syntax( "mhsDLSubmitPermissions", 0 );
113 certif_init(); /* initialize certificate syntax handler */
117 * From RFC 1779 "A String Representation of Distinguished Names"
119 * Key Attribute (X.520 keys)
120 * ------------------------------
123 * ST StateOrProvinceName
125 * OU OrganizationalUnitName
127 * STREET StreetAddress
130 * Table 1: Standardised Keywords
132 * There is an escape mechanism from the normal user oriented form, so
133 * that this syntax may be used to print any valid distinguished name.
135 * 1. Attributes types are represented in a (big-endian) dotted
136 * notation. (e.g., OID.2.6.53).
142 char *key /* return key, caller allocated */
147 x = attr2name_aux ( at );
151 } else if ( isdigit ( (unsigned char) *x ) ) {
152 sprintf ( key, "OID.%s", x );
154 } else if (strcasecmp(x,"commonName")==0) {
156 } else if (strcasecmp(x,"localityName")==0) {
158 } else if (strcasecmp(x,"stateOrProvinceName")==0) {
160 } else if (strcasecmp(x,"organizationName")==0) {
162 } else if (strcasecmp(x,"organizationalUnitName")==0) {
164 } else if (strcasecmp(x,"countryName")==0) {
166 } else if (strcasecmp(x,"streetAddress")==0) {
173 #define SEPARATOR(c) ((c) == ',' || (c) == ';')
174 #define SPACE(c) ((c) == ' ' || (c) == '\n')
192 if ( dn->dn_parent != NULLDN ) {
193 dn_print_real( ps, dn->dn_parent, format );
194 ps_print( ps, ", " );
197 if ( (rps = ps_alloc( str_open )) == NULLPS )
199 if ( str_setup( rps, NULLCP, 0, 0 ) == NOTOK )
203 for ( rdn = dn->dn_rdn; rdn != NULLRDN; rdn = rdn->rdn_next ) {
207 ps_print( ps, " + " );
209 attr_key_rfc1779 ( rdn->rdn_at, key );
211 ps_print ( ps, key );
214 if ( rdn->rdn_at->oa_syntax == ldap_dn_syntax ) {
215 dn_print_real( rps, (DN) rdn->rdn_av.av_struct,
218 value = rps->ps_base;
220 AttrV_print( rps, &rdn->rdn_av, EDBOUT );
222 if ( rps->ps_ptr - rps->ps_base >= 5 &&
223 strncmp( rps->ps_base, "{ASN}", 5 ) == 0 ) {
225 SAFEMEMCPY( rps->ps_base + 1, rps->ps_base + 5,
226 rps->ps_ptr - rps->ps_base - 4 );
228 value = rps->ps_base;
233 * ,+="\\\n all go in quotes. " and \\ need to
234 * be preceeded by \\.
237 if ( strpbrk( value, ",+=\"\\\n" ) != NULL || SPACE( value[0] )
238 || SPACE( value[max( strlen(value) - 1, (size_t) 0 )] ) ) {
242 ps_print( ps, "\"" );
245 for ( p = value; *p != '\0'; p++ ) {
246 if ( *p == '"' || *p == '\\' ) {
250 if ( specialcount > 0 ) {
251 tmp = smalloc( strlen( value ) + specialcount
253 for ( p = value, t = tmp; *p != '\0'; p++ ) {
267 ps_print( ps, value );
270 ps_print( ps, "\"" );
272 ps_print( ps, value );
275 rps->ps_ptr = rps->ps_base;
287 DN base, /* if non-NULL, subsitute '*' for base (for CLDAP) */
294 Debug( LDAP_DEBUG_TRACE, "ldap_dn_print\n", 0, 0, 0 );
297 if ( base != NULLDN && dn != NULL ) {
298 for ( tmpdn = dn; base != NULLDN && tmpdn != NULLDN;
299 base = base->dn_parent, tmpdn = tmpdn->dn_parent ) {
300 if ( dn_comp_cmp( base, tmpdn ) == NOTOK ) {
304 if (( addstar = ( base == NULLDN && tmpdn != NULL ))) {
309 dn_print_real( ps, dn, format );
311 ps_print( ps, ", *" );
319 DN base /* if non-NULL, subsitute '*' for base (for CLDAP) */
325 Debug( LDAP_DEBUG_TRACE, "encode_dn\n", 0, 0, 0 );
327 if ( (ps = ps_alloc( str_open )) == NULLPS )
329 if ( str_setup( ps, NULLCP, 0, 0 ) == NOTOK )
332 ldap_dn_print( ps, dn, base, EDBOUT );
335 rc = ber_printf( ber, "s", ps->ps_base );
343 put_jpeg_value( BerElement *ber, AttributeValue av )
348 Debug( LDAP_DEBUG_TRACE, "put_jpeg_value\n", 0, 0, 0 );
350 if (av->av_syntax == AV_FILE)
351 pe = (PE) (((struct file_syntax *) av->av_struct)->
354 pe = (PE) av->av_struct;
356 Debug( LDAP_DEBUG_ARGS,
357 "put_jpeg_value: pe_class %x, pe_form %x, pe_id %x\n",
358 pe->pe_class, pe->pe_form, pe->pe_id );
360 if ( (pe->pe_class != PE_CLASS_UNIV && pe->pe_class != PE_CLASS_CONT)
361 || pe->pe_form != PE_FORM_PRIM || pe->pe_id != PE_PRIM_OCTS ) {
362 Debug( LDAP_DEBUG_ANY, "put_jpeg_value: unknown type\n", 0,
367 if ( pe_pullup( pe ) == NOTOK ) {
368 Debug( LDAP_DEBUG_ANY, "put_jpeg_value: cannot pullup\n", 0,
373 len = ps_get_abs( pe );
375 Debug( LDAP_DEBUG_ARGS, "put_jeg_value: ber_printf %d bytes\n",
377 if ( ber_printf( ber, "o", (char *) pe->pe_prim, len ) == -1 ) {
378 Debug( LDAP_DEBUG_ANY, "put_jpeg_value: ber_printf failed\n",
387 put_audio_value( BerElement *ber, AttributeValue av )
393 Debug( LDAP_DEBUG_TRACE, "put_audio_value\n", 0, 0, 0 );
395 qb = (struct qbuf *) (((struct file_syntax *)
396 av->av_struct)->fs_attr->av_struct);
399 for ( p = qb->qb_forw; p != qb; p = p->qb_forw ) {
403 if ( (buf = (char *) malloc( len )) == NULL )
407 for ( p = qb->qb_forw; p != qb; p = p->qb_forw ) {
408 SAFEMEMCPY( buf + len, p->qb_data, p->qb_len );
412 Debug( LDAP_DEBUG_ARGS, "put_audio_value: ber_printf %d bytes\n",
415 if ( (rc = ber_printf( ber, "o", buf, len )) == -1 )
416 Debug( LDAP_DEBUG_ANY, "put_audio_value: ber_printf failed\n",
425 put_photo_value( BerElement *ber, AttributeValue av )
430 char *faxparamset = "\000\300\000\000";
433 Debug( LDAP_DEBUG_TRACE, "put_photo_value\n", 0, 0, 0 );
435 pe = (PE) (((struct file_syntax *) av->av_struct)->fs_attr->av_struct);
437 /* old bit string-like format - only handle this for now */
438 if ( pe->pe_class == PE_CLASS_UNIV && pe->pe_form == PE_FORM_PRIM
439 && pe->pe_id == PE_PRIM_BITS ) {
440 len = ps_get_abs( pe );
441 Debug( LDAP_DEBUG_ARGS, "put_photo_val: ber_printf %d bytes\n",
443 if (( phber = der_alloc()) == NULL ) {
444 Debug( LDAP_DEBUG_ANY, "der_alloc failed\n", 0, 0, 0 );
447 if ( ber_printf( phber, "t{[tB]{B}}", 0xA3, 0x81, faxparamset,
448 31, (char *)pe->pe_prim, len * 8 ) == -1 ) {
449 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
450 ber_free( phber, 1 );
453 if ( ber_printf( ber, "o", phber->ber_buf, phber->ber_ptr
454 - phber->ber_buf ) == -1 ) {
455 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
456 ber_free( phber, 1 );
459 ber_free( phber, 1 );
462 * try just writing this into a PS and sending it along
464 ps_len_strategy = PS_LEN_LONG;
465 if ( (ps = ps_alloc( str_open )) == NULLPS )
467 if ( str_setup( ps, NULLCP, 0, 0 ) == NOTOK ||
468 pe2ps( ps, pe ) == NOTOK ) {
473 len = ps->ps_ptr - ps->ps_base;
474 Debug( LDAP_DEBUG_ARGS, "put_photo_val: ber_printf %d bytes\n",
476 if ( ber_printf( ber, "o", (char *) ps->ps_base, len ) == -1 ) {
477 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
498 Debug( LDAP_DEBUG_TRACE, "put_values\n", 0, 0, 0 );
500 for ( av = vals; av != NULLAV; av = av->avseq_next ) {
501 if ( syntax == ldap_jpeg_syntax ||
502 syntax == ldap_jpeg_nonfile_syntax ) {
503 if ( put_jpeg_value( ber, &av->avseq_av ) == -1 )
505 } else if ( syntax == ldap_photo_syntax ) {
506 if ( put_photo_value( ber, &av->avseq_av ) == -1 )
508 } else if ( syntax == ldap_audio_syntax ) {
509 if ( put_audio_value( ber, &av->avseq_av ) == -1 )
511 } else if ( syntax == ldap_dn_syntax ) {
512 if ( encode_dn( ber, (DN) av->avseq_av.av_struct,
515 } else if ( syntax > AV_WRITE_FILE ) {
516 struct file_syntax *fsyntax;
518 fsyntax = (struct file_syntax *) av->avseq_av.av_struct;
520 ps->ps_ptr = ps->ps_base;
521 AttrV_print( ps, fsyntax->fs_attr, EDBOUT );
524 if ( ber_printf( ber, "o", ps->ps_base,
525 ps->ps_ptr - ps->ps_base ) == -1 )
528 ps->ps_ptr = ps->ps_base;
529 AttrV_print( ps, &av->avseq_av, EDBOUT );
531 de_t61( ps->ps_base, 0 );
533 if ( syntax_is_string( av->avseq_av.av_syntax ) &&
534 *ps->ps_base == '\0' ) {
536 * If this is a zero-length string, make it
537 * a single blank (this is gross, but it works
538 * around a dsap library bug).
540 Debug( LDAP_DEBUG_ANY,
541 "put_values: replaced zero-length string with single blank\n", 0, 0, 0 );
544 strvalue = ps->ps_base;
546 if ( ber_printf( ber, "s", strvalue ) == -1 )
555 encode_attrs( BerElement *ber, Attr_Sequence as )
559 Debug( LDAP_DEBUG_TRACE, "encode_attrs\n", 0, 0, 0 );
561 if ( (ps = ps_alloc( str_open )) == NULLPS )
563 if ( str_setup( ps, NULLCP, 0, 0 ) == NOTOK )
567 if ( ber_printf( ber, "t{", ldap_compat == 20 ? OLD_LBER_SEQUENCE :
568 LBER_SEQUENCE ) == -1 ) {
570 if ( ber_printf( ber, "{" ) == -1 ) {
576 while ( as != NULLATTR ) {
577 ps->ps_ptr = ps->ps_base;
578 AttrT_print( ps, as->attr_type, EDBOUT );
582 if ( ber_printf( ber, "t{st[", ldap_compat == 20 ?
583 OLD_LBER_SEQUENCE : LBER_SEQUENCE, ps->ps_base,
584 ldap_compat == 20 ? OLD_LBER_SET : LBER_SET ) == -1 ) {
586 if ( ber_printf( ber, "{s[", ps->ps_base ) == -1 ) {
592 put_values( ber, ps, as->attr_type->oa_syntax, as->attr_value );
594 if ( ber_printf( ber, "]}" ) == -1 ) {
603 if ( ber_printf( ber, "}" ) == -1 )
610 trim_trailing_spaces( char *s )
625 ldap_str2dn( char *str )
628 RDN rdn, newrdn, tmprdn;
631 char *type, *value, *savestr;
634 Debug( LDAP_DEBUG_TRACE, "ldap_str2dn\n", 0, 0, 0 );
636 savestr = str = strdup( str );
646 while ( *str == ' ' || *str == '\n' )
649 while ( *str != '\0' && *str != '=' )
651 if ( *str == '\0' ) {
653 Debug( LDAP_DEBUG_ARGS, "no =\n", 0, 0, 0 );
657 if ( strncmp( type, "OID.", 4 ) == 0 )
669 /* break or return out */
670 while ( state != ENDVALUE ) {
673 if ( state == BEGINVALUE ) {
676 } else if ( state == INQUOTE ) {
681 Debug( LDAP_DEBUG_ARGS,
682 "quote state %d\n", state,
691 if ( state == INVALUE ) {
693 } else if ( state == INQUOTE ) {
697 Debug( LDAP_DEBUG_ARGS,
698 "comma state %d\n", state,
706 if ( state == BEGINVALUE ) {
723 if ( state == BEGINVALUE )
730 while ( SPACE( *str ) )
737 if ( SEPARATOR( *str ) )
743 trim_trailing_spaces( type );
744 if ( (at = str2AttrT( type )) == NULLAttrT ) {
747 Debug( LDAP_DEBUG_ARGS, "bad type (%s)\n",
749 return( NULLDN ); /* LDAP_UNDEFINED_TYPE */
752 if ( (av = ldap_str2AttrV( value, at->oa_syntax ))
756 Debug( LDAP_DEBUG_ARGS, "bad val\n", 0, 0, 0 );
757 return( NULLDN ); /* LDAP_INVALID_SYNTAX */
760 newrdn = rdn_comp_new( at, av );
762 /* add it to the list */
763 for ( tmprdn = rdn; tmprdn != NULLRDN &&
764 tmprdn->rdn_next != NULLRDN;
765 tmprdn = tmprdn->rdn_next )
767 if ( tmprdn != NULLRDN )
768 tmprdn->rdn_next = newrdn;
773 } while ( morerdncomps );
776 dn = dn_comp_new( rdn );
777 dn->dn_parent = save;
778 } while ( str != NULL && *str != '\0' );
781 Debug( LDAP_DEBUG_TRACE, "ldap_str2dn OK\n", 0, 0, 0 );
789 de_t61( char *s, int t61mark )
798 if ( strncasecmp( s, T61, T61LEN) == 0 ) {
816 /* reverse solidus character itself */
823 else if ( c >= 'A' && c <= 'F' )
825 else if ( c >= 'a' && c <= 'f' )
835 else if ( c >= 'A' && c <= 'F' )
837 else if ( c >= 'a' && c <= 'f' )
859 bv_asn2pe( struct berval *bv )
864 if (( ps = ps_alloc(str_open)) == NULLPS || str_setup( ps, bv->bv_val,
865 bv->bv_len, 0 ) == NOTOK ) {
866 Debug( LDAP_DEBUG_TRACE, "bv_asn2pe: ps_alloc failed\n",
872 if ( ps->ps_errno != PS_ERR_NONE ) {
873 Debug( LDAP_DEBUG_TRACE, "bv_asn2pe: ps2pe failed %s\n",
874 ps_error(ps->ps_errno), 0, 0 );
875 if ( pe != NULLPE ) {
886 bv_octet2AttrV( struct berval *bv )
891 if ( av == NULLAttrV ) {
895 if (( av->av_struct = (caddr_t) str2prim( bv->bv_val, bv->bv_len,
896 PE_CLASS_UNIV, PE_PRIM_OCTS )) == NULL ) {
907 bv_asn2AttrV( struct berval *bv )
912 if ( av == NULLAttrV ) {
916 if (( av->av_struct = (caddr_t) bv_asn2pe( bv )) == NULL ) {
927 ldap_strdn2AttrV( char *dnstr )
932 if (( dn = ldap_str2dn( dnstr )) == NULL ) {
937 if ( av == NULLAttrV ) {
942 av->av_struct = (caddr_t)dn;
943 av->av_syntax = ldap_dn_syntax;
948 ldap_str2rdn( char *rdnstr )
953 if ( (dn = ldap_str2dn( rdnstr )) == NULL ) {
957 if ( (rdn = rdn_cpy( dn->dn_rdn )) == NULL ) {
967 ldap_str_at2AttrV( char *str, AttributeType type )
971 Debug( LDAP_DEBUG_TRACE, "ldap_str_at2AttrV str (%s) type (%s)\n", str,
972 type->oa_ot.ot_name, 0 );
974 if ( type->oa_syntax == ldap_rts_cred_syntax ||
975 type->oa_syntax == ldap_mtai_syntax ||
976 type->oa_syntax == ldap_acl_syntax ||
977 type->oa_syntax == ldap_mailbox_syntax ||
978 type->oa_syntax == ldap_caseignorelist_syntax ||
979 type->oa_syntax == ldap_certif_syntax ||
980 type->oa_syntax == ldap_iattr_syntax ||
981 type->oa_syntax == ldap_telex_syntax ||
982 type->oa_syntax == ldap_deliverymethod_syntax ||
983 type->oa_syntax == ldap_facsimileTelephoneNumber_syntax ||
984 type->oa_syntax == ldap_presentationAddress_syntax ||
985 type->oa_syntax == ldap_teletexTerminalIdentifier_syntax ||
986 type->oa_syntax == ldap_searchGuide_syntax ||
987 type->oa_syntax == ldap_dLSubmitPermission_syntax ||
988 type->oa_syntax == ldap_rtl_syntax ) {
991 res = (char *) malloc( max( 2 * strlen( str ), (size_t) 10 ) );
994 for ( s = str; *s; s++ ) {
1002 sprintf( r, "\\%02x", *s & 0xff );
1013 Debug( LDAP_DEBUG_TRACE, "ldap_str_at2AttrV returning (%s)\n", res,
1016 return( str_at2AttrV( res, type ) );
1020 ldap_str2AttrV( char *value, short syntax )
1022 if ( syntax == ldap_dn_syntax ) {
1023 return( ldap_strdn2AttrV( value ) );
1025 return( str2AttrV( value, syntax ) );
1031 syntax_is_string( short syntax )
1034 * this code depends on the order and nunber of strings that are in
1035 * the ISODE file lib/syntax/x500/string.c
1037 return ( syntax >= ldap_caseexactstring_syntax &&
1038 syntax <= ldap_caseexactstring_syntax + 8 );