summaryrefslogtreecommitdiff
path: root/source4/auth
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2004-10-29 09:15:41 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:05:01 -0500
commit85796280f4e9a4f8ac6a1c327c13c7dbef9ce424 (patch)
treeefa09f459b67d9cdebfaeaf5480e9745a70c857f /source4/auth
parent09d0b152b7bd85aa01898af81bd166a7673ab886 (diff)
downloadsamba-85796280f4e9a4f8ac6a1c327c13c7dbef9ce424.tar.gz
samba-85796280f4e9a4f8ac6a1c327c13c7dbef9ce424.tar.bz2
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/auth')
-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
4 files changed, 163 insertions, 10 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;