1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * 3*0Sstevel@tonic-gate * Portions Copyright %G% Sun Microsystems, Inc. 4*0Sstevel@tonic-gate * All Rights Reserved 5*0Sstevel@tonic-gate * 6*0Sstevel@tonic-gate */ 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 9*0Sstevel@tonic-gate 10*0Sstevel@tonic-gate /* 11*0Sstevel@tonic-gate * Copyright (c) 1994 Regents of the University of Michigan. 12*0Sstevel@tonic-gate * All rights reserved. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * getdn.c 15*0Sstevel@tonic-gate */ 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gate #ifndef lint 18*0Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; 19*0Sstevel@tonic-gate #endif 20*0Sstevel@tonic-gate 21*0Sstevel@tonic-gate #include <stdio.h> 22*0Sstevel@tonic-gate #include <ctype.h> 23*0Sstevel@tonic-gate #include <string.h> 24*0Sstevel@tonic-gate #include <stdlib.h> /* malloc(), realloc(), calloc() for Solaris */ 25*0Sstevel@tonic-gate #ifdef MACOS 26*0Sstevel@tonic-gate #include <stdlib.h> 27*0Sstevel@tonic-gate #include "macos.h" 28*0Sstevel@tonic-gate #else /* MACOS */ 29*0Sstevel@tonic-gate #if defined( DOS ) || defined( _WIN32 ) 30*0Sstevel@tonic-gate #include <malloc.h> 31*0Sstevel@tonic-gate #include "msdos.h" 32*0Sstevel@tonic-gate #else /* DOS */ 33*0Sstevel@tonic-gate #include <sys/types.h> 34*0Sstevel@tonic-gate #include <sys/socket.h> 35*0Sstevel@tonic-gate #endif /* DOS */ 36*0Sstevel@tonic-gate #endif /* MACOS */ 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate #include "lber.h" 39*0Sstevel@tonic-gate #include "ldap.h" 40*0Sstevel@tonic-gate #include "ldap-private.h" 41*0Sstevel@tonic-gate #include "ldap-int.h" 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate char * 44*0Sstevel@tonic-gate ldap_get_dn( LDAP *ld, LDAPMessage *entry ) 45*0Sstevel@tonic-gate { 46*0Sstevel@tonic-gate char *dn; 47*0Sstevel@tonic-gate BerElement tmp; 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 181, "ldap_get_dn\n"), 0, 0, 0 ); 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate if ( entry == NULL ) { 52*0Sstevel@tonic-gate ld->ld_errno = LDAP_PARAM_ERROR; 53*0Sstevel@tonic-gate return( NULL ); 54*0Sstevel@tonic-gate } 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate tmp = *entry->lm_ber; /* struct copy */ 57*0Sstevel@tonic-gate if ( ber_scanf( &tmp, "{a", &dn ) == LBER_ERROR ) { 58*0Sstevel@tonic-gate ld->ld_errno = LDAP_DECODING_ERROR; 59*0Sstevel@tonic-gate return( NULL ); 60*0Sstevel@tonic-gate } 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate return( dn ); 63*0Sstevel@tonic-gate } 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate char * 66*0Sstevel@tonic-gate ldap_dn2ufn( char *dn ) 67*0Sstevel@tonic-gate { 68*0Sstevel@tonic-gate char *p, *ufn, *r; 69*0Sstevel@tonic-gate int state; 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 182, "ldap_dn2ufn\n"), 0, 0, 0 ); 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate if ( ldap_is_dns_dn( dn ) || ( p = strchr( dn, '=' )) == NULL ) 74*0Sstevel@tonic-gate return( strdup( dn )); 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate ufn = strdup( ++p ); 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate #define INQUOTE 1 79*0Sstevel@tonic-gate #define OUTQUOTE 2 80*0Sstevel@tonic-gate state = OUTQUOTE; 81*0Sstevel@tonic-gate for ( p = ufn, r = ufn; *p; p++ ) { 82*0Sstevel@tonic-gate switch ( *p ) { 83*0Sstevel@tonic-gate case '\\': 84*0Sstevel@tonic-gate if ( *++p == '\0' ) 85*0Sstevel@tonic-gate p--; 86*0Sstevel@tonic-gate else { 87*0Sstevel@tonic-gate *r++ = '\\'; 88*0Sstevel@tonic-gate *r++ = *p; 89*0Sstevel@tonic-gate } 90*0Sstevel@tonic-gate break; 91*0Sstevel@tonic-gate case '"': 92*0Sstevel@tonic-gate if ( state == INQUOTE ) 93*0Sstevel@tonic-gate state = OUTQUOTE; 94*0Sstevel@tonic-gate else 95*0Sstevel@tonic-gate state = INQUOTE; 96*0Sstevel@tonic-gate *r++ = *p; 97*0Sstevel@tonic-gate break; 98*0Sstevel@tonic-gate case ';': 99*0Sstevel@tonic-gate case ',': 100*0Sstevel@tonic-gate if ( state == OUTQUOTE ) 101*0Sstevel@tonic-gate *r++ = ','; 102*0Sstevel@tonic-gate else 103*0Sstevel@tonic-gate *r++ = *p; 104*0Sstevel@tonic-gate break; 105*0Sstevel@tonic-gate case '=': 106*0Sstevel@tonic-gate if ( state == INQUOTE ) 107*0Sstevel@tonic-gate *r++ = *p; 108*0Sstevel@tonic-gate else { 109*0Sstevel@tonic-gate char *rsave = r; 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate *r-- = '\0'; 112*0Sstevel@tonic-gate while ( !isspace( *r ) && *r != ';' 113*0Sstevel@tonic-gate && *r != ',' && r > ufn ) 114*0Sstevel@tonic-gate r--; 115*0Sstevel@tonic-gate r++; 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate if ( strcasecmp( r, "c" ) 118*0Sstevel@tonic-gate && strcasecmp( r, "o" ) 119*0Sstevel@tonic-gate && strcasecmp( r, "ou" ) 120*0Sstevel@tonic-gate && strcasecmp( r, "st" ) 121*0Sstevel@tonic-gate && strcasecmp( r, "l" ) 122*0Sstevel@tonic-gate && strcasecmp( r, "cn" ) ) { 123*0Sstevel@tonic-gate r = rsave; 124*0Sstevel@tonic-gate *r++ = '='; 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate } 127*0Sstevel@tonic-gate break; 128*0Sstevel@tonic-gate default: 129*0Sstevel@tonic-gate *r++ = *p; 130*0Sstevel@tonic-gate break; 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate *r = '\0'; 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate return( ufn ); 136*0Sstevel@tonic-gate } 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate char ** 139*0Sstevel@tonic-gate ldap_explode_dns( char *dn ) 140*0Sstevel@tonic-gate { 141*0Sstevel@tonic-gate int ncomps, maxcomps; 142*0Sstevel@tonic-gate char *s; 143*0Sstevel@tonic-gate char **rdns; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate if ( (rdns = (char **) malloc( 8 * sizeof(char *) )) == NULL ) { 146*0Sstevel@tonic-gate return( NULL ); 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate maxcomps = 8; 150*0Sstevel@tonic-gate ncomps = 0; 151*0Sstevel@tonic-gate for ( s = strtok( dn, "@." ); s != NULL; s = strtok( NULL, "@." ) ) { 152*0Sstevel@tonic-gate if ( ncomps == maxcomps ) { 153*0Sstevel@tonic-gate maxcomps *= 2; 154*0Sstevel@tonic-gate if ( (rdns = (char **) realloc( rdns, maxcomps * 155*0Sstevel@tonic-gate sizeof(char *) )) == NULL ) { 156*0Sstevel@tonic-gate return( NULL ); 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate rdns[ncomps++] = strdup( s ); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate rdns[ncomps] = NULL; 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate return( rdns ); 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate char ** 167*0Sstevel@tonic-gate ldap_explode_dn( char *dn, int notypes ) 168*0Sstevel@tonic-gate { 169*0Sstevel@tonic-gate char *p, *q, *rdnstart, **rdns = NULL; 170*0Sstevel@tonic-gate int state, count = 0, endquote; 171*0Sstevel@tonic-gate ssize_t len; 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 183, "ldap_explode_dn\n"), 0, 0, 0 ); 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate if ( ldap_is_dns_dn( dn ) ) { 176*0Sstevel@tonic-gate return( ldap_explode_dns( dn ) ); 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate rdnstart = dn; 180*0Sstevel@tonic-gate p = dn-1; 181*0Sstevel@tonic-gate state = OUTQUOTE; 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate do { 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate ++p; 186*0Sstevel@tonic-gate switch ( *p ) { 187*0Sstevel@tonic-gate case '\\': 188*0Sstevel@tonic-gate if ( *++p == '\0' ) 189*0Sstevel@tonic-gate p--; 190*0Sstevel@tonic-gate break; 191*0Sstevel@tonic-gate case '"': 192*0Sstevel@tonic-gate if ( state == INQUOTE ) 193*0Sstevel@tonic-gate state = OUTQUOTE; 194*0Sstevel@tonic-gate else 195*0Sstevel@tonic-gate state = INQUOTE; 196*0Sstevel@tonic-gate break; 197*0Sstevel@tonic-gate case ';': 198*0Sstevel@tonic-gate case ',': 199*0Sstevel@tonic-gate case '\0': 200*0Sstevel@tonic-gate if ( state == OUTQUOTE ) { 201*0Sstevel@tonic-gate ++count; 202*0Sstevel@tonic-gate if ( rdns == NULL ) { 203*0Sstevel@tonic-gate if (( rdns = (char **)malloc( 8 204*0Sstevel@tonic-gate * sizeof( char *))) == NULL ) 205*0Sstevel@tonic-gate return( NULL ); 206*0Sstevel@tonic-gate } else if ( count >= 8 ) { 207*0Sstevel@tonic-gate if (( rdns = (char **)realloc( rdns, 208*0Sstevel@tonic-gate (count+1) * sizeof( char *))) 209*0Sstevel@tonic-gate == NULL ) 210*0Sstevel@tonic-gate return( NULL ); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate rdns[ count ] = NULL; 213*0Sstevel@tonic-gate endquote = 0; 214*0Sstevel@tonic-gate if ( notypes ) { 215*0Sstevel@tonic-gate for ( q = rdnstart; 216*0Sstevel@tonic-gate q < p && *q != '='; ++q ) { 217*0Sstevel@tonic-gate ; 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate if ( q < p ) { 220*0Sstevel@tonic-gate rdnstart = ++q; 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate if ( *rdnstart == '"' ) { 223*0Sstevel@tonic-gate ++rdnstart; 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate if ( *(p-1) == '"' ) { 227*0Sstevel@tonic-gate endquote = 1; 228*0Sstevel@tonic-gate --p; 229*0Sstevel@tonic-gate } 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate len = p - rdnstart; 233*0Sstevel@tonic-gate if (( rdns[ count-1 ] = (char *)calloc( 1, 234*0Sstevel@tonic-gate len + 1 )) != NULL ) { 235*0Sstevel@tonic-gate (void) SAFEMEMCPY( rdns[ count-1 ], rdnstart, 236*0Sstevel@tonic-gate len ); 237*0Sstevel@tonic-gate rdns[ count-1 ][ len ] = '\0'; 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate /* 241*0Sstevel@tonic-gate * Don't forget to increment 'p' back to where 242*0Sstevel@tonic-gate * it should be. If we don't, then we will 243*0Sstevel@tonic-gate * never get past an "end quote." 244*0Sstevel@tonic-gate */ 245*0Sstevel@tonic-gate if ( endquote == 1 ) 246*0Sstevel@tonic-gate p++; 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate rdnstart = *p ? p + 1 : p; 249*0Sstevel@tonic-gate while ( isspace( *rdnstart )) 250*0Sstevel@tonic-gate ++rdnstart; 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate break; 253*0Sstevel@tonic-gate } 254*0Sstevel@tonic-gate } while ( *p ); 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate return( rdns ); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate int 261*0Sstevel@tonic-gate ldap_is_dns_dn( char *dn ) 262*0Sstevel@tonic-gate { 263*0Sstevel@tonic-gate return( dn[ 0 ] != '\0' && strchr( dn, '=' ) == NULL && 264*0Sstevel@tonic-gate strchr( dn, ',' ) == NULL ); 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate #if defined( ultrix ) || defined( NeXT ) 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate char *strdup( char *s ) 271*0Sstevel@tonic-gate { 272*0Sstevel@tonic-gate char *p; 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate if ( (p = (char *) malloc( strlen( s ) + 1 )) == NULL ) 275*0Sstevel@tonic-gate return( NULL ); 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate strcpy( p, s ); 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate return( p ); 280*0Sstevel@tonic-gate } 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate #endif /* ultrix */ 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate /* 286*0Sstevel@tonic-gate * Convert a DNS domain name into an X.500 distinguished name. 287*0Sstevel@tonic-gate * For example, "sales.wiz.com" -> "dc=sales,dc=wiz,dc=com" 288*0Sstevel@tonic-gate * 289*0Sstevel@tonic-gate * If an error is encountered zero is returned, otherwise a string 290*0Sstevel@tonic-gate * distinguished name and the number of nameparts is returned. 291*0Sstevel@tonic-gate * The caller should free the returned string if it is non-zero. 292*0Sstevel@tonic-gate */ 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate char * 295*0Sstevel@tonic-gate ldap_dns_to_dn( 296*0Sstevel@tonic-gate char *dns_name, 297*0Sstevel@tonic-gate int *nameparts 298*0Sstevel@tonic-gate ) 299*0Sstevel@tonic-gate { 300*0Sstevel@tonic-gate size_t dns_len; 301*0Sstevel@tonic-gate char *dn = 0; 302*0Sstevel@tonic-gate char *cp; 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate /* check for NULL string, empty name and name ending in '.' */ 305*0Sstevel@tonic-gate if (dns_name && (dns_len = strlen(dns_name)) && 306*0Sstevel@tonic-gate (dns_name[dns_len - 1] != '.')) { 307*0Sstevel@tonic-gate if (dn = (char *)malloc(dns_len * 3 + 1)) { 308*0Sstevel@tonic-gate *nameparts = 0; 309*0Sstevel@tonic-gate cp = dn; 310*0Sstevel@tonic-gate while (*dns_name) { 311*0Sstevel@tonic-gate *cp++ = 'd'; 312*0Sstevel@tonic-gate *cp++ = 'c'; 313*0Sstevel@tonic-gate *cp++ = '='; 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate while (*dns_name && (*dns_name != '.')) { 316*0Sstevel@tonic-gate *cp++ = *dns_name++; 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate if (*dns_name == '.') { 319*0Sstevel@tonic-gate dns_name++; 320*0Sstevel@tonic-gate *cp++ = ','; 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate (*nameparts)++; 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate *cp = '\0'; 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate return (dn); 328*0Sstevel@tonic-gate } 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate char ** 331*0Sstevel@tonic-gate ldap_explode_rdn( char *rdn, int notypes ) 332*0Sstevel@tonic-gate { 333*0Sstevel@tonic-gate char *p, *q, *rdnstart, **rdncomps = NULL; 334*0Sstevel@tonic-gate int state, count = 0, endquote; 335*0Sstevel@tonic-gate size_t len; 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 183, "ldap_explode_rdn\n"), 0, 0, 0 ); 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate rdnstart = rdn; 340*0Sstevel@tonic-gate p = rdn-1; 341*0Sstevel@tonic-gate state = OUTQUOTE; 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate do { 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate ++p; 346*0Sstevel@tonic-gate switch ( *p ) { 347*0Sstevel@tonic-gate case '\\': 348*0Sstevel@tonic-gate if ( *++p == '\0' ) 349*0Sstevel@tonic-gate p--; 350*0Sstevel@tonic-gate break; 351*0Sstevel@tonic-gate case '"': 352*0Sstevel@tonic-gate if ( state == INQUOTE ) 353*0Sstevel@tonic-gate state = OUTQUOTE; 354*0Sstevel@tonic-gate else 355*0Sstevel@tonic-gate state = INQUOTE; 356*0Sstevel@tonic-gate break; 357*0Sstevel@tonic-gate case '+': 358*0Sstevel@tonic-gate case '\0': 359*0Sstevel@tonic-gate if ( state == OUTQUOTE ) { 360*0Sstevel@tonic-gate ++count; 361*0Sstevel@tonic-gate if ( rdncomps == NULL ) { 362*0Sstevel@tonic-gate if (( rdncomps = (char **)malloc( 8 * sizeof( char *))) == NULL ) 363*0Sstevel@tonic-gate return( NULL ); 364*0Sstevel@tonic-gate } else if ( count >= 8 ) { 365*0Sstevel@tonic-gate if (( rdncomps = (char **)realloc( rdncomps, 366*0Sstevel@tonic-gate (count+1) * sizeof( char *))) 367*0Sstevel@tonic-gate == NULL ) 368*0Sstevel@tonic-gate return( NULL ); 369*0Sstevel@tonic-gate } 370*0Sstevel@tonic-gate rdncomps[ count ] = NULL; 371*0Sstevel@tonic-gate endquote = 0; 372*0Sstevel@tonic-gate if ( notypes ) { 373*0Sstevel@tonic-gate for ( q = rdnstart; 374*0Sstevel@tonic-gate q < p && *q != '='; ++q ) { 375*0Sstevel@tonic-gate ; 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate if ( q < p ) { 378*0Sstevel@tonic-gate rdnstart = ++q; 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate if ( *rdnstart == '"' ) { 381*0Sstevel@tonic-gate ++rdnstart; 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate if ( *(p-1) == '"' ) { 385*0Sstevel@tonic-gate endquote = 1; 386*0Sstevel@tonic-gate --p; 387*0Sstevel@tonic-gate } 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate len = p - rdnstart; 391*0Sstevel@tonic-gate if (( rdncomps[ count-1 ] = (char *)calloc( 1, len + 1 )) != NULL ) { 392*0Sstevel@tonic-gate SAFEMEMCPY( rdncomps[ count-1 ], rdnstart, 393*0Sstevel@tonic-gate len ); 394*0Sstevel@tonic-gate rdncomps[ count-1 ][ len ] = '\0'; 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate /* 398*0Sstevel@tonic-gate * Don't forget to increment 'p' back to where 399*0Sstevel@tonic-gate * it should be. If we don't, then we will 400*0Sstevel@tonic-gate * never get past an "end quote." 401*0Sstevel@tonic-gate */ 402*0Sstevel@tonic-gate if ( endquote == 1 ) 403*0Sstevel@tonic-gate p++; 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate rdnstart = *p ? p + 1 : p; 406*0Sstevel@tonic-gate while ( isspace( *rdnstart )) 407*0Sstevel@tonic-gate ++rdnstart; 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate break; 410*0Sstevel@tonic-gate } 411*0Sstevel@tonic-gate } while ( *p ); 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate return( rdncomps ); 414*0Sstevel@tonic-gate } 415