diff options
Diffstat (limited to 'source3/auth')
-rw-r--r-- | source3/auth/auth.c | 76 | ||||
-rw-r--r-- | source3/auth/auth_compat.c | 5 | ||||
-rw-r--r-- | source3/auth/auth_ntlmssp.c | 6 | ||||
-rw-r--r-- | source3/auth/auth_util.c | 40 | ||||
-rw-r--r-- | source3/auth/auth_wbc.c | 150 |
5 files changed, 207 insertions, 70 deletions
diff --git a/source3/auth/auth.c b/source3/auth/auth.c index 505098c76a..fd4c503752 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -2,17 +2,17 @@ Unix SMB/CIFS implementation. Password and authentication handling Copyright (C) Andrew Bartlett 2001-2002 - + 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 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -49,7 +49,7 @@ NTSTATUS smb_register_auth(int version, const char *name, auth_init_function ini DEBUG(0,("There already is an auth method registered with the name %s!\n", name)); return NT_STATUS_OBJECT_NAME_COLLISION; } - + entry = SMB_XMALLOC_P(struct auth_init_function_entry); entry->name = smb_xstrdup(name); entry->init = init; @@ -67,7 +67,7 @@ static struct auth_init_function_entry *auth_find_backend_entry(const char *name if (strcmp(entry->name, name)==0) return entry; entry = entry->next; } - + return NULL; } @@ -76,7 +76,8 @@ static struct auth_init_function_entry *auth_find_backend_entry(const char *name Returns a const char of length 8 bytes. ****************************************************************************/ -static const uint8 *get_ntlm_challenge(struct auth_context *auth_context) +static void get_ntlm_challenge(struct auth_context *auth_context, + uint8_t chal[8]) { DATA_BLOB challenge = data_blob_null; const char *challenge_set_by = NULL; @@ -86,7 +87,8 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context) if (auth_context->challenge.length) { DEBUG(5, ("get_ntlm_challenge (auth subsystem): returning previous challenge by module %s (normal)\n", auth_context->challenge_set_by)); - return auth_context->challenge.data; + memcpy(chal, auth_context->challenge.data, 8); + return; } auth_context->challenge_may_be_modified = False; @@ -108,7 +110,7 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context) if (!mem_ctx) { smb_panic("talloc_init() failed!"); } - + challenge = auth_method->get_chal(auth_context, &auth_method->private_data, mem_ctx); if (!challenge.length) { DEBUG(3, ("auth_get_challenge: getting challenge from authentication method %s FAILED.\n", @@ -121,27 +123,27 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context) } talloc_destroy(mem_ctx); } - + if (!challenge_set_by) { - uchar chal[8]; - - generate_random_buffer(chal, sizeof(chal)); + uchar tmp[8]; + + generate_random_buffer(tmp, sizeof(tmp)); auth_context->challenge = data_blob_talloc(auth_context->mem_ctx, - chal, sizeof(chal)); - + tmp, sizeof(tmp)); + challenge_set_by = "random"; auth_context->challenge_may_be_modified = True; } - + DEBUG(5, ("auth_context challenge created by %s\n", challenge_set_by)); DEBUG(5, ("challenge is: \n")); dump_data(5, auth_context->challenge.data, auth_context->challenge.length); - + SMB_ASSERT(auth_context->challenge.length == 8); auth_context->challenge_set_by=challenge_set_by; - return auth_context->challenge.data; + memcpy(chal, auth_context->challenge.data, 8); } @@ -249,7 +251,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next) { NTSTATUS result; - + mem_ctx = talloc_init("%s authentication for user %s\\%s", auth_method->name, user_info->domain, user_info->smb_name); @@ -281,7 +283,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, } /* successful authentication */ - + if (NT_STATUS_IS_OK(nt_status)) { unix_username = (*server_info)->unix_name; if (!(*server_info)->guest) { @@ -289,7 +291,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, become_root(); nt_status = smb_pam_accountcheck(unix_username); unbecome_root(); - + if (NT_STATUS_IS_OK(nt_status)) { DEBUG(5, ("check_ntlm_password: PAM Account for user [%s] succeeded\n", unix_username)); @@ -298,7 +300,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, unix_username, nt_errstr(nt_status))); } } - + if (NT_STATUS_IS_OK(nt_status)) { DEBUG((*server_info)->guest ? 5 : 2, ("check_ntlm_password: %sauthentication for user [%s] -> [%s] -> [%s] succeeded\n", @@ -307,17 +309,17 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, user_info->internal_username, unix_username)); } - + return nt_status; } - + /* failed authentication; check for guest lapping */ - + DEBUG(2, ("check_ntlm_password: Authentication for user [%s] -> [%s] FAILED with error %s\n", user_info->smb_name, user_info->internal_username, nt_errstr(nt_status))); ZERO_STRUCTP(server_info); - + return nt_status; } @@ -349,7 +351,7 @@ static NTSTATUS make_auth_context(struct auth_context **auth_context) TALLOC_CTX *mem_ctx; mem_ctx = talloc_init("authentication context"); - + *auth_context = TALLOC_P(mem_ctx, struct auth_context); if (!*auth_context) { DEBUG(0,("make_auth_context: talloc failed!\n")); @@ -362,7 +364,7 @@ static NTSTATUS make_auth_context(struct auth_context **auth_context) (*auth_context)->check_ntlm_password = check_ntlm_password; (*auth_context)->get_ntlm_challenge = get_ntlm_challenge; (*auth_context)->free = free_auth_context; - + return NT_STATUS_OK; } @@ -382,21 +384,21 @@ bool load_auth_module(struct auth_context *auth_context, static_init_auth; initialised_static_modules = True; } - + DEBUG(5,("load_auth_module: Attempting to find an auth method to match %s\n", module)); - + p = strchr(module_name, ':'); if (p) { *p = 0; module_params = p+1; trim_char(module_params, ' ', ' '); } - + trim_char(module_name, ' ', ' '); - + entry = auth_find_backend_entry(module_name); - + if (entry == NULL) { if (NT_STATUS_IS_OK(smb_probe_module("auth", module_name))) { entry = auth_find_backend_entry(module_name); @@ -434,7 +436,7 @@ static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context, DEBUG(2,("make_auth_context_text_list: No auth method list!?\n")); return NT_STATUS_UNSUCCESSFUL; } - + if (!NT_STATUS_IS_OK(nt_status = make_auth_context(auth_context))) return nt_status; @@ -443,9 +445,9 @@ static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context, DLIST_ADD_END(list, t, auth_methods *); } } - + (*auth_context)->auth_method_list = list; - + return nt_status; } @@ -523,7 +525,7 @@ NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context) } else { DEBUG(5,("Using specified auth order\n")); } - + nt_status = make_auth_context_text_list(auth_context, auth_method_list); @@ -541,7 +543,7 @@ NTSTATUS make_auth_context_fixed(struct auth_context **auth_context, uchar chal[ if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(auth_context))) { return nt_status; } - + (*auth_context)->challenge = data_blob_talloc((*auth_context)->mem_ctx, chal, 8); (*auth_context)->challenge_set_by = "fixed"; return nt_status; diff --git a/source3/auth/auth_compat.c b/source3/auth/auth_compat.c index 00d9dea816..925c0d4f81 100644 --- a/source3/auth/auth_compat.c +++ b/source3/auth/auth_compat.c @@ -39,13 +39,14 @@ NTSTATUS check_plaintext_password(const char *smb_name, DATA_BLOB plaintext_pass { struct auth_context *plaintext_auth_context = NULL; auth_usersupplied_info *user_info = NULL; - const uint8 *chal; + uint8_t chal[8]; NTSTATUS nt_status; if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) { return nt_status; } - chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context); + plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context, + chal); if (!make_user_info_for_reply(&user_info, smb_name, lp_workgroup(), chal, diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c index 0d46b14f97..034d354a33 100644 --- a/source3/auth/auth_ntlmssp.c +++ b/source3/auth/auth_ntlmssp.c @@ -27,11 +27,13 @@ * @return an 8 byte random challenge */ -static const uint8 *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state) +static void auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state, + uint8_t chal[8]) { AUTH_NTLMSSP_STATE *auth_ntlmssp_state = (AUTH_NTLMSSP_STATE *)ntlmssp_state->auth_context; - return auth_ntlmssp_state->auth_context->get_ntlm_challenge(auth_ntlmssp_state->auth_context); + auth_ntlmssp_state->auth_context->get_ntlm_challenge( + auth_ntlmssp_state->auth_context, chal); } /** diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 0dab05b97c..c39aa8501d 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -710,8 +710,6 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info) NTSTATUS status; size_t i; struct dom_sid tmp_sid; - const char *name_to_use; - bool force_nss; /* * If winbind is not around, we can not make much use of the SIDs the @@ -719,22 +717,11 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info) * mapped to some local unix user. */ - DEBUG(10, ("creating token for %s (SAM: %s)\n", server_info->unix_name, - server_info->sam_account->username)); - - force_nss = lp_force_username_map() && !server_info->nss_token; if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) || - server_info->nss_token || force_nss) { - if (force_nss) - name_to_use = - pdb_get_username(server_info->sam_account); - else - name_to_use = server_info->unix_name; - + (server_info->nss_token)) { status = create_token_from_username(server_info, - name_to_use, + server_info->unix_name, server_info->guest, - force_nss, &server_info->utok.uid, &server_info->utok.gid, &server_info->unix_name, @@ -819,7 +806,7 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info) } /* - * Create an artificial NT token given just a username. (Initially indended + * Create an artificial NT token given just a username. (Initially intended * for force user) * * We go through lookup_name() to avoid problems we had with 'winbind use @@ -839,7 +826,6 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info) NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username, bool is_guest, - bool force_nss, uid_t *uid, gid_t *gid, char **found_username, struct nt_user_token **token) @@ -855,9 +841,6 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username, size_t num_gids; size_t i; - DEBUG(10, ("creating token for %s,%s guest,%s forcing NSS lookup\n", - username, is_guest ? "" : " not", force_nss ? "" : " not")); - tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { DEBUG(0, ("talloc_new failed\n")); @@ -876,13 +859,7 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username, goto done; } - if (!sid_to_uid(&user_sid, uid)) { - DEBUG(1, ("sid_to_uid for %s (%s) failed\n", - username, sid_string_dbg(&user_sid))); - goto done; - } - - if (sid_check_is_in_our_domain(&user_sid) && !force_nss) { + if (sid_check_is_in_our_domain(&user_sid)) { bool ret; /* This is a passdb user, so ask passdb */ @@ -924,7 +901,7 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username, *found_username = talloc_strdup(mem_ctx, pdb_get_username(sam_acct)); - } else if (force_nss || sid_check_is_in_unix_users(&user_sid)) { + } else if (sid_check_is_in_unix_users(&user_sid)) { /* This is a unix user not in passdb. We need to ask nss * directly, without consulting passdb */ @@ -939,6 +916,12 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username, unix_user: + if (!sid_to_uid(&user_sid, uid)) { + DEBUG(1, ("sid_to_uid for %s (%s) failed\n", + username, sid_string_dbg(&user_sid))); + goto done; + } + uid_to_unix_users_sid(*uid, &user_sid); pass = getpwuid_alloc(tmp_ctx, *uid); @@ -1080,7 +1063,6 @@ bool user_in_group_sid(const char *username, const DOM_SID *group_sid) } status = create_token_from_username(mem_ctx, username, False, - lp_force_username_map(), &uid, &gid, &found_username, &token); diff --git a/source3/auth/auth_wbc.c b/source3/auth/auth_wbc.c new file mode 100644 index 0000000000..580c8b550d --- /dev/null +++ b/source3/auth/auth_wbc.c @@ -0,0 +1,150 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client authentication mechanism designed to defer all + authentication to the winbind daemon. + + Copyright (C) Tim Potter 2000 + Copyright (C) Andrew Bartlett 2001 - 2002 + Copyright (C) Dan Sledz 2009 + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* This auth module is very similar to auth_winbind with 3 distinct + * differences. + * + * 1) Does not fallback to another auth module if winbindd is unavailable + * 2) Does not validate the domain of the user + * 3) Handles unencrypted passwords + * + * The purpose of this module is to defer all authentication decisions (ie: + * local user vs NIS vs LDAP vs AD; encrypted vs plaintext) to the wbc + * compatible daemon. This centeralizes all authentication decisions to a + * single provider. + * + * This auth backend is most useful when used in conjunction with pdb_wbc_sam. + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_AUTH + +/* Authenticate a user with a challenge/response */ + +static NTSTATUS check_wbc_security(const struct auth_context *auth_context, + void *my_private_data, + TALLOC_CTX *mem_ctx, + const auth_usersupplied_info *user_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status; + wbcErr wbc_status; + struct wbcAuthUserParams params; + struct wbcAuthUserInfo *info = NULL; + struct wbcAuthErrorInfo *err = NULL; + + if (!user_info || !auth_context || !server_info) { + return NT_STATUS_INVALID_PARAMETER; + } + /* Send off request */ + + params.account_name = user_info->smb_name; + params.domain_name = user_info->domain; + params.workstation_name = user_info->wksta_name; + + params.flags = 0; + params.parameter_control= user_info->logon_parameters; + + /* Handle plaintext */ + if (!user_info->encrypted) { + DEBUG(3,("Checking plaintext password for %s.\n", + user_info->internal_username)); + params.level = WBC_AUTH_USER_LEVEL_PLAIN; + + params.password.plaintext = (char *)user_info->plaintext_password.data; + } else { + DEBUG(3,("Checking encrypted password for %s.\n", + user_info->internal_username)); + params.level = WBC_AUTH_USER_LEVEL_RESPONSE; + + memcpy(params.password.response.challenge, + auth_context->challenge.data, + sizeof(params.password.response.challenge)); + + params.password.response.nt_length = user_info->nt_resp.length; + params.password.response.nt_data = user_info->nt_resp.data; + params.password.response.lm_length = user_info->lm_resp.length; + params.password.response.lm_data = user_info->lm_resp.data; + + } + + /* we are contacting the privileged pipe */ + become_root(); + wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); + unbecome_root(); + + if (!WBC_ERROR_IS_OK(wbc_status)) { + DEBUG(10,("wbcAuthenticateUserEx failed (%d): %s\n", + wbc_status, wbcErrorString(wbc_status))); + } + + if (wbc_status == WBC_ERR_NO_MEMORY) { + return NT_STATUS_NO_MEMORY; + } + + if (wbc_status == WBC_ERR_AUTH_ERROR) { + nt_status = NT_STATUS(err->nt_status); + wbcFreeMemory(err); + return nt_status; + } + + if (!WBC_ERROR_IS_OK(wbc_status)) { + return NT_STATUS_LOGON_FAILURE; + } + + DEBUG(10,("wbcAuthenticateUserEx succeeded\n")); + + nt_status = make_server_info_wbcAuthUserInfo(mem_ctx, + user_info->smb_name, + user_info->domain, + info, server_info); + wbcFreeMemory(info); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + (*server_info)->nss_token |= user_info->was_mapped; + + return nt_status; +} + +/* module initialisation */ +static NTSTATUS auth_init_wbc(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +{ + if (!make_auth_methods(auth_context, auth_method)) { + return NT_STATUS_NO_MEMORY; + } + + (*auth_method)->name = "wbc"; + (*auth_method)->auth = check_wbc_security; + + return NT_STATUS_OK; +} + +NTSTATUS auth_wbc_init(void) +{ + return smb_register_auth(AUTH_INTERFACE_VERSION, "wbc", auth_init_wbc); +} |