diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/auth/auth.c | 4 | ||||
-rw-r--r-- | source4/auth/auth.h | 1 | ||||
-rw-r--r-- | source4/auth/auth_util.c | 125 | ||||
-rw-r--r-- | source4/auth/auth_winbind.c | 43 | ||||
-rw-r--r-- | source4/libcli/auth/gensec_ntlmssp.c | 7 | ||||
-rw-r--r-- | source4/smb_server/sesssetup.c | 31 |
6 files changed, 188 insertions, 23 deletions
diff --git a/source4/auth/auth.c b/source4/auth/auth.c index 62e2b93ecb..23dae12811 100644 --- a/source4/auth/auth.c +++ b/source4/auth/auth.c @@ -154,6 +154,7 @@ static BOOL check_domain_match(const char *user, const char *domain) static NTSTATUS check_ntlm_password(struct auth_context *auth_context, const struct auth_usersupplied_info *user_info, + TALLOC_CTX *out_mem_ctx, struct auth_serversupplied_info **server_info) { /* if all the modules say 'not for me' this is reasonable */ @@ -220,6 +221,9 @@ static NTSTATUS check_ntlm_password(struct auth_context *auth_context, if (NT_STATUS_IS_OK(nt_status)) { DEBUG(3, ("check_ntlm_password: %s authentication for user [%s] succeeded\n", auth_method->name, user_info->smb_name.str)); + + /* Give the server info to the client to hold onto */ + talloc_reference(out_mem_ctx, *server_info); } else { DEBUG(5, ("check_ntlm_password: %s authentication for user [%s] FAILED with error %s\n", auth_method->name, user_info->smb_name.str, nt_errstr(nt_status))); diff --git a/source4/auth/auth.h b/source4/auth/auth.h index 2f35b36a15..98b0994283 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -122,6 +122,7 @@ struct auth_context { const uint8_t *(*get_ntlm_challenge)(struct auth_context *auth_context); NTSTATUS (*check_ntlm_password)(struct auth_context *auth_context, const struct auth_usersupplied_info *user_info, + TALLOC_CTX *out_mem_ctx, struct auth_serversupplied_info **server_info); NTSTATUS (*nt_status_squash)(NTSTATUS nt_status); }; diff --git a/source4/auth/auth_util.c b/source4/auth/auth_util.c index 839e87585b..ef008d62c5 100644 --- a/source4/auth/auth_util.c +++ b/source4/auth/auth_util.c @@ -437,7 +437,7 @@ NTSTATUS make_server_info(const TALLOC_CTX *mem_ctx, /*************************************************************************** Make (and fill) a user_info struct for a guest login. ***************************************************************************/ -NTSTATUS make_server_info_guest(const TALLOC_CTX *mem_ctx, struct auth_serversupplied_info **server_info) +NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; @@ -486,6 +486,127 @@ NTSTATUS make_server_info_guest(const TALLOC_CTX *mem_ctx, struct auth_serversup } /*************************************************************************** + Make a server_info struct from the info3 returned by a domain logon +***************************************************************************/ + +NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, + const char *internal_username, + struct auth_serversupplied_info **server_info, + struct netr_SamInfo3 *info3) +{ + NTSTATUS nt_status; + + nt_status = make_server_info(mem_ctx, server_info, internal_username); + + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + (*server_info)->guest = False; + + /* + Here is where we should check the list of + trusted domains, and verify that the SID + matches. + */ + + (*server_info)->user_sid = dom_sid_add_rid(*server_info, dom_sid_dup(*server_info, info3->base.domain_sid), info3->base.rid); + (*server_info)->primary_group_sid = dom_sid_add_rid(*server_info, dom_sid_dup(*server_info, info3->base.domain_sid), info3->base.primary_gid); + + /* TODO: pull in other groups: */ + + + (*server_info)->domain_groups = talloc_array_p((*server_info), struct dom_sid*, info3->base.group_count); + if (!(*server_info)->domain_groups) { + return NT_STATUS_NO_MEMORY; + } + + for ((*server_info)->n_domain_groups = 0; + (*server_info)->n_domain_groups < info3->base.group_count; + (*server_info)->n_domain_groups++) { + struct dom_sid *sid; + sid = dom_sid_dup(*server_info, info3->base.domain_sid); + if (!sid) { + return NT_STATUS_NO_MEMORY; + } + (*server_info)->domain_groups[(*server_info)->n_domain_groups] + = dom_sid_add_rid(*server_info, sid, + info3->base.groupids[(*server_info)->n_domain_groups].rid); + if (!(*server_info)->domain_groups[(*server_info)->n_domain_groups]) { + return NT_STATUS_NO_MEMORY; + } + } + + if (info3->base.account_name.string) { + (*server_info)->account_name = talloc_reference(*server_info, info3->base.account_name.string); + } else { + (*server_info)->account_name = talloc_strdup(*server_info, internal_username); + } + + if (info3->base.domain.string) { + (*server_info)->domain = talloc_reference(*server_info, info3->base.domain.string); + } else { + (*server_info)->domain = NULL; + } + + if (info3->base.full_name.string) { + (*server_info)->full_name = talloc_reference(*server_info, info3->base.full_name.string); + } else { + (*server_info)->full_name = NULL; + } + + if (info3->base.logon_script.string) { + (*server_info)->logon_script = talloc_reference(*server_info, info3->base.logon_script.string); + } else { + (*server_info)->logon_script = NULL; + } + + if (info3->base.profile_path.string) { + (*server_info)->profile_path = talloc_reference(*server_info, info3->base.profile_path.string); + } else { + (*server_info)->profile_path = NULL; + } + + if (info3->base.home_directory.string) { + (*server_info)->home_directory = talloc_reference(*server_info, info3->base.home_directory.string); + } else { + (*server_info)->home_directory = NULL; + } + + if (info3->base.home_drive.string) { + (*server_info)->home_drive = talloc_reference(*server_info, info3->base.home_drive.string); + } else { + (*server_info)->home_drive = NULL; + } + (*server_info)->last_logon = info3->base.last_logon; + (*server_info)->last_logoff = info3->base.last_logoff; + (*server_info)->acct_expiry = info3->base.acct_expiry; + (*server_info)->last_password_change = info3->base.last_password_change; + (*server_info)->allow_password_change = info3->base.allow_password_change; + (*server_info)->force_password_change = info3->base.force_password_change; + + (*server_info)->logon_count = info3->base.logon_count; + (*server_info)->bad_password_count = info3->base.bad_password_count; + + (*server_info)->acct_flags = info3->base.acct_flags; + + /* ensure we are never given NULL session keys */ + + if (all_zero(info3->base.key.key, sizeof(info3->base.key.key))) { + (*server_info)->user_session_key = data_blob(NULL, 0); + } else { + (*server_info)->user_session_key = data_blob_talloc((*server_info), info3->base.key.key, sizeof(info3->base.key.key)); + } + + if (all_zero(info3->base.LMSessKey.key, sizeof(info3->base.LMSessKey.key))) { + (*server_info)->lm_session_key = data_blob(NULL, 0); + } else { + (*server_info)->lm_session_key = data_blob_talloc((*server_info), info3->base.LMSessKey.key, sizeof(info3->base.LMSessKey.key)); + } + return NT_STATUS_OK; +} + +/*************************************************************************** Free a user_info struct ***************************************************************************/ @@ -546,7 +667,7 @@ NTSTATUS make_session_info(TALLOC_CTX *mem_ctx, } (*session_info)->server_info = server_info; - talloc_reference(*session_info, server_info); + talloc_reference(*session_info, (*session_info)->server_info); /* unless set otherwise, the session key is the user session * key from the auth subsystem */ diff --git a/source4/auth/auth_winbind.c b/source4/auth/auth_winbind.c index 1bc4ecbc9f..c37f65f441 100644 --- a/source4/auth/auth_winbind.c +++ b/source4/auth/auth_winbind.c @@ -26,6 +26,25 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH +static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response *response, struct netr_SamInfo3 *info3) +{ + size_t len = response->length - sizeof(struct winbindd_response); + if (len > 4) { + NTSTATUS status; + DATA_BLOB blob; + blob.length = len - 4; + blob.data = ((char *)response->extra_data) + 4; + + status = ndr_pull_struct_blob(&blob, mem_ctx, info3, + (ndr_pull_flags_fn_t)ndr_pull_netr_SamInfo3); + + return status; + } else { + DEBUG(2, ("get_info3_from_ndr: No info3 struct found!\n")); + return NT_STATUS_UNSUCCESSFUL; + } +} + /* Authenticate a user with a challenge/response */ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, @@ -38,6 +57,7 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, struct winbindd_response response; NSS_STATUS result; NTSTATUS nt_status; + struct netr_SamInfo3 info3; if (!user_info) { return NT_STATUS_INVALID_PARAMETER; @@ -53,9 +73,7 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, ZERO_STRUCT(request); ZERO_STRUCT(response); -#if 0 - request.data.auth_crap.flags = WINBIND_PAM_INFO3_NDR; -#endif + request.flags = WBFLAG_PAM_INFO3_NDR; fstrcpy(request.data.auth_crap.user, user_info->smb_name.str); fstrcpy(request.data.auth_crap.domain, @@ -79,22 +97,31 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, nt_status = NT_STATUS(response.data.auth.nt_status); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + if (result == NSS_STATUS_SUCCESS && response.extra_data) { -#if 0 if (NT_STATUS_IS_OK(nt_status)) { if (NT_STATUS_IS_OK(nt_status = get_info3_from_ndr(mem_ctx, &response, &info3))) { nt_status = make_server_info_info3(mem_ctx, user_info->internal_username.str, - user_info->smb_name.str, - user_info->domain.str, server_info, &info3); } } -#endif + SAFE_FREE(response.extra_data); + } else if (result == NSS_STATUS_SUCCESS && !response.extra_data) { + DEBUG(0, ("Winbindd authenticated the user [%s]\\[%s], " + "but did not include the required info3 reply!\n", + user_info->smb_name.str, user_info->domain.str)); + nt_status = NT_STATUS_INSUFFICIENT_LOGON_INFO; } else if (NT_STATUS_IS_OK(nt_status)) { - nt_status = NT_STATUS_UNSUCCESSFUL; + DEBUG(1, ("Winbindd authentication for [%s]\\[%s] failed, " + "but no error code is available!\n", + user_info->smb_name.str, user_info->domain.str)); + nt_status = NT_STATUS_NO_LOGON_SERVERS; } return nt_status; diff --git a/source4/libcli/auth/gensec_ntlmssp.c b/source4/libcli/auth/gensec_ntlmssp.c index 48438aaae1..f75e7b4d73 100644 --- a/source4/libcli/auth/gensec_ntlmssp.c +++ b/source4/libcli/auth/gensec_ntlmssp.c @@ -115,8 +115,11 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, return nt_status; } - nt_status = gensec_ntlmssp_state->auth_context->check_ntlm_password(gensec_ntlmssp_state->auth_context, - user_info, &gensec_ntlmssp_state->server_info); + nt_status = gensec_ntlmssp_state-> + auth_context->check_ntlm_password(gensec_ntlmssp_state->auth_context, + user_info, + gensec_ntlmssp_state, + &gensec_ntlmssp_state->server_info); free_user_info(&user_info); diff --git a/source4/smb_server/sesssetup.c b/source4/smb_server/sesssetup.c index 03a750e070..7aaec90f13 100644 --- a/source4/smb_server/sesssetup.c +++ b/source4/smb_server/sesssetup.c @@ -45,7 +45,7 @@ static NTSTATUS sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *s struct auth_serversupplied_info *server_info = NULL; struct auth_session_info *session_info; - TALLOC_CTX *mem_ctx = talloc_init("NT1 session setup"); + TALLOC_CTX *mem_ctx = talloc_named(req, 0, "NT1 session setup"); char *remote_machine; if (!mem_ctx) { return NT_STATUS_NO_MEMORY; @@ -62,20 +62,23 @@ static NTSTATUS sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *s remote_machine, sess->old.in.password, data_blob(NULL, 0)); - talloc_free(mem_ctx); if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx); return NT_STATUS_ACCESS_DENIED; } status = req->smb_conn->negotiate.auth_context->check_ntlm_password(req->smb_conn->negotiate.auth_context, - user_info, - &server_info); + user_info, + mem_ctx, + &server_info); if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx); return nt_status_squash(status); } /* This references server_info into session_info */ status = make_session_info(req, server_info, &session_info); + talloc_free(mem_ctx); if (!NT_STATUS_IS_OK(status)) { return nt_status_squash(status); } @@ -105,6 +108,11 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s struct auth_usersupplied_info *user_info = NULL; struct auth_serversupplied_info *server_info = NULL; struct auth_session_info *session_info; + TALLOC_CTX *mem_ctx = talloc_named(req, 0, "NT1 session setup"); + + if (!mem_ctx) { + return NT_STATUS_NO_MEMORY; + } if (!req->smb_conn->negotiate.done_sesssetup) { req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize; @@ -123,18 +131,16 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s status = make_auth_context_subsystem(req->smb_conn, &auth_context); if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx); return status; } status = auth_context->check_ntlm_password(auth_context, user_info, + mem_ctx, &server_info); } else { - TALLOC_CTX *mem_ctx = talloc_init("NT1 session setup"); char *remote_machine; - if (!mem_ctx) { - return NT_STATUS_NO_MEMORY; - } remote_machine = socket_get_peer_addr(req->smb_conn->connection->socket, mem_ctx); status = make_user_info_for_reply_enc(req->smb_conn, &user_info, @@ -142,8 +148,8 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s remote_machine, sess->nt1.in.password1, sess->nt1.in.password2); - talloc_free(mem_ctx); if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx); return NT_STATUS_ACCESS_DENIED; } @@ -151,22 +157,25 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s .auth_context->check_ntlm_password(req->smb_conn->negotiate .auth_context, user_info, + req, &server_info); } if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx); return nt_status_squash(status); } /* This references server_info into session_info */ - status = make_session_info(req, server_info, &session_info); + status = make_session_info(mem_ctx, server_info, &session_info); if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx); return nt_status_squash(status); } - talloc_free(server_info); sess->nt1.out.action = 0; sess->nt1.out.vuid = smbsrv_register_session(req->smb_conn, session_info, NULL); + talloc_free(mem_ctx); if (sess->nt1.out.vuid == UID_FIELD_INVALID) { return NT_STATUS_ACCESS_DENIED; } |