2004-10-03 21:17:45 +00:00
/*
Unix SMB / CIFS implementation .
LDAP server
Copyright ( C ) Simo Sorce 2004
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
# include "ldap_parse.h"
2004-10-04 21:02:00 +00:00
char char_from_hex ( char a , char b ) {
char m , l ;
if ( ' 0 ' < = a & & a < = ' 9 ' ) {
m = a - ' 0 ' ;
} else if ( ' A ' < = a & & a < = ' F ' ) {
m = 10 + ( a - ' A ' ) ;
} else if ( ' a ' < = a & & a < = ' f ' ) {
m = 10 + ( a - ' a ' ) ;
} else {
return a ;
}
if ( ' 0 ' < = b & & b < = ' 9 ' ) {
l = b - ' 0 ' ;
} else if ( ' A ' < = b & & b < = ' F ' ) {
l = 10 + ( b - ' A ' ) ;
} else if ( ' a ' < = b & & b < = ' f ' ) {
l = 10 + ( b - ' a ' ) ;
} else {
return a ;
}
return ( ( m < < 4 ) + l ) ;
}
char * parse_slash ( char * p , char * end ) {
switch ( * ( p + 1 ) ) {
case ' , ' :
case ' = ' :
case ' \n ' :
case ' + ' :
case ' < ' :
case ' > ' :
case ' # ' :
case ' ; ' :
case ' \\ ' :
case ' " ' :
memmove ( p , p + 1 , end - ( p + 1 ) ) ;
return ( end - 1 ) ;
default :
* p = char_from_hex ( * ( p + 1 ) , * ( p + 2 ) ) ;
memmove ( p + 1 , p + 3 , end - ( p + 3 ) ) ;
return ( end - 2 ) ;
}
}
2004-10-03 21:17:45 +00:00
struct ldap_dn * ldap_parse_dn ( TALLOC_CTX * mem_ctx , const char * orig_dn )
{
struct ldap_dn * dn ;
struct dn_component * component ;
struct dn_attribute * attribute ;
char * p , * start , * separator , * src , * dest , * dn_copy , * dn_end ;
int i , size ;
2004-10-04 21:02:00 +00:00
dn = talloc_p ( mem_ctx , struct ldap_dn ) ;
2004-10-03 21:17:45 +00:00
dn - > comp_num = 0 ;
2004-10-04 21:02:00 +00:00
dn - > components = talloc_array_p ( dn , struct dn_component * , 1 ) ;
component = talloc_p ( dn , struct dn_component ) ;
2004-10-03 21:17:45 +00:00
component - > attr_num = 0 ;
dn_copy = p = talloc_strdup ( mem_ctx , orig_dn ) ;
2004-10-04 21:02:00 +00:00
dn_end = dn_copy + strlen ( orig_dn ) + 1 ;
2004-10-03 21:17:45 +00:00
do {
2004-10-04 21:02:00 +00:00
component - > attributes = talloc_array_p ( component , struct dn_attribute * , 1 ) ;
attribute = talloc_p ( component , struct dn_attribute ) ;
2004-10-03 21:17:45 +00:00
/* skip "spaces" */
while ( * p = = ' ' | | * p = = ' \n ' ) {
p + + ;
}
/* start parsing this component */
do {
start = p ;
/* find out key separator '=' */
while ( * p & & * p ! = ' = ' ) {
if ( * p = = ' \\ ' ) {
2004-10-04 21:02:00 +00:00
dn_end = parse_slash ( p , dn_end ) ;
2004-10-03 21:17:45 +00:00
}
p + + ;
}
separator = p ;
/* remove spaces */
while ( * ( p - 1 ) = = ' ' | | * ( p - 1 ) = = ' \n ' ) {
p - - ;
}
/* save key name */
attribute - > name = talloc_strndup ( attribute , start , p - start ) ;
DEBUG ( 10 , ( " attribute name: [%s] \n " , attribute - > name ) ) ;
p = separator + 1 ;
/* skip spaces past the separator */
p = separator + strspn ( p , " \n " ) + 1 ;
start = p ;
/* check if the value is enclosed in QUOTATION */
if ( * p = = ' " ' ) {
start = p + 1 ;
while ( * p & & * p ! = ' " ' ) {
if ( * p = = ' \\ ' ) {
2004-10-04 21:02:00 +00:00
dn_end = parse_slash ( p , dn_end ) ;
2004-10-03 21:17:45 +00:00
}
p + + ;
}
/* skip spaces until the separator */
separator = p + strspn ( p , " \n " ) ;
if ( * separator ! = ' , ' & & * separator ! = ' ; ' & & * separator ! = ' + ' ) { /* there must be a separator here */
/* Error Malformed DN */
DEBUG ( 0 , ( " Error: Malformed DN! \n " ) ) ;
break ;
}
} else {
while ( * p & & ! ( * p = = ' , ' | | * p = = ' ; ' | | * p = = ' + ' ) ) {
if ( * p = = ' \\ ' ) {
2004-10-04 21:02:00 +00:00
dn_end = parse_slash ( p , dn_end ) ;
2004-10-03 21:17:45 +00:00
}
p + + ;
} /* found separator */
separator = p ;
/* remove spaces */
while ( * ( p - 1 ) = = ' ' | | * ( p - 1 ) = = ' \n ' ) {
p - - ;
}
}
/* save the value */
attribute - > value = talloc_strndup ( attribute , start , p - start ) ;
DEBUG ( 10 , ( " attribute value: [%s] \n " , attribute - > value ) ) ;
attribute - > attribute = talloc_asprintf ( attribute , " %s=%s " , attribute - > name , attribute - > value ) ;
DEBUG ( 10 , ( " attribute: [%s] \n " , attribute - > attribute ) ) ;
/* save the attribute */
component - > attributes [ component - > attr_num ] = attribute ;
component - > attr_num + + ;
if ( * separator = = ' + ' ) { /* expect other attributes in this component */
2004-10-04 21:02:00 +00:00
component - > attributes = talloc_realloc_p ( component , component - > attributes , struct dn_attribute * , component - > attr_num + 1 ) ;
2004-10-03 21:17:45 +00:00
/* allocate new attribute structure */
2004-10-04 21:02:00 +00:00
attribute = talloc_p ( component , struct dn_attribute ) ;
2004-10-03 21:17:45 +00:00
/* skip spaces past the separator */
p = separator + strspn ( p , " \n " ) ;
}
} while ( * separator = = ' + ' ) ;
/* found component bounds */
for ( i = 0 , size = 0 ; i < component - > attr_num ; i + + ) {
size = size + strlen ( component - > attributes [ i ] - > attribute ) + 1 ;
}
/* rebuild the normlaized component and put it here */
component - > component = dest = talloc ( component , size ) ;
for ( i = 0 ; i < component - > attr_num ; i + + ) {
if ( i ! = 0 ) {
* dest = ' + ' ;
dest + + ;
}
src = component - > attributes [ i ] - > attribute ;
do {
* ( dest + + ) = * ( src + + ) ;
} while ( * src ) ;
* dest = ' \0 ' ;
}
DEBUG ( 10 , ( " component: [%s] \n " , component - > component ) ) ;
dn - > components [ dn - > comp_num ] = component ;
dn - > comp_num + + ;
if ( * separator = = ' , ' | | * separator = = ' ; ' ) {
2004-10-04 21:02:00 +00:00
dn - > components = talloc_realloc_p ( dn , dn - > components , struct dn_component * , dn - > comp_num + 1 ) ;
component = talloc_p ( dn , struct dn_component ) ;
2004-10-03 21:17:45 +00:00
component - > attr_num = 0 ;
}
p = separator + 1 ;
} while ( * separator = = ' , ' | | * separator = = ' ; ' ) ;
for ( i = 0 , size = 0 ; i < dn - > comp_num ; i + + ) {
size = size + strlen ( dn - > components [ i ] - > component ) + 1 ;
}
/* rebuild the normlaized dn and put it here */
dn - > dn = dest = talloc ( dn , size ) ;
for ( i = 0 ; i < dn - > comp_num ; i + + ) {
if ( i ! = 0 ) {
* dest = ' , ' ;
dest + + ;
}
src = dn - > components [ i ] - > component ;
do {
* ( dest + + ) = * ( src + + ) ;
} while ( * src ) ;
* dest = ' \0 ' ;
}
DEBUG ( 10 , ( " dn: [%s] \n " , dn - > dn ) ) ;
talloc_free ( dn_copy ) ;
return dn ;
}