2006-11-16 13:47:15 +03:00
/*
Unix SMB / CIFS implementation .
CLDAP server - rootdse handling
Copyright ( C ) Stefan Metzmacher 2006
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2006-11-16 13:47:15 +03:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-11-16 13:47:15 +03:00
*/
# include "includes.h"
2009-02-13 15:13:54 +03:00
# include <tevent.h>
2011-02-10 06:12:51 +03:00
# include <ldb.h>
# include <ldb_errors.h>
2020-11-20 17:27:17 +03:00
# include "samba/service_task.h"
2006-11-16 13:47:15 +03:00
# include "cldap_server/cldap_server.h"
# include "librpc/gen_ndr/ndr_misc.h"
# include "dsdb/samdb/samdb.h"
2007-11-16 22:12:00 +03:00
# include "ldb_wrap.h"
2006-11-16 13:47:15 +03:00
static void cldapd_rootdse_fill ( struct cldapd_server * cldapd ,
TALLOC_CTX * mem_ctx ,
struct ldap_SearchRequest * search ,
struct ldap_SearchResEntry * * response ,
struct ldap_Result * result )
{
struct ldap_SearchResEntry * ent = NULL ;
struct ldb_result * res = NULL ;
struct ldb_request * lreq ;
const char * * attrs = NULL ;
const char * errstr = NULL ;
2010-06-18 21:11:35 +04:00
int ret = LDAP_SUCCESS , ldb_ret ;
2006-11-16 13:47:15 +03:00
if ( search - > num_attributes > = 1 ) {
int i ;
attrs = talloc_array ( mem_ctx , const char * , search - > num_attributes + 1 ) ;
if ( attrs = = NULL ) goto nomem ;
for ( i = 0 ; i < search - > num_attributes ; i + + ) {
attrs [ i ] = search - > attributes [ i ] ;
}
attrs [ i ] = NULL ;
}
res = talloc_zero ( mem_ctx , struct ldb_result ) ;
if ( res = = NULL ) goto nomem ;
2008-09-12 02:38:40 +04:00
ldb_ret = ldb_build_search_req_ex ( & lreq , cldapd - > samctx , mem_ctx ,
2010-06-18 21:11:35 +04:00
NULL , LDB_SCOPE_BASE ,
2008-09-12 02:38:40 +04:00
search - > tree , attrs ,
NULL ,
res , ldb_search_default_callback ,
NULL ) ;
2006-11-16 13:47:15 +03:00
2008-09-12 02:38:40 +04:00
if ( ldb_ret ! = LDB_SUCCESS ) {
goto reply ;
}
2006-11-16 13:47:15 +03:00
/* Copy the timeout from the incoming call */
ldb_set_timeout ( cldapd - > samctx , lreq , search - > timelimit ) ;
ldb_ret = ldb_request ( cldapd - > samctx , lreq ) ;
if ( ldb_ret ! = LDB_SUCCESS ) {
goto reply ;
}
ldb_ret = ldb_wait ( lreq - > handle , LDB_WAIT_ALL ) ;
if ( ldb_ret ! = LDB_SUCCESS ) {
goto reply ;
}
if ( res - > count > 1 ) {
errstr = " Internal error: to much replies " ;
ldb_ret = LDB_ERR_OTHER ;
goto reply ;
} else if ( res - > count = = 1 ) {
int j ;
ent = talloc ( mem_ctx , struct ldap_SearchResEntry ) ;
if ( ent = = NULL ) goto nomem ;
2006-11-22 05:05:19 +03:00
ent - > dn = ldb_dn_alloc_linearized ( ent , res - > msgs [ 0 ] - > dn ) ;
2006-11-16 13:47:15 +03:00
if ( ent - > dn = = NULL ) goto nomem ;
ent - > num_attributes = 0 ;
ent - > attributes = NULL ;
if ( res - > msgs [ 0 ] - > num_elements = = 0 ) {
goto reply ;
}
ent - > num_attributes = res - > msgs [ 0 ] - > num_elements ;
2010-06-18 21:11:35 +04:00
ent - > attributes = talloc_array ( ent , struct ldb_message_element ,
ent - > num_attributes ) ;
2006-11-16 13:47:15 +03:00
if ( ent - > attributes = = NULL ) goto nomem ;
for ( j = 0 ; j < ent - > num_attributes ; j + + ) {
2010-06-18 21:11:35 +04:00
ent - > attributes [ j ] . name = talloc_steal ( ent - > attributes ,
res - > msgs [ 0 ] - > elements [ j ] . name ) ;
2006-11-16 13:47:15 +03:00
ent - > attributes [ j ] . num_values = 0 ;
ent - > attributes [ j ] . values = NULL ;
if ( search - > attributesonly & & ( res - > msgs [ 0 ] - > elements [ j ] . num_values = = 0 ) ) {
continue ;
}
ent - > attributes [ j ] . num_values = res - > msgs [ 0 ] - > elements [ j ] . num_values ;
ent - > attributes [ j ] . values = res - > msgs [ 0 ] - > elements [ j ] . values ;
talloc_steal ( ent - > attributes , res - > msgs [ 0 ] - > elements [ j ] . values ) ;
}
}
reply :
2010-06-18 21:11:35 +04:00
if ( ret ! = LDAP_SUCCESS ) {
2006-11-16 13:47:15 +03:00
/* nothing ... */
} else if ( ldb_ret = = LDB_SUCCESS ) {
ret = LDAP_SUCCESS ;
errstr = NULL ;
} else {
ret = ldb_ret ;
errstr = ldb_errstring ( cldapd - > samctx ) ;
}
goto done ;
nomem :
talloc_free ( ent ) ;
ret = LDAP_OPERATIONS_ERROR ;
errstr = " No memory " ;
done :
* response = ent ;
result - > resultcode = ret ;
result - > errormessage = ( errstr ? talloc_strdup ( mem_ctx , errstr ) : NULL ) ;
}
/*
handle incoming cldap requests
*/
void cldapd_rootdse_request ( struct cldap_socket * cldap ,
2009-02-13 15:13:54 +03:00
struct cldapd_server * cldapd ,
TALLOC_CTX * tmp_ctx ,
2006-11-16 13:47:15 +03:00
uint32_t message_id ,
struct ldap_SearchRequest * search ,
2009-02-13 15:13:54 +03:00
struct tsocket_address * src )
2006-11-16 13:47:15 +03:00
{
NTSTATUS status ;
struct cldap_reply reply ;
struct ldap_Result result ;
ZERO_STRUCT ( result ) ;
reply . messageid = message_id ;
reply . dest = src ;
reply . response = NULL ;
reply . result = & result ;
2013-11-01 13:52:02 +04:00
/* Note: The remoteAddress should rather be set on a ldb request.
* We can set this savely on the context here ,
* since cldapd_rootdse_fill operates synchronously . */
ldb_set_opaque ( cldapd - > samctx , " remoteAddress " , src ) ;
2010-06-18 21:11:35 +04:00
cldapd_rootdse_fill ( cldapd , tmp_ctx , search , & reply . response ,
reply . result ) ;
2006-11-16 13:47:15 +03:00
2018-04-04 03:38:25 +03:00
/*
* We clear this after cldapd_rootdse_fill as this is shared ldb
* and if it was not cleared the audit logging would report changes
* made by internal processes as coming from the last cldap requester
*/
ldb_set_opaque ( cldapd - > samctx , " remoteAddress " , NULL ) ;
2006-11-16 13:47:15 +03:00
status = cldap_reply_send ( cldap , & reply ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 2 , ( " cldap rootdse query failed '%s' - %s \n " ,
ldb_filter_from_tree ( tmp_ctx , search - > tree ) , nt_errstr ( status ) ) ) ;
}
return ;
}