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"
2010-08-05 04:25:37 +04:00
# include "secrets.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"
2008-07-13 14:07:40 +04:00
static char * idmap_fetch_secret ( const char * backend , bool alloc ,
const char * domain , const char * identity )
{
char * tmp , * ret ;
int r ;
if ( alloc ) {
r = asprintf ( & tmp , " IDMAP_ALLOC_%s " , backend ) ;
} else {
r = asprintf ( & tmp , " IDMAP_%s_%s " , backend , domain ) ;
}
if ( r < 0 )
return NULL ;
strupper_m ( tmp ) ; /* make sure the key is case insensitive */
ret = secrets_fetch_generic ( tmp , identity ) ;
SAFE_FREE ( tmp ) ;
return ret ;
}
2010-06-17 21:45:39 +04:00
struct idmap_ldap_alloc_context {
2007-02-06 20:29:18 +03:00
struct smbldap_state * smbldap_state ;
char * url ;
char * suffix ;
char * user_dn ;
} ;
2010-06-17 21:45:39 +04:00
struct idmap_ldap_context {
2006-12-12 17:52:13 +03:00
struct smbldap_state * smbldap_state ;
char * url ;
char * suffix ;
char * user_dn ;
2010-06-17 21:45:39 +04:00
bool anon ;
struct idmap_ldap_alloc_context * alloc ;
2006-12-12 17:52:13 +03:00
} ;
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
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 ;
2009-10-16 03:55:40 +04:00
* dn = NULL ;
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-17 20:59:28 +04:00
static NTSTATUS verify_idpool ( struct idmap_domain * dom )
2006-12-12 17:52:13 +03:00
{
NTSTATUS ret ;
2010-06-17 21:45:39 +04:00
TALLOC_CTX * mem_ctx ;
2006-12-12 17:52:13 +03:00
LDAPMessage * result = NULL ;
LDAPMod * * mods = NULL ;
const char * * attr_list ;
char * filter ;
int count ;
int rc ;
2010-06-17 21:45:39 +04:00
struct idmap_ldap_context * ctx ;
ctx = talloc_get_type ( dom - > private_data , struct idmap_ldap_context ) ;
2007-09-10 23:04:57 +04:00
2010-06-17 21:45:39 +04:00
if ( ! ctx - > alloc ) {
2006-12-12 17:52:13 +03:00
return NT_STATUS_UNSUCCESSFUL ;
}
2010-06-17 21:45:39 +04:00
mem_ctx = talloc_new ( ctx - > alloc ) ;
if ( mem_ctx = = NULL ) {
2006-12-12 17:52:13 +03:00
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-06-17 21:45:39 +04:00
filter = talloc_asprintf ( mem_ctx , " (objectclass=%s) " , LDAP_OBJ_IDPOOL ) ;
2006-12-12 17:52:13 +03:00
CHECK_ALLOC_DONE ( filter ) ;
2007-09-10 23:04:57 +04:00
2010-06-17 21:45:39 +04:00
attr_list = get_attr_list ( mem_ctx , idpool_attr_list ) ;
2006-12-12 17:52:13 +03:00
CHECK_ALLOC_DONE ( attr_list ) ;
2010-06-17 21:45:39 +04:00
rc = smbldap_search ( ctx - > alloc - > smbldap_state ,
ctx - > alloc - > 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 ;
}
2010-06-17 21:45:39 +04:00
count = ldap_count_entries ( ctx - > alloc - > smbldap_state - > ldap_struct ,
2007-09-10 23:04:57 +04:00
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 " ,
2010-06-17 21:45:39 +04:00
filter , ctx - > alloc - > suffix ) ) ;
2006-12-12 17:52:13 +03:00
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
else if ( count = = 0 ) {
char * uid_str , * gid_str ;
2007-09-10 23:04:57 +04:00
2010-06-17 21:45:39 +04:00
uid_str = talloc_asprintf ( mem_ctx , " %lu " ,
2010-06-17 20:59:28 +04:00
( unsigned long ) dom - > low_id ) ;
2010-06-17 21:45:39 +04:00
gid_str = talloc_asprintf ( mem_ctx , " %lu " ,
2010-06-17 20:59:28 +04:00
( unsigned long ) dom - > low_id ) ;
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 ) {
2010-06-17 21:45:39 +04:00
rc = smbldap_modify ( ctx - > alloc - > smbldap_state ,
ctx - > alloc - > suffix ,
2006-12-12 17:52:13 +03:00
mods ) ;
ldap_mods_free ( mods , True ) ;
} else {
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
}
ret = ( rc = = LDAP_SUCCESS ) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
done :
2010-06-17 21:45:39 +04:00
talloc_free ( mem_ctx ) ;
2006-12-12 17:52:13 +03:00
return ret ;
}
/*****************************************************************************
2007-09-10 23:04:57 +04:00
Initialise idmap database .
2006-12-12 17:52:13 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-17 21:45:39 +04:00
static int idmap_ldap_alloc_close_destructor ( struct idmap_ldap_alloc_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 ;
}
2010-06-17 20:59:28 +04:00
static NTSTATUS idmap_ldap_alloc_init ( struct idmap_domain * dom ,
const char * params )
2006-12-12 17:52:13 +03:00
{
2007-09-10 23:04:57 +04:00
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL ;
2006-12-12 17:52:13 +03:00
const char * tmp ;
2010-06-17 21:45:39 +04:00
struct idmap_ldap_context * ctx ;
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 ;
}
2010-06-17 21:45:39 +04:00
ctx = talloc_get_type ( dom - > private_data , struct idmap_ldap_context ) ;
ctx - > alloc = talloc_zero ( ctx , struct idmap_ldap_alloc_context ) ;
CHECK_ALLOC_DONE ( ctx - > alloc ) ;
2007-09-10 23:04:57 +04:00
2006-12-12 17:52:13 +03:00
if ( params & & * params ) {
/* assume location is the only parameter */
2010-06-17 21:45:39 +04:00
ctx - > alloc - > url = talloc_strdup ( ctx - > alloc , params ) ;
2006-12-12 17:52:13 +03:00
} 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
2010-06-17 21:45:39 +04:00
ctx - > alloc - > url = talloc_strdup ( ctx - > alloc , tmp ) ;
2006-12-12 17:52:13 +03:00
}
2010-06-17 21:45:39 +04:00
CHECK_ALLOC_DONE ( ctx - > alloc - > url ) ;
2006-12-12 17:52:13 +03:00
2010-06-17 21:45:39 +04:00
trim_char ( ctx - > alloc - > url , ' \" ' , ' \" ' ) ;
2009-11-20 14:38:44 +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
}
2010-06-17 21:45:39 +04:00
ctx - > alloc - > suffix = talloc_strdup ( ctx - > alloc , tmp ) ;
CHECK_ALLOC_DONE ( ctx - > alloc - > suffix ) ;
2007-09-10 23:04:57 +04:00
2010-06-17 21:45:39 +04:00
ret = smbldap_init ( ctx - > alloc , winbind_event_context ( ) ,
ctx - > alloc - > url ,
& ctx - > alloc - > smbldap_state ) ;
2007-09-10 23:04:57 +04:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 1 , ( " ERROR: smbldap_init (%s) failed! \n " ,
2010-06-17 21:45:39 +04:00
ctx - > alloc - > url ) ) ;
2007-09-10 23:04:57 +04:00
goto done ;
2006-12-12 17:52:13 +03:00
}
2010-06-17 21:45:39 +04:00
talloc_set_destructor ( ctx - > alloc , idmap_ldap_alloc_close_destructor ) ;
ret = get_credentials ( ctx - > alloc ,
ctx - > alloc - > smbldap_state ,
" idmap alloc config " , NULL ,
& ctx - > alloc - > user_dn ) ;
2007-02-06 20:29:18 +03:00
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 */
2010-06-17 20:59:28 +04:00
ret = verify_idpool ( dom ) ;
2007-02-06 20:29:18 +03:00
done :
if ( ! NT_STATUS_IS_OK ( ret ) )
2010-06-17 21:45:39 +04:00
TALLOC_FREE ( ctx - > alloc ) ;
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-06-17 21:03:12 +04:00
static NTSTATUS idmap_ldap_allocate_id ( struct idmap_domain * dom ,
struct unixid * xid )
2006-12-12 17:52:13 +03:00
{
2010-06-17 21:45:39 +04:00
TALLOC_CTX * mem_ctx ;
2006-12-12 17:52:13 +03:00
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 ;
2010-06-17 21:45:39 +04:00
struct idmap_ldap_context * ctx ;
2006-12-12 17:52:13 +03:00
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 ;
}
2010-06-17 21:45:39 +04:00
ctx = talloc_get_type ( dom - > private_data , struct idmap_ldap_context ) ;
if ( ! ctx - > alloc ) {
2006-12-12 17:52:13 +03:00
return NT_STATUS_UNSUCCESSFUL ;
}
2010-06-17 21:45:39 +04:00
mem_ctx = talloc_new ( ctx - > alloc ) ;
if ( ! mem_ctx ) {
2006-12-12 17:52:13 +03:00
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 ;
}
2010-06-17 21:45:39 +04:00
filter = talloc_asprintf ( mem_ctx , " (objectClass=%s) " , LDAP_OBJ_IDPOOL ) ;
2006-12-12 17:52:13 +03:00
CHECK_ALLOC_DONE ( filter ) ;
2010-06-17 21:45:39 +04:00
attr_list = get_attr_list ( mem_ctx , idpool_attr_list ) ;
2006-12-12 17:52:13 +03:00
CHECK_ALLOC_DONE ( attr_list ) ;
DEBUG ( 10 , ( " Search of the id pool (filter: %s) \n " , filter ) ) ;
2010-06-17 21:45:39 +04:00
rc = smbldap_search ( ctx - > alloc - > smbldap_state ,
ctx - > alloc - > suffix ,
2006-12-12 17:52:13 +03:00
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 ;
}
2010-06-17 21:45:39 +04:00
talloc_autofree_ldapmsg ( mem_ctx , result ) ;
2007-09-10 23:04:57 +04:00
2010-06-17 21:45:39 +04:00
count = ldap_count_entries ( ctx - > alloc - > smbldap_state - > ldap_struct ,
2007-09-10 23:04:57 +04:00
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 ;
}
2010-06-17 21:45:39 +04:00
entry = ldap_first_entry ( ctx - > alloc - > smbldap_state - > ldap_struct ,
2007-09-10 23:04:57 +04:00
result ) ;
2006-12-12 17:52:13 +03:00
2010-06-17 21:45:39 +04:00
dn = smbldap_talloc_dn ( mem_ctx ,
ctx - > alloc - > smbldap_state - > ldap_struct ,
2007-09-10 23:04:57 +04:00
entry ) ;
2006-12-12 17:52:13 +03:00
if ( ! dn ) {
goto done ;
}
2010-06-17 21:45:39 +04:00
id_str = smbldap_talloc_single_attribute (
ctx - > alloc - > smbldap_state - > ldap_struct ,
entry , type , mem_ctx ) ;
if ( id_str = = NULL ) {
2006-12-12 17:52:13 +03:00
DEBUG ( 0 , ( " %s attribute not found \n " , type ) ) ;
2010-06-17 22:50:36 +04:00
ret = NT_STATUS_UNSUCCESSFUL ;
2006-12-12 17:52:13 +03:00
goto done ;
}
xid - > id = strtoul ( id_str , NULL , 10 ) ;
/* make sure we still have room to grow */
switch ( xid - > type ) {
case ID_TYPE_UID :
2010-06-17 21:03:12 +04:00
if ( xid - > id > dom - > high_id ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 0 , ( " Cannot allocate uid above %lu! \n " ,
2010-06-17 21:03:12 +04:00
( unsigned long ) dom - > high_id ) ) ;
2006-12-12 17:52:13 +03:00
goto done ;
}
break ;
2007-09-10 23:04:57 +04:00
case ID_TYPE_GID :
2010-06-17 21:03:12 +04:00
if ( xid - > id > dom - > high_id ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 0 , ( " Cannot allocate gid above %lu! \n " ,
2010-06-17 21:03:12 +04:00
( unsigned long ) dom - > high_id ) ) ;
2006-12-12 17:52:13 +03:00
goto done ;
}
break ;
default :
/* impossible */
goto done ;
}
2007-09-10 23:04:57 +04:00
2010-06-17 21:45:39 +04:00
new_id_str = talloc_asprintf ( mem_ctx , " %lu " , ( unsigned long ) xid - > id + 1 ) ;
2006-12-12 17:52:13 +03:00
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
2010-06-17 21:45:39 +04:00
rc = smbldap_modify ( ctx - > alloc - > smbldap_state , dn , mods ) ;
2006-12-12 17:52:13 +03:00
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 :
2010-06-17 21:45:39 +04:00
talloc_free ( mem_ctx ) ;
2006-12-12 17:52:13 +03:00
return ret ;
}
/**********************************************************************
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-07-13 14:07:40 +04:00
static NTSTATUS idmap_ldap_db_init ( struct idmap_domain * dom ,
const char * params )
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 * 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 ;
}
2009-05-27 21:25:44 +04:00
if ( strequal ( dom - > name , " * " ) ) {
2010-06-17 12:16:20 +04:00
/* more specific configuration can go here */
2009-05-27 21:25:44 +04:00
} else {
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 ;
2006-12-12 17:52:13 +03:00
}
}
2008-07-13 14:07:40 +04:00
if ( params ! = NULL ) {
2006-12-12 17:52:13 +03:00
/* assume location is the only parameter */
2008-07-13 14:07:40 +04:00
ctx - > url = talloc_strdup ( ctx , 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 ) ;
2009-11-20 14:44:43 +03:00
trim_char ( ctx - > url , ' \" ' , ' \" ' ) ;
2009-11-20 17:03:59 +03: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 ;
2007-09-10 20:21:55 +04:00
}
2009-11-20 17:03:59 +03:00
}
2007-09-10 20:21:55 +04:00
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 ;
}
2009-11-20 17:03:59 +03: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 ;
2010-06-17 21:17:48 +04:00
ret = idmap_ldap_alloc_init ( dom , params ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 1 , ( " idmap_ldap_db_init: Failed to initialize alloc "
" subsystem: %s \n " , nt_errstr ( ret ) ) ) ;
goto done ;
}
2006-12-12 17:52:13 +03:00
talloc_free ( config_option ) ;
return NT_STATUS_OK ;
/*failed */
done :
talloc_free ( ctx ) ;
return ret ;
}
2010-06-17 22:15:25 +04:00
/**
* set a mapping .
*/
/* TODO: change this: This function cannot be called to modify a mapping,
* only set a new one */
static NTSTATUS idmap_ldap_set_mapping ( struct idmap_domain * dom ,
const struct id_map * map )
{
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 ;
/* Only do query if we are online */
if ( idmap_is_offline ( ) ) {
return NT_STATUS_FILE_IS_OFFLINE ;
}
ctx = talloc_get_type ( dom - > private_data , struct idmap_ldap_context ) ;
switch ( map - > xid . type ) {
case ID_TYPE_UID :
type = get_attr_key2string ( sidmap_attr_list ,
LDAP_ATTR_UIDNUMBER ) ;
break ;
case ID_TYPE_GID :
type = get_attr_key2string ( sidmap_attr_list ,
LDAP_ATTR_GIDNUMBER ) ;
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 ) ;
sid = talloc_strdup ( memctx , sid_string_talloc ( memctx , map - > sid ) ) ;
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 ) ;
smbldap_set_mod ( & mods , LDAP_MOD_ADD ,
" objectClass " , LDAP_OBJ_IDMAP_ENTRY ) ;
smbldap_make_mod ( ctx - > smbldap_state - > ldap_struct ,
entry , & mods , type , id_str ) ;
smbldap_make_mod ( ctx - > smbldap_state - > ldap_struct , entry , & mods ,
get_attr_key2string ( sidmap_attr_list , LDAP_ATTR_SID ) ,
sid ) ;
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 ) ;
ldap_mods_free ( mods , True ) ;
if ( rc ! = LDAP_SUCCESS ) {
char * ld_error = NULL ;
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 " ,
ld_error ? ld_error : " (NULL) " , ldap_err2string ( rc ) ) ) ;
if ( ld_error ) {
ldap_memfree ( ld_error ) ;
}
ret = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
DEBUG ( 10 , ( " ldap_set_mapping: Successfully created mapping from %s to "
" %lu [%s] \n " , sid , ( unsigned long ) map - > xid . id , type ) ) ;
ret = NT_STATUS_OK ;
done :
talloc_free ( memctx ) ;
return ret ;
}
2006-12-12 17:52:13 +03:00
/* 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 ;
2009-05-22 13:58:00 +04:00
LDAPMessage * entry = NULL ;
2006-12-12 17:52:13 +03:00
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 ;
}
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 ;
}
2009-02-26 12:44:33 +03:00
for ( i = 0 ; ids [ i ] ; i + + ) {
ids [ i ] - > status = ID_UNKNOWN ;
}
2006-12-12 17:52:13 +03:00
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 + + ) {
char * sidstr = NULL ;
2009-11-20 17:03:59 +03:00
char * tmp = NULL ;
2006-12-12 17:52:13 +03:00
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 ) ;
2010-06-17 12:00:49 +04:00
if ( ! idmap_unix_id_is_in_range ( id , dom ) ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 5 , ( " Requested id (%u) out of range (%u - %u). "
" Filtered! \n " , id ,
2010-06-17 12:00:49 +04:00
dom - > low_id , dom - > 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 ;
}
2009-05-25 13:29:14 +04:00
if ( map - > status = = ID_MAPPED ) {
DEBUG ( 1 , ( " WARNING: duplicate %s mapping in LDAP. "
" overwriting mapping %u -> %s with %u -> %s \n " ,
( type = = ID_TYPE_UID ) ? " UID " : " GID " ,
id , sid_string_dbg ( map - > sid ) , id , sidstr ) ) ;
}
2006-12-12 17:52:13 +03:00
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 */
2010-05-21 05:25:01 +04:00
static struct id_map * find_map_by_sid ( struct id_map * * maps , struct dom_sid * sid )
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 ( 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
{
2009-11-20 17:03:59 +03: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 ;
}
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 ;
}
2009-02-26 12:44:33 +03:00
for ( i = 0 ; ids [ i ] ; i + + ) {
ids [ i ] - > status = ID_UNKNOWN ;
}
2006-12-12 17:52:13 +03:00
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 ;
2010-05-21 05:25:01 +04:00
struct dom_sid sid ;
2006-12-12 17:52:13 +03:00
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 ;
}
/* 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 " ) ) ;
2009-05-25 13:54:43 +04:00
TALLOC_FREE ( sidstr ) ;
2006-12-12 17:52:13 +03:00
continue ;
}
id = strtoul ( tmp , NULL , 10 ) ;
2010-06-17 12:00:49 +04:00
if ( ! idmap_unix_id_is_in_range ( id , dom ) ) {
2007-09-10 23:04:57 +04:00
DEBUG ( 5 , ( " Requested id (%u) out of range (%u - %u). "
" Filtered! \n " , id ,
2010-06-17 12:00:49 +04:00
dom - > low_id , dom - > high_id ) ) ;
2009-05-25 13:54:43 +04:00
TALLOC_FREE ( sidstr ) ;
2006-12-12 17:52:13 +03:00
TALLOC_FREE ( tmp ) ;
continue ;
}
TALLOC_FREE ( tmp ) ;
2009-05-25 13:54:43 +04:00
if ( map - > status = = ID_MAPPED ) {
DEBUG ( 1 , ( " WARNING: duplicate %s mapping in LDAP. "
" overwriting mapping %s -> %u with %s -> %u \n " ,
( type = = ID_TYPE_UID ) ? " UID " : " GID " ,
sidstr , map - > xid . id , sidstr , id ) ) ;
}
TALLOC_FREE ( sidstr ) ;
2006-12-12 17:52:13 +03:00
/* 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
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 ,
2010-06-22 16:49:00 +04:00
. allocate_id = idmap_ldap_get_new_id ,
2006-12-12 17:52:13 +03:00
. close_fn = idmap_ldap_close
} ;
2008-07-16 20:14:33 +04:00
NTSTATUS idmap_ldap_init ( void ) ;
2006-12-12 17:52:13 +03:00
NTSTATUS idmap_ldap_init ( void )
{
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
}