2006-12-12 17:52:13 +03:00
/*
Unix SMB / CIFS implementation .
idmap LDAP backend
Copyright ( C ) Tim Potter 2000
Copyright ( C ) Jim McDonough < jmcd @ us . ibm . com > 2003
Copyright ( C ) Gerald Carter 2003
2007-09-10 23:04:57 +04:00
Copyright ( C ) Simo Sorce 2003 - 2007
2006-12-12 17:52:13 +03: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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2006-12-12 17:52:13 +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 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-12-12 17:52:13 +03:00
*/
# include "includes.h"
2007-03-11 19:49:16 +03:00
# include "winbindd.h"
2006-12-12 17:52:13 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_IDMAP
# include <lber.h>
# include <ldap.h>
# include "smbldap.h"
2007-02-06 20:29:18 +03:00
struct idmap_ldap_context {
struct smbldap_state * smbldap_state ;
char * url ;
char * suffix ;
char * user_dn ;
uint32_t filter_low_id , filter_high_id ; /* Filter range */
2007-10-19 04:40:25 +04:00
bool anon ;
2007-02-06 20:29:18 +03:00
} ;
2006-12-12 17:52:13 +03:00
struct idmap_ldap_alloc_context {
struct smbldap_state * smbldap_state ;
char * url ;
char * suffix ;
char * user_dn ;
uid_t low_uid , high_uid ; /* Range of uids */
gid_t low_gid , high_gid ; /* Range of gids */
} ;
2007-09-10 23:04:57 +04:00
# define CHECK_ALLOC_DONE(mem) do { \
if ( ! mem ) { \
DEBUG ( 0 , ( " Out of memory! \n " ) ) ; \
ret = NT_STATUS_NO_MEMORY ; \
goto done ; \
} } while ( 0 )
2006-12-12 17:52:13 +03:00
/**********************************************************************
IDMAP ALLOC TDB BACKEND
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
static struct idmap_ldap_alloc_context * idmap_alloc_ldap ;
2007-02-06 20:29:18 +03:00
/*********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-10 23:04:57 +04:00
static NTSTATUS get_credentials ( TALLOC_CTX * mem_ctx ,
2007-02-06 20:29:18 +03:00
struct smbldap_state * ldap_state ,
const char * config_option ,
struct idmap_domain * dom ,
char * * dn )
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL ;
char * secret = NULL ;
const char * tmp = NULL ;
2007-09-10 23:04:57 +04:00
char * user_dn = NULL ;
2007-10-19 04:40:25 +04:00
bool anon = False ;
2007-09-10 23:04:57 +04:00
2007-02-06 20:29:18 +03:00
/* assume anonymous if we don't have a specified user */
tmp = lp_parm_const_string ( - 1 , config_option , " ldap_user_dn " , NULL ) ;
if ( tmp ) {
2007-05-03 16:28:25 +04:00
if ( ! dom ) {
2007-09-10 23:04:57 +04:00
/* only the alloc backend can pass in a NULL dom */
2007-09-10 23:19:59 +04:00
secret = idmap_fetch_secret ( " ldap " , True ,
2007-09-10 23:04:57 +04:00
NULL , tmp ) ;
2007-05-03 16:28:25 +04:00
} else {
2007-09-10 23:19:59 +04:00
secret = idmap_fetch_secret ( " ldap " , False ,
2007-09-10 23:04:57 +04:00
dom - > name , tmp ) ;
}
2007-05-03 16:28:25 +04:00
2007-02-06 20:29:18 +03:00
if ( ! secret ) {
DEBUG ( 0 , ( " get_credentials: Unable to fetch "
" auth credentials for %s in %s \n " ,
2007-05-03 16:28:25 +04:00
tmp , ( dom = = NULL ) ? " ALLOC " : dom - > name ) ) ;
2007-02-06 20:29:18 +03:00
ret = NT_STATUS_ACCESS_DENIED ;
goto done ;
2007-09-10 23:04:57 +04:00
}
2007-02-06 20:29:18 +03:00
* dn = talloc_strdup ( mem_ctx , tmp ) ;
2007-09-10 23:04:57 +04:00
CHECK_ALLOC_DONE ( * dn ) ;
2007-02-06 20:29:18 +03:00
} else {
2007-09-10 23:04:57 +04:00
if ( ! fetch_ldap_pw ( & user_dn , & secret ) ) {
2007-02-06 20:29:18 +03:00
DEBUG ( 2 , ( " get_credentials: Failed to lookup ldap "
2007-09-10 23:04:57 +04:00
" bind creds. Using anonymous connection. \n " ) ) ;
2007-09-10 23:19:59 +04:00
anon = True ;
2007-02-06 20:29:18 +03:00
} else {
* dn = talloc_strdup ( mem_ctx , user_dn ) ;
2007-09-10 23:04:57 +04:00
SAFE_FREE ( user_dn ) ;
2007-02-06 20:29:18 +03:00
CHECK_ALLOC_DONE ( * dn ) ;
2007-09-10 23:04:57 +04:00
}
2007-02-06 20:29:18 +03:00
}
2007-09-10 23:14:22 +04:00
smbldap_set_creds ( ldap_state , anon , * dn , secret ) ;
2007-02-06 20:29:18 +03:00
ret = NT_STATUS_OK ;
2007-09-10 23:04:57 +04:00
2007-09-10 23:14:22 +04:00
done :
2007-09-10 23:04:57 +04:00
SAFE_FREE ( secret ) ;
2007-02-06 20:29:18 +03:00
2007-09-10 23:04:57 +04:00
return ret ;
2007-02-06 20:29:18 +03:00
}
2006-12-12 17:52:13 +03:00
/**********************************************************************
2007-09-10 23:04:57 +04:00
Verify the sambaUnixIdPool entry in the directory .
2006-12-12 17:52:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS verify_idpool ( void )
{
NTSTATUS ret ;
TALLOC_CTX * ctx ;
LDAPMessage * result = NULL ;
LDAPMod * * mods = NULL ;
const char * * attr_list ;
char * filter ;
int count ;
int rc ;
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
if ( ! idmap_alloc_ldap ) {
return NT_STATUS_UNSUCCESSFUL ;
}
ctx = talloc_new ( idmap_alloc_ldap ) ;
if ( ! ctx ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
filter = talloc_asprintf ( ctx , " (objectclass=%s) " , LDAP_OBJ_IDPOOL ) ;
CHECK_ALLOC_DONE ( filter ) ;
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
attr_list = get_attr_list ( ctx , idpool_attr_list ) ;
CHECK_ALLOC_DONE ( attr_list ) ;
rc = smbldap_search ( idmap_alloc_ldap - > smbldap_state ,
2007-09-10 23:04:57 +04:00
idmap_alloc_ldap - > suffix ,
2006-12-12 17:52:13 +03:00
LDAP_SCOPE_SUBTREE ,
filter ,
attr_list ,
0 ,
& result ) ;
if ( rc ! = LDAP_SUCCESS ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 1 , ( " Unable to verify the idpool, "
" cannot continue initialization! \n " ) ) ;
2006-12-12 17:52:13 +03:00
return NT_STATUS_UNSUCCESSFUL ;
}
2007-09-10 23:04:57 +04:00
count = ldap_count_entries ( idmap_alloc_ldap - > smbldap_state - > ldap_struct ,
result ) ;
2006-12-12 17:52:13 +03:00
ldap_msgfree ( result ) ;
if ( count > 1 ) {
DEBUG ( 0 , ( " Multiple entries returned from %s (base == %s) \n " ,
filter , idmap_alloc_ldap - > suffix ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
else if ( count = = 0 ) {
char * uid_str , * gid_str ;
2007-09-10 23:04:57 +04:00
uid_str = talloc_asprintf ( ctx , " %lu " ,
( unsigned long ) idmap_alloc_ldap - > low_uid ) ;
gid_str = talloc_asprintf ( ctx , " %lu " ,
( unsigned long ) idmap_alloc_ldap - > low_gid ) ;
2006-12-12 17:52:13 +03:00
smbldap_set_mod ( & mods , LDAP_MOD_ADD ,
" objectClass " , LDAP_OBJ_IDPOOL ) ;
2007-09-10 23:04:57 +04:00
smbldap_set_mod ( & mods , LDAP_MOD_ADD ,
get_attr_key2string ( idpool_attr_list ,
LDAP_ATTR_UIDNUMBER ) ,
2006-12-12 17:52:13 +03:00
uid_str ) ;
smbldap_set_mod ( & mods , LDAP_MOD_ADD ,
2007-09-10 23:04:57 +04:00
get_attr_key2string ( idpool_attr_list ,
LDAP_ATTR_GIDNUMBER ) ,
2006-12-12 17:52:13 +03:00
gid_str ) ;
if ( mods ) {
rc = smbldap_modify ( idmap_alloc_ldap - > smbldap_state ,
idmap_alloc_ldap - > suffix ,
mods ) ;
ldap_mods_free ( mods , True ) ;
} else {
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
}
ret = ( rc = = LDAP_SUCCESS ) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
done :
talloc_free ( ctx ) ;
return ret ;
}
/*****************************************************************************
2007-09-10 23:04:57 +04:00
Initialise idmap database .
2006-12-12 17:52:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS idmap_ldap_alloc_init ( const char * params )
{
2007-09-10 23:04:57 +04:00
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL ;
2006-12-12 17:52:13 +03:00
const char * range ;
const char * tmp ;
2006-12-16 21:37:33 +03:00
uid_t low_uid = 0 ;
uid_t high_uid = 0 ;
gid_t low_gid = 0 ;
gid_t high_gid = 0 ;
2006-12-12 17:52:13 +03:00
2007-04-19 01:10:37 +04:00
/* Only do init if we are online */
if ( idmap_is_offline ( ) ) {
return NT_STATUS_FILE_IS_OFFLINE ;
}
2007-04-28 03:18:41 +04:00
idmap_alloc_ldap = TALLOC_ZERO_P ( NULL , struct idmap_ldap_alloc_context ) ;
2007-02-06 20:29:18 +03:00
CHECK_ALLOC_DONE ( idmap_alloc_ldap ) ;
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
/* load ranges */
2007-02-06 20:29:18 +03:00
2006-12-12 17:52:13 +03:00
idmap_alloc_ldap - > low_uid = 0 ;
idmap_alloc_ldap - > high_uid = 0 ;
idmap_alloc_ldap - > low_gid = 0 ;
idmap_alloc_ldap - > high_gid = 0 ;
range = lp_parm_const_string ( - 1 , " idmap alloc config " , " range " , NULL ) ;
if ( range & & range [ 0 ] ) {
2006-12-16 21:37:33 +03:00
unsigned low_id , high_id ;
2006-12-12 17:52:13 +03:00
if ( sscanf ( range , " %u - %u " , & low_id , & high_id ) = = 2 ) {
if ( low_id < high_id ) {
2007-09-10 23:04:57 +04:00
idmap_alloc_ldap - > low_gid = low_id ;
idmap_alloc_ldap - > low_uid = low_id ;
idmap_alloc_ldap - > high_gid = high_id ;
idmap_alloc_ldap - > high_uid = high_id ;
2006-12-12 17:52:13 +03:00
} else {
2007-09-10 23:04:57 +04:00
DEBUG ( 1 , ( " ERROR: invalid idmap alloc range "
" [%s] " , range ) ) ;
2006-12-12 17:52:13 +03:00
}
} else {
2007-09-10 23:04:57 +04:00
DEBUG ( 1 , ( " ERROR: invalid syntax for idmap alloc "
" config:range [%s] " , range ) ) ;
2006-12-12 17:52:13 +03:00
}
}
2006-12-16 21:37:33 +03:00
if ( lp_idmap_uid ( & low_uid , & high_uid ) ) {
idmap_alloc_ldap - > low_uid = low_uid ;
idmap_alloc_ldap - > high_uid = high_uid ;
2006-12-12 17:52:13 +03:00
}
2006-12-16 21:37:33 +03:00
if ( lp_idmap_gid ( & low_gid , & high_gid ) ) {
idmap_alloc_ldap - > low_gid = low_gid ;
idmap_alloc_ldap - > high_gid = high_gid ;
2006-12-12 17:52:13 +03:00
}
if ( idmap_alloc_ldap - > high_uid < = idmap_alloc_ldap - > low_uid ) {
DEBUG ( 1 , ( " idmap uid range missing or invalid \n " ) ) ;
DEBUGADD ( 1 , ( " idmap will be unable to map foreign SIDs \n " ) ) ;
2007-02-06 20:29:18 +03:00
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
2006-12-12 17:52:13 +03:00
}
if ( idmap_alloc_ldap - > high_gid < = idmap_alloc_ldap - > low_gid ) {
DEBUG ( 1 , ( " idmap gid range missing or invalid \n " ) ) ;
DEBUGADD ( 1 , ( " idmap will be unable to map foreign SIDs \n " ) ) ;
2007-02-06 20:29:18 +03:00
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
2006-12-12 17:52:13 +03:00
}
if ( params & & * params ) {
/* assume location is the only parameter */
idmap_alloc_ldap - > url = talloc_strdup ( idmap_alloc_ldap , params ) ;
} else {
2007-09-10 23:04:57 +04:00
tmp = lp_parm_const_string ( - 1 , " idmap alloc config " ,
" ldap_url " , NULL ) ;
2006-12-12 17:52:13 +03:00
if ( ! tmp ) {
DEBUG ( 1 , ( " ERROR: missing idmap ldap url \n " ) ) ;
2007-02-06 20:29:18 +03:00
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
2006-12-12 17:52:13 +03:00
}
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
idmap_alloc_ldap - > url = talloc_strdup ( idmap_alloc_ldap , tmp ) ;
}
2007-02-06 20:29:18 +03:00
CHECK_ALLOC_DONE ( idmap_alloc_ldap - > url ) ;
2006-12-12 17:52:13 +03:00
2007-09-10 23:04:57 +04:00
tmp = lp_parm_const_string ( - 1 , " idmap alloc config " ,
" ldap_base_dn " , NULL ) ;
2006-12-12 17:52:13 +03:00
if ( ! tmp | | ! * tmp ) {
2007-09-10 20:21:55 +04:00
tmp = lp_ldap_idmap_suffix ( ) ;
2007-02-06 20:29:18 +03:00
if ( ! tmp ) {
DEBUG ( 1 , ( " ERROR: missing idmap ldap suffix \n " ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
2006-12-12 17:52:13 +03:00
}
2007-02-06 20:29:18 +03:00
idmap_alloc_ldap - > suffix = talloc_strdup ( idmap_alloc_ldap , tmp ) ;
CHECK_ALLOC_DONE ( idmap_alloc_ldap - > suffix ) ;
2007-09-10 23:04:57 +04:00
2007-03-11 19:49:16 +03:00
ret = smbldap_init ( idmap_alloc_ldap , winbind_event_context ( ) ,
idmap_alloc_ldap - > url ,
2007-09-10 23:04:57 +04:00
& idmap_alloc_ldap - > smbldap_state ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 1 , ( " ERROR: smbldap_init (%s) failed! \n " ,
2007-02-06 20:29:18 +03:00
idmap_alloc_ldap - > url ) ) ;
2007-09-10 23:04:57 +04:00
goto done ;
2006-12-12 17:52:13 +03:00
}
2007-09-10 23:04:57 +04:00
ret = get_credentials ( idmap_alloc_ldap ,
idmap_alloc_ldap - > smbldap_state ,
2007-02-06 20:29:18 +03:00
" idmap alloc config " , NULL ,
& idmap_alloc_ldap - > user_dn ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 1 , ( " idmap_ldap_alloc_init: Failed to get connection "
" credentials (%s) \n " , nt_errstr ( ret ) ) ) ;
goto done ;
2007-09-10 23:04:57 +04:00
}
2006-12-12 17:52:13 +03:00
/* see if the idmap suffix and sub entries exists */
2007-09-10 23:04:57 +04:00
ret = verify_idpool ( ) ;
2007-02-06 20:29:18 +03:00
done :
if ( ! NT_STATUS_IS_OK ( ret ) )
TALLOC_FREE ( idmap_alloc_ldap ) ;
2007-09-10 23:04:57 +04:00
2007-02-06 20:29:18 +03:00
return ret ;
2006-12-12 17:52:13 +03:00
}
/********************************
Allocate a new uid or gid
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS idmap_ldap_allocate_id ( struct unixid * xid )
{
TALLOC_CTX * ctx ;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL ;
int rc = LDAP_SERVER_DOWN ;
int count = 0 ;
LDAPMessage * result = NULL ;
LDAPMessage * entry = NULL ;
LDAPMod * * mods = NULL ;
char * id_str ;
char * new_id_str ;
char * filter = NULL ;
const char * dn = NULL ;
const char * * attr_list ;
const char * type ;
2007-04-19 01:10:37 +04:00
/* Only do query if we are online */
if ( idmap_is_offline ( ) ) {
return NT_STATUS_FILE_IS_OFFLINE ;
}
2006-12-12 17:52:13 +03:00
if ( ! idmap_alloc_ldap ) {
return NT_STATUS_UNSUCCESSFUL ;
}
ctx = talloc_new ( idmap_alloc_ldap ) ;
if ( ! ctx ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
/* get type */
switch ( xid - > type ) {
case ID_TYPE_UID :
2007-09-10 23:04:57 +04:00
type = get_attr_key2string ( idpool_attr_list ,
LDAP_ATTR_UIDNUMBER ) ;
2006-12-12 17:52:13 +03:00
break ;
case ID_TYPE_GID :
2007-09-10 23:04:57 +04:00
type = get_attr_key2string ( idpool_attr_list ,
LDAP_ATTR_GIDNUMBER ) ;
2006-12-12 17:52:13 +03:00
break ;
default :
DEBUG ( 2 , ( " Invalid ID type (0x%x) \n " , xid - > type ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
filter = talloc_asprintf ( ctx , " (objectClass=%s) " , LDAP_OBJ_IDPOOL ) ;
CHECK_ALLOC_DONE ( filter ) ;
attr_list = get_attr_list ( ctx , idpool_attr_list ) ;
CHECK_ALLOC_DONE ( attr_list ) ;
DEBUG ( 10 , ( " Search of the id pool (filter: %s) \n " , filter ) ) ;
rc = smbldap_search ( idmap_alloc_ldap - > smbldap_state ,
idmap_alloc_ldap - > suffix ,
LDAP_SCOPE_SUBTREE , filter ,
attr_list , 0 , & result ) ;
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
if ( rc ! = LDAP_SUCCESS ) {
DEBUG ( 0 , ( " %s object not found \n " , LDAP_OBJ_IDPOOL ) ) ;
goto done ;
}
talloc_autofree_ldapmsg ( ctx , result ) ;
2007-09-10 23:04:57 +04:00
count = ldap_count_entries ( idmap_alloc_ldap - > smbldap_state - > ldap_struct ,
result ) ;
2006-12-12 17:52:13 +03:00
if ( count ! = 1 ) {
DEBUG ( 0 , ( " Single %s object not found \n " , LDAP_OBJ_IDPOOL ) ) ;
goto done ;
}
2007-09-10 23:04:57 +04:00
entry = ldap_first_entry ( idmap_alloc_ldap - > smbldap_state - > ldap_struct ,
result ) ;
2006-12-12 17:52:13 +03:00
2007-09-10 23:04:57 +04:00
dn = smbldap_talloc_dn ( ctx ,
idmap_alloc_ldap - > smbldap_state - > ldap_struct ,
entry ) ;
2006-12-12 17:52:13 +03:00
if ( ! dn ) {
goto done ;
}
if ( ! ( id_str = smbldap_talloc_single_attribute ( idmap_alloc_ldap - > smbldap_state - > ldap_struct ,
entry , type , ctx ) ) ) {
DEBUG ( 0 , ( " %s attribute not found \n " , type ) ) ;
goto done ;
}
if ( ! id_str ) {
DEBUG ( 0 , ( " Out of memory \n " ) ) ;
ret = NT_STATUS_NO_MEMORY ;
goto done ;
}
xid - > id = strtoul ( id_str , NULL , 10 ) ;
/* make sure we still have room to grow */
switch ( xid - > type ) {
case ID_TYPE_UID :
if ( xid - > id > idmap_alloc_ldap - > high_uid ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 0 , ( " Cannot allocate uid above %lu! \n " ,
2006-12-12 17:52:13 +03:00
( unsigned long ) idmap_alloc_ldap - > high_uid ) ) ;
goto done ;
}
break ;
2007-09-10 23:04:57 +04:00
case ID_TYPE_GID :
2006-12-12 17:52:13 +03:00
if ( xid - > id > idmap_alloc_ldap - > high_gid ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 0 , ( " Cannot allocate gid above %lu! \n " ,
2006-12-12 17:52:13 +03:00
( unsigned long ) idmap_alloc_ldap - > high_uid ) ) ;
goto done ;
}
break ;
default :
/* impossible */
goto done ;
}
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
new_id_str = talloc_asprintf ( ctx , " %lu " , ( unsigned long ) xid - > id + 1 ) ;
if ( ! new_id_str ) {
DEBUG ( 0 , ( " Out of memory \n " ) ) ;
ret = NT_STATUS_NO_MEMORY ;
goto done ;
}
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
smbldap_set_mod ( & mods , LDAP_MOD_DELETE , type , id_str ) ;
smbldap_set_mod ( & mods , LDAP_MOD_ADD , type , new_id_str ) ;
if ( mods = = NULL ) {
DEBUG ( 0 , ( " smbldap_set_mod() failed. \n " ) ) ;
2007-09-10 23:04:57 +04:00
goto done ;
2006-12-12 17:52:13 +03:00
}
2007-09-10 23:04:57 +04:00
DEBUG ( 10 , ( " Try to atomically increment the id (%s -> %s) \n " ,
id_str , new_id_str ) ) ;
2006-12-12 17:52:13 +03:00
rc = smbldap_modify ( idmap_alloc_ldap - > smbldap_state , dn , mods ) ;
ldap_mods_free ( mods , True ) ;
if ( rc ! = LDAP_SUCCESS ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 1 , ( " Failed to allocate new %s. "
" smbldap_modify() failed. \n " , type ) ) ;
2006-12-12 17:52:13 +03:00
goto done ;
}
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
ret = NT_STATUS_OK ;
done :
talloc_free ( ctx ) ;
return ret ;
}
/**********************************
2007-09-10 23:04:57 +04:00
Get current highest id .
2006-12-12 17:52:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS idmap_ldap_get_hwm ( struct unixid * xid )
{
TALLOC_CTX * memctx ;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL ;
int rc = LDAP_SERVER_DOWN ;
int count = 0 ;
LDAPMessage * result = NULL ;
LDAPMessage * entry = NULL ;
char * id_str ;
char * filter = NULL ;
const char * * attr_list ;
const char * type ;
2007-04-19 01:10:37 +04:00
/* Only do query if we are online */
if ( idmap_is_offline ( ) ) {
return NT_STATUS_FILE_IS_OFFLINE ;
}
2006-12-12 17:52:13 +03:00
if ( ! idmap_alloc_ldap ) {
return NT_STATUS_UNSUCCESSFUL ;
}
memctx = talloc_new ( idmap_alloc_ldap ) ;
if ( ! memctx ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
/* get type */
switch ( xid - > type ) {
case ID_TYPE_UID :
2007-09-10 23:04:57 +04:00
type = get_attr_key2string ( idpool_attr_list ,
LDAP_ATTR_UIDNUMBER ) ;
2006-12-12 17:52:13 +03:00
break ;
case ID_TYPE_GID :
2007-09-10 23:04:57 +04:00
type = get_attr_key2string ( idpool_attr_list ,
LDAP_ATTR_GIDNUMBER ) ;
2006-12-12 17:52:13 +03:00
break ;
default :
DEBUG ( 2 , ( " Invalid ID type (0x%x) \n " , xid - > type ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
filter = talloc_asprintf ( memctx , " (objectClass=%s) " , LDAP_OBJ_IDPOOL ) ;
CHECK_ALLOC_DONE ( filter ) ;
attr_list = get_attr_list ( memctx , idpool_attr_list ) ;
CHECK_ALLOC_DONE ( attr_list ) ;
rc = smbldap_search ( idmap_alloc_ldap - > smbldap_state ,
idmap_alloc_ldap - > suffix ,
LDAP_SCOPE_SUBTREE , filter ,
attr_list , 0 , & result ) ;
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
if ( rc ! = LDAP_SUCCESS ) {
DEBUG ( 0 , ( " %s object not found \n " , LDAP_OBJ_IDPOOL ) ) ;
goto done ;
}
talloc_autofree_ldapmsg ( memctx , result ) ;
2007-09-10 23:04:57 +04:00
count = ldap_count_entries ( idmap_alloc_ldap - > smbldap_state - > ldap_struct ,
result ) ;
2006-12-12 17:52:13 +03:00
if ( count ! = 1 ) {
DEBUG ( 0 , ( " Single %s object not found \n " , LDAP_OBJ_IDPOOL ) ) ;
goto done ;
}
2007-09-10 23:04:57 +04:00
entry = ldap_first_entry ( idmap_alloc_ldap - > smbldap_state - > ldap_struct ,
result ) ;
2006-12-12 17:52:13 +03:00
id_str = smbldap_talloc_single_attribute ( idmap_alloc_ldap - > smbldap_state - > ldap_struct ,
entry , type , memctx ) ;
if ( ! id_str ) {
DEBUG ( 0 , ( " %s attribute not found \n " , type ) ) ;
goto done ;
}
if ( ! id_str ) {
DEBUG ( 0 , ( " Out of memory \n " ) ) ;
ret = NT_STATUS_NO_MEMORY ;
goto done ;
}
xid - > id = strtoul ( id_str , NULL , 10 ) ;
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
ret = NT_STATUS_OK ;
done :
talloc_free ( memctx ) ;
return ret ;
}
/**********************************
2007-09-10 23:04:57 +04:00
Set highest id .
2006-12-12 17:52:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS idmap_ldap_set_hwm ( struct unixid * xid )
{
TALLOC_CTX * ctx ;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL ;
int rc = LDAP_SERVER_DOWN ;
int count = 0 ;
LDAPMessage * result = NULL ;
LDAPMessage * entry = NULL ;
LDAPMod * * mods = NULL ;
char * new_id_str ;
char * filter = NULL ;
const char * dn = NULL ;
const char * * attr_list ;
const char * type ;
2007-04-19 01:10:37 +04:00
/* Only do query if we are online */
if ( idmap_is_offline ( ) ) {
return NT_STATUS_FILE_IS_OFFLINE ;
}
2006-12-12 17:52:13 +03:00
if ( ! idmap_alloc_ldap ) {
return NT_STATUS_UNSUCCESSFUL ;
}
ctx = talloc_new ( idmap_alloc_ldap ) ;
if ( ! ctx ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
/* get type */
switch ( xid - > type ) {
case ID_TYPE_UID :
2007-09-10 23:04:57 +04:00
type = get_attr_key2string ( idpool_attr_list ,
LDAP_ATTR_UIDNUMBER ) ;
2006-12-12 17:52:13 +03:00
break ;
case ID_TYPE_GID :
2007-09-10 23:04:57 +04:00
type = get_attr_key2string ( idpool_attr_list ,
LDAP_ATTR_GIDNUMBER ) ;
2006-12-12 17:52:13 +03:00
break ;
default :
DEBUG ( 2 , ( " Invalid ID type (0x%x) \n " , xid - > type ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
filter = talloc_asprintf ( ctx , " (objectClass=%s) " , LDAP_OBJ_IDPOOL ) ;
CHECK_ALLOC_DONE ( filter ) ;
attr_list = get_attr_list ( ctx , idpool_attr_list ) ;
CHECK_ALLOC_DONE ( attr_list ) ;
rc = smbldap_search ( idmap_alloc_ldap - > smbldap_state ,
idmap_alloc_ldap - > suffix ,
LDAP_SCOPE_SUBTREE , filter ,
attr_list , 0 , & result ) ;
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
if ( rc ! = LDAP_SUCCESS ) {
DEBUG ( 0 , ( " %s object not found \n " , LDAP_OBJ_IDPOOL ) ) ;
goto done ;
}
talloc_autofree_ldapmsg ( ctx , result ) ;
2007-09-10 23:04:57 +04:00
count = ldap_count_entries ( idmap_alloc_ldap - > smbldap_state - > ldap_struct ,
result ) ;
2006-12-12 17:52:13 +03:00
if ( count ! = 1 ) {
DEBUG ( 0 , ( " Single %s object not found \n " , LDAP_OBJ_IDPOOL ) ) ;
goto done ;
}
2007-09-10 23:04:57 +04:00
entry = ldap_first_entry ( idmap_alloc_ldap - > smbldap_state - > ldap_struct ,
result ) ;
2006-12-12 17:52:13 +03:00
2007-09-10 23:04:57 +04:00
dn = smbldap_talloc_dn ( ctx ,
idmap_alloc_ldap - > smbldap_state - > ldap_struct ,
entry ) ;
2006-12-12 17:52:13 +03:00
if ( ! dn ) {
goto done ;
}
new_id_str = talloc_asprintf ( ctx , " %lu " , ( unsigned long ) xid - > id ) ;
if ( ! new_id_str ) {
DEBUG ( 0 , ( " Out of memory \n " ) ) ;
ret = NT_STATUS_NO_MEMORY ;
goto done ;
}
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
smbldap_set_mod ( & mods , LDAP_MOD_REPLACE , type , new_id_str ) ;
if ( mods = = NULL ) {
DEBUG ( 0 , ( " smbldap_set_mod() failed. \n " ) ) ;
2007-09-10 23:04:57 +04:00
goto done ;
2006-12-12 17:52:13 +03:00
}
rc = smbldap_modify ( idmap_alloc_ldap - > smbldap_state , dn , mods ) ;
ldap_mods_free ( mods , True ) ;
if ( rc ! = LDAP_SUCCESS ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 1 , ( " Failed to allocate new %s. "
" smbldap_modify() failed. \n " , type ) ) ;
2006-12-12 17:52:13 +03:00
goto done ;
}
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
ret = NT_STATUS_OK ;
done :
talloc_free ( ctx ) ;
return ret ;
}
/**********************************
Close idmap ldap alloc
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS idmap_ldap_alloc_close ( void )
{
if ( idmap_alloc_ldap ) {
smbldap_free_struct ( & idmap_alloc_ldap - > smbldap_state ) ;
DEBUG ( 5 , ( " The connection to the LDAP server was closed \n " ) ) ;
/* maybe free the results here --metze */
TALLOC_FREE ( idmap_alloc_ldap ) ;
}
return NT_STATUS_OK ;
}
/**********************************************************************
IDMAP MAPPING LDAP BACKEND
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
static int idmap_ldap_close_destructor ( struct idmap_ldap_context * ctx )
{
smbldap_free_struct ( & ctx - > smbldap_state ) ;
DEBUG ( 5 , ( " The connection to the LDAP server was closed \n " ) ) ;
/* maybe free the results here --metze */
return 0 ;
}
/********************************
2007-09-10 23:04:57 +04:00
Initialise idmap database .
2006-12-12 17:52:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-04-19 01:10:37 +04:00
static NTSTATUS idmap_ldap_db_init ( struct idmap_domain * dom )
2006-12-12 17:52:13 +03:00
{
NTSTATUS ret ;
2007-02-06 20:29:18 +03:00
struct idmap_ldap_context * ctx = NULL ;
char * config_option = NULL ;
const char * range = NULL ;
const char * tmp = NULL ;
2007-04-19 01:10:37 +04:00
/* Only do init if we are online */
if ( idmap_is_offline ( ) ) {
return NT_STATUS_FILE_IS_OFFLINE ;
}
2007-04-28 03:18:41 +04:00
ctx = TALLOC_ZERO_P ( dom , struct idmap_ldap_context ) ;
2006-12-12 17:52:13 +03:00
if ( ! ctx ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
config_option = talloc_asprintf ( ctx , " idmap config %s " , dom - > name ) ;
if ( ! config_option ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
ret = NT_STATUS_NO_MEMORY ;
goto done ;
}
/* load ranges */
range = lp_parm_const_string ( - 1 , config_option , " range " , NULL ) ;
if ( range & & range [ 0 ] ) {
2007-09-10 23:04:57 +04:00
if ( ( sscanf ( range , " %u - %u " , & ctx - > filter_low_id ,
& ctx - > filter_high_id ) ! = 2 ) | |
2006-12-12 17:52:13 +03:00
( ctx - > filter_low_id > ctx - > filter_high_id ) ) {
DEBUG ( 1 , ( " ERROR: invalid filter range [%s] " , range ) ) ;
ctx - > filter_low_id = 0 ;
ctx - > filter_high_id = 0 ;
}
}
2007-04-19 01:10:37 +04:00
if ( dom - > params & & * ( dom - > params ) ) {
2006-12-12 17:52:13 +03:00
/* assume location is the only parameter */
2007-04-19 01:10:37 +04:00
ctx - > url = talloc_strdup ( ctx , dom - > params ) ;
2006-12-12 17:52:13 +03:00
} else {
tmp = lp_parm_const_string ( - 1 , config_option , " ldap_url " , NULL ) ;
if ( ! tmp ) {
DEBUG ( 1 , ( " ERROR: missing idmap ldap url \n " ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
ctx - > url = talloc_strdup ( ctx , tmp ) ;
}
CHECK_ALLOC_DONE ( ctx - > url ) ;
2007-09-10 20:21:55 +04:00
tmp = lp_parm_const_string ( - 1 , config_option , " ldap_base_dn " , NULL ) ;
if ( ! tmp | | ! * tmp ) {
tmp = lp_ldap_idmap_suffix ( ) ;
if ( ! tmp ) {
DEBUG ( 1 , ( " ERROR: missing idmap ldap suffix \n " ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
}
2006-12-12 17:52:13 +03:00
ctx - > suffix = talloc_strdup ( ctx , tmp ) ;
CHECK_ALLOC_DONE ( ctx - > suffix ) ;
2007-03-11 19:49:16 +03:00
ret = smbldap_init ( ctx , winbind_event_context ( ) , ctx - > url ,
& ctx - > smbldap_state ) ;
2006-12-12 17:52:13 +03:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 1 , ( " ERROR: smbldap_init (%s) failed! \n " , ctx - > url ) ) ;
goto done ;
}
2007-09-10 23:04:57 +04:00
ret = get_credentials ( ctx , ctx - > smbldap_state , config_option ,
2007-02-06 20:29:18 +03:00
dom , & ctx - > user_dn ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 1 , ( " idmap_ldap_db_init: Failed to get connection "
" credentials (%s) \n " , nt_errstr ( ret ) ) ) ;
goto done ;
2007-09-10 23:04:57 +04:00
}
2006-12-12 17:52:13 +03:00
/* set the destructor on the context, so that resource are properly
2007-02-06 20:29:18 +03:00
freed if the contexts is released */
2006-12-12 17:52:13 +03:00
talloc_set_destructor ( ctx , idmap_ldap_close_destructor ) ;
dom - > private_data = ctx ;
2007-05-10 01:38:41 +04:00
dom - > initialized = True ;
2006-12-12 17:52:13 +03:00
talloc_free ( config_option ) ;
return NT_STATUS_OK ;
/*failed */
done :
talloc_free ( ctx ) ;
return ret ;
}
/* max number of ids requested per batch query */
2007-09-10 23:04:57 +04:00
# define IDMAP_LDAP_MAX_IDS 30
2006-12-12 17:52:13 +03:00
/**********************************
2007-09-10 23:04:57 +04:00
lookup a set of unix ids .
2006-12-12 17:52:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-10 23:04:57 +04:00
/* this function searches up to IDMAP_LDAP_MAX_IDS entries
* in maps for a match */
static struct id_map * find_map_by_id ( struct id_map * * maps ,
enum id_type type ,
uint32_t id )
2006-12-12 17:52:13 +03:00
{
int i ;
for ( i = 0 ; i < IDMAP_LDAP_MAX_IDS ; i + + ) {
if ( maps [ i ] = = NULL ) { /* end of the run */
return NULL ;
}
if ( ( maps [ i ] - > xid . type = = type ) & & ( maps [ i ] - > xid . id = = id ) ) {
return maps [ i ] ;
}
}
2007-09-10 23:04:57 +04:00
return NULL ;
2006-12-12 17:52:13 +03:00
}
2007-09-10 23:04:57 +04:00
static NTSTATUS idmap_ldap_unixids_to_sids ( struct idmap_domain * dom ,
struct id_map * * ids )
2006-12-12 17:52:13 +03:00
{
NTSTATUS ret ;
TALLOC_CTX * memctx ;
struct idmap_ldap_context * ctx ;
LDAPMessage * result = NULL ;
const char * uidNumber ;
const char * gidNumber ;
const char * * attr_list ;
char * filter = NULL ;
2007-10-19 04:40:25 +04:00
bool multi = False ;
2006-12-12 17:52:13 +03:00
int idx = 0 ;
int bidx = 0 ;
int count ;
int rc ;
int i ;
2007-04-19 01:10:37 +04:00
/* Only do query if we are online */
if ( idmap_is_offline ( ) ) {
return NT_STATUS_FILE_IS_OFFLINE ;
}
/* Initilization my have been deferred because we were offline */
if ( ! dom - > initialized ) {
ret = idmap_ldap_db_init ( dom ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
return ret ;
}
}
2007-09-10 23:04:57 +04:00
ctx = talloc_get_type ( dom - > private_data , struct idmap_ldap_context ) ;
2006-12-12 17:52:13 +03:00
memctx = talloc_new ( ctx ) ;
if ( ! memctx ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
uidNumber = get_attr_key2string ( idpool_attr_list , LDAP_ATTR_UIDNUMBER ) ;
gidNumber = get_attr_key2string ( idpool_attr_list , LDAP_ATTR_GIDNUMBER ) ;
2007-08-24 15:25:38 +04:00
attr_list = get_attr_list ( memctx , sidmap_attr_list ) ;
2006-12-12 17:52:13 +03:00
if ( ! ids [ 1 ] ) {
/* if we are requested just one mapping use the simple filter */
filter = talloc_asprintf ( memctx , " (&(objectClass=%s)(%s=%lu)) " ,
LDAP_OBJ_IDMAP_ENTRY ,
( ids [ 0 ] - > xid . type = = ID_TYPE_UID ) ? uidNumber : gidNumber ,
( unsigned long ) ids [ 0 ] - > xid . id ) ;
CHECK_ALLOC_DONE ( filter ) ;
DEBUG ( 10 , ( " Filter: [%s] \n " , filter ) ) ;
} else {
/* multiple mappings */
multi = True ;
}
again :
if ( multi ) {
talloc_free ( filter ) ;
2007-09-10 23:04:57 +04:00
filter = talloc_asprintf ( memctx ,
" (&(objectClass=%s)(| " ,
LDAP_OBJ_IDMAP_ENTRY ) ;
2006-12-12 17:52:13 +03:00
CHECK_ALLOC_DONE ( filter ) ;
bidx = idx ;
for ( i = 0 ; ( i < IDMAP_LDAP_MAX_IDS ) & & ids [ idx ] ; i + + , idx + + ) {
2007-09-14 21:42:10 +04:00
filter = talloc_asprintf_append_buffer ( filter , " (%s=%lu) " ,
2006-12-12 17:52:13 +03:00
( ids [ idx ] - > xid . type = = ID_TYPE_UID ) ? uidNumber : gidNumber ,
( unsigned long ) ids [ idx ] - > xid . id ) ;
CHECK_ALLOC_DONE ( filter ) ;
}
2007-09-14 21:42:10 +04:00
filter = talloc_asprintf_append_buffer ( filter , " )) " ) ;
2006-12-12 17:52:13 +03:00
CHECK_ALLOC_DONE ( filter ) ;
DEBUG ( 10 , ( " Filter: [%s] \n " , filter ) ) ;
} else {
bidx = 0 ;
idx = 1 ;
}
2007-09-10 23:04:57 +04:00
rc = smbldap_search ( ctx - > smbldap_state , ctx - > suffix , LDAP_SCOPE_SUBTREE ,
2006-12-12 17:52:13 +03:00
filter , attr_list , 0 , & result ) ;
if ( rc ! = LDAP_SUCCESS ) {
DEBUG ( 3 , ( " Failure looking up ids (%s) \n " , ldap_err2string ( rc ) ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
count = ldap_count_entries ( ctx - > smbldap_state - > ldap_struct , result ) ;
if ( count = = 0 ) {
DEBUG ( 10 , ( " NO SIDs found \n " ) ) ;
}
for ( i = 0 ; i < count ; i + + ) {
LDAPMessage * entry = NULL ;
char * sidstr = NULL ;
char * tmp = NULL ;
enum id_type type ;
struct id_map * map ;
uint32_t id ;
if ( i = = 0 ) { /* first entry */
2007-09-10 23:04:57 +04:00
entry = ldap_first_entry ( ctx - > smbldap_state - > ldap_struct ,
result ) ;
2006-12-12 17:52:13 +03:00
} else { /* following ones */
2007-09-10 23:04:57 +04:00
entry = ldap_next_entry ( ctx - > smbldap_state - > ldap_struct ,
entry ) ;
2006-12-12 17:52:13 +03:00
}
if ( ! entry ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 2 , ( " ERROR: Unable to fetch ldap entries "
" from results \n " ) ) ;
2007-06-09 22:18:24 +04:00
break ;
2006-12-12 17:52:13 +03:00
}
/* first check if the SID is present */
sidstr = smbldap_talloc_single_attribute (
ctx - > smbldap_state - > ldap_struct ,
entry , LDAP_ATTRIBUTE_SID , memctx ) ;
if ( ! sidstr ) { /* no sid, skip entry */
DEBUG ( 2 , ( " WARNING SID not found on entry \n " ) ) ;
continue ;
}
/* now try to see if it is a uid, if not try with a gid
* ( gid is more common , but in case both uidNumber and
2007-09-10 23:04:57 +04:00
* gidNumber are returned the SID is mapped to the uid
* not the gid ) */
2006-12-12 17:52:13 +03:00
type = ID_TYPE_UID ;
tmp = smbldap_talloc_single_attribute (
ctx - > smbldap_state - > ldap_struct ,
entry , uidNumber , memctx ) ;
if ( ! tmp ) {
type = ID_TYPE_GID ;
tmp = smbldap_talloc_single_attribute (
ctx - > smbldap_state - > ldap_struct ,
entry , gidNumber , memctx ) ;
}
if ( ! tmp ) { /* wow very strange entry, how did it match ? */
2007-09-10 23:04:57 +04:00
DEBUG ( 5 , ( " Unprobable match on (%s), no uidNumber, "
" nor gidNumber returned \n " , sidstr ) ) ;
2006-12-12 17:52:13 +03:00
TALLOC_FREE ( sidstr ) ;
continue ;
}
id = strtoul ( tmp , NULL , 10 ) ;
if ( ( id = = 0 ) | |
( ctx - > filter_low_id & & ( id < ctx - > filter_low_id ) ) | |
( ctx - > filter_high_id & & ( id > ctx - > filter_high_id ) ) ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 5 , ( " Requested id (%u) out of range (%u - %u). "
" Filtered! \n " , id ,
ctx - > filter_low_id , ctx - > filter_high_id ) ) ;
2006-12-12 17:52:13 +03:00
TALLOC_FREE ( sidstr ) ;
TALLOC_FREE ( tmp ) ;
continue ;
}
TALLOC_FREE ( tmp ) ;
map = find_map_by_id ( & ids [ bidx ] , type , id ) ;
if ( ! map ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 2 , ( " WARNING: couldn't match sid (%s) "
" with requested ids \n " , sidstr ) ) ;
2006-12-12 17:52:13 +03:00
TALLOC_FREE ( sidstr ) ;
continue ;
}
if ( ! string_to_sid ( map - > sid , sidstr ) ) {
DEBUG ( 2 , ( " ERROR: Invalid SID on entry \n " ) ) ;
TALLOC_FREE ( sidstr ) ;
continue ;
}
TALLOC_FREE ( sidstr ) ;
/* mapped */
2007-01-14 20:58:24 +03:00
map - > status = ID_MAPPED ;
2006-12-12 17:52:13 +03:00
2007-12-15 23:11:36 +03:00
DEBUG ( 10 , ( " Mapped %s -> %lu (%d) \n " , sid_string_dbg ( map - > sid ) ,
2007-09-10 23:04:57 +04:00
( unsigned long ) map - > xid . id , map - > xid . type ) ) ;
2006-12-12 17:52:13 +03:00
}
/* free the ldap results */
if ( result ) {
ldap_msgfree ( result ) ;
result = NULL ;
}
if ( multi & & ids [ idx ] ) { /* still some values to map */
goto again ;
}
ret = NT_STATUS_OK ;
2007-04-19 01:10:37 +04:00
/* mark all unknwon/expired ones as unmapped */
2007-01-14 20:58:24 +03:00
for ( i = 0 ; ids [ i ] ; i + + ) {
2007-04-19 01:10:37 +04:00
if ( ids [ i ] - > status ! = ID_MAPPED )
ids [ i ] - > status = ID_UNMAPPED ;
2007-01-14 20:58:24 +03:00
}
2006-12-12 17:52:13 +03:00
done :
talloc_free ( memctx ) ;
return ret ;
}
/**********************************
2007-09-10 23:04:57 +04:00
lookup a set of sids .
2006-12-12 17:52:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-10 23:04:57 +04:00
/* this function searches up to IDMAP_LDAP_MAX_IDS entries
* in maps for a match */
2006-12-12 17:52:13 +03:00
static struct id_map * find_map_by_sid ( struct id_map * * maps , DOM_SID * sid )
{
int i ;
for ( i = 0 ; i < IDMAP_LDAP_MAX_IDS ; i + + ) {
if ( maps [ i ] = = NULL ) { /* end of the run */
return NULL ;
}
if ( sid_equal ( maps [ i ] - > sid , sid ) ) {
return maps [ i ] ;
}
}
2007-09-10 23:04:57 +04:00
return NULL ;
2006-12-12 17:52:13 +03:00
}
2007-09-10 23:04:57 +04:00
static NTSTATUS idmap_ldap_sids_to_unixids ( struct idmap_domain * dom ,
struct id_map * * ids )
2006-12-12 17:52:13 +03:00
{
2007-04-18 20:45:00 +04:00
LDAPMessage * entry = NULL ;
2006-12-12 17:52:13 +03:00
NTSTATUS ret ;
TALLOC_CTX * memctx ;
struct idmap_ldap_context * ctx ;
LDAPMessage * result = NULL ;
const char * uidNumber ;
const char * gidNumber ;
const char * * attr_list ;
char * filter = NULL ;
2007-10-19 04:40:25 +04:00
bool multi = False ;
2006-12-12 17:52:13 +03:00
int idx = 0 ;
int bidx = 0 ;
int count ;
int rc ;
int i ;
2007-04-19 01:10:37 +04:00
/* Only do query if we are online */
if ( idmap_is_offline ( ) ) {
return NT_STATUS_FILE_IS_OFFLINE ;
}
/* Initilization my have been deferred because we were offline */
if ( ! dom - > initialized ) {
ret = idmap_ldap_db_init ( dom ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
return ret ;
}
}
2007-09-10 23:04:57 +04:00
ctx = talloc_get_type ( dom - > private_data , struct idmap_ldap_context ) ;
2006-12-12 17:52:13 +03:00
memctx = talloc_new ( ctx ) ;
if ( ! memctx ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
uidNumber = get_attr_key2string ( idpool_attr_list , LDAP_ATTR_UIDNUMBER ) ;
gidNumber = get_attr_key2string ( idpool_attr_list , LDAP_ATTR_GIDNUMBER ) ;
2007-08-24 15:25:38 +04:00
attr_list = get_attr_list ( memctx , sidmap_attr_list ) ;
2006-12-12 17:52:13 +03:00
if ( ! ids [ 1 ] ) {
/* if we are requested just one mapping use the simple filter */
filter = talloc_asprintf ( memctx , " (&(objectClass=%s)(%s=%s)) " ,
LDAP_OBJ_IDMAP_ENTRY ,
LDAP_ATTRIBUTE_SID ,
2007-12-15 23:10:58 +03:00
sid_string_talloc ( memctx , ids [ 0 ] - > sid ) ) ;
2006-12-12 17:52:13 +03:00
CHECK_ALLOC_DONE ( filter ) ;
DEBUG ( 10 , ( " Filter: [%s] \n " , filter ) ) ;
} else {
/* multiple mappings */
multi = True ;
}
again :
if ( multi ) {
TALLOC_FREE ( filter ) ;
2007-09-10 23:04:57 +04:00
filter = talloc_asprintf ( memctx ,
" (&(objectClass=%s)(| " ,
LDAP_OBJ_IDMAP_ENTRY ) ;
2006-12-12 17:52:13 +03:00
CHECK_ALLOC_DONE ( filter ) ;
bidx = idx ;
for ( i = 0 ; ( i < IDMAP_LDAP_MAX_IDS ) & & ids [ idx ] ; i + + , idx + + ) {
2007-09-14 21:42:10 +04:00
filter = talloc_asprintf_append_buffer ( filter , " (%s=%s) " ,
2006-12-12 17:52:13 +03:00
LDAP_ATTRIBUTE_SID ,
2007-12-15 23:10:58 +03:00
sid_string_talloc ( memctx ,
ids [ idx ] - > sid ) ) ;
2006-12-12 17:52:13 +03:00
CHECK_ALLOC_DONE ( filter ) ;
}
2007-09-14 21:42:10 +04:00
filter = talloc_asprintf_append_buffer ( filter , " )) " ) ;
2006-12-12 17:52:13 +03:00
CHECK_ALLOC_DONE ( filter ) ;
DEBUG ( 10 , ( " Filter: [%s] " , filter ) ) ;
} else {
bidx = 0 ;
idx = 1 ;
}
2007-09-10 23:04:57 +04:00
rc = smbldap_search ( ctx - > smbldap_state , ctx - > suffix , LDAP_SCOPE_SUBTREE ,
2006-12-12 17:52:13 +03:00
filter , attr_list , 0 , & result ) ;
if ( rc ! = LDAP_SUCCESS ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 3 , ( " Failure looking up sids (%s) \n " ,
ldap_err2string ( rc ) ) ) ;
2006-12-12 17:52:13 +03:00
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
count = ldap_count_entries ( ctx - > smbldap_state - > ldap_struct , result ) ;
if ( count = = 0 ) {
DEBUG ( 10 , ( " NO SIDs found \n " ) ) ;
}
for ( i = 0 ; i < count ; i + + ) {
char * sidstr = NULL ;
char * tmp = NULL ;
enum id_type type ;
struct id_map * map ;
DOM_SID sid ;
uint32_t id ;
if ( i = = 0 ) { /* first entry */
2007-09-10 23:04:57 +04:00
entry = ldap_first_entry ( ctx - > smbldap_state - > ldap_struct ,
result ) ;
2006-12-12 17:52:13 +03:00
} else { /* following ones */
2007-09-10 23:04:57 +04:00
entry = ldap_next_entry ( ctx - > smbldap_state - > ldap_struct ,
entry ) ;
2006-12-12 17:52:13 +03:00
}
2007-06-09 22:18:24 +04:00
if ( ! entry ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 2 , ( " ERROR: Unable to fetch ldap entries "
" from results \n " ) ) ;
2007-06-09 22:18:24 +04:00
break ;
}
2006-12-12 17:52:13 +03:00
/* first check if the SID is present */
sidstr = smbldap_talloc_single_attribute (
ctx - > smbldap_state - > ldap_struct ,
entry , LDAP_ATTRIBUTE_SID , memctx ) ;
if ( ! sidstr ) { /* no sid ??, skip entry */
DEBUG ( 2 , ( " WARNING SID not found on entry \n " ) ) ;
continue ;
}
if ( ! string_to_sid ( & sid , sidstr ) ) {
DEBUG ( 2 , ( " ERROR: Invalid SID on entry \n " ) ) ;
TALLOC_FREE ( sidstr ) ;
continue ;
}
map = find_map_by_sid ( & ids [ bidx ] , & sid ) ;
if ( ! map ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 2 , ( " WARNING: couldn't find entry sid (%s) "
" in ids " , sidstr ) ) ;
2006-12-12 17:52:13 +03:00
TALLOC_FREE ( sidstr ) ;
continue ;
}
TALLOC_FREE ( sidstr ) ;
/* now try to see if it is a uid, if not try with a gid
* ( gid is more common , but in case both uidNumber and
2007-09-10 23:04:57 +04:00
* gidNumber are returned the SID is mapped to the uid
* not the gid ) */
2006-12-12 17:52:13 +03:00
type = ID_TYPE_UID ;
tmp = smbldap_talloc_single_attribute (
ctx - > smbldap_state - > ldap_struct ,
entry , uidNumber , memctx ) ;
if ( ! tmp ) {
type = ID_TYPE_GID ;
tmp = smbldap_talloc_single_attribute (
ctx - > smbldap_state - > ldap_struct ,
entry , gidNumber , memctx ) ;
}
if ( ! tmp ) { /* no ids ?? */
2007-09-10 23:04:57 +04:00
DEBUG ( 5 , ( " no uidNumber, "
" nor gidNumber attributes found \n " ) ) ;
2006-12-12 17:52:13 +03:00
continue ;
}
id = strtoul ( tmp , NULL , 10 ) ;
if ( ( id = = 0 ) | |
( ctx - > filter_low_id & & ( id < ctx - > filter_low_id ) ) | |
( ctx - > filter_high_id & & ( id > ctx - > filter_high_id ) ) ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 5 , ( " Requested id (%u) out of range (%u - %u). "
" Filtered! \n " , id ,
ctx - > filter_low_id , ctx - > filter_high_id ) ) ;
2006-12-12 17:52:13 +03:00
TALLOC_FREE ( tmp ) ;
continue ;
}
TALLOC_FREE ( tmp ) ;
/* mapped */
map - > xid . type = type ;
map - > xid . id = id ;
2007-01-14 20:58:24 +03:00
map - > status = ID_MAPPED ;
2007-09-10 23:04:57 +04:00
2007-12-15 23:11:36 +03:00
DEBUG ( 10 , ( " Mapped %s -> %lu (%d) \n " , sid_string_dbg ( map - > sid ) ,
2007-09-10 23:04:57 +04:00
( unsigned long ) map - > xid . id , map - > xid . type ) ) ;
2006-12-12 17:52:13 +03:00
}
/* free the ldap results */
if ( result ) {
ldap_msgfree ( result ) ;
result = NULL ;
}
if ( multi & & ids [ idx ] ) { /* still some values to map */
goto again ;
}
ret = NT_STATUS_OK ;
2007-04-19 01:10:37 +04:00
/* mark all unknwon/expired ones as unmapped */
2007-01-14 20:58:24 +03:00
for ( i = 0 ; ids [ i ] ; i + + ) {
2007-04-19 01:10:37 +04:00
if ( ids [ i ] - > status ! = ID_MAPPED )
ids [ i ] - > status = ID_UNMAPPED ;
2007-01-14 20:58:24 +03:00
}
2006-12-12 17:52:13 +03:00
done :
talloc_free ( memctx ) ;
return ret ;
}
/**********************************
2007-09-10 23:04:57 +04:00
set a mapping .
2006-12-12 17:52:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-10 23:04:57 +04:00
/* TODO: change this: This function cannot be called to modify a mapping,
* only set a new one */
2006-12-12 17:52:13 +03:00
2007-09-10 23:04:57 +04:00
static NTSTATUS idmap_ldap_set_mapping ( struct idmap_domain * dom ,
const struct id_map * map )
2006-12-12 17:52:13 +03:00
{
NTSTATUS ret ;
TALLOC_CTX * memctx ;
struct idmap_ldap_context * ctx ;
LDAPMessage * entry = NULL ;
LDAPMod * * mods = NULL ;
const char * type ;
char * id_str ;
char * sid ;
char * dn ;
int rc = - 1 ;
2007-04-19 01:10:37 +04:00
/* Only do query if we are online */
if ( idmap_is_offline ( ) ) {
return NT_STATUS_FILE_IS_OFFLINE ;
}
/* Initilization my have been deferred because we were offline */
if ( ! dom - > initialized ) {
ret = idmap_ldap_db_init ( dom ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
return ret ;
}
}
2007-09-10 23:04:57 +04:00
ctx = talloc_get_type ( dom - > private_data , struct idmap_ldap_context ) ;
2006-12-12 17:52:13 +03:00
switch ( map - > xid . type ) {
case ID_TYPE_UID :
2007-09-10 23:04:57 +04:00
type = get_attr_key2string ( sidmap_attr_list ,
LDAP_ATTR_UIDNUMBER ) ;
2006-12-12 17:52:13 +03:00
break ;
case ID_TYPE_GID :
2007-09-10 23:04:57 +04:00
type = get_attr_key2string ( sidmap_attr_list ,
LDAP_ATTR_GIDNUMBER ) ;
2006-12-12 17:52:13 +03:00
break ;
default :
return NT_STATUS_INVALID_PARAMETER ;
}
memctx = talloc_new ( ctx ) ;
if ( ! memctx ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
id_str = talloc_asprintf ( memctx , " %lu " , ( unsigned long ) map - > xid . id ) ;
CHECK_ALLOC_DONE ( id_str ) ;
2007-12-15 23:10:58 +03:00
sid = talloc_strdup ( memctx , sid_string_talloc ( memctx , map - > sid ) ) ;
2006-12-12 17:52:13 +03:00
CHECK_ALLOC_DONE ( sid ) ;
dn = talloc_asprintf ( memctx , " %s=%s,%s " ,
get_attr_key2string ( sidmap_attr_list , LDAP_ATTR_SID ) ,
sid ,
ctx - > suffix ) ;
CHECK_ALLOC_DONE ( dn ) ;
2007-09-10 23:04:57 +04:00
smbldap_set_mod ( & mods , LDAP_MOD_ADD ,
" objectClass " , LDAP_OBJ_IDMAP_ENTRY ) ;
2006-12-12 17:52:13 +03:00
2007-09-10 23:04:57 +04:00
smbldap_make_mod ( ctx - > smbldap_state - > ldap_struct ,
entry , & mods , type , id_str ) ;
2006-12-12 17:52:13 +03:00
2007-09-10 23:04:57 +04:00
smbldap_make_mod ( ctx - > smbldap_state - > ldap_struct , entry , & mods ,
get_attr_key2string ( sidmap_attr_list , LDAP_ATTR_SID ) ,
sid ) ;
2006-12-12 17:52:13 +03:00
if ( ! mods ) {
DEBUG ( 2 , ( " ERROR: No mods? \n " ) ) ;
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
/* TODO: remove conflicting mappings! */
smbldap_set_mod ( & mods , LDAP_MOD_ADD , " objectClass " , LDAP_OBJ_SID_ENTRY ) ;
DEBUG ( 10 , ( " Set DN %s (%s -> %s) \n " , dn , sid , id_str ) ) ;
rc = smbldap_add ( ctx - > smbldap_state , dn , mods ) ;
2007-09-10 23:04:57 +04:00
ldap_mods_free ( mods , True ) ;
2006-12-12 17:52:13 +03:00
if ( rc ! = LDAP_SUCCESS ) {
char * ld_error = NULL ;
2007-09-10 23:04:57 +04:00
ldap_get_option ( ctx - > smbldap_state - > ldap_struct ,
LDAP_OPT_ERROR_STRING , & ld_error ) ;
DEBUG ( 0 , ( " ldap_set_mapping_internals: Failed to add %s to %lu "
" mapping [%s] \n " , sid ,
( unsigned long ) map - > xid . id , type ) ) ;
DEBUG ( 0 , ( " ldap_set_mapping_internals: Error was: %s (%s) \n " ,
2006-12-12 17:52:13 +03:00
ld_error ? ld_error : " (NULL) " , ldap_err2string ( rc ) ) ) ;
2007-03-01 05:43:33 +03:00
if ( ld_error ) {
ldap_memfree ( ld_error ) ;
}
2006-12-12 17:52:13 +03:00
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
2007-09-10 23:04:57 +04:00
DEBUG ( 10 , ( " ldap_set_mapping: Successfully created mapping from %s to "
" %lu [%s] \n " , sid , ( unsigned long ) map - > xid . id , type ) ) ;
2006-12-12 17:52:13 +03:00
ret = NT_STATUS_OK ;
done :
talloc_free ( memctx ) ;
return ret ;
}
/**********************************
2007-09-10 23:04:57 +04:00
Close the idmap ldap instance
2006-12-12 17:52:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS idmap_ldap_close ( struct idmap_domain * dom )
{
struct idmap_ldap_context * ctx ;
if ( dom - > private_data ) {
2007-09-10 23:04:57 +04:00
ctx = talloc_get_type ( dom - > private_data ,
struct idmap_ldap_context ) ;
2006-12-12 17:52:13 +03:00
talloc_free ( ctx ) ;
dom - > private_data = NULL ;
}
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
return NT_STATUS_OK ;
}
static struct idmap_methods idmap_ldap_methods = {
. init = idmap_ldap_db_init ,
. unixids_to_sids = idmap_ldap_unixids_to_sids ,
. sids_to_unixids = idmap_ldap_sids_to_unixids ,
. set_mapping = idmap_ldap_set_mapping ,
. close_fn = idmap_ldap_close
} ;
static struct idmap_alloc_methods idmap_ldap_alloc_methods = {
. init = idmap_ldap_alloc_init ,
. allocate_id = idmap_ldap_allocate_id ,
. get_id_hwm = idmap_ldap_get_hwm ,
. set_id_hwm = idmap_ldap_set_hwm ,
. close_fn = idmap_ldap_alloc_close ,
/* .dump_data = TODO */
} ;
NTSTATUS idmap_alloc_ldap_init ( void )
{
2007-09-10 23:04:57 +04:00
return smb_register_idmap_alloc ( SMB_IDMAP_INTERFACE_VERSION , " ldap " ,
& idmap_ldap_alloc_methods ) ;
2006-12-12 17:52:13 +03:00
}
NTSTATUS idmap_ldap_init ( void )
{
NTSTATUS ret ;
2007-09-10 23:04:57 +04:00
/* FIXME: bad hack to actually register also the alloc_ldap module
* without changining configure . in */
2006-12-12 17:52:13 +03:00
ret = idmap_alloc_ldap_init ( ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
return ret ;
}
2007-09-10 23:04:57 +04:00
return smb_register_idmap ( SMB_IDMAP_INTERFACE_VERSION , " ldap " ,
& idmap_ldap_methods ) ;
2006-12-12 17:52:13 +03:00
}