Home | History | Annotate | Download | only in common
      1 /*
      2  * Portions Copyright 1998 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 #pragma ident	"@(#)getdn.c	1.7	07/03/16 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
     16 static 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 
     41 char *
     42 ldap_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 
     63 char *
     64 ldap_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 
    136 char **
    137 ldap_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 
    164 char **
    165 ldap_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 
    258 int
    259 ldap_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 
    268 char *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 
    292 char *
    293 ldap_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 
    328 char **
    329 ldap_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