diff options
author | Günther Deschner <gd@samba.org> | 2005-06-29 14:03:53 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:58:07 -0500 |
commit | 2e7f22e833fbb549f698460f9ed4d81af68b86e9 (patch) | |
tree | 58f04a4311fa6cb4b2acdb33222b8b340675badb /source3/nsswitch | |
parent | 3922667cbe6cd56c6d29c88692b7e7d3342c1f1f (diff) | |
download | samba-2e7f22e833fbb549f698460f9ed4d81af68b86e9.tar.gz samba-2e7f22e833fbb549f698460f9ed4d81af68b86e9.tar.bz2 samba-2e7f22e833fbb549f698460f9ed4d81af68b86e9.zip |
r7994: This adds support in Winbindd's "security = ads"-mode to retrieve the POSIX
homedirectory and the loginshell from Active Directory's "Services for Unix".
Enable it with:
winbind sfu support = yes
User-Accounts without SFU-Unix-Attributes will be assigned template-based
Shells and Homedirs as before.
Note that it doesn't matter which version of Services for Unix you use (2.0,
2.2, 3.0 or 3.5). Samba should detect the correct attributes (msSFULoginShell,
msSFU30LoginShell, etc.) automatically.
If you also want to share the same uid/gid-space as SFU then also use PADL's
ad-idmap-Plugin:
idmap backend = ad
When using the idmap-plugin only those accounts will appear in Name Service
Switch that have those UNIX-attributes which avoids potential uid/gid-space
clashes between SFU-ids and automatically assigned idmap-ids.
Guenther
(This used to be commit 28b59699425b1c954d191fc0e3bd357e4a4e4cd8)
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/winbindd.h | 4 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 24 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_async.c | 9 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 8 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_nss.h | 2 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_rpc.c | 9 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_user.c | 118 |
7 files changed, 127 insertions, 47 deletions
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 378120c80b..3a7728e4a2 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -84,6 +84,8 @@ struct getent_state { struct getpwent_user { fstring name; /* Account name */ fstring gecos; /* User information */ + fstring homedir; /* User Home Directory */ + fstring shell; /* User Login Shell */ DOM_SID user_sid; /* NT user and primary group SIDs */ DOM_SID group_sid; }; @@ -103,6 +105,8 @@ extern struct winbindd_state server_state; /* Server information */ typedef struct { char *acct_name; char *full_name; + char *homedir; + char *shell; DOM_SID user_sid; /* NT user and primary group SIDs */ DOM_SID group_sid; } WINBIND_USERINFO; diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index c807ec59a5..868a7bc2ac 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -95,6 +95,11 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) return NULL; } + if (lp_winbind_sfu_support() && (!ads_check_sfu_mapping(ads))) { + DEBUG(0,("ads_cached_connection: failed to check sfu attributes\n")); + return NULL; + } + /* set the flag that says we don't own the memory even though we do so that ads_destroy() won't destroy the structure we pass back by reference */ @@ -116,7 +121,10 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, const char *attrs[] = {"userPrincipalName", "sAMAccountName", "name", "objectSid", "primaryGroupID", - "sAMAccountType", NULL}; + "sAMAccountType", + ADS_ATTR_SFU_HOMEDIR_OID, + ADS_ATTR_SFU_SHELL_OID, + NULL}; int i, count; ADS_STATUS rc; void *res = NULL; @@ -155,7 +163,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, i = 0; for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { - char *name, *gecos; + char *name, *gecos, *homedir, *shell; uint32 group; uint32 atype; @@ -167,6 +175,9 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, name = ads_pull_username(ads, mem_ctx, msg); gecos = ads_pull_string(ads, mem_ctx, msg, "name"); + homedir = ads_pull_string(ads, mem_ctx, msg, ads->schema.sfu_homedir_attr); + shell = ads_pull_string(ads, mem_ctx, msg, ads->schema.sfu_shell_attr); + if (!ads_pull_sid(ads, msg, "objectSid", &(*info)[i].user_sid)) { DEBUG(1,("No sid for %s !?\n", name)); @@ -179,6 +190,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, (*info)[i].acct_name = name; (*info)[i].full_name = gecos; + (*info)[i].homedir = homedir; + (*info)[i].shell = shell; sid_compose(&(*info)[i].group_sid, &domain->sid, group); i++; } @@ -364,7 +377,10 @@ static NTSTATUS query_user(struct winbindd_domain *domain, const char *attrs[] = {"userPrincipalName", "sAMAccountName", "name", - "primaryGroupID", NULL}; + "primaryGroupID", + ADS_ATTR_SFU_HOMEDIR_OID, + ADS_ATTR_SFU_SHELL_OID, + NULL}; ADS_STATUS rc; int count; void *msg = NULL; @@ -402,6 +418,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain, info->acct_name = ads_pull_username(ads, mem_ctx, msg); info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); + info->homedir = ads_pull_string(ads, mem_ctx, msg, ads->schema.sfu_homedir_attr); + info->shell = ads_pull_string(ads, mem_ctx, msg, ads->schema.sfu_shell_attr); if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) { DEBUG(1,("No primary group for %s !?\n", diff --git a/source3/nsswitch/winbindd_async.c b/source3/nsswitch/winbindd_async.c index d227177ec1..acae7e7f37 100644 --- a/source3/nsswitch/winbindd_async.c +++ b/source3/nsswitch/winbindd_async.c @@ -1372,16 +1372,19 @@ static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success, void *c, void *private_data) { void (*cont)(void *priv, BOOL succ, const char *acct_name, - const char *full_name, uint32 group_rid) = c; + const char *full_name, const char *homedir, + const char *shell, uint32 group_rid) = c; if (!success) { DEBUG(5, ("Could not trigger query_user\n")); - cont(private_data, False, NULL, NULL, -1); + cont(private_data, False, NULL, NULL, NULL, NULL, -1); return; } cont(private_data, True, response->data.user_info.acct_name, response->data.user_info.full_name, + response->data.user_info.homedir, + response->data.user_info.shell, response->data.user_info.group_rid); } @@ -1390,6 +1393,8 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, void (*cont)(void *private_data, BOOL success, const char *acct_name, const char *full_name, + const char *homedir, + const char *shell, uint32 group_rid), void *private_data) { diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 90ccb43a6e..730da7a9b5 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -652,6 +652,8 @@ static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WI return; centry_put_string(centry, info->acct_name); centry_put_string(centry, info->full_name); + centry_put_string(centry, info->homedir); + centry_put_string(centry, info->shell); 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)); @@ -689,6 +691,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, for (i=0; i<(*num_entries); i++) { (*info)[i].acct_name = centry_string(centry, mem_ctx); (*info)[i].full_name = centry_string(centry, mem_ctx); + (*info)[i].homedir = centry_string(centry, mem_ctx); + (*info)[i].shell = centry_string(centry, mem_ctx); centry_sid(centry, &(*info)[i].user_sid); centry_sid(centry, &(*info)[i].group_sid); } @@ -747,6 +751,8 @@ do_query: for (i=0; i<(*num_entries); i++) { centry_put_string(centry, (*info)[i].acct_name); centry_put_string(centry, (*info)[i].full_name); + centry_put_string(centry, (*info)[i].homedir); + centry_put_string(centry, (*info)[i].shell); centry_put_sid(centry, &(*info)[i].user_sid); centry_put_sid(centry, &(*info)[i].group_sid); if (domain->backend->consistent) { @@ -1082,6 +1088,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain, info->acct_name = centry_string(centry, mem_ctx); info->full_name = centry_string(centry, mem_ctx); + info->homedir = centry_string(centry, mem_ctx); + info->shell = centry_string(centry, mem_ctx); centry_sid(centry, &info->user_sid); centry_sid(centry, &info->group_sid); status = centry->status; diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index b249b62d69..cf0fae74a0 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/nsswitch/winbindd_nss.h @@ -322,6 +322,8 @@ struct winbindd_response { struct { fstring acct_name; fstring full_name; + fstring homedir; + fstring shell; uint32 group_rid; } user_info; } data; diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index 2b4c020d88..63e2487700 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -101,6 +101,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, (*info)[i].acct_name = talloc_strdup(mem_ctx, username ); (*info)[i].full_name = talloc_strdup(mem_ctx, fullname ); + (*info)[i].homedir = NULL; + (*info)[i].shell = NULL; sid_compose(&(*info)[i].user_sid, &domain->sid, rid); /* For the moment we set the primary group for @@ -352,7 +354,10 @@ static NTSTATUS query_user(struct winbindd_domain *domain, &user->uni_user_name); user_info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name); - + + user_info->homedir = NULL; + user_info->shell = NULL; + SAFE_FREE(user); return NT_STATUS_OK; @@ -388,6 +393,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain, &ctr->info.id21->uni_user_name); user_info->full_name = unistr2_tdup(mem_ctx, &ctr->info.id21->uni_full_name); + user_info->homedir = NULL; + user_info->shell = NULL; return NT_STATUS_OK; } diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index 576ceaea23..f849bff42d 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -30,15 +30,50 @@ extern userdom_struct current_user_info; +static BOOL fillup_pw_field(const char *lp_template, + const char *username, + const char *domname, + uid_t uid, + gid_t gid, + const char *in, + fstring out) +{ + char *templ; + + if (out == NULL) + return False; + + if (in && !strequal(in,"") && lp_security() == SEC_ADS && lp_winbind_sfu_support()) { + safe_strcpy(out, in, sizeof(fstring) - 1); + return True; + } + + /* Home directory and shell - use template config parameters. The + defaults are /tmp for the home directory and /bin/false for + shell. */ + + /* The substitution of %U and %D in the 'template homedir' is done + by alloc_sub_specified() below. */ + + templ = alloc_sub_specified(lp_template, username, domname, uid, gid); + + if (!templ) + return False; + + safe_strcpy(out, templ, sizeof(fstring) - 1); + SAFE_FREE(templ); + + return True; + +} /* Fill a pwent structure with information we have obtained */ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, DOM_SID *user_sid, DOM_SID *group_sid, - char *full_name, struct winbindd_pw *pw) + char *full_name, char *homedir, char *shell, + struct winbindd_pw *pw) { fstring output_username; - char *homedir; - char *shell; fstring sid_string; if (!pw || !dom_name || !user_name) @@ -79,25 +114,14 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, fstrcpy(current_user_info.domain, dom_name); - homedir = alloc_sub_specified(lp_template_homedir(), user_name, dom_name, pw->pw_uid, pw->pw_gid); - - if (!homedir) + if (!fillup_pw_field(lp_template_homedir(), user_name, dom_name, + pw->pw_uid, pw->pw_gid, homedir, pw->pw_dir)) return False; - - safe_strcpy(pw->pw_dir, homedir, sizeof(pw->pw_dir) - 1); - - SAFE_FREE(homedir); - - shell = alloc_sub_specified(lp_template_shell(), user_name, dom_name, pw->pw_uid, pw->pw_gid); - if (!shell) + if (!fillup_pw_field(lp_template_shell(), user_name, dom_name, + pw->pw_uid, pw->pw_gid, shell, pw->pw_shell)) return False; - safe_strcpy(pw->pw_shell, shell, - sizeof(pw->pw_shell) - 1); - - SAFE_FREE(shell); - /* Password - set to "x" as we can't generate anything useful here. Authentication can be done using the pam_winbind module. */ @@ -136,6 +160,8 @@ enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain, fstrcpy(state->response.data.user_info.acct_name, user_info.acct_name); 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); 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", @@ -151,6 +177,8 @@ struct getpwsid_state { struct winbindd_domain *domain; char *username; char *fullname; + char *homedir; + char *shell; DOM_SID user_sid; uid_t uid; DOM_SID group_sid; @@ -159,7 +187,10 @@ struct getpwsid_state { static void getpwsid_queryuser_recv(void *private_data, BOOL success, const char *acct_name, - const char *full_name, uint32 group_rid); + const char *full_name, + const char *homedir, + const char *shell, + 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); @@ -194,7 +225,10 @@ static void winbindd_getpwsid(struct winbindd_cli_state *state, static void getpwsid_queryuser_recv(void *private_data, BOOL success, const char *acct_name, - const char *full_name, uint32 group_rid) + const char *full_name, + const char *homedir, + const char *shell, + uint32 group_rid) { struct getpwsid_state *s = talloc_get_type_abort(private_data, struct getpwsid_state); @@ -208,6 +242,8 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success, s->username = talloc_strdup(s->state->mem_ctx, acct_name); 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); sid_copy(&s->group_sid, &s->domain->sid); sid_append_rid(&s->group_sid, group_rid); @@ -238,8 +274,6 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid) talloc_get_type_abort(private_data, struct getpwsid_state); struct winbindd_pw *pw; fstring output_username; - char *homedir; - char *shell; if (!success) { DEBUG(5, ("Could not query user's %s\\%s\n gid", @@ -256,32 +290,19 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid) safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1); safe_strcpy(pw->pw_gecos, s->fullname, sizeof(pw->pw_gecos) - 1); - /* Home directory and shell - use template config parameters. The - defaults are /tmp for the home directory and /bin/false for - shell. */ - - /* The substitution of %U and %D in the 'template homedir' is done - by alloc_sub_specified() below. */ - fstrcpy(current_user_info.domain, s->domain->name); - homedir = alloc_sub_specified(lp_template_homedir(), s->username, - s->domain->name, pw->pw_uid, pw->pw_gid); - if (homedir == NULL) { + if (!fillup_pw_field(lp_template_homedir(), s->username, s->domain->name, + pw->pw_uid, pw->pw_gid, s->homedir, pw->pw_dir)) { DEBUG(5, ("Could not compose homedir\n")); goto failed; } - safe_strcpy(pw->pw_dir, homedir, sizeof(pw->pw_dir) - 1); - SAFE_FREE(homedir); - - shell = alloc_sub_specified(lp_template_shell(), s->username, - s->domain->name, pw->pw_uid, pw->pw_gid); - if (shell == NULL) { + + if (!fillup_pw_field(lp_template_shell(), s->username, s->domain->name, + pw->pw_uid, pw->pw_gid, s->shell, pw->pw_shell)) { DEBUG(5, ("Could not compose shell\n")); goto failed; } - safe_strcpy(pw->pw_shell, shell, sizeof(pw->pw_shell) - 1); - SAFE_FREE(shell); /* Password - set to "x" as we can't generate anything useful here. Authentication can be done using the pam_winbind module. */ @@ -555,7 +576,20 @@ static BOOL get_sam_user_entries(struct getent_state *ent, TALLOC_CTX *mem_ctx) fstrcpy(name_list[ent->num_sam_entries + i].gecos, info[i].full_name); } - + if (!info[i].homedir) { + fstrcpy(name_list[ent->num_sam_entries + i].homedir, ""); + } else { + fstrcpy(name_list[ent->num_sam_entries + i].homedir, + info[i].homedir); + } + if (!info[i].shell) { + fstrcpy(name_list[ent->num_sam_entries + i].shell, ""); + } else { + fstrcpy(name_list[ent->num_sam_entries + i].shell, + info[i].shell); + } + + /* User and group ids */ sid_copy(&name_list[ent->num_sam_entries+i].user_sid, &info[i].user_sid); @@ -658,6 +692,8 @@ void winbindd_getpwent(struct winbindd_cli_state *state) &name_list[ent->sam_entry_index].user_sid, &name_list[ent->sam_entry_index].group_sid, name_list[ent->sam_entry_index].gecos, + name_list[ent->sam_entry_index].homedir, + name_list[ent->sam_entry_index].shell, &user_list[user_list_ndx]); ent->sam_entry_index++; |