diff options
Diffstat (limited to 'source/nsswitch')
-rw-r--r-- | source/nsswitch/pam_winbind.c | 27 | ||||
-rw-r--r-- | source/nsswitch/wbinfo.c | 67 | ||||
-rw-r--r-- | source/nsswitch/winbind_nss_aix.c | 9 | ||||
-rw-r--r-- | source/nsswitch/winbindd.h | 2 | ||||
-rw-r--r-- | source/nsswitch/winbindd_cache.c | 2 | ||||
-rw-r--r-- | source/nsswitch/winbindd_group.c | 18 | ||||
-rw-r--r-- | source/nsswitch/winbindd_nss.h | 4 | ||||
-rw-r--r-- | source/nsswitch/winbindd_pam.c | 108 | ||||
-rw-r--r-- | source/nsswitch/winbindd_sid.c | 4 | ||||
-rw-r--r-- | source/nsswitch/winbindd_util.c | 7 |
10 files changed, 152 insertions, 96 deletions
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c index 64e21738221..9d4f0954ceb 100644 --- a/source/nsswitch/pam_winbind.c +++ b/source/nsswitch/pam_winbind.c @@ -45,7 +45,9 @@ 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"))) + else if (!strncasecmp(*argv, "require_membership_of", strlen("require_membership_of"))) + ctrl |= WINBIND_REQUIRED_MEMBERSHIP; + else if (!strncasecmp(*argv, "require-membership-of", strlen("require-membership-of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; else { _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); @@ -213,28 +215,28 @@ static int winbind_auth_request(const char *user, const char *pass, const char * /* lookup name? */ if (!strncmp("S-", member, 2) == 0) { - struct winbindd_request request; - struct winbindd_response response; + struct winbindd_request sid_request; + struct winbindd_response sid_response; - ZERO_STRUCT(request); - ZERO_STRUCT(response); + ZERO_STRUCT(sid_request); + ZERO_STRUCT(sid_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); + strcpy(sid_request.data.name.name, member); - if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &request, &response, ctrl, user)) { + if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &sid_request, &sid_response, ctrl, user)) { _pam_log(LOG_INFO, "could not lookup name: %s\n", member); return PAM_AUTH_ERR; } - member = strdup(response.data.sid.sid); + member = sid_response.data.sid.sid; } - strncpy(request.data.auth.required_membership_sid, member, - sizeof(request.data.auth.required_membership_sid)-1); + strncpy(request.data.auth.require_membership_of_sid, member, + sizeof(request.data.auth.require_membership_of_sid)-1); return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user); } @@ -488,13 +490,14 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* Retrieve membership-string here */ for ( i=0; i<argc; i++ ) { - if (!strncmp(argv[i], "required_membership", strlen("required_membership"))) { + if ((strncmp(argv[i], "require_membership_of", strlen("require_membership_of")) == 0) + || (strncmp(argv[i], "require-membership-of", strlen("require-membership-of")) == 0)) { char *p; char *parm = strdup(argv[i]); if ( (p = strchr( parm, '=' )) == NULL) { - _pam_log(LOG_INFO, "no \"=\" delimiter for \"required_membership\" found\n"); + _pam_log(LOG_INFO, "no \"=\" delimiter for \"require_membership_of\" found\n"); break; } diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c index b6a09bf2a1f..69f464f446a 100644 --- a/source/nsswitch/wbinfo.c +++ b/source/nsswitch/wbinfo.c @@ -567,28 +567,61 @@ static BOOL wbinfo_auth_crap(char *username) parse_wbinfo_domain_user(username, name_domain, name_user); - if (push_utf8_fstring(request.data.auth_crap.user, name_user) == -1) { - d_printf("unable to create utf8 string for '%s'\n", - name_user); - return False; - } + fstrcpy(request.data.auth_crap.user, name_user); - if (push_utf8_fstring(request.data.auth_crap.domain, - name_domain) == -1) { - d_printf("unable to create utf8 string for '%s'\n", - name_domain); - return False; - } + fstrcpy(request.data.auth_crap.domain, + name_domain); generate_random_buffer(request.data.auth_crap.chal, 8); - SMBencrypt(pass, request.data.auth_crap.chal, - (uchar *)request.data.auth_crap.lm_resp); - SMBNTencrypt(pass, request.data.auth_crap.chal, - (uchar *)request.data.auth_crap.nt_resp); + if (lp_client_ntlmv2_auth()) { + DATA_BLOB server_chal; + DATA_BLOB names_blob; + + DATA_BLOB lm_response; + DATA_BLOB nt_response; + + server_chal = data_blob(request.data.auth_crap.chal, 8); + + /* Pretend this is a login to 'us', for blob purposes */ + names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup()); + + if (!SMBNTLMv2encrypt(name_user, name_domain, pass, &server_chal, + &names_blob, + &lm_response, &nt_response, NULL)) { + data_blob_free(&names_blob); + data_blob_free(&server_chal); + return False; + } + data_blob_free(&names_blob); + data_blob_free(&server_chal); + + memcpy(request.data.auth_crap.nt_resp, nt_response.data, + MIN(nt_response.length, + sizeof(request.data.auth_crap.nt_resp))); + request.data.auth_crap.nt_resp_len = nt_response.length; + + memcpy(request.data.auth_crap.lm_resp, lm_response.data, + MIN(lm_response.length, + sizeof(request.data.auth_crap.lm_resp))); + request.data.auth_crap.lm_resp_len = lm_response.length; + + data_blob_free(&nt_response); + data_blob_free(&lm_response); - request.data.auth_crap.lm_resp_len = 24; - request.data.auth_crap.nt_resp_len = 24; + } else { + if (lp_client_lanman_auth() + && SMBencrypt(pass, request.data.auth_crap.chal, + (uchar *)request.data.auth_crap.lm_resp)) { + request.data.auth_crap.lm_resp_len = 24; + } else { + request.data.auth_crap.lm_resp_len = 0; + } + SMBNTencrypt(pass, request.data.auth_crap.chal, + (uchar *)request.data.auth_crap.nt_resp); + + request.data.auth_crap.nt_resp_len = 24; + } result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); diff --git a/source/nsswitch/winbind_nss_aix.c b/source/nsswitch/winbind_nss_aix.c index 3e00e54e5c4..c90dc2f3f10 100644 --- a/source/nsswitch/winbind_nss_aix.c +++ b/source/nsswitch/winbind_nss_aix.c @@ -159,12 +159,13 @@ static unsigned decode_id(const char *name) return id; } +static struct passwd *wb_aix_getpwuid(uid_t uid); + static char *decode_user(const char *name) { struct passwd *pwd; unsigned id; char *ret; - static struct passwd *wb_aix_getpwuid(uid_t uid); sscanf(name+1, "%u", &id); pwd = wb_aix_getpwuid(id); @@ -741,6 +742,7 @@ static void wb_aix_close(void *token) return; } +#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST /* return a list of additional attributes supported by the backend */ @@ -764,6 +766,7 @@ static attrlist_t **wb_aix_attrlist(void) return ret; } +#endif /* @@ -977,7 +980,9 @@ int wb_aix_init(struct secmethod_table *methods) { ZERO_STRUCTP(methods); +#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION methods->method_version = SECMETHOD_VERSION_520; +#endif methods->method_getgrgid = wb_aix_getgrgid; methods->method_getgrnam = wb_aix_getgrnam; @@ -997,7 +1002,9 @@ int wb_aix_init(struct secmethod_table *methods) methods->method_passwdrestrictions = wb_aix_passwdrestrictions; methods->method_getgracct = wb_aix_getgracct; methods->method_getgrusers = wb_aix_getgrusers; +#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST methods->method_attrlist = wb_aix_attrlist; +#endif #if LOG_UNIMPLEMENTED_CALLS methods->method_delgroup = method_delgroup; diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h index 751f6f3700f..477d2e0f682 100644 --- a/source/nsswitch/winbindd.h +++ b/source/nsswitch/winbindd.h @@ -230,7 +230,7 @@ struct winbindd_idmap_methods { void (*status)(void); }; -#include "../nsswitch/winbindd_proto.h" +#include "nsswitch/winbindd_proto.h" #include "rpc_parse.h" #include "rpc_client.h" diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c index 493255a5a65..a6ebafca965 100644 --- a/source/nsswitch/winbindd_cache.c +++ b/source/nsswitch/winbindd_cache.c @@ -751,8 +751,8 @@ do_query: if (domain->backend->consistent) { /* when the backend is consistent we can pre-prime some mappings */ wcache_save_name_to_sid(domain, NT_STATUS_OK, - (*info)[i].acct_name, domain->name, + (*info)[i].acct_name, (*info)[i].user_sid, SID_NAME_USER); wcache_save_sid_to_name(domain, NT_STATUS_OK, diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c index a3b826278b5..8ab5150bbe3 100644 --- a/source/nsswitch/winbindd_group.c +++ b/source/nsswitch/winbindd_group.c @@ -919,24 +919,6 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state) return WINBINDD_OK; } -static void add_gid_to_array_unique(gid_t gid, gid_t **gids, int *num) -{ - int i; - - for (i=0; i<*num; i++) { - if ((*gids)[i] == gid) - return; - } - - *gids = Realloc(*gids, (*num+1) * sizeof(gid_t)); - - if (*gids == NULL) - return; - - (*gids)[*num] = gid; - *num += 1; -} - static void add_local_gids_from_sid(DOM_SID *sid, gid_t **gids, int *num) { gid_t gid; diff --git a/source/nsswitch/winbindd_nss.h b/source/nsswitch/winbindd_nss.h index 6a457f38004..9a99bad9d74 100644 --- a/source/nsswitch/winbindd_nss.h +++ b/source/nsswitch/winbindd_nss.h @@ -181,7 +181,7 @@ struct winbindd_request { character is. */ fstring user; fstring pass; - fstring required_membership_sid; + fstring require_membership_of_sid; } auth; /* pam_winbind auth module */ struct { unsigned char chal[8]; @@ -192,7 +192,7 @@ struct winbindd_request { fstring nt_resp; uint16 nt_resp_len; fstring workstation; - fstring required_membership_sid; + fstring require_membership_of_sid; } auth_crap; struct { fstring user; diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c index 129f876f817..e13649afe15 100644 --- a/source/nsswitch/winbindd_pam.c +++ b/source/nsswitch/winbindd_pam.c @@ -59,7 +59,7 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *info3, const char *group_sid) { - DOM_SID required_membership_sid; + DOM_SID require_membership_of_sid; DOM_SID *all_sids; size_t num_all_sids = (2 + info3->num_groups2 + info3->num_other_sids); size_t i, j = 0; @@ -71,7 +71,7 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } - if (!string_to_sid(&required_membership_sid, group_sid)) { + if (!string_to_sid(&require_membership_of_sid, group_sid)) { DEBUG(0, ("check_info3_in_group: could not parse %s as a SID!", group_sid)); @@ -133,9 +133,9 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, fstring sid1, sid2; DEBUG(10, ("User has SID: %s\n", sid_to_string(sid1, &all_sids[i]))); - if (sid_equal(&required_membership_sid, &all_sids[i])) { + if (sid_equal(&require_membership_of_sid, &all_sids[i])) { DEBUG(10, ("SID %s matches %s - user permitted to authenticate!\n", - sid_to_string(sid1, &required_membership_sid), sid_to_string(sid2, &all_sids[i]))); + sid_to_string(sid1, &require_membership_of_sid), sid_to_string(sid2, &all_sids[i]))); return NT_STATUS_OK; } } @@ -190,13 +190,59 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) /* do password magic */ + generate_random_buffer(chal, 8); - SMBencrypt(state->request.data.auth.pass, chal, local_lm_response); + if (lp_client_ntlmv2_auth()) { + DATA_BLOB server_chal; + DATA_BLOB names_blob; + DATA_BLOB nt_response; + DATA_BLOB lm_response; + server_chal = data_blob_talloc(mem_ctx, chal, 8); + + /* note that the 'workgroup' here is a best guess - we don't know + the server's domain at this point. The 'server name' is also + dodgy... + */ + names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup()); - SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response); + if (!SMBNTLMv2encrypt(name_user, name_domain, + state->request.data.auth.pass, + &server_chal, + &names_blob, + &lm_response, &nt_response, NULL)) { + data_blob_free(&names_blob); + data_blob_free(&server_chal); + DEBUG(0, ("winbindd_pam_auth: SMBNTLMv2encrypt() failed!\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } + data_blob_free(&names_blob); + data_blob_free(&server_chal); + lm_resp = data_blob_talloc(mem_ctx, lm_response.data, lm_response.length); + nt_resp = data_blob_talloc(mem_ctx, nt_response.data, nt_response.length); + data_blob_free(&lm_response); + data_blob_free(&nt_response); + + } else { + if (lp_client_lanman_auth() + && SMBencrypt(state->request.data.auth.pass, + chal, + local_lm_response)) { + lm_resp = data_blob_talloc(mem_ctx, + local_lm_response, + sizeof(local_lm_response)); + } else { + lm_resp = data_blob(NULL, 0); + } + SMBNTencrypt(state->request.data.auth.pass, + chal, + local_nt_response); + + nt_resp = data_blob_talloc(mem_ctx, + local_nt_response, + sizeof(local_nt_response)); + } - lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response)); - nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response)); /* what domain should we contact? */ @@ -288,10 +334,10 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) /* Check if the user is in the right group */ - if (!NT_STATUS_IS_OK(result = check_info3_in_group(mem_ctx, &info3, state->request.data.auth.required_membership_sid))) { + if (!NT_STATUS_IS_OK(result = check_info3_in_group(mem_ctx, &info3, state->request.data.auth.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n", state->request.data.auth.user, - state->request.data.auth.required_membership_sid)); + state->request.data.auth.require_membership_of_sid)); } } @@ -368,7 +414,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) NET_USER_INFO_3 info3; struct cli_state *cli = NULL; TALLOC_CTX *mem_ctx = NULL; - char *name_user = NULL; + const char *name_user = NULL; const char *name_domain = NULL; const char *workstation; struct winbindd_domain *contact_domain; @@ -386,7 +432,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) /* send a better message than ACCESS_DENIED */ asprintf(&error_string, "winbind client not authorized to use winbindd_pam_auth_crap. Ensure permissions on %s are set correctly.", get_winbind_priv_pipe_dir()); - push_utf8_fstring(state->response.data.auth.error_string, error_string); + fstrcpy(state->response.data.auth.error_string, error_string); SAFE_FREE(error_string); result = NT_STATUS_ACCESS_DENIED; goto done; @@ -396,26 +442,16 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]=0; state->request.data.auth_crap.domain[sizeof(state->request.data.auth_crap.domain)-1]=0; - if (!(mem_ctx = talloc_init("winbind pam auth crap for (utf8) %s", state->request.data.auth_crap.user))) { + if (!(mem_ctx = talloc_init("winbind pam auth crap for %s", state->request.data.auth_crap.user))) { DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n")); result = NT_STATUS_NO_MEMORY; goto done; } - if (pull_utf8_talloc(mem_ctx, &name_user, state->request.data.auth_crap.user) == (size_t)-1) { - DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + name_user = state->request.data.auth_crap.user; if (*state->request.data.auth_crap.domain) { - char *dom = NULL; - if (pull_utf8_talloc(mem_ctx, &dom, state->request.data.auth_crap.domain) == (size_t)-1) { - DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - name_domain = dom; + name_domain = state->request.data.auth_crap.domain; } else if (lp_winbind_use_default_domain()) { name_domain = lp_workgroup(); } else { @@ -429,13 +465,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) name_domain, name_user)); if (*state->request.data.auth_crap.workstation) { - char *wrk = NULL; - if (pull_utf8_talloc(mem_ctx, &wrk, state->request.data.auth_crap.workstation) == (size_t)-1) { - DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - workstation = wrk; + workstation = state->request.data.auth_crap.workstation; } else { workstation = global_myname(); } @@ -541,10 +571,10 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) netsamlogon_cache_store( cli->mem_ctx, name_user, &info3 ); wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3); - if (!NT_STATUS_IS_OK(result = check_info3_in_group(mem_ctx, &info3, state->request.data.auth_crap.required_membership_sid))) { + if (!NT_STATUS_IS_OK(result = check_info3_in_group(mem_ctx, &info3, state->request.data.auth_crap.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n", state->request.data.auth_crap.user, - state->request.data.auth_crap.required_membership_sid)); + state->request.data.auth_crap.require_membership_of_sid)); goto done; } @@ -570,8 +600,8 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) DEBUG(5, ("Setting unix username to [%s]\n", username_out)); - /* this interface is in UTF8 */ - if (push_utf8_allocate((char **)&state->response.extra_data, username_out) == -1) { + state->response.extra_data = strdup(username_out); + if (!state->response.extra_data) { result = NT_STATUS_NO_MEMORY; goto done; } @@ -597,11 +627,11 @@ done: } state->response.data.auth.nt_status = NT_STATUS_V(result); - push_utf8_fstring(state->response.data.auth.nt_status_string, nt_errstr(result)); + fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); /* we might have given a more useful error above */ if (!*state->response.data.auth.error_string) - push_utf8_fstring(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); + fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); state->response.data.auth.pam_error = nt_status_to_pam(result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, @@ -631,7 +661,7 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state) DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid, state->request.data.chauthtok.user)); - if (!(mem_ctx = talloc_init("winbind password change for (utf8) %s", + if (!(mem_ctx = talloc_init("winbind password change for %s", state->request.data.chauthtok.user))) { DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n")); result = NT_STATUS_NO_MEMORY; diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c index 97e676813dd..060e66fbc2d 100644 --- a/source/nsswitch/winbindd_sid.c +++ b/source/nsswitch/winbindd_sid.c @@ -219,7 +219,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) if (NT_STATUS_IS_OK(result)) return WINBINDD_OK; - DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid)); + DEBUG(4, ("Could not get uid for sid %s\n", state->request.data.sid)); return WINBINDD_ERROR; } @@ -337,7 +337,7 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) if (NT_STATUS_IS_OK(result)) return WINBINDD_OK; - DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid)); + DEBUG(4, ("Could not get gid for sid %s\n", state->request.data.sid)); return WINBINDD_ERROR; } diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c index 66006905385..a96f652c617 100644 --- a/source/nsswitch/winbindd_util.c +++ b/source/nsswitch/winbindd_util.c @@ -641,14 +641,15 @@ BOOL parse_domain_user(const char *domuser, fstring domain, fstring user) */ void fill_domain_username(fstring name, const char *domain, const char *user) { + strlower_m( name ); + if (assume_domain(domain)) { strlcpy(name, user, sizeof(fstring)); } else { - slprintf(name, sizeof(fstring) - 1, "%s%s%s", - domain, lp_winbind_separator(), + slprintf(name, sizeof(fstring) - 1, "%s%c%s", + domain, *lp_winbind_separator(), user); } - strlower_m(name); } /* |