2004-08-12 08:55:59 +04:00
/*
Unix SMB / CIFS mplementation .
LDAP protocol helper functions for SAMBA
Copyright ( C ) Andrew Tridgell 2004
Copyright ( C ) Volker Lendecke 2004
2004-08-13 11:10:46 +04:00
Copyright ( C ) Stefan Metzmacher 2004
Copyright ( C ) Simo Sorce 2004
2004-08-12 08:55:59 +04:00
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"
2004-11-02 04:42:45 +03:00
# include "system/iconv.h"
2004-11-02 09:42:15 +03:00
# include "asn_1.h"
2005-02-10 10:08:40 +03:00
# include "libcli/ldap/ldap.h"
2004-08-12 08:55:59 +04:00
2005-05-11 09:59:46 +04:00
2005-06-13 10:06:29 +04:00
static BOOL ldap_push_filter ( struct asn1_data * data , struct ldb_parse_tree * tree )
2004-08-12 08:55:59 +04:00
{
2005-06-14 07:53:35 +04:00
int i ;
2004-08-12 08:55:59 +04:00
switch ( tree - > operation ) {
2005-06-14 07:53:35 +04:00
case LDB_OP_SIMPLE :
2004-08-12 08:55:59 +04:00
if ( ( tree - > u . simple . value . length = = 1 ) & &
( ( ( char * ) ( tree - > u . simple . value . data ) ) [ 0 ] = = ' * ' ) ) {
/* Just a presence test */
2005-06-18 16:45:28 +04:00
asn1_push_tag ( data , ASN1_CONTEXT_SIMPLE ( 7 ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write ( data , tree - > u . simple . attr ,
strlen ( tree - > u . simple . attr ) ) ;
asn1_pop_tag ( data ) ;
return ! data - > has_error ;
}
2005-06-14 07:53:35 +04:00
/* equality test */
2005-06-18 16:45:28 +04:00
asn1_push_tag ( data , ASN1_CONTEXT ( 3 ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write_OctetString ( data , tree - > u . simple . attr ,
strlen ( tree - > u . simple . attr ) ) ;
asn1_write_OctetString ( data , tree - > u . simple . value . data ,
tree - > u . simple . value . length ) ;
asn1_pop_tag ( data ) ;
break ;
2005-06-14 07:53:35 +04:00
case LDB_OP_EXTENDED :
/*
MatchingRuleAssertion : : = SEQUENCE {
matchingRule [ 1 ] MatchingRuleID OPTIONAL ,
type [ 2 ] AttributeDescription OPTIONAL ,
matchValue [ 3 ] AssertionValue ,
dnAttributes [ 4 ] BOOLEAN DEFAULT FALSE
}
*/
2005-06-18 16:45:28 +04:00
asn1_push_tag ( data , ASN1_CONTEXT ( 9 ) ) ;
2005-06-14 07:53:35 +04:00
if ( tree - > u . extended . rule_id ) {
2005-06-18 16:45:28 +04:00
asn1_push_tag ( data , ASN1_CONTEXT_SIMPLE ( 1 ) ) ;
asn1_write_LDAPString ( data , tree - > u . extended . rule_id ) ;
2005-06-14 07:53:35 +04:00
asn1_pop_tag ( data ) ;
}
if ( tree - > u . extended . attr ) {
2005-06-18 16:45:28 +04:00
asn1_push_tag ( data , ASN1_CONTEXT_SIMPLE ( 2 ) ) ;
asn1_write_LDAPString ( data , tree - > u . extended . attr ) ;
2005-06-14 07:53:35 +04:00
asn1_pop_tag ( data ) ;
}
2005-06-18 16:45:28 +04:00
asn1_push_tag ( data , ASN1_CONTEXT_SIMPLE ( 3 ) ) ;
asn1_write_LDAPString ( data , tree - > u . extended . value . data ) ;
asn1_pop_tag ( data ) ;
asn1_push_tag ( data , ASN1_CONTEXT_SIMPLE ( 4 ) ) ;
asn1_write_uint8 ( data , tree - > u . extended . dnAttributes ) ;
2005-06-14 07:53:35 +04:00
asn1_pop_tag ( data ) ;
2004-08-12 08:55:59 +04:00
asn1_pop_tag ( data ) ;
break ;
2005-06-14 07:53:35 +04:00
2004-08-12 08:55:59 +04:00
2005-06-14 07:53:35 +04:00
case LDB_OP_AND :
case LDB_OP_OR :
2005-06-18 16:45:28 +04:00
asn1_push_tag ( data , ASN1_CONTEXT ( tree - > operation = = LDB_OP_AND ? 0 : 1 ) ) ;
2004-08-12 08:55:59 +04:00
for ( i = 0 ; i < tree - > u . list . num_elements ; i + + ) {
2005-06-18 16:45:28 +04:00
if ( ! ldap_push_filter ( data , tree - > u . list . elements [ i ] ) ) {
return False ;
}
2004-08-12 08:55:59 +04:00
}
asn1_pop_tag ( data ) ;
break ;
2005-06-14 07:53:35 +04:00
2005-06-18 14:38:06 +04:00
case LDB_OP_NOT :
2005-06-18 16:48:42 +04:00
asn1_push_tag ( data , ASN1_CONTEXT ( 2 ) ) ;
if ( ! ldap_push_filter ( data , tree - > u . not . child ) ) {
return False ;
}
asn1_pop_tag ( data ) ;
break ;
2005-06-18 14:38:06 +04:00
2004-08-12 08:55:59 +04:00
default :
return False ;
}
return ! data - > has_error ;
}
2004-11-02 09:42:15 +03:00
static void ldap_encode_response ( struct asn1_data * data , struct ldap_Result * result )
2004-08-12 08:55:59 +04:00
{
asn1_write_enumerated ( data , result - > resultcode ) ;
asn1_write_OctetString ( data , result - > dn ,
( result - > dn ) ? strlen ( result - > dn ) : 0 ) ;
asn1_write_OctetString ( data , result - > errormessage ,
( result - > errormessage ) ?
strlen ( result - > errormessage ) : 0 ) ;
2004-11-06 23:43:36 +03:00
if ( result - > referral ) {
asn1_push_tag ( data , ASN1_CONTEXT ( 3 ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write_OctetString ( data , result - > referral ,
strlen ( result - > referral ) ) ;
2004-11-06 23:43:36 +03:00
asn1_pop_tag ( data ) ;
}
2004-08-12 08:55:59 +04:00
}
BOOL ldap_encode ( struct ldap_message * msg , DATA_BLOB * result )
{
2004-11-02 09:42:15 +03:00
struct asn1_data data ;
2004-08-12 08:55:59 +04:00
int i , j ;
ZERO_STRUCT ( data ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_write_Integer ( & data , msg - > messageid ) ;
switch ( msg - > type ) {
case LDAP_TAG_BindRequest : {
struct ldap_BindRequest * r = & msg - > r . BindRequest ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write_Integer ( & data , r - > version ) ;
asn1_write_OctetString ( & data , r - > dn ,
( r - > dn ! = NULL ) ? strlen ( r - > dn ) : 0 ) ;
switch ( r - > mechanism ) {
case LDAP_AUTH_MECH_SIMPLE :
/* context, primitive */
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_CONTEXT_SIMPLE ( 0 ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write ( & data , r - > creds . password ,
strlen ( r - > creds . password ) ) ;
asn1_pop_tag ( & data ) ;
break ;
case LDAP_AUTH_MECH_SASL :
/* context, constructed */
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_CONTEXT ( 3 ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write_OctetString ( & data , r - > creds . SASL . mechanism ,
strlen ( r - > creds . SASL . mechanism ) ) ;
2004-08-13 09:26:38 +04:00
asn1_write_OctetString ( & data , r - > creds . SASL . secblob . data ,
r - > creds . SASL . secblob . length ) ;
2004-08-12 08:55:59 +04:00
asn1_pop_tag ( & data ) ;
break ;
default :
return False ;
}
asn1_pop_tag ( & data ) ;
break ;
}
case LDAP_TAG_BindResponse : {
struct ldap_BindResponse * r = & msg - > r . BindResponse ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
ldap_encode_response ( & data , & r - > response ) ;
2005-06-13 10:06:29 +04:00
asn1_write_ContextSimple ( & data , 7 , & r - > SASL . secblob ) ;
2004-10-08 16:08:43 +04:00
asn1_pop_tag ( & data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case LDAP_TAG_UnbindRequest : {
/* struct ldap_UnbindRequest *r = &msg->r.UnbindRequest; */
break ;
}
case LDAP_TAG_SearchRequest : {
struct ldap_SearchRequest * r = & msg - > r . SearchRequest ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write_OctetString ( & data , r - > basedn , strlen ( r - > basedn ) ) ;
asn1_write_enumerated ( & data , r - > scope ) ;
asn1_write_enumerated ( & data , r - > deref ) ;
asn1_write_Integer ( & data , r - > sizelimit ) ;
asn1_write_Integer ( & data , r - > timelimit ) ;
2004-09-01 18:49:43 +04:00
asn1_write_BOOLEAN ( & data , r - > attributesonly ) ;
2004-08-12 08:55:59 +04:00
2005-06-18 16:45:28 +04:00
if ( ! ldap_push_filter ( & data , r - > tree ) ) {
return False ;
}
2004-08-12 08:55:59 +04:00
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
for ( i = 0 ; i < r - > num_attributes ; i + + ) {
asn1_write_OctetString ( & data , r - > attributes [ i ] ,
strlen ( r - > attributes [ i ] ) ) ;
}
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
break ;
}
case LDAP_TAG_SearchResultEntry : {
struct ldap_SearchResEntry * r = & msg - > r . SearchResultEntry ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write_OctetString ( & data , r - > dn , strlen ( r - > dn ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
for ( i = 0 ; i < r - > num_attributes ; i + + ) {
2005-06-15 05:02:53 +04:00
struct ldb_message_element * attr = & r - > attributes [ i ] ;
2004-08-12 08:55:59 +04:00
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_write_OctetString ( & data , attr - > name ,
strlen ( attr - > name ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 1 ) ) ;
for ( j = 0 ; j < attr - > num_values ; j + + ) {
asn1_write_OctetString ( & data ,
attr - > values [ j ] . data ,
attr - > values [ j ] . length ) ;
}
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
}
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
break ;
}
case LDAP_TAG_SearchResultDone : {
2004-08-12 10:37:12 +04:00
struct ldap_Result * r = & msg - > r . SearchResultDone ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
ldap_encode_response ( & data , r ) ;
asn1_pop_tag ( & data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case LDAP_TAG_ModifyRequest : {
struct ldap_ModifyRequest * r = & msg - > r . ModifyRequest ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write_OctetString ( & data , r - > dn , strlen ( r - > dn ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
for ( i = 0 ; i < r - > num_mods ; i + + ) {
2005-06-15 05:02:53 +04:00
struct ldb_message_element * attrib = & r - > mods [ i ] . attrib ;
2004-08-12 08:55:59 +04:00
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_write_enumerated ( & data , r - > mods [ i ] . type ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_write_OctetString ( & data , attrib - > name ,
strlen ( attrib - > name ) ) ;
asn1_push_tag ( & data , ASN1_SET ) ;
for ( j = 0 ; j < attrib - > num_values ; j + + ) {
asn1_write_OctetString ( & data ,
attrib - > values [ j ] . data ,
attrib - > values [ j ] . length ) ;
}
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
}
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
break ;
}
case LDAP_TAG_ModifyResponse : {
struct ldap_Result * r = & msg - > r . ModifyResponse ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
ldap_encode_response ( & data , r ) ;
asn1_pop_tag ( & data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case LDAP_TAG_AddRequest : {
struct ldap_AddRequest * r = & msg - > r . AddRequest ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write_OctetString ( & data , r - > dn , strlen ( r - > dn ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
for ( i = 0 ; i < r - > num_attributes ; i + + ) {
2005-06-15 05:02:53 +04:00
struct ldb_message_element * attrib = & r - > attributes [ i ] ;
2004-08-12 08:55:59 +04:00
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_write_OctetString ( & data , attrib - > name ,
strlen ( attrib - > name ) ) ;
asn1_push_tag ( & data , ASN1_SET ) ;
for ( j = 0 ; j < r - > attributes [ i ] . num_values ; j + + ) {
asn1_write_OctetString ( & data ,
attrib - > values [ j ] . data ,
attrib - > values [ j ] . length ) ;
}
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
}
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
break ;
}
case LDAP_TAG_AddResponse : {
struct ldap_Result * r = & msg - > r . AddResponse ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
ldap_encode_response ( & data , r ) ;
asn1_pop_tag ( & data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
2004-09-27 19:40:12 +04:00
case LDAP_TAG_DelRequest : {
struct ldap_DelRequest * r = & msg - > r . DelRequest ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION_SIMPLE ( msg - > type ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write ( & data , r - > dn , strlen ( r - > dn ) ) ;
asn1_pop_tag ( & data ) ;
break ;
}
2004-09-27 19:40:12 +04:00
case LDAP_TAG_DelResponse : {
struct ldap_Result * r = & msg - > r . DelResponse ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
ldap_encode_response ( & data , r ) ;
asn1_pop_tag ( & data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case LDAP_TAG_ModifyDNRequest : {
struct ldap_ModifyDNRequest * r = & msg - > r . ModifyDNRequest ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write_OctetString ( & data , r - > dn , strlen ( r - > dn ) ) ;
asn1_write_OctetString ( & data , r - > newrdn , strlen ( r - > newrdn ) ) ;
2004-09-01 18:49:43 +04:00
asn1_write_BOOLEAN ( & data , r - > deleteolddn ) ;
2004-08-12 08:55:59 +04:00
if ( r - > newsuperior ! = NULL ) {
asn1_push_tag ( & data , ASN1_CONTEXT_SIMPLE ( 0 ) ) ;
asn1_write ( & data , r - > newsuperior ,
strlen ( r - > newsuperior ) ) ;
asn1_pop_tag ( & data ) ;
}
asn1_pop_tag ( & data ) ;
break ;
}
case LDAP_TAG_ModifyDNResponse : {
2004-08-17 15:22:44 +04:00
struct ldap_Result * r = & msg - > r . ModifyDNResponse ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
ldap_encode_response ( & data , r ) ;
asn1_pop_tag ( & data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case LDAP_TAG_CompareRequest : {
struct ldap_CompareRequest * r = & msg - > r . CompareRequest ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
2004-08-12 08:55:59 +04:00
asn1_write_OctetString ( & data , r - > dn , strlen ( r - > dn ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_write_OctetString ( & data , r - > attribute ,
strlen ( r - > attribute ) ) ;
2004-09-29 16:18:06 +04:00
asn1_write_OctetString ( & data , r - > value . data ,
r - > value . length ) ;
2004-08-12 08:55:59 +04:00
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
break ;
}
case LDAP_TAG_CompareResponse : {
2004-09-29 16:18:06 +04:00
struct ldap_Result * r = & msg - > r . ModifyDNResponse ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
ldap_encode_response ( & data , r ) ;
asn1_pop_tag ( & data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case LDAP_TAG_AbandonRequest : {
struct ldap_AbandonRequest * r = & msg - > r . AbandonRequest ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION_SIMPLE ( msg - > type ) ) ;
2004-09-15 17:29:59 +04:00
asn1_write_implicit_Integer ( & data , r - > messageid ) ;
2004-08-12 08:55:59 +04:00
asn1_pop_tag ( & data ) ;
break ;
}
case LDAP_TAG_SearchResultReference : {
2004-11-06 23:43:36 +03:00
struct ldap_SearchResRef * r = & msg - > r . SearchResultReference ;
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
asn1_write_OctetString ( & data , r - > referral , strlen ( r - > referral ) ) ;
asn1_pop_tag ( & data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case LDAP_TAG_ExtendedRequest : {
struct ldap_ExtendedRequest * r = & msg - > r . ExtendedRequest ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
2004-08-12 08:55:59 +04:00
asn1_push_tag ( & data , ASN1_CONTEXT_SIMPLE ( 0 ) ) ;
asn1_write ( & data , r - > oid , strlen ( r - > oid ) ) ;
asn1_pop_tag ( & data ) ;
asn1_push_tag ( & data , ASN1_CONTEXT_SIMPLE ( 1 ) ) ;
asn1_write ( & data , r - > value . data , r - > value . length ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
break ;
}
case LDAP_TAG_ExtendedResponse : {
struct ldap_ExtendedResponse * r = & msg - > r . ExtendedResponse ;
2004-10-08 16:08:43 +04:00
asn1_push_tag ( & data , ASN1_APPLICATION ( msg - > type ) ) ;
ldap_encode_response ( & data , & r - > response ) ;
asn1_pop_tag ( & data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
default :
return False ;
}
asn1_pop_tag ( & data ) ;
2005-06-18 16:45:28 +04:00
if ( data . has_error ) {
asn1_free ( & data ) ;
return False ;
}
2004-08-12 08:55:59 +04:00
* result = data_blob ( data . data , data . length ) ;
asn1_free ( & data ) ;
return True ;
}
static const char * blob2string_talloc ( TALLOC_CTX * mem_ctx ,
DATA_BLOB blob )
{
2005-01-06 06:06:58 +03:00
char * result = talloc_size ( mem_ctx , blob . length + 1 ) ;
2004-08-12 08:55:59 +04:00
memcpy ( result , blob . data , blob . length ) ;
result [ blob . length ] = ' \0 ' ;
return result ;
}
static BOOL asn1_read_OctetString_talloc ( TALLOC_CTX * mem_ctx ,
2004-11-02 09:42:15 +03:00
struct asn1_data * data ,
2004-08-12 08:55:59 +04:00
const char * * result )
{
DATA_BLOB string ;
if ( ! asn1_read_OctetString ( data , & string ) )
return False ;
* result = blob2string_talloc ( mem_ctx , string ) ;
data_blob_free ( & string ) ;
return True ;
}
static void ldap_decode_response ( TALLOC_CTX * mem_ctx ,
2004-11-02 09:42:15 +03:00
struct asn1_data * data ,
2004-08-12 08:55:59 +04:00
struct ldap_Result * result )
{
asn1_read_enumerated ( data , & result - > resultcode ) ;
asn1_read_OctetString_talloc ( mem_ctx , data , & result - > dn ) ;
asn1_read_OctetString_talloc ( mem_ctx , data , & result - > errormessage ) ;
2004-08-17 15:22:44 +04:00
if ( asn1_peek_tag ( data , ASN1_CONTEXT ( 3 ) ) ) {
asn1_start_tag ( data , ASN1_CONTEXT ( 3 ) ) ;
2004-08-12 08:55:59 +04:00
asn1_read_OctetString_talloc ( mem_ctx , data , & result - > referral ) ;
2004-08-17 15:22:44 +04:00
asn1_end_tag ( data ) ;
2004-08-13 10:27:02 +04:00
} else {
2004-08-17 15:22:44 +04:00
result - > referral = NULL ;
2004-08-13 10:27:02 +04:00
}
}
2005-06-13 13:10:17 +04:00
/*
parse the ASN .1 formatted search string into a ldb_parse_tree
*/
2005-06-13 11:36:52 +04:00
static struct ldb_parse_tree * ldap_decode_filter_tree ( TALLOC_CTX * mem_ctx ,
struct asn1_data * data )
2004-08-12 08:55:59 +04:00
{
2005-06-18 16:45:28 +04:00
uint8_t filter_tag ;
2005-06-13 11:36:52 +04:00
struct ldb_parse_tree * ret ;
2005-05-10 05:57:47 +04:00
2005-06-13 11:36:52 +04:00
if ( ! asn1_peek_uint8 ( data , & filter_tag ) ) {
return NULL ;
}
2004-08-12 08:55:59 +04:00
filter_tag & = 0x1f ; /* strip off the asn1 stuff */
2005-06-13 11:36:52 +04:00
ret = talloc ( mem_ctx , struct ldb_parse_tree ) ;
if ( ret = = NULL ) return NULL ;
2004-08-12 08:55:59 +04:00
2005-06-13 11:36:52 +04:00
switch ( filter_tag ) {
case 0 :
case 1 :
/* AND or OR of one or more filters */
ret - > operation = ( filter_tag = = 0 ) ? LDB_OP_AND : LDB_OP_OR ;
ret - > u . list . num_elements = 0 ;
ret - > u . list . elements = NULL ;
if ( ! asn1_start_tag ( data , ASN1_CONTEXT ( filter_tag ) ) ) {
goto failed ;
}
2004-08-12 08:55:59 +04:00
while ( asn1_tag_remaining ( data ) > 0 ) {
2005-06-13 11:36:52 +04:00
struct ldb_parse_tree * subtree ;
subtree = ldap_decode_filter_tree ( ret , data ) ;
if ( subtree = = NULL ) {
goto failed ;
}
ret - > u . list . elements =
talloc_realloc ( ret , ret - > u . list . elements ,
struct ldb_parse_tree * ,
ret - > u . list . num_elements + 1 ) ;
if ( ret - > u . list . elements = = NULL ) {
goto failed ;
}
talloc_steal ( ret - > u . list . elements , subtree ) ;
ret - > u . list . elements [ ret - > u . list . num_elements ] = subtree ;
ret - > u . list . num_elements + + ;
}
if ( ! asn1_end_tag ( data ) ) {
goto failed ;
2004-08-12 08:55:59 +04:00
}
break ;
2005-06-13 11:36:52 +04:00
2005-06-14 07:53:35 +04:00
case 2 :
/* 'not' operation */
if ( ! asn1_start_tag ( data , ASN1_CONTEXT ( filter_tag ) ) ) {
goto failed ;
}
2005-06-13 10:06:29 +04:00
2005-06-14 07:53:35 +04:00
ret - > operation = LDB_OP_NOT ;
ret - > u . not . child = ldap_decode_filter_tree ( ret , data ) ;
2005-06-13 11:36:52 +04:00
2005-06-14 07:53:35 +04:00
if ( ! asn1_end_tag ( data ) ) {
2005-06-13 11:36:52 +04:00
goto failed ;
}
2005-06-14 07:53:35 +04:00
break ;
2005-06-13 11:36:52 +04:00
2005-06-14 07:53:35 +04:00
case 3 : {
/* equalityMatch */
const char * attrib ;
DATA_BLOB value ;
asn1_start_tag ( data , ASN1_CONTEXT ( filter_tag ) ) ;
2004-08-12 08:55:59 +04:00
asn1_read_OctetString_talloc ( mem_ctx , data , & attrib ) ;
2005-05-11 09:59:46 +04:00
asn1_read_OctetString ( data , & value ) ;
2004-08-12 08:55:59 +04:00
asn1_end_tag ( data ) ;
2005-06-13 11:36:52 +04:00
if ( ( data - > has_error ) | | ( attrib = = NULL ) | | ( value . data = = NULL ) ) {
goto failed ;
}
2005-06-14 07:53:35 +04:00
ret - > operation = LDB_OP_SIMPLE ;
2005-06-13 11:36:52 +04:00
ret - > u . simple . attr = talloc_steal ( ret , attrib ) ;
ret - > u . simple . value . data = talloc_steal ( ret , value . data ) ;
ret - > u . simple . value . length = value . length ;
2004-08-12 08:55:59 +04:00
break ;
}
case 7 : {
/* Normal presence, "attribute=*" */
2005-06-14 07:53:35 +04:00
char * attr ;
if ( ! asn1_start_tag ( data , ASN1_CONTEXT_SIMPLE ( filter_tag ) ) ) {
2005-06-13 11:36:52 +04:00
goto failed ;
}
2005-06-14 07:53:35 +04:00
if ( ! asn1_read_LDAPString ( data , & attr ) ) {
2005-06-13 11:36:52 +04:00
goto failed ;
}
ret - > operation = LDB_OP_SIMPLE ;
2005-06-14 07:53:35 +04:00
ret - > u . simple . attr = talloc_steal ( ret , attr ) ;
ret - > u . simple . value . data = talloc_strdup ( ret , " * " ) ;
if ( ret - > u . simple . value . data = = NULL ) {
2005-06-13 11:36:52 +04:00
goto failed ;
}
2005-06-14 07:53:35 +04:00
ret - > u . simple . value . length = 1 ;
if ( ! asn1_end_tag ( data ) ) {
2005-06-13 11:36:52 +04:00
goto failed ;
}
2005-06-14 07:53:35 +04:00
break ;
}
case 9 : {
char * oid , * attr , * value ;
uint8_t dnAttributes ;
/* an extended search */
if ( ! asn1_start_tag ( data , ASN1_CONTEXT ( filter_tag ) ) ) {
2005-06-13 11:36:52 +04:00
goto failed ;
}
2005-06-14 07:53:35 +04:00
asn1_start_tag ( data , ASN1_CONTEXT_SIMPLE ( 1 ) ) ;
asn1_read_LDAPString ( data , & oid ) ;
asn1_end_tag ( data ) ;
asn1_start_tag ( data , ASN1_CONTEXT_SIMPLE ( 2 ) ) ;
asn1_read_LDAPString ( data , & attr ) ;
asn1_end_tag ( data ) ;
asn1_start_tag ( data , ASN1_CONTEXT_SIMPLE ( 3 ) ) ;
asn1_read_LDAPString ( data , & value ) ;
asn1_end_tag ( data ) ;
asn1_start_tag ( data , ASN1_CONTEXT_SIMPLE ( 4 ) ) ;
asn1_read_uint8 ( data , & dnAttributes ) ;
asn1_end_tag ( data ) ;
if ( ( data - > has_error ) | | ( oid = = NULL ) | | ( value = = NULL ) ) {
goto failed ;
}
ret - > operation = LDB_OP_EXTENDED ;
ret - > u . extended . attr = talloc_steal ( ret , attr ) ;
ret - > u . extended . rule_id = talloc_steal ( ret , oid ) ;
ret - > u . extended . value . data = talloc_steal ( ret , value ) ;
ret - > u . extended . value . length = strlen ( value ) ;
ret - > u . extended . dnAttributes = dnAttributes ;
2005-06-13 11:36:52 +04:00
if ( ! asn1_end_tag ( data ) ) {
goto failed ;
}
2004-08-12 08:55:59 +04:00
break ;
}
2005-06-14 07:53:35 +04:00
2004-08-12 08:55:59 +04:00
default :
2005-06-13 11:36:52 +04:00
DEBUG ( 0 , ( " Unsupported LDAP filter operation 0x%x \n " , filter_tag ) ) ;
goto failed ;
2004-08-12 08:55:59 +04:00
}
2005-06-13 11:36:52 +04:00
return ret ;
failed :
talloc_free ( ret ) ;
DEBUG ( 0 , ( " Failed to parse ASN.1 LDAP filter \n " ) ) ;
return NULL ;
}
2005-05-10 05:57:47 +04:00
2004-11-02 09:42:15 +03:00
static void ldap_decode_attrib ( TALLOC_CTX * mem_ctx , struct asn1_data * data ,
2005-06-15 05:02:53 +04:00
struct ldb_message_element * attrib )
2004-08-12 08:55:59 +04:00
{
asn1_start_tag ( data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_read_OctetString_talloc ( mem_ctx , data , & attrib - > name ) ;
asn1_start_tag ( data , ASN1_SET ) ;
while ( asn1_peek_tag ( data , ASN1_OCTET_STRING ) ) {
DATA_BLOB blob ;
asn1_read_OctetString ( data , & blob ) ;
2005-06-15 05:12:31 +04:00
add_value_to_attrib ( mem_ctx , & blob , attrib ) ;
2004-08-12 08:55:59 +04:00
}
asn1_end_tag ( data ) ;
asn1_end_tag ( data ) ;
}
2004-11-02 09:42:15 +03:00
static void ldap_decode_attribs ( TALLOC_CTX * mem_ctx , struct asn1_data * data ,
2005-06-15 05:02:53 +04:00
struct ldb_message_element * * attributes ,
2004-08-12 08:55:59 +04:00
int * num_attributes )
{
asn1_start_tag ( data , ASN1_SEQUENCE ( 0 ) ) ;
while ( asn1_peek_tag ( data , ASN1_SEQUENCE ( 0 ) ) ) {
2005-06-15 05:02:53 +04:00
struct ldb_message_element attrib ;
2004-08-12 08:55:59 +04:00
ZERO_STRUCT ( attrib ) ;
ldap_decode_attrib ( mem_ctx , data , & attrib ) ;
add_attrib_to_array_talloc ( mem_ctx , & attrib ,
attributes , num_attributes ) ;
}
asn1_end_tag ( data ) ;
}
2004-11-02 09:42:15 +03:00
BOOL ldap_decode ( struct asn1_data * data , struct ldap_message * msg )
2004-08-12 08:55:59 +04:00
{
2005-02-10 08:09:35 +03:00
uint8_t tag ;
2004-08-12 08:55:59 +04:00
asn1_start_tag ( data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_read_Integer ( data , & msg - > messageid ) ;
if ( ! asn1_peek_uint8 ( data , & tag ) )
return False ;
switch ( tag ) {
case ASN1_APPLICATION ( LDAP_TAG_BindRequest ) : {
struct ldap_BindRequest * r = & msg - > r . BindRequest ;
msg - > type = LDAP_TAG_BindRequest ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2004-08-12 08:55:59 +04:00
asn1_read_Integer ( data , & r - > version ) ;
2005-06-15 04:27:51 +04:00
asn1_read_OctetString_talloc ( msg , data , & r - > dn ) ;
2004-10-08 16:08:43 +04:00
if ( asn1_peek_tag ( data , ASN1_CONTEXT_SIMPLE ( 0 ) ) ) {
2004-08-12 08:55:59 +04:00
int pwlen ;
r - > creds . password = " " ;
2004-10-08 16:08:43 +04:00
r - > mechanism = LDAP_AUTH_MECH_SIMPLE ;
asn1_start_tag ( data , ASN1_CONTEXT_SIMPLE ( 0 ) ) ;
2004-08-12 08:55:59 +04:00
pwlen = asn1_tag_remaining ( data ) ;
if ( pwlen ! = 0 ) {
2005-06-15 04:27:51 +04:00
char * pw = talloc_size ( msg , pwlen + 1 ) ;
2004-08-12 08:55:59 +04:00
asn1_read ( data , pw , pwlen ) ;
pw [ pwlen ] = ' \0 ' ;
r - > creds . password = pw ;
}
asn1_end_tag ( data ) ;
2004-10-08 16:08:43 +04:00
} else if ( asn1_peek_tag ( data , ASN1_CONTEXT ( 3 ) ) ) {
asn1_start_tag ( data , ASN1_CONTEXT ( 3 ) ) ;
r - > mechanism = LDAP_AUTH_MECH_SASL ;
2005-06-15 04:27:51 +04:00
asn1_read_OctetString_talloc ( msg , data , & r - > creds . SASL . mechanism ) ;
2004-10-08 16:08:43 +04:00
asn1_read_OctetString ( data , & r - > creds . SASL . secblob ) ;
if ( r - > creds . SASL . secblob . data ) {
2005-06-15 04:27:51 +04:00
talloc_steal ( msg , r - > creds . SASL . secblob . data ) ;
2004-10-08 16:08:43 +04:00
}
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
}
asn1_end_tag ( data ) ;
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_BindResponse ) : {
struct ldap_BindResponse * r = & msg - > r . BindResponse ;
msg - > type = LDAP_TAG_BindResponse ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
ldap_decode_response ( msg , data , & r - > response ) ;
2004-08-17 15:22:44 +04:00
if ( asn1_peek_tag ( data , ASN1_CONTEXT_SIMPLE ( 7 ) ) ) {
DATA_BLOB tmp_blob = data_blob ( NULL , 0 ) ;
asn1_read_ContextSimple ( data , 7 , & tmp_blob ) ;
2005-06-15 04:27:51 +04:00
r - > SASL . secblob = data_blob_talloc ( msg , tmp_blob . data , tmp_blob . length ) ;
2004-08-17 15:22:44 +04:00
data_blob_free ( & tmp_blob ) ;
} else {
r - > SASL . secblob = data_blob ( NULL , 0 ) ;
}
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
2004-09-22 14:42:58 +04:00
case ASN1_APPLICATION_SIMPLE ( LDAP_TAG_UnbindRequest ) : {
2004-08-12 08:55:59 +04:00
msg - > type = LDAP_TAG_UnbindRequest ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2004-09-22 14:42:58 +04:00
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_SearchRequest ) : {
struct ldap_SearchRequest * r = & msg - > r . SearchRequest ;
msg - > type = LDAP_TAG_SearchRequest ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
asn1_read_OctetString_talloc ( msg , data , & r - > basedn ) ;
2004-08-12 08:55:59 +04:00
asn1_read_enumerated ( data , ( int * ) & ( r - > scope ) ) ;
asn1_read_enumerated ( data , ( int * ) & ( r - > deref ) ) ;
asn1_read_Integer ( data , & r - > sizelimit ) ;
asn1_read_Integer ( data , & r - > timelimit ) ;
2004-09-01 18:49:43 +04:00
asn1_read_BOOLEAN ( data , & r - > attributesonly ) ;
2004-08-12 08:55:59 +04:00
2005-06-15 04:27:51 +04:00
r - > tree = ldap_decode_filter_tree ( msg , data ) ;
2005-06-13 13:10:17 +04:00
if ( r - > tree = = NULL ) {
return False ;
}
2004-08-12 08:55:59 +04:00
asn1_start_tag ( data , ASN1_SEQUENCE ( 0 ) ) ;
r - > num_attributes = 0 ;
r - > attributes = NULL ;
while ( asn1_tag_remaining ( data ) > 0 ) {
const char * attr ;
2005-06-15 04:27:51 +04:00
if ( ! asn1_read_OctetString_talloc ( msg , data ,
2004-08-12 08:55:59 +04:00
& attr ) )
return False ;
2005-06-15 04:27:51 +04:00
if ( ! add_string_to_array ( msg , attr ,
2004-08-12 08:55:59 +04:00
& r - > attributes ,
& r - > num_attributes ) )
return False ;
}
asn1_end_tag ( data ) ;
asn1_end_tag ( data ) ;
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_SearchResultEntry ) : {
struct ldap_SearchResEntry * r = & msg - > r . SearchResultEntry ;
msg - > type = LDAP_TAG_SearchResultEntry ;
r - > attributes = NULL ;
r - > num_attributes = 0 ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
asn1_read_OctetString_talloc ( msg , data , & r - > dn ) ;
ldap_decode_attribs ( msg , data , & r - > attributes ,
2004-08-12 08:55:59 +04:00
& r - > num_attributes ) ;
asn1_end_tag ( data ) ;
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_SearchResultDone ) : {
2004-08-12 10:37:12 +04:00
struct ldap_Result * r = & msg - > r . SearchResultDone ;
2004-08-12 08:55:59 +04:00
msg - > type = LDAP_TAG_SearchResultDone ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
ldap_decode_response ( msg , data , r ) ;
2004-10-08 16:08:43 +04:00
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_SearchResultReference ) : {
2004-11-06 23:43:36 +03:00
struct ldap_SearchResRef * r = & msg - > r . SearchResultReference ;
2004-08-12 08:55:59 +04:00
msg - > type = LDAP_TAG_SearchResultReference ;
2004-11-06 23:43:36 +03:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
asn1_read_OctetString_talloc ( msg , data , & r - > referral ) ;
2004-11-06 23:43:36 +03:00
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_ModifyRequest ) : {
struct ldap_ModifyRequest * r = & msg - > r . ModifyRequest ;
msg - > type = LDAP_TAG_ModifyRequest ;
asn1_start_tag ( data , ASN1_APPLICATION ( LDAP_TAG_ModifyRequest ) ) ;
2005-06-15 04:27:51 +04:00
asn1_read_OctetString_talloc ( msg , data , & r - > dn ) ;
2004-08-12 08:55:59 +04:00
asn1_start_tag ( data , ASN1_SEQUENCE ( 0 ) ) ;
r - > num_mods = 0 ;
r - > mods = NULL ;
while ( asn1_tag_remaining ( data ) > 0 ) {
struct ldap_mod mod ;
2004-11-02 14:16:34 +03:00
int v ;
2004-08-12 08:55:59 +04:00
ZERO_STRUCT ( mod ) ;
asn1_start_tag ( data , ASN1_SEQUENCE ( 0 ) ) ;
2004-11-02 14:16:34 +03:00
asn1_read_enumerated ( data , & v ) ;
mod . type = v ;
2005-06-15 04:27:51 +04:00
ldap_decode_attrib ( msg , data , & mod . attrib ) ;
2004-08-12 08:55:59 +04:00
asn1_end_tag ( data ) ;
2005-06-15 04:27:51 +04:00
if ( ! add_mod_to_array_talloc ( msg , & mod ,
2004-08-12 08:55:59 +04:00
& r - > mods , & r - > num_mods ) )
break ;
}
asn1_end_tag ( data ) ;
asn1_end_tag ( data ) ;
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_ModifyResponse ) : {
2004-08-12 10:37:12 +04:00
struct ldap_Result * r = & msg - > r . ModifyResponse ;
2004-08-12 08:55:59 +04:00
msg - > type = LDAP_TAG_ModifyResponse ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
ldap_decode_response ( msg , data , r ) ;
2004-10-08 16:08:43 +04:00
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_AddRequest ) : {
struct ldap_AddRequest * r = & msg - > r . AddRequest ;
msg - > type = LDAP_TAG_AddRequest ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
asn1_read_OctetString_talloc ( msg , data , & r - > dn ) ;
2004-08-12 08:55:59 +04:00
r - > attributes = NULL ;
r - > num_attributes = 0 ;
2005-06-15 04:27:51 +04:00
ldap_decode_attribs ( msg , data , & r - > attributes ,
2004-08-12 08:55:59 +04:00
& r - > num_attributes ) ;
asn1_end_tag ( data ) ;
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_AddResponse ) : {
2004-08-12 10:37:12 +04:00
struct ldap_Result * r = & msg - > r . AddResponse ;
2004-08-12 08:55:59 +04:00
msg - > type = LDAP_TAG_AddResponse ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
ldap_decode_response ( msg , data , r ) ;
2004-10-08 16:08:43 +04:00
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
2004-09-27 19:40:12 +04:00
case ASN1_APPLICATION_SIMPLE ( LDAP_TAG_DelRequest ) : {
struct ldap_DelRequest * r = & msg - > r . DelRequest ;
2004-08-12 08:55:59 +04:00
int len ;
char * dn ;
2004-09-27 19:40:12 +04:00
msg - > type = LDAP_TAG_DelRequest ;
2004-08-12 08:55:59 +04:00
asn1_start_tag ( data ,
2004-09-27 19:40:12 +04:00
ASN1_APPLICATION_SIMPLE ( LDAP_TAG_DelRequest ) ) ;
2004-08-12 08:55:59 +04:00
len = asn1_tag_remaining ( data ) ;
2005-06-15 04:27:51 +04:00
dn = talloc_size ( msg , len + 1 ) ;
2004-08-12 08:55:59 +04:00
if ( dn = = NULL )
break ;
asn1_read ( data , dn , len ) ;
dn [ len ] = ' \0 ' ;
r - > dn = dn ;
asn1_end_tag ( data ) ;
break ;
}
2004-09-27 19:40:12 +04:00
case ASN1_APPLICATION ( LDAP_TAG_DelResponse ) : {
struct ldap_Result * r = & msg - > r . DelResponse ;
msg - > type = LDAP_TAG_DelResponse ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
ldap_decode_response ( msg , data , r ) ;
2004-10-08 16:08:43 +04:00
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_ModifyDNRequest ) : {
2004-08-17 15:22:44 +04:00
struct ldap_ModifyDNRequest * r = & msg - > r . ModifyDNRequest ;
2004-08-12 08:55:59 +04:00
msg - > type = LDAP_TAG_ModifyDNRequest ;
2004-08-17 15:22:44 +04:00
asn1_start_tag ( data ,
ASN1_APPLICATION ( LDAP_TAG_ModifyDNRequest ) ) ;
2005-06-15 04:27:51 +04:00
asn1_read_OctetString_talloc ( msg , data , & r - > dn ) ;
asn1_read_OctetString_talloc ( msg , data , & r - > newrdn ) ;
2004-09-01 18:49:43 +04:00
asn1_read_BOOLEAN ( data , & r - > deleteolddn ) ;
2004-08-17 15:22:44 +04:00
r - > newsuperior = NULL ;
if ( asn1_tag_remaining ( data ) > 0 ) {
int len ;
char * newsup ;
asn1_start_tag ( data , ASN1_CONTEXT_SIMPLE ( 0 ) ) ;
len = asn1_tag_remaining ( data ) ;
2005-06-15 04:27:51 +04:00
newsup = talloc_size ( msg , len + 1 ) ;
2004-08-17 15:22:44 +04:00
if ( newsup = = NULL )
break ;
asn1_read ( data , newsup , len ) ;
newsup [ len ] = ' \0 ' ;
r - > newsuperior = newsup ;
asn1_end_tag ( data ) ;
}
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_ModifyDNResponse ) : {
2004-08-12 10:37:12 +04:00
struct ldap_Result * r = & msg - > r . ModifyDNResponse ;
2004-08-12 08:55:59 +04:00
msg - > type = LDAP_TAG_ModifyDNResponse ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
ldap_decode_response ( msg , data , r ) ;
2004-10-08 16:08:43 +04:00
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_CompareRequest ) : {
2004-09-29 16:18:06 +04:00
struct ldap_CompareRequest * r = & msg - > r . CompareRequest ;
2004-08-12 08:55:59 +04:00
msg - > type = LDAP_TAG_CompareRequest ;
2004-09-29 16:18:06 +04:00
asn1_start_tag ( data ,
ASN1_APPLICATION ( LDAP_TAG_CompareRequest ) ) ;
2005-06-15 04:27:51 +04:00
asn1_read_OctetString_talloc ( msg , data , & r - > dn ) ;
2004-09-29 16:18:06 +04:00
asn1_start_tag ( data , ASN1_SEQUENCE ( 0 ) ) ;
2005-06-15 04:27:51 +04:00
asn1_read_OctetString_talloc ( msg , data , & r - > attribute ) ;
2004-09-29 16:18:06 +04:00
asn1_read_OctetString ( data , & r - > value ) ;
if ( r - > value . data ) {
2005-06-15 04:27:51 +04:00
talloc_steal ( msg , r - > value . data ) ;
2004-09-29 16:18:06 +04:00
}
asn1_end_tag ( data ) ;
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_CompareResponse ) : {
2004-08-12 10:37:12 +04:00
struct ldap_Result * r = & msg - > r . CompareResponse ;
2004-08-12 08:55:59 +04:00
msg - > type = LDAP_TAG_CompareResponse ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
ldap_decode_response ( msg , data , r ) ;
2004-10-08 16:08:43 +04:00
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
2004-09-29 17:06:26 +04:00
case ASN1_APPLICATION_SIMPLE ( LDAP_TAG_AbandonRequest ) : {
struct ldap_AbandonRequest * r = & msg - > r . AbandonRequest ;
2004-08-12 08:55:59 +04:00
msg - > type = LDAP_TAG_AbandonRequest ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2004-09-29 17:06:26 +04:00
asn1_read_implicit_Integer ( data , & r - > messageid ) ;
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_ExtendedRequest ) : {
2004-09-22 14:42:58 +04:00
struct ldap_ExtendedRequest * r = & msg - > r . ExtendedRequest ;
DATA_BLOB tmp_blob = data_blob ( NULL , 0 ) ;
2004-08-12 08:55:59 +04:00
msg - > type = LDAP_TAG_ExtendedRequest ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2004-09-22 14:42:58 +04:00
if ( ! asn1_read_ContextSimple ( data , 0 , & tmp_blob ) ) {
return False ;
}
2005-06-15 04:27:51 +04:00
r - > oid = blob2string_talloc ( msg , tmp_blob ) ;
2004-09-22 14:42:58 +04:00
data_blob_free ( & tmp_blob ) ;
if ( ! r - > oid ) {
return False ;
}
if ( asn1_peek_tag ( data , ASN1_CONTEXT_SIMPLE ( 1 ) ) ) {
asn1_read_ContextSimple ( data , 1 , & tmp_blob ) ;
2005-06-15 04:27:51 +04:00
r - > value = data_blob_talloc ( msg , tmp_blob . data , tmp_blob . length ) ;
2004-09-22 14:42:58 +04:00
data_blob_free ( & tmp_blob ) ;
} else {
r - > value = data_blob ( NULL , 0 ) ;
}
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
case ASN1_APPLICATION ( LDAP_TAG_ExtendedResponse ) : {
struct ldap_ExtendedResponse * r = & msg - > r . ExtendedResponse ;
msg - > type = LDAP_TAG_ExtendedResponse ;
2004-10-08 16:08:43 +04:00
asn1_start_tag ( data , tag ) ;
2005-06-15 04:27:51 +04:00
ldap_decode_response ( msg , data , & r - > response ) ;
2004-08-12 08:55:59 +04:00
/* I have to come across an operation that actually sends
* something back to really see what ' s going on . The currently
* needed pwdchange does not send anything back . */
r - > name = NULL ;
r - > value . data = NULL ;
r - > value . length = 0 ;
2004-10-08 16:08:43 +04:00
asn1_end_tag ( data ) ;
2004-08-12 08:55:59 +04:00
break ;
}
2004-09-22 14:42:58 +04:00
default :
return False ;
2004-08-12 08:55:59 +04:00
}
2004-10-10 03:59:12 +04:00
msg - > num_controls = 0 ;
msg - > controls = NULL ;
if ( asn1_peek_tag ( data , ASN1_CONTEXT ( 0 ) ) ) {
int i ;
struct ldap_Control * ctrl = NULL ;
asn1_start_tag ( data , ASN1_CONTEXT ( 0 ) ) ;
for ( i = 0 ; asn1_peek_tag ( data , ASN1_SEQUENCE ( 0 ) ) ; i + + ) {
asn1_start_tag ( data , ASN1_SEQUENCE ( 0 ) ) ;
2005-06-15 04:27:51 +04:00
ctrl = talloc_realloc ( msg , ctrl , struct ldap_Control , i + 1 ) ;
2004-10-10 03:59:12 +04:00
if ( ! ctrl ) {
return False ;
}
ctrl [ i ] . oid = NULL ;
ctrl [ i ] . critical = False ;
ctrl [ i ] . value = data_blob ( NULL , 0 ) ;
asn1_read_OctetString_talloc ( ctrl , data , & ctrl [ i ] . oid ) ;
if ( asn1_peek_tag ( data , ASN1_BOOLEAN ) ) {
asn1_read_BOOLEAN ( data , & ctrl [ i ] . critical ) ;
}
if ( asn1_peek_tag ( data , ASN1_OCTET_STRING ) ) {
asn1_read_OctetString ( data , & ctrl [ i ] . value ) ;
if ( ctrl [ i ] . value . data ) {
2005-06-15 04:27:51 +04:00
talloc_steal ( msg , ctrl [ i ] . value . data ) ;
2004-10-10 03:59:12 +04:00
}
}
asn1_end_tag ( data ) ;
}
msg - > num_controls = i ;
msg - > controls = ctrl ;
asn1_end_tag ( data ) ;
}
2004-08-12 08:55:59 +04:00
asn1_end_tag ( data ) ;
return ( ( ! data - > has_error ) & & ( data - > nesting = = NULL ) ) ;
}
2005-05-10 05:57:47 +04:00