diff options
author | Gerald Carter <jerry@samba.org> | 2004-09-23 12:21:10 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2004-09-23 12:21:10 +0000 |
commit | 3cf617a8c779ef153080bd00d20bfaa349603096 (patch) | |
tree | 8950e518321f034d21006ebe087a8cd4a80d1ca8 /source/nsswitch | |
parent | f36cd948f0006d177ff67ab5bb2636d32493ce28 (diff) | |
download | samba-3cf617a8c779ef153080bd00d20bfaa349603096.tar.gz samba-3cf617a8c779ef153080bd00d20bfaa349603096.tar.xz samba-3cf617a8c779ef153080bd00d20bfaa349603096.zip |
r2565: syncing up for 3.0.8pre1
Diffstat (limited to 'source/nsswitch')
-rw-r--r-- | source/nsswitch/pam_winbind.c | 64 | ||||
-rw-r--r-- | source/nsswitch/pam_winbind.h | 1 | ||||
-rw-r--r-- | source/nsswitch/wbinfo.c | 41 | ||||
-rw-r--r-- | source/nsswitch/winbind_nss_linux.c | 41 | ||||
-rw-r--r-- | source/nsswitch/winbindd.c | 25 | ||||
-rw-r--r-- | source/nsswitch/winbindd_cache.c | 4 | ||||
-rw-r--r-- | source/nsswitch/winbindd_dual.c | 2 | ||||
-rw-r--r-- | source/nsswitch/winbindd_group.c | 7 | ||||
-rw-r--r-- | source/nsswitch/winbindd_sid.c | 78 | ||||
-rw-r--r-- | source/nsswitch/winbindd_user.c | 2 | ||||
-rw-r--r-- | source/nsswitch/winbindd_util.c | 8 |
11 files changed, 175 insertions, 98 deletions
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c index 123f6703665..64e21738221 100644 --- a/source/nsswitch/pam_winbind.c +++ b/source/nsswitch/pam_winbind.c @@ -45,6 +45,8 @@ static int _pam_parse(int argc, const char **argv) ctrl |= WINBIND_TRY_FIRST_PASS_ARG; else if (!strcasecmp(*argv, "unknown_ok")) ctrl |= WINBIND_UNKNOWN_OK_ARG; + else if (!strncasecmp(*argv, "required_membership", strlen("required_membership"))) + ctrl |= WINBIND_REQUIRED_MEMBERSHIP; else { _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); } @@ -148,7 +150,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type, switch (retval) { case PAM_AUTH_ERR: /* incorrect password */ - _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", user); + _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password or invalid membership)", user); return retval; case PAM_ACCT_EXPIRED: /* account expired */ @@ -174,7 +176,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type, case PAM_SUCCESS: if (req_type == WINBINDD_PAM_AUTH) { /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted acces", user); + _pam_log(LOG_NOTICE, "user '%s' granted access", user); } else if (req_type == WINBINDD_PAM_CHAUTHTOK) { /* Otherwise, the authentication looked good */ _pam_log(LOG_NOTICE, "user '%s' password changed", user); @@ -192,7 +194,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type, } /* talk to winbindd */ -static int winbind_auth_request(const char *user, const char *pass, int ctrl) +static int winbind_auth_request(const char *user, const char *pass, const char *member, int ctrl) { struct winbindd_request request; struct winbindd_response response; @@ -204,7 +206,35 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl) strncpy(request.data.auth.pass, pass, sizeof(request.data.auth.pass)-1); - + + if (member == NULL ) + return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user); + + /* lookup name? */ + if (!strncmp("S-", member, 2) == 0) { + + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (ctrl & WINBIND_DEBUG_ARG) + _pam_log(LOG_DEBUG, "no sid given, looking up: %s\n", member); + + /* fortunatly winbindd can handle non-separated names */ + strcpy(request.data.name.name, member); + + if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &request, &response, ctrl, user)) { + _pam_log(LOG_INFO, "could not lookup name: %s\n", member); + return PAM_AUTH_ERR; + } + + member = strdup(response.data.sid.sid); + } + + strncpy(request.data.auth.required_membership_sid, member, + sizeof(request.data.auth.required_membership_sid)-1); return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user); } @@ -419,7 +449,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, { const char *username; const char *password; + const char *member = NULL; int retval = PAM_AUTH_ERR; + int i; /* parse arguments */ int ctrl = _pam_parse(argc, argv); @@ -453,8 +485,25 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, #endif } + /* Retrieve membership-string here */ + for ( i=0; i<argc; i++ ) { + + if (!strncmp(argv[i], "required_membership", strlen("required_membership"))) { + + char *p; + char *parm = strdup(argv[i]); + + if ( (p = strchr( parm, '=' )) == NULL) { + _pam_log(LOG_INFO, "no \"=\" delimiter for \"required_membership\" found\n"); + break; + } + + member = strdup(p+1); + } + } + /* Now use the username to look up password */ - return winbind_auth_request(username, password, ctrl); + return winbind_auth_request(username, password, member, ctrl); } PAM_EXTERN @@ -502,7 +551,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, return PAM_USER_UNKNOWN; case 0: /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted acces", username); + _pam_log(LOG_NOTICE, "user '%s' granted access", username); return PAM_SUCCESS; default: /* we don't know anything about this return value */ @@ -546,6 +595,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, /* <DO NOT free() THESE> */ const char *user; + const char *member = NULL; char *pass_old, *pass_new; /* </DO NOT free() THESE> */ @@ -606,7 +656,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, } /* verify that this is the password for this user */ - retval = winbind_auth_request(user, pass_old, ctrl); + retval = winbind_auth_request(user, pass_old, member, ctrl); if (retval != PAM_ACCT_EXPIRED && retval != PAM_AUTHTOK_EXPIRED diff --git a/source/nsswitch/pam_winbind.h b/source/nsswitch/pam_winbind.h index 0afcceb6aa2..7cae477714b 100644 --- a/source/nsswitch/pam_winbind.h +++ b/source/nsswitch/pam_winbind.h @@ -82,6 +82,7 @@ do { \ #define WINBIND_TRY_FIRST_PASS_ARG (1<<3) #define WINBIND_USE_FIRST_PASS_ARG (1<<4) #define WINBIND__OLD_PASSWORD (1<<5) +#define WINBIND_REQUIRED_MEMBERSHIP (1<<6) /* * here is the string to inform the user that the new passwords they diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c index 0028982d201..b6a09bf2a1f 100644 --- a/source/nsswitch/wbinfo.c +++ b/source/nsswitch/wbinfo.c @@ -398,27 +398,6 @@ static BOOL wbinfo_sid_to_uid(char *sid) ZERO_STRUCT(request); ZERO_STRUCT(response); - /* First see whether the SID is actually a user -- otherwise - * winbind might end up a uid number for a group SID and this - * is asking for trouble later. */ - - fstrcpy(request.data.sid, sid); - - if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) != - NSS_STATUS_SUCCESS) { - d_printf("Could not lookup sid %s\n", sid); - return False; - } - - if (response.data.name.type != SID_NAME_USER) { - d_printf("SID is of type %s\n", - sid_type_lookup(response.data.name.type)); - return False; - } - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - /* Send request */ fstrcpy(request.data.sid, sid); @@ -442,26 +421,6 @@ static BOOL wbinfo_sid_to_gid(char *sid) ZERO_STRUCT(request); ZERO_STRUCT(response); - /* First see whether the SID is actually a group -- otherwise - * winbind might end up a gid number for a user SID and this - * is asking for trouble later. */ - - fstrcpy(request.data.sid, sid); - - if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) != - NSS_STATUS_SUCCESS) { - d_printf("Could not lookup sid %s\n", sid); - return False; - } - - if ((response.data.name.type != SID_NAME_DOM_GRP) && - (response.data.name.type != SID_NAME_ALIAS) && - (response.data.name.type != SID_NAME_WKN_GRP)) { - d_printf("SID is of type %s\n", - sid_type_lookup(response.data.name.type)); - return False; - } - /* Send request */ fstrcpy(request.data.sid, sid); diff --git a/source/nsswitch/winbind_nss_linux.c b/source/nsswitch/winbind_nss_linux.c index ae2bcc7ade9..0ea5db74da6 100644 --- a/source/nsswitch/winbind_nss_linux.c +++ b/source/nsswitch/winbind_nss_linux.c @@ -833,25 +833,40 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, /* Skip primary group */ - if (gid_list[i] == group) continue; - - /* Add to buffer */ + if (gid_list[i] == group) { + continue; + } - if (*start == *size && limit <= 0) { - (*groups) = realloc( - (*groups), (2 * (*size) + 1) * sizeof(**groups)); - if (! *groups) goto done; - *size = 2 * (*size) + 1; + /* Filled buffer ? If so, resize. */ + + if (*start == *size) { + long int newsize; + gid_t *newgroups; + + newsize = 2 * (*size); + if (limit > 0) { + if (*size == limit) { + goto done; + } + if (newsize > limit) { + newsize = limit; + } + } + + newgroups = realloc((*groups), newsize * sizeof(**groups)); + if (!newgroups) { + *errnop = ENOMEM; + ret = NSS_STATUS_NOTFOUND; + goto done; + } + *groups = newgroups; + *size = newsize; } - if (*start == *size) goto done; + /* Add to buffer */ (*groups)[*start] = gid_list[i]; *start += 1; - - /* Filled buffer? */ - - if (*start == limit) goto done; } } diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c index d08aa84face..455fb74f171 100644 --- a/source/nsswitch/winbindd.c +++ b/source/nsswitch/winbindd.c @@ -28,6 +28,8 @@ BOOL opt_nocache = False; BOOL opt_dual_daemon = True; +extern BOOL override_logfile; + /* Reload configuration */ static BOOL reload_services_file(void) @@ -587,6 +589,7 @@ static void process_loop(void) int maxfd, listen_sock, listen_priv_sock, selret; struct timeval timeout; + again: /* Handle messages */ message_dispatch(); @@ -715,6 +718,15 @@ static void process_loop(void) for (state = winbindd_client_list(); state; state = state->next) { + /* Data available for writing */ + + if (FD_ISSET(state->sock, &w_fds)) + client_write(state); + } + + for (state = winbindd_client_list(); state; + state = state->next) { + /* Data available for reading */ if (FD_ISSET(state->sock, &r_fds)) { @@ -747,13 +759,10 @@ static void process_loop(void) if (state->read_buf_len == sizeof(state->request)) { winbind_process_packet(state); + winbindd_demote_client(state); + goto again; } } - - /* Data available for writing */ - - if (FD_ISSET(state->sock, &w_fds)) - client_write(state); } } @@ -846,8 +855,10 @@ int main(int argc, char **argv) exit(1); } - pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); + if (!override_logfile) { + pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE); + lp_set_logfile(logfile); + } setup_logging("winbindd", log_stdout); reopen_logs(); diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c index b81f8ecd45a..493255a5a65 100644 --- a/source/nsswitch/winbindd_cache.c +++ b/source/nsswitch/winbindd_cache.c @@ -609,7 +609,6 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain, { struct cache_entry *centry; fstring uname; - fstring sid_string; centry = centry_start(domain, status); if (!centry) @@ -619,7 +618,8 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain, fstrcpy(uname, name); strupper_m(uname); centry_end(centry, "NS/%s/%s", domain_name, uname); - DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, sid_string)); + DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, + sid_string_static(sid))); centry_free(centry); } diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c index a9796afa367..d4ec6e586db 100644 --- a/source/nsswitch/winbindd_dual.c +++ b/source/nsswitch/winbindd_dual.c @@ -155,7 +155,7 @@ void do_dual_daemon(void) dual_daemon_pipe = fdpair[1]; state.sock = fdpair[0]; - if (fork() != 0) { + if (sys_fork() != 0) { close(fdpair[0]); return; } diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c index ca7f72d0178..a3b826278b5 100644 --- a/source/nsswitch/winbindd_group.c +++ b/source/nsswitch/winbindd_group.c @@ -495,8 +495,6 @@ enum winbindd_result winbindd_endgrent(struct winbindd_cli_state *state) The dispinfo_ndx field is incremented to the index of the next group to fetch. Return True if some groups were returned, False otherwise. */ -#define MAX_FETCH_SAM_ENTRIES 100 - static BOOL get_sam_group_entries(struct getent_state *ent) { NTSTATUS status; @@ -925,14 +923,11 @@ static void add_gid_to_array_unique(gid_t gid, gid_t **gids, int *num) { int i; - if ((*num) >= groups_max()) - return; - for (i=0; i<*num; i++) { if ((*gids)[i] == gid) return; } - + *gids = Realloc(*gids, (*num+1) * sizeof(gid_t)); if (*gids == NULL) diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c index 61da9b3d92f..c6e503bef39 100644 --- a/source/nsswitch/winbindd_sid.c +++ b/source/nsswitch/winbindd_sid.c @@ -119,7 +119,7 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state) enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) { DOM_SID sid; - uint32 flags = 0x0; + NTSTATUS result; /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; @@ -166,8 +166,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) /* But first check and see if we don't already have a mapping */ - flags = ID_QUERY_ONLY; - if ( NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) ) + if ( NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), ID_QUERY_ONLY)) ) return WINBINDD_OK; /* now fall back to the hard way */ @@ -191,17 +190,37 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) } - if ( state->request.flags & WBFLAG_QUERY_ONLY ) - flags = ID_QUERY_ONLY; - /* Find uid for this sid and return it */ - - if ( !NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) ) { - DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid)); + + result = idmap_sid_to_uid(&sid, &(state->response.data.uid), + ID_QUERY_ONLY); + + if (NT_STATUS_IS_OK(result)) + return WINBINDD_OK; + + if (state->request.flags & WBFLAG_QUERY_ONLY) return WINBINDD_ERROR; + + /* The query-only did not work, allocate a new uid *if* it's a user */ + + { + fstring dom_name, name; + enum SID_NAME_USE type; + + if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type)) + return WINBINDD_ERROR; + + if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) + return WINBINDD_ERROR; } + + result = idmap_sid_to_uid(&sid, &(state->response.data.uid), 0); - return WINBINDD_OK; + if (NT_STATUS_IS_OK(result)) + return WINBINDD_OK; + + DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid)); + return WINBINDD_ERROR; } /* Convert a sid to a gid. We assume we only have one rid attached to the @@ -210,7 +229,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) { DOM_SID sid; - uint32 flags = 0x0; + NTSTATUS result; /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; @@ -256,8 +275,7 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) /* But first check and see if we don't already have a mapping */ - flags = ID_QUERY_ONLY; - if ( NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), flags)) ) + if ( NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), ID_QUERY_ONLY)) ) return WINBINDD_OK; /* now fall back to the hard way */ @@ -281,16 +299,38 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) } - if ( state->request.flags & WBFLAG_QUERY_ONLY ) - flags = ID_QUERY_ONLY; - /* Find gid for this sid and return it */ - if ( !NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), flags)) ) { - DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid)); + + result = idmap_sid_to_gid(&sid, &(state->response.data.gid), + ID_QUERY_ONLY); + + if (NT_STATUS_IS_OK(result)) + return WINBINDD_OK; + + if (state->request.flags & WBFLAG_QUERY_ONLY) return WINBINDD_ERROR; + + /* The query-only did not work, allocate a new gid *if* it's a group */ + + { + fstring dom_name, name; + enum SID_NAME_USE type; + + if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type)) + return WINBINDD_ERROR; + + if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) && + (type != SID_NAME_WKN_GRP)) + return WINBINDD_ERROR; } + + result = idmap_sid_to_gid(&sid, &(state->response.data.gid), 0); - return WINBINDD_OK; + if (NT_STATUS_IS_OK(result)) + return WINBINDD_OK; + + DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid)); + return WINBINDD_ERROR; } /* Convert a uid to a sid */ diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c index 795d657aae7..6f5a86f43ae 100644 --- a/source/nsswitch/winbindd_user.c +++ b/source/nsswitch/winbindd_user.c @@ -385,8 +385,6 @@ enum winbindd_result winbindd_endpwent(struct winbindd_cli_state *state) field is incremented to the index of the next user to fetch. Return True if some users were returned, False otherwise. */ -#define MAX_FETCH_SAM_ENTRIES 100 - static BOOL get_sam_user_entries(struct getent_state *ent) { NTSTATUS status; diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c index faa6e8d8da4..a9197d35616 100644 --- a/source/nsswitch/winbindd_util.c +++ b/source/nsswitch/winbindd_util.c @@ -736,6 +736,14 @@ void winbindd_remove_client(struct winbindd_cli_state *cli) _num_clients--; } +/* Demote a client to be the last in the list */ + +void winbindd_demote_client(struct winbindd_cli_state *cli) +{ + struct winbindd_cli_state *tmp; + DLIST_DEMOTE(_client_list, cli, tmp); +} + /* Close all open clients */ void winbindd_kill_all_clients(void) |