mirror of
https://github.com/samba-team/samba.git
synced 2025-03-27 22:50:26 +03:00
r20986: Commit the prototype of the nss_info plugin interface.
This allows a provider to supply the homedirectory, etc... attributes for a user without requiring support in core winbindd code. The idmap_ad.c module has been modified to provide the idmap 'ad' library as well as the rfc2307 and sfu "winbind nss info" support. The SID/id mapping is working in idmap_ad but the nss_info still has a few quirks that I'm in the process of resolving. (This used to be commit aaec0115e2c96935499052d9a637a20c6445986e)
This commit is contained in:
parent
78f5f4b260
commit
b9b26be174
@ -181,7 +181,9 @@ RPC_MODULES = @RPC_MODULES@
|
||||
IDMAP_MODULES = @IDMAP_MODULES@
|
||||
CHARSET_MODULES = @CHARSET_MODULES@
|
||||
AUTH_MODULES = @AUTH_MODULES@
|
||||
MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) $(CHARSET_MODULES) $(AUTH_MODULES)
|
||||
NSS_INFO_MODULES = @NSS_INFO_MODULES@
|
||||
MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) \
|
||||
$(CHARSET_MODULES) $(AUTH_MODULES) $(NSS_INFO_MODULES)
|
||||
|
||||
######################################################################
|
||||
# object file lists
|
||||
@ -289,7 +291,7 @@ LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
|
||||
libads/authdata.o libads/cldap.o
|
||||
|
||||
LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o \
|
||||
libads/ldap_schema.o nsswitch/nss_info.o
|
||||
libads/ldap_schema.o
|
||||
|
||||
SECRETS_OBJ = passdb/secrets.o passdb/machine_sid.o
|
||||
|
||||
@ -745,7 +747,8 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) $(LIBNDR_OBJ) $(LIBNDR_GEN_OBJ) \
|
||||
$(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \
|
||||
$(RPC_ECHO_OBJ) $(RPC_SVCCTL_OBJ) $(RPC_EVENTLOG_OBJ) $(SMBLDAP_OBJ) \
|
||||
$(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) $(RPC_UNIXINFO_OBJ) \
|
||||
$(RPC_NTSVCS_OBJ) $(RPC_INITSHUTDOWN_OBJ) $(PASSWD_UTIL_OBJ) $(LIBGPO_OBJ)
|
||||
$(RPC_NTSVCS_OBJ) $(RPC_INITSHUTDOWN_OBJ) utils/passwd_util.o \
|
||||
$(LIBGPO_OBJ) $(NSS_INFO_OBJ)
|
||||
|
||||
WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) \
|
||||
$(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(NSSWINS_OBJ) $(KRBCLIENT_OBJ) $(SECRETS_OBJ)
|
||||
@ -758,6 +761,10 @@ PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \
|
||||
|
||||
IDMAP_OBJ = nsswitch/idmap.o nsswitch/idmap_cache.o nsswitch/idmap_util.o @IDMAP_STATIC@
|
||||
|
||||
NSS_INFO_OBJ = nsswitch/nss_info.o @NSS_INFO_STATIC@
|
||||
|
||||
IDMAP_NSS_OBJ = sam/idmap_nss.o @IDMAP_NSS_STATIC@
|
||||
|
||||
WINBINDD_OBJ1 = \
|
||||
nsswitch/winbindd.o \
|
||||
nsswitch/winbindd_user.o \
|
||||
@ -785,7 +792,7 @@ WINBINDD_OBJ = \
|
||||
$(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(RPC_PARSE_OBJ) \
|
||||
$(PROFILE_OBJ) $(SLCACHE_OBJ) $(SMBLDAP_OBJ) \
|
||||
$(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \
|
||||
$(DCUTIL_OBJ) $(IDMAP_OBJ) \
|
||||
$(DCUTIL_OBJ) $(IDMAP_OBJ) $(NSS_INFO_OBJ) \
|
||||
$(AFS_OBJ) $(AFS_SETTOKEN_OBJ) \
|
||||
$(LIBADS_SERVER_OBJ) $(SERVER_MUTEX_OBJ) $(LDB_OBJ)
|
||||
|
||||
@ -1549,6 +1556,12 @@ bin/gpfs.@SHLIBEXT@: $(VFS_GPFS_OBJ)
|
||||
@$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_GPFS_OBJ) \
|
||||
@SONAMEFLAG@`basename $@`
|
||||
|
||||
#########################################################
|
||||
## IdMap NSS plugins
|
||||
|
||||
## None here right now
|
||||
#########################################################
|
||||
|
||||
bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy
|
||||
@echo Linking $@
|
||||
@$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@
|
||||
|
@ -592,7 +592,7 @@ AC_SUBST(DYNEXP)
|
||||
|
||||
dnl Add modules that have to be built by default here
|
||||
dnl These have to be built static:
|
||||
default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_winreg rpc_initshutdown rpc_lsa_ds rpc_wkssvc rpc_svcctl rpc_ntsvcs rpc_net rpc_netdfs rpc_srvsvc rpc_spoolss rpc_eventlog rpc_unixinfo auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin vfs_default"
|
||||
default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_winreg rpc_initshutdown rpc_lsa_ds rpc_wkssvc rpc_svcctl rpc_ntsvcs rpc_net rpc_netdfs rpc_srvsvc rpc_spoolss rpc_eventlog rpc_unixinfo auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin vfs_default nss_info_template"
|
||||
|
||||
dnl These are preferably build shared, and static if dlopen() is not available
|
||||
default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy charset_CP850 charset_CP437 auth_script"
|
||||
@ -5862,6 +5862,11 @@ MODULE_idmap_tdb=STATIC
|
||||
MODULE_idmap_passdb=STATIC
|
||||
MODULE_idmap_nss=STATIC
|
||||
|
||||
MODULE_idmap_passdb=STATIC
|
||||
MODULE_idmap_nss=STATIC
|
||||
|
||||
MODULE_nss_info_template=STATIC
|
||||
|
||||
AC_ARG_WITH(static-modules,
|
||||
[ --with-static-modules=MODULES Comma-separated list of names of modules to statically link in],
|
||||
[ if test $withval; then
|
||||
@ -5912,6 +5917,9 @@ SMB_MODULE(idmap_rid, nsswitch/idmap_rid.o, "bin/rid.$SHLIBEXT", IDMAP)
|
||||
SMB_MODULE(idmap_ad, nsswitch/idmap_ad.o, "bin/ad.$SHLIBEXT", IDMAP)
|
||||
SMB_SUBSYSTEM(IDMAP, nsswitch/idmap.o)
|
||||
|
||||
SMB_MODULE(nss_info_template, nsswitch/nss_info_template.o, "bin/template.$SHLIBEXT", NSS_INFO)
|
||||
SMB_SUBSYSTEM(NSS_INFO, nsswitch/nss_info.o)
|
||||
|
||||
SMB_MODULE(charset_weird, modules/weird.o, "bin/weird.$SHLIBEXT", CHARSET)
|
||||
SMB_MODULE(charset_CP850, modules/CP850.o, "bin/CP850.$SHLIBEXT", CHARSET)
|
||||
SMB_MODULE(charset_CP437, modules/CP437.o, "bin/CP437.$SHLIBEXT", CHARSET)
|
||||
|
@ -57,19 +57,20 @@ typedef struct {
|
||||
time_t current_time;
|
||||
int tried_closest_dc;
|
||||
} config;
|
||||
|
||||
/* info derived from the servers schema */
|
||||
struct {
|
||||
enum wb_posix_mapping map_type;
|
||||
char *posix_homedir_attr;
|
||||
char *posix_shell_attr;
|
||||
char *posix_uidnumber_attr;
|
||||
char *posix_gidnumber_attr;
|
||||
char *posix_gecos_attr;
|
||||
} schema;
|
||||
|
||||
} ADS_STRUCT;
|
||||
|
||||
/* used to remember the names of the posix attributes in AD */
|
||||
/* see the rfc2307 & sfu nss backends */
|
||||
|
||||
struct posix_schema {
|
||||
char *posix_homedir_attr;
|
||||
char *posix_shell_attr;
|
||||
char *posix_uidnumber_attr;
|
||||
char *posix_gidnumber_attr;
|
||||
char *posix_gecos_attr;
|
||||
};
|
||||
|
||||
|
||||
/* there are 5 possible types of errors the ads subsystem can produce */
|
||||
enum ads_error_type {ENUM_ADS_ERROR_KRB5, ENUM_ADS_ERROR_GSS,
|
||||
ENUM_ADS_ERROR_LDAP, ENUM_ADS_ERROR_SYSTEM, ENUM_ADS_ERROR_NT};
|
||||
|
@ -768,6 +768,8 @@ enum flush_reason_enum {
|
||||
/* NUM_FLUSH_REASONS must remain the last value in the enumeration. */
|
||||
NUM_FLUSH_REASONS};
|
||||
|
||||
#include "nss_info.h"
|
||||
|
||||
/***** automatically generated prototypes *****/
|
||||
#ifndef NO_PROTO_H
|
||||
#include "proto.h"
|
||||
|
68
source3/include/nss_info.h
Normal file
68
source3/include/nss_info.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Idmap NSS headers
|
||||
|
||||
Copyright (C) Gerald Carter 2006
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _IDMAP_NSS_H
|
||||
#define _IDMAP_NSS_H
|
||||
|
||||
/* The interface version specifier */
|
||||
|
||||
#define SMB_NSS_INFO_INTERFACE_VERSION 1
|
||||
|
||||
/* List of available backends. All backends must
|
||||
register themselves */
|
||||
|
||||
struct nss_function_entry {
|
||||
struct nss_function_entry *prev, *next;
|
||||
|
||||
const char *name;
|
||||
struct nss_info_methods *methods;
|
||||
};
|
||||
|
||||
/* List of configured domains. Each domain points
|
||||
back to its configured backend. */
|
||||
|
||||
struct nss_domain_entry {
|
||||
struct nss_domain_entry *prev, *next;
|
||||
|
||||
const char *domain;
|
||||
|
||||
NTSTATUS init_status;
|
||||
struct nss_function_entry *backend;
|
||||
|
||||
/* hold state on a per domain basis */
|
||||
|
||||
void *state;
|
||||
};
|
||||
|
||||
/* API */
|
||||
|
||||
struct nss_info_methods {
|
||||
NTSTATUS (*init)( struct nss_domain_entry *e );
|
||||
NTSTATUS (*get_nss_info)( struct nss_domain_entry *e,
|
||||
const DOM_SID *sid,
|
||||
TALLOC_CTX *ctx,
|
||||
ADS_STRUCT *ads, LDAPMessage *msg,
|
||||
char **homedir, char **shell, char **gecos, gid_t *p_gid);
|
||||
NTSTATUS (*close_fn)( void );
|
||||
};
|
||||
|
||||
#endif /* _IDMAP_NSS_H_ */
|
@ -161,12 +161,6 @@ void ads_destroy(ADS_STRUCT **ads)
|
||||
SAFE_FREE((*ads)->config.server_site_name);
|
||||
SAFE_FREE((*ads)->config.client_site_name);
|
||||
|
||||
SAFE_FREE((*ads)->schema.posix_uidnumber_attr);
|
||||
SAFE_FREE((*ads)->schema.posix_gidnumber_attr);
|
||||
SAFE_FREE((*ads)->schema.posix_shell_attr);
|
||||
SAFE_FREE((*ads)->schema.posix_homedir_attr);
|
||||
SAFE_FREE((*ads)->schema.posix_gecos_attr);
|
||||
|
||||
ZERO_STRUCTP(*ads);
|
||||
|
||||
if ( is_mine )
|
||||
|
@ -186,7 +186,10 @@ static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **s
|
||||
* @return ADS_STATUS status of search (False if one or more attributes couldn't be
|
||||
* found in Active Directory)
|
||||
**/
|
||||
ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping map_type)
|
||||
ADS_STATUS ads_check_posix_schema_mapping(TALLOC_CTX *mem_ctx,
|
||||
ADS_STRUCT *ads,
|
||||
enum wb_posix_mapping map_type,
|
||||
struct posix_schema **s )
|
||||
{
|
||||
TALLOC_CTX *ctx = NULL;
|
||||
ADS_STATUS status;
|
||||
@ -194,6 +197,7 @@ ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping
|
||||
size_t num_names;
|
||||
char *schema_path = NULL;
|
||||
int i;
|
||||
struct posix_schema *schema = NULL;
|
||||
|
||||
const char *oids_sfu[] = { ADS_ATTR_SFU_UIDNUMBER_OID,
|
||||
ADS_ATTR_SFU_GIDNUMBER_OID,
|
||||
@ -209,34 +213,15 @@ ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping
|
||||
|
||||
DEBUG(10,("ads_check_posix_schema_mapping\n"));
|
||||
|
||||
switch (map_type) {
|
||||
|
||||
case WB_POSIX_MAP_TEMPLATE:
|
||||
case WB_POSIX_MAP_UNIXINFO:
|
||||
DEBUG(10,("ads_check_posix_schema_mapping: nothing to do\n"));
|
||||
return ADS_ERROR(LDAP_SUCCESS);
|
||||
|
||||
case WB_POSIX_MAP_SFU:
|
||||
case WB_POSIX_MAP_RFC2307:
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG(0,("ads_check_posix_schema_mapping: "
|
||||
"unknown enum %d\n", map_type));
|
||||
return ADS_ERROR(LDAP_PARAM_ERROR);
|
||||
}
|
||||
|
||||
ads->schema.posix_uidnumber_attr = NULL;
|
||||
ads->schema.posix_gidnumber_attr = NULL;
|
||||
ads->schema.posix_homedir_attr = NULL;
|
||||
ads->schema.posix_shell_attr = NULL;
|
||||
ads->schema.posix_gecos_attr = NULL;
|
||||
|
||||
ctx = talloc_init("ads_check_posix_schema_mapping");
|
||||
if (ctx == NULL) {
|
||||
if ( (ctx = talloc_init("ads_check_posix_schema_mapping")) == NULL ) {
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
if ( (schema = TALLOC_P(mem_ctx, struct posix_schema)) == NULL ) {
|
||||
TALLOC_FREE( ctx );
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
status = ads_schema_path(ads, ctx, &schema_path);
|
||||
if (!ADS_ERR_OK(status)) {
|
||||
DEBUG(3,("ads_check_posix_mapping: Unable to retrieve schema DN!\n"));
|
||||
@ -257,10 +242,7 @@ ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping
|
||||
DEBUG(3,("ads_check_posix_schema_mapping: failed %s\n",
|
||||
ads_errstr(status)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
DEBUG(10,("ads_check_posix_schema_mapping: query succeeded, identified: %s\n",
|
||||
wb_posix_map_str(map_type)));
|
||||
}
|
||||
|
||||
for (i=0; i<num_names; i++) {
|
||||
|
||||
@ -268,43 +250,48 @@ ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping
|
||||
|
||||
if (strequal(ADS_ATTR_RFC2307_UIDNUMBER_OID, oids_out[i]) ||
|
||||
strequal(ADS_ATTR_SFU_UIDNUMBER_OID, oids_out[i])) {
|
||||
SAFE_FREE(ads->schema.posix_uidnumber_attr);
|
||||
ads->schema.posix_uidnumber_attr = SMB_STRDUP(names_out[i]);
|
||||
schema->posix_uidnumber_attr = talloc_strdup(schema, names_out[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strequal(ADS_ATTR_RFC2307_GIDNUMBER_OID, oids_out[i]) ||
|
||||
strequal(ADS_ATTR_SFU_GIDNUMBER_OID, oids_out[i])) {
|
||||
SAFE_FREE(ads->schema.posix_gidnumber_attr);
|
||||
ads->schema.posix_gidnumber_attr = SMB_STRDUP(names_out[i]);
|
||||
schema->posix_gidnumber_attr = talloc_strdup(schema, names_out[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strequal(ADS_ATTR_RFC2307_HOMEDIR_OID, oids_out[i]) ||
|
||||
strequal(ADS_ATTR_SFU_HOMEDIR_OID, oids_out[i])) {
|
||||
SAFE_FREE(ads->schema.posix_homedir_attr);
|
||||
ads->schema.posix_homedir_attr = SMB_STRDUP(names_out[i]);
|
||||
schema->posix_homedir_attr = talloc_strdup(schema, names_out[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strequal(ADS_ATTR_RFC2307_SHELL_OID, oids_out[i]) ||
|
||||
strequal(ADS_ATTR_SFU_SHELL_OID, oids_out[i])) {
|
||||
SAFE_FREE(ads->schema.posix_shell_attr);
|
||||
ads->schema.posix_shell_attr = SMB_STRDUP(names_out[i]);
|
||||
schema->posix_shell_attr = talloc_strdup(schema, names_out[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strequal(ADS_ATTR_RFC2307_GECOS_OID, oids_out[i]) ||
|
||||
strequal(ADS_ATTR_SFU_GECOS_OID, oids_out[i])) {
|
||||
SAFE_FREE(ads->schema.posix_gecos_attr);
|
||||
ads->schema.posix_gecos_attr = SMB_STRDUP(names_out[i]);
|
||||
schema->posix_gecos_attr = talloc_strdup(schema, names_out[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ads->schema.posix_uidnumber_attr ||
|
||||
!ads->schema.posix_gidnumber_attr ||
|
||||
!ads->schema.posix_homedir_attr ||
|
||||
!ads->schema.posix_shell_attr ||
|
||||
!ads->schema.posix_gecos_attr) {
|
||||
if (!schema->posix_uidnumber_attr ||
|
||||
!schema->posix_gidnumber_attr ||
|
||||
!schema->posix_homedir_attr ||
|
||||
!schema->posix_shell_attr ||
|
||||
!schema->posix_gecos_attr) {
|
||||
status = ADS_ERROR(LDAP_NO_MEMORY);
|
||||
TALLOC_FREE( schema );
|
||||
goto done;
|
||||
}
|
||||
|
||||
*s = schema;
|
||||
|
||||
status = ADS_ERROR(LDAP_SUCCESS);
|
||||
|
||||
ads->schema.map_type = map_type;
|
||||
done:
|
||||
if (ctx) {
|
||||
talloc_destroy(ctx);
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
* Copyright (C) Andrew Tridgell 2001
|
||||
* Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
|
||||
* Copyright (C) Gerald (Jerry) Carter 2004
|
||||
* Copyright (C) Gerald (Jerry) Carter 2004-2007
|
||||
* Copyright (C) Luke Howard 2001-2004
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -32,56 +32,36 @@
|
||||
|
||||
#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
|
||||
|
||||
#define IDMAP_AD_MAX_IDS 30
|
||||
#define CHECK_ALLOC_DONE(mem) do { \
|
||||
if (!mem) { \
|
||||
DEBUG(0, ("Out of memory!\n")); \
|
||||
ret = NT_STATUS_NO_MEMORY; \
|
||||
goto done; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct idmap_ad_context {
|
||||
uint32_t filter_low_id;
|
||||
uint32_t filter_high_id;
|
||||
};
|
||||
|
||||
NTSTATUS init_module(void);
|
||||
|
||||
static ADS_STRUCT *ad_idmap_ads = NULL;
|
||||
static struct posix_schema *ad_schema = NULL;
|
||||
static enum wb_posix_mapping ad_map_type = WB_POSIX_MAP_UNKNOWN;
|
||||
|
||||
static char *attr_uidnumber = NULL;
|
||||
static char *attr_gidnumber = NULL;
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
static ADS_STATUS ad_idmap_check_attr_mapping(ADS_STRUCT *ads)
|
||||
{
|
||||
ADS_STATUS status;
|
||||
enum wb_posix_mapping map_type;
|
||||
|
||||
if (attr_uidnumber != NULL && attr_gidnumber != NULL) {
|
||||
return ADS_ERROR(LDAP_SUCCESS);
|
||||
}
|
||||
|
||||
SMB_ASSERT(ads->server.workgroup);
|
||||
|
||||
map_type = get_nss_info(ads->server.workgroup);
|
||||
|
||||
if ((map_type == WB_POSIX_MAP_SFU) ||
|
||||
(map_type == WB_POSIX_MAP_RFC2307)) {
|
||||
|
||||
status = ads_check_posix_schema_mapping(ads, map_type);
|
||||
if (ADS_ERR_OK(status)) {
|
||||
attr_uidnumber = SMB_STRDUP(ads->schema.posix_uidnumber_attr);
|
||||
attr_gidnumber = SMB_STRDUP(ads->schema.posix_gidnumber_attr);
|
||||
ADS_ERROR_HAVE_NO_MEMORY(attr_uidnumber);
|
||||
ADS_ERROR_HAVE_NO_MEMORY(attr_gidnumber);
|
||||
return ADS_ERROR(LDAP_SUCCESS);
|
||||
} else {
|
||||
DEBUG(0,("ads_check_posix_schema_mapping failed: %s\n", ads_errstr(status)));
|
||||
/* return status; */
|
||||
}
|
||||
}
|
||||
|
||||
/* fallback to XAD defaults */
|
||||
attr_uidnumber = SMB_STRDUP("uidNumber");
|
||||
attr_gidnumber = SMB_STRDUP("gidNumber");
|
||||
ADS_ERROR_HAVE_NO_MEMORY(attr_uidnumber);
|
||||
ADS_ERROR_HAVE_NO_MEMORY(attr_gidnumber);
|
||||
|
||||
return ADS_ERROR(LDAP_SUCCESS);
|
||||
}
|
||||
|
||||
static ADS_STRUCT *ad_idmap_cached_connection(void)
|
||||
static ADS_STRUCT *ad_idmap_cached_connection_internal(void)
|
||||
{
|
||||
ADS_STRUCT *ads;
|
||||
ADS_STATUS status;
|
||||
BOOL local = False;
|
||||
fstring dc_name;
|
||||
struct in_addr dc_ip;
|
||||
|
||||
if (ad_idmap_ads != NULL) {
|
||||
ads = ad_idmap_ads;
|
||||
@ -98,6 +78,7 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
|
||||
ads_destroy( &ads );
|
||||
ads_kdestroy(WINBIND_CCACHE_NAME);
|
||||
ad_idmap_ads = NULL;
|
||||
TALLOC_FREE( ad_schema );
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,8 +87,7 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
|
||||
setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
|
||||
}
|
||||
|
||||
ads = ads_init(lp_realm(), lp_workgroup(), NULL);
|
||||
if (!ads) {
|
||||
if ( (ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL ) {
|
||||
DEBUG(1,("ads_init failed\n"));
|
||||
return NULL;
|
||||
}
|
||||
@ -119,6 +99,10 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
|
||||
SAFE_FREE(ads->auth.realm);
|
||||
ads->auth.realm = SMB_STRDUP(lp_realm());
|
||||
|
||||
/* setup server affinity */
|
||||
|
||||
get_dc_name( NULL, ads->auth.realm, dc_name, &dc_ip );
|
||||
|
||||
status = ads_connect(ads);
|
||||
if (!ADS_ERR_OK(status)) {
|
||||
DEBUG(1, ("ad_idmap_init: failed to connect to AD\n"));
|
||||
@ -128,21 +112,47 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
|
||||
|
||||
ads->is_mine = False;
|
||||
|
||||
status = ad_idmap_check_attr_mapping(ads);
|
||||
if (!ADS_ERR_OK(status)) {
|
||||
DEBUG(1, ("ad_idmap_init: failed to check attribute mapping\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ad_idmap_ads = ads;
|
||||
|
||||
return ads;
|
||||
}
|
||||
|
||||
struct idmap_ad_context {
|
||||
uint32_t filter_low_id, filter_high_id; /* Filter range */
|
||||
};
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
static ADS_STRUCT *ad_idmap_cached_connection(void)
|
||||
{
|
||||
ADS_STRUCT *ads = ad_idmap_cached_connection_internal();
|
||||
|
||||
if ( !ads )
|
||||
return NULL;
|
||||
|
||||
/* if we have a valid ADS_STRUCT and the schema model is
|
||||
defined, then we can return here. */
|
||||
|
||||
if ( ad_schema )
|
||||
return ads;
|
||||
|
||||
/* Otherwise, set the schema model */
|
||||
|
||||
if ( (ad_map_type == WB_POSIX_MAP_SFU) ||
|
||||
(ad_map_type == WB_POSIX_MAP_RFC2307) )
|
||||
{
|
||||
ADS_STATUS schema_status;
|
||||
|
||||
schema_status = ads_check_posix_schema_mapping( NULL, ads, ad_map_type, &ad_schema);
|
||||
if ( !ADS_ERR_OK(schema_status) ) {
|
||||
DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n"));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ads;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
/* Initialize and check conf is appropriate */
|
||||
static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, const char *params)
|
||||
{
|
||||
struct idmap_ad_context *ctx;
|
||||
@ -151,19 +161,16 @@ static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, const char *params
|
||||
ADS_STRUCT *ads;
|
||||
|
||||
/* verify AD is reachable (not critical, we may just be offline at start) */
|
||||
ads = ad_idmap_cached_connection();
|
||||
if (ads == NULL) {
|
||||
if ( (ads = ad_idmap_cached_connection()) == NULL ) {
|
||||
DEBUG(1, ("WARNING: Could not init an AD connection! Mapping might not work.\n"));
|
||||
}
|
||||
|
||||
ctx = talloc_zero(dom, struct idmap_ad_context);
|
||||
if ( ! ctx) {
|
||||
if ( (ctx = talloc_zero(dom, struct idmap_ad_context)) == NULL ) {
|
||||
DEBUG(0, ("Out of memory!\n"));
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
|
||||
if ( ! config_option) {
|
||||
if ( (config_option = talloc_asprintf(ctx, "idmap config %s", dom->name)) == NULL ) {
|
||||
DEBUG(0, ("Out of memory!\n"));
|
||||
talloc_free(ctx);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
@ -194,29 +201,28 @@ static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, const char *params
|
||||
"NOTE: make sure the ranges do not overlap\n",
|
||||
dom->name, dom->name, dom->name, dom->name));
|
||||
}
|
||||
if ( ! dom->readonly) {
|
||||
|
||||
if ( !dom->readonly ) {
|
||||
DEBUG(1, ("WARNING: forcing to readonly, as idmap_ad can't write on AD.\n"));
|
||||
dom->readonly = true; /* force readonly */
|
||||
dom->readonly = true;
|
||||
}
|
||||
|
||||
dom->private_data = ctx;
|
||||
|
||||
talloc_free(config_option);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
#define IDMAP_AD_MAX_IDS 30
|
||||
#define CHECK_ALLOC_DONE(mem) do { if (!mem) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } } while (0)
|
||||
/************************************************************************
|
||||
Search up to IDMAP_AD_MAX_IDS entries in maps for a match.
|
||||
***********************************************************************/
|
||||
|
||||
/* this function searches up to IDMAP_AD_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)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IDMAP_AD_MAX_IDS; i++) {
|
||||
if (maps[i] == NULL) { /* end of the run */
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
|
||||
if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
|
||||
return maps[i];
|
||||
}
|
||||
@ -225,6 +231,26 @@ static struct id_map *find_map_by_id(struct id_map **maps, enum id_type type, ui
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Search up to IDMAP_AD_MAX_IDS entries in maps for a match
|
||||
***********************************************************************/
|
||||
|
||||
static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
|
||||
if (sid_equal(maps[i]->sid, sid)) {
|
||||
return maps[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
|
||||
{
|
||||
NTSTATUS ret;
|
||||
@ -234,132 +260,89 @@ static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map
|
||||
ADS_STRUCT *ads;
|
||||
const char *attrs[] = { "sAMAccountType",
|
||||
"objectSid",
|
||||
NULL, /* attr_uidnumber */
|
||||
NULL, /* attr_gidnumber */
|
||||
NULL, /* uidnumber */
|
||||
NULL, /* gidnumber */
|
||||
NULL };
|
||||
LDAPMessage *res = NULL;
|
||||
char *filter = NULL;
|
||||
BOOL multi = False;
|
||||
int idx = 0;
|
||||
int bidx = 0;
|
||||
int count;
|
||||
int i;
|
||||
char *u_filter = NULL;
|
||||
char *g_filter = NULL;
|
||||
|
||||
ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
|
||||
ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
|
||||
|
||||
memctx = talloc_new(ctx);
|
||||
if ( ! memctx) {
|
||||
if ( (memctx = talloc_new(ctx)) == NULL ) {
|
||||
DEBUG(0, ("Out of memory!\n"));
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
ads = ad_idmap_cached_connection();
|
||||
if (ads == NULL) {
|
||||
if ( (ads = ad_idmap_cached_connection()) == NULL ) {
|
||||
DEBUG(1, ("ADS uninitialized\n"));
|
||||
ret = NT_STATUS_UNSUCCESSFUL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* attr_uidnumber and attr_gidnumber are surely successfully initialized now */
|
||||
attrs[2] = attr_uidnumber;
|
||||
attrs[3] = attr_gidnumber;
|
||||
|
||||
if ( ! ids[1]) {
|
||||
/* if we are requested just one mapping use the simple filter */
|
||||
switch (ids[0]->xid.type) {
|
||||
case ID_TYPE_UID:
|
||||
|
||||
filter = talloc_asprintf(memctx,
|
||||
"(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d))(%s=%lu))",
|
||||
ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
|
||||
attr_uidnumber,
|
||||
(unsigned long)ids[0]->xid.id);
|
||||
break;
|
||||
case ID_TYPE_GID:
|
||||
|
||||
filter = talloc_asprintf(memctx,
|
||||
"(&(|(sAMAccountType=%d)(sAMAccountType=%d))(%s=%lu))",
|
||||
ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP,
|
||||
attr_gidnumber,
|
||||
(unsigned long)ids[0]->xid.id);
|
||||
break;
|
||||
default:
|
||||
DEBUG(3, ("Unknown ID type\n"));
|
||||
ret = NT_STATUS_INVALID_PARAMETER;
|
||||
goto done;
|
||||
}
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
DEBUG(10, ("Filter: [%s]\n", filter));
|
||||
} else {
|
||||
/* multiple mappings */
|
||||
multi = True;
|
||||
}
|
||||
attrs[2] = ad_schema->posix_uidnumber_attr;
|
||||
attrs[3] = ad_schema->posix_gidnumber_attr;
|
||||
|
||||
again:
|
||||
if (multi) {
|
||||
char *u_filter = NULL;
|
||||
char *g_filter = NULL;
|
||||
|
||||
bidx = idx;
|
||||
for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
|
||||
switch (ids[idx]->xid.type) {
|
||||
case ID_TYPE_UID:
|
||||
|
||||
if ( ! u_filter) {
|
||||
u_filter = talloc_asprintf(memctx, "(&(|"
|
||||
"(sAMAccountType=%d)"
|
||||
"(sAMAccountType=%d)"
|
||||
"(sAMAccountType=%d))(|",
|
||||
ATYPE_NORMAL_ACCOUNT,
|
||||
ATYPE_WORKSTATION_TRUST,
|
||||
ATYPE_INTERDOMAIN_TRUST);
|
||||
}
|
||||
u_filter = talloc_asprintf_append(u_filter, "(%s=%lu)",
|
||||
attr_uidnumber,
|
||||
(unsigned long)ids[idx]->xid.id);
|
||||
CHECK_ALLOC_DONE(u_filter);
|
||||
break;
|
||||
|
||||
case ID_TYPE_GID:
|
||||
if ( ! g_filter) {
|
||||
g_filter = talloc_asprintf(memctx, "(&(|"
|
||||
"(sAMAccountType=%d)"
|
||||
"(sAMAccountType=%d))(|",
|
||||
ATYPE_SECURITY_GLOBAL_GROUP,
|
||||
ATYPE_SECURITY_LOCAL_GROUP);
|
||||
}
|
||||
g_filter = talloc_asprintf_append(g_filter, "(%s=%lu)",
|
||||
attr_gidnumber,
|
||||
(unsigned long)ids[idx]->xid.id);
|
||||
CHECK_ALLOC_DONE(g_filter);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG(3, ("Unknown ID type\n"));
|
||||
ids[idx]->status = ID_UNKNOWN;
|
||||
continue;
|
||||
bidx = idx;
|
||||
for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
|
||||
switch (ids[idx]->xid.type) {
|
||||
case ID_TYPE_UID:
|
||||
if ( ! u_filter) {
|
||||
u_filter = talloc_asprintf(memctx, "(&(|"
|
||||
"(sAMAccountType=%d)"
|
||||
"(sAMAccountType=%d)"
|
||||
"(sAMAccountType=%d))(|",
|
||||
ATYPE_NORMAL_ACCOUNT,
|
||||
ATYPE_WORKSTATION_TRUST,
|
||||
ATYPE_INTERDOMAIN_TRUST);
|
||||
}
|
||||
}
|
||||
filter = talloc_asprintf(memctx, "(|");
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
if ( u_filter) {
|
||||
filter = talloc_asprintf_append(filter, "%s))", u_filter);
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
TALLOC_FREE(u_filter);
|
||||
}
|
||||
if ( g_filter) {
|
||||
filter = talloc_asprintf_append(filter, "%s))", g_filter);
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
TALLOC_FREE(g_filter);
|
||||
}
|
||||
filter = talloc_asprintf_append(filter, ")");
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
DEBUG(10, ("Filter: [%s]\n", filter));
|
||||
} else {
|
||||
bidx = 0;
|
||||
idx = 1;
|
||||
}
|
||||
u_filter = talloc_asprintf_append(u_filter, "(%s=%lu)",
|
||||
ad_schema->posix_uidnumber_attr,
|
||||
(unsigned long)ids[idx]->xid.id);
|
||||
CHECK_ALLOC_DONE(u_filter);
|
||||
break;
|
||||
|
||||
case ID_TYPE_GID:
|
||||
if ( ! g_filter) {
|
||||
g_filter = talloc_asprintf(memctx, "(&(|"
|
||||
"(sAMAccountType=%d)"
|
||||
"(sAMAccountType=%d))(|",
|
||||
ATYPE_SECURITY_GLOBAL_GROUP,
|
||||
ATYPE_SECURITY_LOCAL_GROUP);
|
||||
}
|
||||
g_filter = talloc_asprintf_append(g_filter, "(%s=%lu)",
|
||||
ad_schema->posix_gidnumber_attr,
|
||||
(unsigned long)ids[idx]->xid.id);
|
||||
CHECK_ALLOC_DONE(g_filter);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG(3, ("Unknown ID type\n"));
|
||||
ids[idx]->status = ID_UNKNOWN;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
filter = talloc_asprintf(memctx, "(|");
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
if ( u_filter) {
|
||||
filter = talloc_asprintf_append(filter, "%s))", u_filter);
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
TALLOC_FREE(u_filter);
|
||||
}
|
||||
if ( g_filter) {
|
||||
filter = talloc_asprintf_append(filter, "%s))", g_filter);
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
TALLOC_FREE(g_filter);
|
||||
}
|
||||
filter = talloc_asprintf_append(filter, ")");
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
DEBUG(10, ("Filter: [%s]\n", filter));
|
||||
rc = ads_search_retry(ads, &res, filter, attrs);
|
||||
if (!ADS_ERR_OK(rc)) {
|
||||
DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc)));
|
||||
@ -367,8 +350,7 @@ again:
|
||||
goto done;
|
||||
}
|
||||
|
||||
count = ads_count_replies(ads, res);
|
||||
if (count == 0) {
|
||||
if ( (count = ads_count_replies(ads, res)) == 0 ) {
|
||||
DEBUG(10, ("No IDs found\n"));
|
||||
}
|
||||
|
||||
@ -417,10 +399,15 @@ again:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID)?attr_uidnumber:attr_gidnumber, &id)) {
|
||||
if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID) ?
|
||||
ad_schema->posix_uidnumber_attr :
|
||||
ad_schema->posix_gidnumber_attr,
|
||||
&id))
|
||||
{
|
||||
DEBUG(1, ("Could not get unix ID\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((id == 0) ||
|
||||
(ctx->filter_low_id && (id < ctx->filter_low_id)) ||
|
||||
(ctx->filter_high_id && (id > ctx->filter_high_id))) {
|
||||
@ -450,15 +437,16 @@ again:
|
||||
ads_msgfree(ads, res);
|
||||
}
|
||||
|
||||
if (multi && ids[idx]) { /* still some values to map */
|
||||
if (ids[idx]) { /* still some values to map */
|
||||
goto again;
|
||||
}
|
||||
|
||||
ret = NT_STATUS_OK;
|
||||
|
||||
/* mark all unknwon ones as unmapped */
|
||||
/* mark all unknown ones as unmapped */
|
||||
for (i = 0; ids[i]; i++) {
|
||||
if (ids[i]->status == ID_UNKNOWN) ids[i]->status = ID_UNMAPPED;
|
||||
if (ids[i]->status == ID_UNKNOWN)
|
||||
ids[i]->status = ID_UNMAPPED;
|
||||
}
|
||||
|
||||
done:
|
||||
@ -466,22 +454,8 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* this function searches up to IDMAP_AD_MAX_IDS entries in maps for a match */
|
||||
static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IDMAP_AD_MAX_IDS; i++) {
|
||||
if (maps[i] == NULL) { /* end of the run */
|
||||
return NULL;
|
||||
}
|
||||
if (sid_equal(maps[i]->sid, sid)) {
|
||||
return maps[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
|
||||
{
|
||||
@ -497,85 +471,50 @@ static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map
|
||||
NULL };
|
||||
LDAPMessage *res = NULL;
|
||||
char *filter = NULL;
|
||||
BOOL multi = False;
|
||||
int idx = 0;
|
||||
int bidx = 0;
|
||||
int count;
|
||||
int i;
|
||||
char *sidstr;
|
||||
|
||||
ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
|
||||
|
||||
memctx = talloc_new(ctx);
|
||||
if ( ! memctx) {
|
||||
if ( (memctx = talloc_new(ctx)) == NULL ) {
|
||||
DEBUG(0, ("Out of memory!\n"));
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
ads = ad_idmap_cached_connection();
|
||||
if (ads == NULL) {
|
||||
if ( (ads = ad_idmap_cached_connection()) == NULL ) {
|
||||
DEBUG(1, ("ADS uninitialized\n"));
|
||||
ret = NT_STATUS_UNSUCCESSFUL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* attr_uidnumber and attr_gidnumber are surely successfully initialized now */
|
||||
attrs[2] = attr_uidnumber;
|
||||
attrs[3] = attr_gidnumber;
|
||||
|
||||
|
||||
if ( ! ids[1]) {
|
||||
/* if we are requested just one mapping use the simple filter */
|
||||
char *sidstr;
|
||||
|
||||
sidstr = sid_binstring(ids[0]->sid);
|
||||
filter = talloc_asprintf(memctx, "(&(objectSid=%s)(|" /* the requested Sid */
|
||||
"(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)" /* user account types */
|
||||
"(sAMAccountType=%d)(sAMAccountType=%d)))", /* group account types */
|
||||
sidstr,
|
||||
ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
|
||||
ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP);
|
||||
if (! filter) {
|
||||
free(sidstr);
|
||||
ret = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
DEBUG(10, ("Filter: [%s]\n", filter));
|
||||
} else {
|
||||
/* multiple mappings */
|
||||
multi = True;
|
||||
}
|
||||
attrs[2] = ad_schema->posix_uidnumber_attr;
|
||||
attrs[3] = ad_schema->posix_gidnumber_attr;
|
||||
|
||||
again:
|
||||
if (multi) {
|
||||
char *sidstr;
|
||||
|
||||
filter = talloc_asprintf(memctx,
|
||||
"(&(|"
|
||||
"(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)" /* user account types */
|
||||
"(sAMAccountType=%d)(sAMAccountType=%d)" /* group account types */
|
||||
")(|",
|
||||
ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
|
||||
ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP);
|
||||
filter = talloc_asprintf(memctx, "(&(|"
|
||||
"(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)" /* user account types */
|
||||
"(sAMAccountType=%d)(sAMAccountType=%d)" /* group account types */
|
||||
")(|",
|
||||
ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
|
||||
ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP);
|
||||
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
|
||||
bidx = idx;
|
||||
for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
|
||||
bidx = idx;
|
||||
for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
|
||||
|
||||
sidstr = sid_binstring(ids[idx]->sid);
|
||||
filter = talloc_asprintf_append(filter, "(objectSid=%s)", sidstr);
|
||||
sidstr = sid_binstring(ids[idx]->sid);
|
||||
filter = talloc_asprintf_append(filter, "(objectSid=%s)", sidstr);
|
||||
|
||||
free(sidstr);
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
}
|
||||
filter = talloc_asprintf_append(filter, "))");
|
||||
free(sidstr);
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
DEBUG(10, ("Filter: [%s]\n", filter));
|
||||
} else {
|
||||
bidx = 0;
|
||||
idx = 1;
|
||||
}
|
||||
filter = talloc_asprintf_append(filter, "))");
|
||||
CHECK_ALLOC_DONE(filter);
|
||||
DEBUG(10, ("Filter: [%s]\n", filter));
|
||||
|
||||
rc = ads_search_retry(ads, &res, filter, attrs);
|
||||
if (!ADS_ERR_OK(rc)) {
|
||||
@ -584,8 +523,7 @@ again:
|
||||
goto done;
|
||||
}
|
||||
|
||||
count = ads_count_replies(ads, res);
|
||||
if (count == 0) {
|
||||
if ( (count = ads_count_replies(ads, res)) == 0 ) {
|
||||
DEBUG(10, ("No IDs found\n"));
|
||||
}
|
||||
|
||||
@ -640,7 +578,11 @@ again:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID)?attr_uidnumber:attr_gidnumber, &id)) {
|
||||
if (!ads_pull_uint32(ads, entry, (type==ID_TYPE_UID) ?
|
||||
ad_schema->posix_uidnumber_attr :
|
||||
ad_schema->posix_gidnumber_attr,
|
||||
&id))
|
||||
{
|
||||
DEBUG(1, ("Could not get unix ID\n"));
|
||||
continue;
|
||||
}
|
||||
@ -667,7 +609,7 @@ again:
|
||||
ads_msgfree(ads, res);
|
||||
}
|
||||
|
||||
if (multi && ids[idx]) { /* still some values to map */
|
||||
if (ids[idx]) { /* still some values to map */
|
||||
goto again;
|
||||
}
|
||||
|
||||
@ -675,7 +617,8 @@ again:
|
||||
|
||||
/* mark all unknwon ones as unmapped */
|
||||
for (i = 0; ids[i]; i++) {
|
||||
if (ids[i]->status == ID_UNKNOWN) ids[i]->status = ID_UNMAPPED;
|
||||
if (ids[i]->status == ID_UNKNOWN)
|
||||
ids[i]->status = ID_UNMAPPED;
|
||||
}
|
||||
|
||||
done:
|
||||
@ -683,6 +626,9 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
static NTSTATUS idmap_ad_close(struct idmap_domain *dom)
|
||||
{
|
||||
ADS_STRUCT *ads = ad_idmap_ads;
|
||||
@ -694,22 +640,176 @@ static NTSTATUS idmap_ad_close(struct idmap_domain *dom)
|
||||
ad_idmap_ads = NULL;
|
||||
}
|
||||
|
||||
SAFE_FREE(attr_uidnumber);
|
||||
SAFE_FREE(attr_gidnumber);
|
||||
TALLOC_FREE( ad_schema );
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static struct idmap_methods ad_methods = {
|
||||
.init = idmap_ad_initialize,
|
||||
.unixids_to_sids = idmap_ad_unixids_to_sids,
|
||||
.sids_to_unixids = idmap_ad_sids_to_unixids,
|
||||
.close_fn = idmap_ad_close
|
||||
};
|
||||
/*
|
||||
* nss_info_{sfu,rfc2307}
|
||||
*/
|
||||
|
||||
/* support for new authentication subsystem */
|
||||
NTSTATUS idmap_ad_init(void)
|
||||
/************************************************************************
|
||||
Initialize the {sfu,rfc2307} state
|
||||
***********************************************************************/
|
||||
|
||||
static NTSTATUS nss_sfu_init( struct nss_domain_entry *e )
|
||||
{
|
||||
return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ad", &ad_methods);
|
||||
/* Sanity check if we have previously been called with a
|
||||
different schema model */
|
||||
|
||||
if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) &&
|
||||
(ad_map_type != WB_POSIX_MAP_SFU) )
|
||||
{
|
||||
DEBUG(0,("nss_sfu_init: Posix Map type has already been set. "
|
||||
"Mixed schema models not supported!\n"));
|
||||
return NT_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
ad_map_type = WB_POSIX_MAP_SFU;
|
||||
|
||||
if ( !ad_idmap_ads )
|
||||
return idmap_ad_initialize( NULL, NULL );
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e )
|
||||
{
|
||||
/* Sanity check if we have previously been called with a
|
||||
different schema model */
|
||||
|
||||
if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) &&
|
||||
(ad_map_type != WB_POSIX_MAP_RFC2307) )
|
||||
{
|
||||
DEBUG(0,("nss_rfc2307_init: Posix Map type has already been set. "
|
||||
"Mixed schema models not supported!\n"));
|
||||
return NT_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
ad_map_type = WB_POSIX_MAP_RFC2307;
|
||||
|
||||
if ( !ad_idmap_ads )
|
||||
return idmap_ad_initialize( NULL, NULL );
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e,
|
||||
const DOM_SID *sid,
|
||||
TALLOC_CTX *ctx,
|
||||
ADS_STRUCT *ads,
|
||||
LDAPMessage *msg,
|
||||
char **homedir,
|
||||
char **shell,
|
||||
char **gecos,
|
||||
uint32 *gid )
|
||||
{
|
||||
char *home, *sh, *gec;
|
||||
|
||||
if ( !ad_schema )
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
|
||||
if ( !homedir || !shell || !gecos )
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
|
||||
home = ads_pull_string( ads, ctx, msg, ad_schema->posix_homedir_attr );
|
||||
sh = ads_pull_string( ads, ctx, msg, ad_schema->posix_shell_attr );
|
||||
gec = ads_pull_string( ads, ctx, msg, ad_schema->posix_gecos_attr );
|
||||
|
||||
if ( gid ) {
|
||||
if ( !ads_pull_uint32(ads, msg, ad_schema->posix_gidnumber_attr, gid ) )
|
||||
*gid = 0;
|
||||
}
|
||||
|
||||
if ( home )
|
||||
*homedir = talloc_strdup( ctx, home );
|
||||
if ( sh )
|
||||
*shell = talloc_strdup( ctx, sh );
|
||||
if ( gec )
|
||||
*gecos = talloc_strdup( ctx, gec );
|
||||
|
||||
SAFE_FREE( home );
|
||||
SAFE_FREE( sh );
|
||||
SAFE_FREE( gec );
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
static NTSTATUS nss_ad_close( void )
|
||||
{
|
||||
/* nothing to do. All memory is free()'d by the idmap close_fn() */
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Function dispatch tables for the idmap and nss plugins
|
||||
***********************************************************************/
|
||||
|
||||
static struct idmap_methods ad_methods = {
|
||||
.init = idmap_ad_initialize,
|
||||
.unixids_to_sids = idmap_ad_unixids_to_sids,
|
||||
.sids_to_unixids = idmap_ad_sids_to_unixids,
|
||||
.close_fn = idmap_ad_close
|
||||
};
|
||||
|
||||
/* The SFU and RFC2307 NSS plugins share everything but the init
|
||||
function which sets the intended schema model to use */
|
||||
|
||||
static struct nss_info_methods nss_rfc2307_methods = {
|
||||
.init = nss_rfc2307_init,
|
||||
.get_nss_info = nss_ad_get_info,
|
||||
.close_fn = nss_ad_close
|
||||
};
|
||||
|
||||
static struct nss_info_methods nss_sfu_methods = {
|
||||
.init = nss_sfu_init,
|
||||
.get_nss_info = nss_ad_get_info,
|
||||
.close_fn = nss_ad_close
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
Initialize the plugins
|
||||
***********************************************************************/
|
||||
|
||||
NTSTATUS idmap_ad_init(void)
|
||||
{
|
||||
static NTSTATUS status_idmap_ad = NT_STATUS_UNSUCCESSFUL;
|
||||
static NTSTATUS status_nss_rfc2307 = NT_STATUS_UNSUCCESSFUL;
|
||||
static NTSTATUS status_nss_sfu = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
/* Always register the AD method first in order to get the
|
||||
idmap_domain interface called */
|
||||
|
||||
if ( !NT_STATUS_IS_OK(status_idmap_ad) ) {
|
||||
status_idmap_ad = smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
|
||||
"ad", &ad_methods);
|
||||
if ( !NT_STATUS_IS_OK(status_idmap_ad) )
|
||||
return status_idmap_ad;
|
||||
}
|
||||
|
||||
if ( !NT_STATUS_IS_OK( status_nss_rfc2307 ) ) {
|
||||
status_nss_rfc2307 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
|
||||
"rfc2307", &nss_rfc2307_methods );
|
||||
if ( !NT_STATUS_IS_OK(status_nss_rfc2307) )
|
||||
return status_nss_rfc2307;
|
||||
}
|
||||
|
||||
if ( !NT_STATUS_IS_OK( status_nss_sfu ) ) {
|
||||
status_nss_sfu = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
|
||||
"sfu", &nss_sfu_methods );
|
||||
if ( !NT_STATUS_IS_OK(status_nss_sfu) )
|
||||
return status_nss_sfu;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
@ -1,111 +1,305 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
nss info helpers
|
||||
Copyright (C) Guenther Deschner 2006
|
||||
Idmap NSS headers
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
Copyright (C) Gerald Carter 2006
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "nss_info.h"
|
||||
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_IDMAP
|
||||
static struct nss_function_entry *backends = NULL;
|
||||
static struct nss_domain_entry *nss_domain_list = NULL;
|
||||
|
||||
static enum wb_posix_mapping wb_posix_map_type(const char *map_str)
|
||||
{
|
||||
if (strequal(map_str, "template"))
|
||||
return WB_POSIX_MAP_TEMPLATE;
|
||||
else if (strequal(map_str, "sfu"))
|
||||
return WB_POSIX_MAP_SFU;
|
||||
else if (strequal(map_str, "rfc2307"))
|
||||
return WB_POSIX_MAP_RFC2307;
|
||||
else if (strequal(map_str, "unixinfo"))
|
||||
return WB_POSIX_MAP_UNIXINFO;
|
||||
|
||||
return WB_POSIX_MAP_UNKNOWN;
|
||||
}
|
||||
|
||||
/* winbind nss info = rfc2307 SO36:sfu FHAIN:rfc2307 PANKOW:template
|
||||
*
|
||||
* syntax is:
|
||||
* 1st param: default setting
|
||||
* following ":" separated list elements:
|
||||
* DOMAIN:setting
|
||||
* setting can be one of "sfu", "rfc2307", "template", "unixinfo"
|
||||
*/
|
||||
|
||||
enum wb_posix_mapping get_nss_info(const char *domain_name)
|
||||
{
|
||||
const char **list = lp_winbind_nss_info();
|
||||
enum wb_posix_mapping map_templ = WB_POSIX_MAP_TEMPLATE;
|
||||
int i;
|
||||
|
||||
DEBUG(11,("get_nss_info for %s\n", domain_name));
|
||||
|
||||
if (!lp_winbind_nss_info() || !*lp_winbind_nss_info()) {
|
||||
return WB_POSIX_MAP_TEMPLATE;
|
||||
}
|
||||
|
||||
if ((map_templ = wb_posix_map_type(list[0])) == WB_POSIX_MAP_UNKNOWN) {
|
||||
DEBUG(0,("get_nss_info: invalid setting: %s\n", list[0]));
|
||||
return WB_POSIX_MAP_TEMPLATE;
|
||||
}
|
||||
|
||||
DEBUG(11,("get_nss_info: using \"%s\" by default\n", list[0]));
|
||||
|
||||
for (i=0; list[i]; i++) {
|
||||
|
||||
const char *p = list[i];
|
||||
fstring tok;
|
||||
|
||||
if (!next_token(&p, tok, ":", sizeof(tok))) {
|
||||
DEBUG(0,("get_nss_info: no \":\" delimitier found\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strequal(tok, domain_name)) {
|
||||
|
||||
enum wb_posix_mapping type;
|
||||
|
||||
if ((type = wb_posix_map_type(p)) == WB_POSIX_MAP_UNKNOWN) {
|
||||
DEBUG(0,("get_nss_info: invalid setting: %s\n", p));
|
||||
/* return WB_POSIX_MAP_TEMPLATE; */
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG(11,("get_nss_info: using \"%s\" for domain: %s\n", p, tok));
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return map_templ;
|
||||
}
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
const char *wb_posix_map_str(enum wb_posix_mapping mtype)
|
||||
{
|
||||
switch (mtype) {
|
||||
case WB_POSIX_MAP_TEMPLATE:
|
||||
return "template";
|
||||
case WB_POSIX_MAP_SFU:
|
||||
return "sfu";
|
||||
case WB_POSIX_MAP_RFC2307:
|
||||
return "rfc2307";
|
||||
case WB_POSIX_MAP_UNIXINFO:
|
||||
return "unixinfo";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
Get idmap nss methods.
|
||||
**********************************************************************/
|
||||
|
||||
static struct nss_function_entry *nss_get_backend(const char *name )
|
||||
{
|
||||
struct nss_function_entry *entry = backends;
|
||||
|
||||
for(entry = backends; entry; entry = entry->next) {
|
||||
if ( strequal(entry->name, name) )
|
||||
return entry;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Allow a module to register itself as a backend.
|
||||
**********************************************************************/
|
||||
|
||||
NTSTATUS smb_register_idmap_nss(int version, const char *name, struct nss_info_methods *methods)
|
||||
{
|
||||
struct nss_function_entry *entry;
|
||||
|
||||
if ((version != SMB_NSS_INFO_INTERFACE_VERSION)) {
|
||||
DEBUG(0, ("smb_register_idmap_nss: Failed to register idmap_nss module.\n"
|
||||
"The module was compiled against SMB_NSS_INFO_INTERFACE_VERSION %d,\n"
|
||||
"current SMB_NSS_INFO_INTERFACE_VERSION is %d.\n"
|
||||
"Please recompile against the current version of samba!\n",
|
||||
version, SMB_NSS_INFO_INTERFACE_VERSION));
|
||||
return NT_STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
if (!name || !name[0] || !methods) {
|
||||
DEBUG(0,("smb_register_idmap_nss: called with NULL pointer or empty name!\n"));
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ( nss_get_backend(name) ) {
|
||||
DEBUG(0,("smb_register_idmap_nss: idmap module %s "
|
||||
"already registered!\n", name));
|
||||
return NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
|
||||
entry = SMB_XMALLOC_P(struct nss_function_entry);
|
||||
entry->name = smb_xstrdup(name);
|
||||
entry->methods = methods;
|
||||
|
||||
DLIST_ADD(backends, entry);
|
||||
DEBUG(5, ("smb_register_idmap_nss: Successfully added idmap "
|
||||
"nss backend '%s'\n", name));
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
*******************************************************************/
|
||||
|
||||
static BOOL parse_nss_parm( const char *config, char **backend, char **domain )
|
||||
{
|
||||
char *p;
|
||||
char *q;
|
||||
int len;
|
||||
|
||||
*backend = *domain = NULL;
|
||||
|
||||
if ( !config )
|
||||
return False;
|
||||
|
||||
p = strchr( config, ':' );
|
||||
|
||||
/* if no : then the string must be the backend name only */
|
||||
|
||||
if ( !p ) {
|
||||
*backend = SMB_STRDUP( config );
|
||||
return (*backend != NULL);
|
||||
}
|
||||
|
||||
/* split the string and return the two parts */
|
||||
|
||||
if ( strlen(p+1) > 0 ) {
|
||||
*domain = SMB_STRDUP( p+1 );
|
||||
}
|
||||
|
||||
len = PTR_DIFF(p,config)+1;
|
||||
if ( (q = SMB_MALLOC_ARRAY( char, len )) == NULL ) {
|
||||
SAFE_FREE( *backend );
|
||||
return False;
|
||||
}
|
||||
|
||||
StrnCpy( q, config, len-1);
|
||||
q[len-1] = '\0';
|
||||
*backend = q;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Each nss backend must not store global state, but rather be able
|
||||
to initialize the state on a per domain basis.
|
||||
*******************************************************************/
|
||||
|
||||
NTSTATUS nss_init( const char **nss_list )
|
||||
{
|
||||
NTSTATUS status;
|
||||
int i;
|
||||
char *backend, *domain;
|
||||
struct nss_function_entry *nss_backend;
|
||||
struct nss_domain_entry *nss_domain;
|
||||
|
||||
/* The "template" backend should alqays be registered as it
|
||||
is a static module */
|
||||
|
||||
if ( (nss_backend = nss_get_backend( "template" )) == NULL ) {
|
||||
static_init_nss_info;
|
||||
}
|
||||
|
||||
/* Create the list of nss_domains (loading any shared plugins
|
||||
as necessary) */
|
||||
|
||||
for ( i=0; nss_list && nss_list[i]; i++ ) {
|
||||
|
||||
if ( !parse_nss_parm(nss_list[i], &backend, &domain) ) {
|
||||
DEBUG(0,("nss_init: failed to parse \"%s\"!\n",
|
||||
nss_list[0]));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* validate the backend */
|
||||
|
||||
if ( (nss_backend = nss_get_backend( backend )) == NULL ) {
|
||||
/* attempt to register the backend */
|
||||
status = smb_probe_module( "nss_info", backend );
|
||||
if ( !NT_STATUS_IS_OK(status) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* try again */
|
||||
if ( (nss_backend = nss_get_backend( backend )) == NULL ) {
|
||||
DEBUG(0,("nss_init: unregistered backend %s!. Skipping\n",
|
||||
backend));
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* fill in the nss_domain_entry and add it to the
|
||||
list of domains */
|
||||
|
||||
nss_domain = TALLOC_ZERO_P( nss_domain_list, struct nss_domain_entry );
|
||||
if ( !nss_domain ) {
|
||||
DEBUG(0,("nss_init: talloc() failure!\n"));
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
nss_domain->backend = nss_backend;
|
||||
nss_domain->domain = talloc_strdup( nss_domain, domain );
|
||||
|
||||
status = nss_domain->backend->methods->init( nss_domain );
|
||||
if ( NT_STATUS_IS_OK( status ) ) {
|
||||
DLIST_ADD( nss_domain_list, nss_domain );
|
||||
} else {
|
||||
DEBUG(0,("nss_init: Failed to init backend for %s domain!\n",
|
||||
nss_domain->domain));
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
|
||||
SAFE_FREE( backend );
|
||||
SAFE_FREE( domain );
|
||||
}
|
||||
|
||||
if ( !nss_domain_list ) {
|
||||
DEBUG(3,("nss_init: no nss backends configured. "
|
||||
"Defaulting to \"template\".\n"));
|
||||
|
||||
|
||||
/* we shouild default to use template here */
|
||||
}
|
||||
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
*******************************************************************/
|
||||
|
||||
NTSTATUS nss_get_info( const char *domain, const DOM_SID *user_sid,
|
||||
TALLOC_CTX *ctx,
|
||||
ADS_STRUCT *ads, LDAPMessage *msg,
|
||||
char **homedir, char **shell, char **gecos,
|
||||
gid_t *p_gid)
|
||||
{
|
||||
struct nss_domain_entry *p;
|
||||
struct nss_info_methods *m;
|
||||
|
||||
for ( p=nss_domain_list; p; p=p->next ) {
|
||||
if ( strequal( p->domain, domain ) )
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we didn't find a match, then use the default nss info */
|
||||
|
||||
if ( !p ) {
|
||||
if ( !nss_domain_list ) {
|
||||
return NT_STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
p = nss_domain_list;
|
||||
}
|
||||
|
||||
m = p->backend->methods;
|
||||
|
||||
return m->get_nss_info( p, user_sid, ctx, ads, msg,
|
||||
homedir, shell, gecos, p_gid );
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
*******************************************************************/
|
||||
|
||||
NTSTATUS nss_close( const char *parameters )
|
||||
{
|
||||
struct nss_domain_entry *p = nss_domain_list;
|
||||
struct nss_domain_entry *q;
|
||||
|
||||
while ( p && p->backend && p->backend->methods ) {
|
||||
/* close the backend */
|
||||
p->backend->methods->close_fn();
|
||||
|
||||
/* free the memory */
|
||||
q = p;
|
||||
p = p->next;
|
||||
TALLOC_FREE( q );
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Invoke the init function for a given domain's backend
|
||||
*******************************************************************/
|
||||
|
||||
NTSTATUS idmap_nss_init_domain( const char *domain )
|
||||
{
|
||||
struct nss_domain_entry *p;
|
||||
|
||||
DEBUG(10,("idmap_nss_init_domain: Searching for %s's init() function\n",
|
||||
domain));
|
||||
|
||||
for ( p=nss_domain_list; p; p=p->next ) {
|
||||
if ( strequal( p->domain, domain ) ) {
|
||||
DEBUG(10,("idmap_nss_init_domain: Calling init function for %s\n",
|
||||
domain));
|
||||
return p->backend->methods->init( p );
|
||||
}
|
||||
}
|
||||
|
||||
return NT_STATUS_NO_SUCH_DOMAIN;
|
||||
}
|
||||
|
||||
|
84
source3/nsswitch/nss_info_template.c
Normal file
84
source3/nsswitch/nss_info_template.c
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
idMap nss template plugin
|
||||
|
||||
Copyright (C) Gerald Carter 2006
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "nss_info.h"
|
||||
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
static NTSTATUS nss_template_init( struct nss_domain_entry *e )
|
||||
{
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
static NTSTATUS nss_template_get_info( struct nss_domain_entry *e,
|
||||
const DOM_SID *sid,
|
||||
TALLOC_CTX *ctx,
|
||||
ADS_STRUCT *ads,
|
||||
LDAPMessage *msg,
|
||||
char **homedir,
|
||||
char **shell,
|
||||
char **gecos,
|
||||
uint32 *gid )
|
||||
{
|
||||
if ( !homedir || !shell || !gecos )
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
|
||||
*homedir = talloc_strdup( ctx, lp_template_homedir() );
|
||||
*shell = talloc_strdup( ctx, lp_template_shell() );
|
||||
*gecos = NULL;
|
||||
|
||||
if ( !*homedir || !*shell ) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
static NTSTATUS nss_template_close( void )
|
||||
{
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
static struct nss_info_methods nss_template_methods = {
|
||||
nss_template_init,
|
||||
nss_template_get_info,
|
||||
nss_template_close
|
||||
};
|
||||
|
||||
NTSTATUS nss_info_template_init( void )
|
||||
{
|
||||
return smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
|
||||
"template",
|
||||
&nss_template_methods);
|
||||
}
|
@ -1009,6 +1009,8 @@ int main(int argc, char **argv, char **envp)
|
||||
DEBUG(1, ("Could not init idmap! - Sid/[UG]id mapping will not be available\n"));
|
||||
}
|
||||
|
||||
nss_init( lp_winbind_nss_info() );
|
||||
|
||||
/* Unblock all signals we are interested in as they may have been
|
||||
blocked by the parent process. */
|
||||
|
||||
|
@ -112,6 +112,8 @@ typedef struct {
|
||||
char *full_name;
|
||||
char *homedir;
|
||||
char *shell;
|
||||
gid_t primary_gid; /* allow the nss_info
|
||||
backend to set the primary group */
|
||||
DOM_SID user_sid; /* NT user and primary group SIDs */
|
||||
DOM_SID group_sid;
|
||||
} WINBIND_USERINFO;
|
||||
|
@ -40,7 +40,6 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
|
||||
{
|
||||
ADS_STRUCT *ads;
|
||||
ADS_STATUS status;
|
||||
enum wb_posix_mapping map_type;
|
||||
|
||||
DEBUG(10,("ads_cached_connection\n"));
|
||||
|
||||
@ -126,17 +125,9 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
map_type = get_nss_info(domain->name);
|
||||
/* initialize the nss backend for this domain */
|
||||
|
||||
if ((map_type == WB_POSIX_MAP_RFC2307)||
|
||||
(map_type == WB_POSIX_MAP_SFU)) {
|
||||
|
||||
status = ads_check_posix_schema_mapping(ads, map_type);
|
||||
if (!ADS_ERR_OK(status)) {
|
||||
DEBUG(10,("ads_check_posix_schema_mapping failed "
|
||||
"with: %s\n", ads_errstr(status)));
|
||||
}
|
||||
}
|
||||
idmap_nss_init_domain( domain->name );
|
||||
|
||||
/* set the flag that says we don't own the memory even
|
||||
though we do so that ads_destroy() won't destroy the
|
||||
@ -156,17 +147,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
|
||||
WINBIND_USERINFO **info)
|
||||
{
|
||||
ADS_STRUCT *ads = NULL;
|
||||
const char *attrs[] = {"userPrincipalName",
|
||||
"sAMAccountName",
|
||||
"name", "objectSid", "primaryGroupID",
|
||||
"sAMAccountType",
|
||||
ADS_ATTR_SFU_HOMEDIR_OID,
|
||||
ADS_ATTR_SFU_SHELL_OID,
|
||||
ADS_ATTR_SFU_GECOS_OID,
|
||||
ADS_ATTR_RFC2307_HOMEDIR_OID,
|
||||
ADS_ATTR_RFC2307_SHELL_OID,
|
||||
ADS_ATTR_RFC2307_GECOS_OID,
|
||||
NULL};
|
||||
const char *attrs[] = { "*", NULL };
|
||||
int i, count;
|
||||
ADS_STATUS rc;
|
||||
LDAPMessage *res = NULL;
|
||||
@ -210,6 +191,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
|
||||
char *shell = NULL;
|
||||
uint32 group;
|
||||
uint32 atype;
|
||||
DOM_SID user_sid;
|
||||
gid_t primary_gid = (gid_t)-1;
|
||||
|
||||
if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) ||
|
||||
ads_atype_map(atype) != SID_NAME_USER) {
|
||||
@ -219,17 +202,10 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
|
||||
|
||||
name = ads_pull_username(ads, mem_ctx, msg);
|
||||
|
||||
if (get_nss_info(domain->name) && ads->schema.map_type) {
|
||||
|
||||
DEBUG(10,("pulling posix attributes (%s schema)\n",
|
||||
wb_posix_map_str(ads->schema.map_type)));
|
||||
|
||||
homedir = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.posix_homedir_attr);
|
||||
shell = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.posix_shell_attr);
|
||||
gecos = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.posix_gecos_attr);
|
||||
if ( ads_pull_sid( ads, msg, "objectSid", &user_sid ) ) {
|
||||
status = nss_get_info( domain->name, &user_sid, mem_ctx,
|
||||
ads, msg, &homedir, &shell, &gecos,
|
||||
&primary_gid );
|
||||
}
|
||||
|
||||
if (gecos == NULL) {
|
||||
@ -250,6 +226,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
|
||||
(*info)[i].full_name = gecos;
|
||||
(*info)[i].homedir = homedir;
|
||||
(*info)[i].shell = shell;
|
||||
(*info)[i].primary_gid = primary_gid;
|
||||
sid_compose(&(*info)[i].group_sid, &domain->sid, group);
|
||||
i++;
|
||||
}
|
||||
@ -454,17 +431,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
|
||||
WINBIND_USERINFO *info)
|
||||
{
|
||||
ADS_STRUCT *ads = NULL;
|
||||
const char *attrs[] = {"userPrincipalName",
|
||||
"sAMAccountName",
|
||||
"name",
|
||||
"primaryGroupID",
|
||||
ADS_ATTR_SFU_HOMEDIR_OID,
|
||||
ADS_ATTR_SFU_SHELL_OID,
|
||||
ADS_ATTR_SFU_GECOS_OID,
|
||||
ADS_ATTR_RFC2307_HOMEDIR_OID,
|
||||
ADS_ATTR_RFC2307_SHELL_OID,
|
||||
ADS_ATTR_RFC2307_GECOS_OID,
|
||||
NULL};
|
||||
const char *attrs[] = { "*", NULL };
|
||||
ADS_STATUS rc;
|
||||
int count;
|
||||
LDAPMessage *msg = NULL;
|
||||
@ -475,9 +442,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
|
||||
|
||||
DEBUG(3,("ads: query_user\n"));
|
||||
|
||||
ads = ads_cached_connection(domain);
|
||||
|
||||
if (!ads) {
|
||||
if ( (ads = ads_cached_connection(domain)) == NULL ) {
|
||||
domain->last_status = NT_STATUS_SERVER_DISABLED;
|
||||
goto done;
|
||||
}
|
||||
@ -502,18 +467,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
|
||||
|
||||
info->acct_name = ads_pull_username(ads, mem_ctx, msg);
|
||||
|
||||
if (get_nss_info(domain->name) && ads->schema.map_type) {
|
||||
|
||||
DEBUG(10,("pulling posix attributes (%s schema)\n",
|
||||
wb_posix_map_str(ads->schema.map_type)));
|
||||
|
||||
info->homedir = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.posix_homedir_attr);
|
||||
info->shell = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.posix_shell_attr);
|
||||
info->full_name = ads_pull_string(ads, mem_ctx, msg,
|
||||
ads->schema.posix_gecos_attr);
|
||||
}
|
||||
info->primary_gid = (gid_t)-1;
|
||||
nss_get_info( domain->name, sid, mem_ctx, ads, msg,
|
||||
&info->homedir, &info->shell, &info->full_name, &info->primary_gid );
|
||||
|
||||
if (info->full_name == NULL) {
|
||||
info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
|
||||
|
@ -764,7 +764,9 @@ enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
|
||||
}
|
||||
|
||||
fstrcpy(state->response.data.name.dom_name, dom_name);
|
||||
TALLOC_FREE(dom_name);
|
||||
fstrcpy(state->response.data.name.name, name);
|
||||
TALLOC_FREE(name);
|
||||
state->response.data.name.type = type;
|
||||
|
||||
TALLOC_FREE(dom_name);
|
||||
@ -1397,13 +1399,13 @@ static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
|
||||
{
|
||||
void (*cont)(void *priv, BOOL succ, const char *acct_name,
|
||||
const char *full_name, const char *homedir,
|
||||
const char *shell, uint32 group_rid) =
|
||||
const char *shell, uint32 gid, uint32 group_rid) =
|
||||
(void (*)(void *, BOOL, const char *, const char *,
|
||||
const char *, const char *, uint32))c;
|
||||
const char *, const char *, uint32, uint32))c;
|
||||
|
||||
if (!success) {
|
||||
DEBUG(5, ("Could not trigger query_user\n"));
|
||||
cont(private_data, False, NULL, NULL, NULL, NULL, -1);
|
||||
cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1411,6 +1413,7 @@ static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
|
||||
response->data.user_info.full_name,
|
||||
response->data.user_info.homedir,
|
||||
response->data.user_info.shell,
|
||||
response->data.user_info.primary_gid,
|
||||
response->data.user_info.group_rid);
|
||||
}
|
||||
|
||||
@ -1421,6 +1424,7 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
|
||||
const char *full_name,
|
||||
const char *homedir,
|
||||
const char *shell,
|
||||
gid_t gid,
|
||||
uint32 group_rid),
|
||||
void *private_data)
|
||||
{
|
||||
|
@ -827,6 +827,7 @@ static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WI
|
||||
centry_put_string(centry, info->full_name);
|
||||
centry_put_string(centry, info->homedir);
|
||||
centry_put_string(centry, info->shell);
|
||||
centry_put_uint32(centry, info->primary_gid);
|
||||
centry_put_sid(centry, &info->user_sid);
|
||||
centry_put_sid(centry, &info->group_sid);
|
||||
centry_end(centry, "U/%s", sid_to_string(sid_string, &info->user_sid));
|
||||
@ -854,7 +855,7 @@ static void wcache_save_lockout_policy(struct winbindd_domain *domain, NTSTATUS
|
||||
}
|
||||
|
||||
static void wcache_save_password_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_1 *policy)
|
||||
{
|
||||
{
|
||||
struct cache_entry *centry;
|
||||
|
||||
centry = centry_start(domain, status);
|
||||
@ -1589,6 +1590,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
|
||||
info->full_name = centry_string(centry, mem_ctx);
|
||||
info->homedir = centry_string(centry, mem_ctx);
|
||||
info->shell = centry_string(centry, mem_ctx);
|
||||
info->primary_gid = centry_uint32(centry);
|
||||
centry_sid(centry, mem_ctx, &info->user_sid);
|
||||
centry_sid(centry, mem_ctx, &info->group_sid);
|
||||
status = centry->status;
|
||||
|
@ -447,6 +447,7 @@ struct winbindd_response {
|
||||
fstring full_name;
|
||||
fstring homedir;
|
||||
fstring shell;
|
||||
uint32 primary_gid;
|
||||
uint32 group_rid;
|
||||
} user_info;
|
||||
struct {
|
||||
|
@ -41,7 +41,7 @@ static BOOL fillup_pw_field(const char *lp_template,
|
||||
if (out == NULL)
|
||||
return False;
|
||||
|
||||
if (in && !strequal(in,"") && lp_security() == SEC_ADS && (get_nss_info(domname))) {
|
||||
if ( in && !strequal(in,"") && lp_security() == SEC_ADS ) {
|
||||
safe_strcpy(out, in, sizeof(fstring) - 1);
|
||||
return True;
|
||||
}
|
||||
@ -156,6 +156,7 @@ enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain,
|
||||
fstrcpy(state->response.data.user_info.full_name, user_info.full_name);
|
||||
fstrcpy(state->response.data.user_info.homedir, user_info.homedir);
|
||||
fstrcpy(state->response.data.user_info.shell, user_info.shell);
|
||||
state->response.data.user_info.primary_gid = user_info.primary_gid;
|
||||
if (!sid_peek_check_rid(&domain->sid, &user_info.group_sid,
|
||||
&state->response.data.user_info.group_rid)) {
|
||||
DEBUG(1, ("Could not extract group rid out of %s\n",
|
||||
@ -184,6 +185,7 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success,
|
||||
const char *full_name,
|
||||
const char *homedir,
|
||||
const char *shell,
|
||||
uint32 gid,
|
||||
uint32 group_rid);
|
||||
static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid);
|
||||
static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid);
|
||||
@ -222,6 +224,7 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success,
|
||||
const char *full_name,
|
||||
const char *homedir,
|
||||
const char *shell,
|
||||
uint32 gid,
|
||||
uint32 group_rid)
|
||||
{
|
||||
fstring username;
|
||||
@ -241,6 +244,7 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success,
|
||||
s->fullname = talloc_strdup(s->state->mem_ctx, full_name);
|
||||
s->homedir = talloc_strdup(s->state->mem_ctx, homedir);
|
||||
s->shell = talloc_strdup(s->state->mem_ctx, shell);
|
||||
s->gid = gid;
|
||||
sid_copy(&s->group_sid, &s->domain->sid);
|
||||
sid_append_rid(&s->group_sid, group_rid);
|
||||
|
||||
@ -272,13 +276,29 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
|
||||
struct winbindd_pw *pw;
|
||||
fstring output_username;
|
||||
|
||||
/* allow the nss backend to override the primary group ID.
|
||||
If the gid has already been set, then keep it.
|
||||
This makes me feel dirty. If the nss backend already
|
||||
gave us a gid, we don't really care whether the sid2gid()
|
||||
call worked or not. --jerry */
|
||||
|
||||
if ( s->gid == (gid_t)-1 ) {
|
||||
if (!success) {
|
||||
DEBUG(5, ("Could not query user's %s\\%s\n gid",
|
||||
s->domain->name, s->username));
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* take what the sid2gid() call gave us */
|
||||
s->gid = gid;
|
||||
}
|
||||
|
||||
/* allow the nss backend to override the primary group ID.
|
||||
If the gid has already been set, then keep it */
|
||||
|
||||
if ( s->gid == (gid_t)-1 ) {
|
||||
s->gid = gid;
|
||||
}
|
||||
|
||||
pw = &s->state->response.data.pw;
|
||||
pw->pw_uid = s->uid;
|
||||
|
@ -1631,7 +1631,6 @@ static void init_globals(BOOL first_time_only)
|
||||
Globals.bWinbindUseDefaultDomain = False;
|
||||
Globals.bWinbindTrustedDomainsOnly = False;
|
||||
Globals.bWinbindNestedGroups = True;
|
||||
Globals.szWinbindNssInfo = str_list_make("template", NULL);
|
||||
Globals.bWinbindRefreshTickets = False;
|
||||
Globals.bWinbindOfflineLogon = False;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user