diff options
author | Andrew Bartlett <abartlet@samba.org> | 2004-10-29 09:15:41 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:05:01 -0500 |
commit | 85796280f4e9a4f8ac6a1c327c13c7dbef9ce424 (patch) | |
tree | efa09f459b67d9cdebfaeaf5480e9745a70c857f /source4 | |
parent | 09d0b152b7bd85aa01898af81bd166a7673ab886 (diff) | |
download | samba-85796280f4e9a4f8ac6a1c327c13c7dbef9ce424.tar.gz samba-85796280f4e9a4f8ac6a1c327c13c7dbef9ce424.tar.xz samba-85796280f4e9a4f8ac6a1c327c13c7dbef9ce424.zip |
r3361: Allow Samba4 (I'm interested in ntlm_auth in particular) to use
Samba3's winbind. This is also the start of domain membership code in
Samba4, as we now (partially) parse the info3, and use it like Samba3
does.
Andrew Bartlett
(This used to be commit c1b7303c1c7d9fb815006c3bd2af20a0010d15a8)
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; } |