summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/auth/auth.c4
-rw-r--r--source4/auth/auth.h1
-rw-r--r--source4/auth/auth_util.c125
-rw-r--r--source4/auth/auth_winbind.c43
-rw-r--r--source4/libcli/auth/gensec_ntlmssp.c7
-rw-r--r--source4/smb_server/sesssetup.c31
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;
}