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