summaryrefslogtreecommitdiff
path: root/source4/auth/auth.c
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2005-01-09 12:55:25 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:08:34 -0500
commit46a32687da249174a666d9166fccbe705c8beba0 (patch)
tree07a43ce2b630ea0a943c01ba4d631c9da18630c8 /source4/auth/auth.c
parentb61b22d73a0b0fb3322884e3712c89a52a47f56b (diff)
downloadsamba-46a32687da249174a666d9166fccbe705c8beba0.tar.gz
samba-46a32687da249174a666d9166fccbe705c8beba0.tar.bz2
samba-46a32687da249174a666d9166fccbe705c8beba0.zip
r4620: - add interface functions to the auth subsystem so that callers doesn't need to
use function pointers anymore - make the module init much easier - a lot of cleanups don't try to read the diff in auth/ better read the new files it passes test_echo.sh and test_rpc.sh abartlet: please fix spelling fixes metze (This used to be commit 3c0d16b8236451f2cfd38fc3db8ae2906106d847)
Diffstat (limited to 'source4/auth/auth.c')
-rw-r--r--source4/auth/auth.c403
1 files changed, 122 insertions, 281 deletions
diff --git a/source4/auth/auth.c b/source4/auth/auth.c
index 33f3020382..674e9a7f46 100644
--- a/source4/auth/auth.c
+++ b/source4/auth/auth.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
Password and authentication handling
Copyright (C) Andrew Bartlett 2001-2002
+ Copyright (C) Stefan Metzmacher 2005
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
@@ -22,111 +23,82 @@
#include "dlinklist.h"
#include "auth/auth.h"
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_AUTH
+/***************************************************************************
+ Set a fixed challenge
+***************************************************************************/
+NTSTATUS auth_context_set_challenge(struct auth_context *auth_ctx, const uint8_t chal[8], const char *set_by)
+{
+ auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
+ NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
+
+ auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
+ NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
+
+ return NT_STATUS_OK;
+}
+
+/***************************************************************************
+ Set a fixed challenge
+***************************************************************************/
+BOOL auth_challenge_may_be_modified(struct auth_context *auth_ctx)
+{
+ return auth_ctx->challenge.may_be_modified;
+}
/****************************************************************************
Try to get a challenge out of the various authentication modules.
Returns a const char of length 8 bytes.
****************************************************************************/
-
-static const uint8_t *get_ntlm_challenge(struct auth_context *auth_context)
+NTSTATUS auth_get_challenge(struct auth_context *auth_ctx, const uint8_t **_chal)
{
- DATA_BLOB challenge = data_blob(NULL, 0);
- const char *challenge_set_by = NULL;
- struct auth_methods *auth_method;
- TALLOC_CTX *mem_ctx;
-
- 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;
+ NTSTATUS nt_status;
+ struct auth_method_context *method;
+
+ if (auth_ctx->challenge.data.length) {
+ DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n",
+ auth_ctx->challenge.set_by));
+ *_chal = auth_ctx->challenge.data.data;
+ return NT_STATUS_OK;
}
- auth_context->challenge_may_be_modified = False;
+ for (method = auth_ctx->methods; method; method = method->next) {
+ DATA_BLOB challenge = data_blob(NULL,0);
- for (auth_method = auth_context->auth_method_list; auth_method; auth_method = auth_method->next) {
- if (auth_method->get_chal == NULL) {
- DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name));
+ nt_status = method->ops->get_challenge(method, auth_ctx, &challenge);
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
continue;
}
- DEBUG(5, ("auth_get_challenge: getting challenge from module %s\n", auth_method->name));
- if (challenge_set_by != NULL) {
- DEBUG(1, ("auth_get_challenge: CONFIGURATION ERROR: authentication method %s has already specified a challenge. Challenge by %s ignored.\n",
- challenge_set_by, auth_method->name));
- continue;
- }
+ NT_STATUS_NOT_OK_RETURN(nt_status);
- mem_ctx = talloc_init("auth_get_challenge for module %s", auth_method->name);
- if (!mem_ctx) {
- smb_panic("talloc_init() failed!");
+ if (challenge.length != 8) {
+ DEBUG(0, ("auth_get_challenge: invalid challenge (length %u) by mothod [%s]\n",
+ challenge.length, method->ops->name));
+ return NT_STATUS_INTERNAL_ERROR;
}
-
- 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",
- auth_method->name));
- } else {
- DEBUG(5, ("auth_get_challenge: sucessfully got challenge from module %s\n", auth_method->name));
- auth_context->challenge = challenge;
- challenge_set_by = auth_method->name;
- auth_context->challenge_set_method = auth_method;
- }
- talloc_destroy(mem_ctx);
- }
-
- if (!challenge_set_by) {
- uint8_t chal[8];
-
- generate_random_buffer(chal, sizeof(chal));
- auth_context->challenge = data_blob_talloc(auth_context,
- chal, sizeof(chal));
-
- 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;
+ auth_ctx->challenge.data = challenge;
+ auth_ctx->challenge.set_by = method->ops->name;
- return auth_context->challenge.data;
-}
+ break;
+ }
+ if (!auth_ctx->challenge.set_by) {
+ uint8_t chal[8];
+ generate_random_buffer(chal, 8);
-/**
- * Check user is in correct domain (if required)
- *
- * @param user Only used to fill in the debug message
- *
- * @param domain The domain to be verified
- *
- * @return True if the user can connect with that domain,
- * False otherwise.
-**/
+ auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
+ NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
+ auth_ctx->challenge.set_by = "random";
-static BOOL check_domain_match(const char *user, const char *domain)
-{
- /*
- * If we aren't serving to trusted domains, we must make sure that
- * the validation request comes from an account in the same domain
- * as the Samba server
- */
-
- if (!lp_allow_trusted_domains() &&
- !(strequal("", domain) ||
- strequal(lp_workgroup(), domain) ||
- is_myname(domain))) {
- DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
- return False;
- } else {
- return True;
+ auth_ctx->challenge.may_be_modified = True;
}
+
+ DEBUG(10,("auth_get_challenge: challenge set by %s\n",
+ auth_ctx->challenge.set_by));
+
+ *_chal = auth_ctx->challenge.data.data;
+ return NT_STATUS_OK;
}
/**
@@ -154,41 +126,38 @@ 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)
+NTSTATUS auth_check_password(struct auth_context *auth_ctx,
+ TALLOC_CTX *mem_ctx,
+ const struct auth_usersupplied_info *user_info,
+ struct auth_serversupplied_info **server_info)
{
/* if all the modules say 'not for me' this is reasonable */
NTSTATUS nt_status = NT_STATUS_NO_SUCH_USER;
- struct auth_methods *auth_method;
- TALLOC_CTX *mem_ctx;
+ struct auth_method_context *method;
+ const char *method_name = "NO METHOD";
+ const uint8_t *challenge;
- if (!user_info || !auth_context || !server_info)
- return NT_STATUS_LOGON_FAILURE;
+ DEBUG(3, ("auth_check_password: Checking password for unmapped user [%s]\\[%s]@[%s]\n",
+ user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name));
- DEBUG(3, ("check_ntlm_password: Checking password for unmapped user [%s]\\[%s]@[%s] with the new password interface\n",
- user_info->client_domain.str, user_info->smb_name.str, user_info->wksta_name.str));
+ DEBUGADD(3,("auth_check_password: mapped user is: [%s]\\[%s]@[%s]\n",
+ user_info->domain_name, user_info->account_name, user_info->workstation_name));
- DEBUG(3, ("check_ntlm_password: mapped user is: [%s]\\[%s]@[%s]\n",
- user_info->domain.str, user_info->internal_username.str, user_info->wksta_name.str));
+ nt_status = auth_get_challenge(auth_ctx, &challenge);
- if (auth_context->challenge.length == 0) {
- /* get a challenge, if we have not asked for one yet */
- get_ntlm_challenge(auth_context);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0, ("auth_check_password: Invalid challenge (length %u) stored for this auth context set_by %s - cannot continue: %s\n",
+ auth_ctx->challenge.data.length, auth_ctx->challenge.set_by, nt_errstr(nt_status)));
+ return nt_status;
}
- if (auth_context->challenge.length != 8) {
- DEBUG(0, ("check_ntlm_password: Invalid challenge stored for this auth context - cannot continue\n"));
- return NT_STATUS_LOGON_FAILURE;
+ if (auth_ctx->challenge.set_by) {
+ DEBUG(10, ("auth_check_password: auth_context challenge created by %s\n",
+ auth_ctx->challenge.set_by));
}
- if (auth_context->challenge_set_by)
- DEBUG(10, ("check_ntlm_password: auth_context challenge created by %s\n",
- auth_context->challenge_set_by));
-
DEBUG(10, ("challenge is: \n"));
- dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
+ dump_data(5, auth_ctx->challenge.data.data, auth_ctx->challenge.data.length);
#ifdef DEBUG_PASSWORD
DEBUG(100, ("user_info has passwords of length %d and %d\n",
@@ -199,204 +168,78 @@ static NTSTATUS check_ntlm_password(struct auth_context *auth_context,
dump_data(100, user_info->nt_resp.data, user_info->nt_resp.length);
#endif
- /* This needs to be sorted: If it doesn't match, what should we do? */
- if (!check_domain_match(user_info->smb_name.str, user_info->domain.str))
- return NT_STATUS_LOGON_FAILURE;
-
- for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next) {
+ for (method = auth_ctx->methods; method; method = method->next) {
NTSTATUS result;
-
- mem_ctx = talloc_init("%s authentication for user %s\\%s", auth_method->name,
- user_info->domain.str, user_info->smb_name.str);
- result = auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info);
+ result = method->ops->check_password(method, mem_ctx, user_info, server_info);
/* check if the module did anything */
- if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ) {
- DEBUG(10,("check_ntlm_password: %s had nothing to say\n", auth_method->name));
- talloc_destroy(mem_ctx);
- continue;
- }
-
- nt_status = result;
-
- 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)));
- }
-
- talloc_destroy(mem_ctx);
-
- if ( NT_STATUS_IS_OK(nt_status))
- {
- break;
+ if (!NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
+ method_name = method->ops->name;
+ nt_status = result;
+ break;
}
- }
- if (NT_STATUS_IS_OK(nt_status)) {
- if (NT_STATUS_IS_OK(nt_status)) {
- DEBUG((*server_info)->guest ? 5 : 2,
- ("check_ntlm_password: %sauthentication for user [%s] -> [%s] succeeded\n",
- (*server_info)->guest ? "guest " : "",
- user_info->smb_name.str,
- user_info->internal_username.str));
- }
+ DEBUG(11,("auth_check_password: %s had nothing to say\n", method->ops->name));
}
if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(2, ("check_ntlm_password: Authentication for user [%s] -> [%s] FAILED with error %s\n",
- user_info->smb_name.str, user_info->internal_username.str,
- nt_errstr(nt_status)));
- ZERO_STRUCTP(server_info);
- }
- return nt_status;
-}
-
-/***************************************************************************
- Clear out a auth_context, and destroy the attached TALLOC_CTX
-***************************************************************************/
-
-void free_auth_context(struct auth_context **auth_context)
-{
- struct auth_methods *auth_method;
-
- if (*auth_context) {
- /* Free private data of context's authentication methods */
- for (auth_method = (*auth_context)->auth_method_list; auth_method; auth_method = auth_method->next) {
- if (auth_method->free_private_data) {
- auth_method->free_private_data (&auth_method->private_data);
- auth_method->private_data = NULL;
- }
- }
-
- talloc_free(*auth_context);
- *auth_context = NULL;
+ DEBUG(2,("auth_check_password: %s authentication for user [%s\\%s] FAILED with error %s\n",
+ method_name, user_info->domain_name, user_info->account_name,
+ nt_errstr(nt_status)));
+ return nt_status;
}
-}
-/***************************************************************************
- Make a auth_info struct
-***************************************************************************/
-
-static NTSTATUS make_auth_context(TALLOC_CTX *mem_ctx, struct auth_context **auth_context)
-{
- *auth_context = talloc_p(mem_ctx, struct auth_context);
- if (!*auth_context) {
- DEBUG(0,("make_auth_context: talloc failed!\n"));
- return NT_STATUS_NO_MEMORY;
- }
- ZERO_STRUCTP(*auth_context);
+ DEBUG(5,("auth_check_password: %s authentication for user [%s\\%s] succeeded\n",
+ method_name, (*server_info)->domain_name, (*server_info)->account_name));
- (*auth_context)->check_ntlm_password = check_ntlm_password;
- (*auth_context)->get_ntlm_challenge = get_ntlm_challenge;
-
- return NT_STATUS_OK;
+ return nt_status;
}
/***************************************************************************
Make a auth_info struct for the auth subsystem
***************************************************************************/
-
-static NTSTATUS make_auth_context_text_list(TALLOC_CTX *mem_ctx,
- struct auth_context **auth_context, char **text_list)
+NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx, const char **methods, struct auth_context **auth_ctx)
{
- struct auth_methods *list = NULL;
- struct auth_methods *t = NULL;
- NTSTATUS nt_status;
+ int i;
+ struct auth_context *ctx;
- if (!text_list) {
- DEBUG(2,("make_auth_context_text_list: No auth method list!?\n"));
- return NT_STATUS_UNSUCCESSFUL;
+ if (!methods) {
+ DEBUG(0,("auth_context_create: No auth method list!?\n"));
+ return NT_STATUS_INTERNAL_ERROR;
}
-
- if (!NT_STATUS_IS_OK(nt_status = make_auth_context(mem_ctx, auth_context)))
- return nt_status;
-
- for (;*text_list; text_list++) {
- char *module_name = smb_xstrdup(*text_list);
- char *module_params = NULL;
- char *p;
- const struct auth_operations *ops;
-
- DEBUG(5,("make_auth_context_text_list: Attempting to find an auth method to match %s\n",
- *text_list));
-
- p = strchr(module_name, ':');
- if (p) {
- *p = 0;
- module_params = p+1;
- trim_string(module_params, " ", " ");
- }
-
- trim_string(module_name, " ", " ");
-
- ops = auth_backend_byname(module_name);
- if (!ops) {
- DEBUG(5,("make_auth_context_text_list: Found auth method %s\n", *text_list));
- SAFE_FREE(module_name);
- break;
- }
- if (NT_STATUS_IS_OK(ops->init(*auth_context, module_params, &t))) {
- DEBUG(5,("make_auth_context_text_list: auth method %s has a valid init\n",
- *text_list));
- DLIST_ADD_END(list, t, struct auth_methods *);
- } else {
- DEBUG(0,("make_auth_context_text_list: auth method %s did not correctly init\n",
- *text_list));
- }
- SAFE_FREE(module_name);
- }
-
- (*auth_context)->auth_method_list = list;
-
- return nt_status;
-}
+ ctx = talloc(mem_ctx, struct auth_context);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+ ctx->challenge.set_by = NULL;
+ ctx->challenge.may_be_modified = False;
+ ctx->challenge.data = data_blob(NULL, 0);
+ ctx->methods = NULL;
-/***************************************************************************
- Make a auth_context struct for the auth subsystem
-***************************************************************************/
+ for (i=0; methods[i] ; i++) {
+ struct auth_method_context *method;
-NTSTATUS make_auth_context_subsystem(TALLOC_CTX *mem_ctx, struct auth_context **auth_context)
-{
- char **auth_method_list = NULL;
- NTSTATUS nt_status;
+ method = talloc(ctx, struct auth_method_context);
+ NT_STATUS_HAVE_NO_MEMORY(method);
- if (lp_auth_methods() && !str_list_copy(&auth_method_list, lp_auth_methods())) {
- return NT_STATUS_NO_MEMORY;
+ method->ops = auth_backend_byname(methods[i]);
+ if (!method->ops) {
+ DEBUG(1,("auth_context_create: failed to find method=%s\n",
+ methods[i]));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ method->auth_ctx = ctx;
+ method->depth = i;
+ DLIST_ADD_END(ctx->methods, method, struct auth_method_context *);
}
- nt_status = make_auth_context_text_list(mem_ctx, auth_context, auth_method_list);
- if (!NT_STATUS_IS_OK(nt_status)) {
- str_list_free(&auth_method_list);
- return nt_status;
+ if (!ctx->methods) {
+ return NT_STATUS_INTERNAL_ERROR;
}
-
- str_list_free(&auth_method_list);
- return nt_status;
-}
-/***************************************************************************
- Make a auth_info struct with a fixed challenge
-***************************************************************************/
+ *auth_ctx = ctx;
-NTSTATUS make_auth_context_fixed(TALLOC_CTX *mem_ctx,
- struct auth_context **auth_context, uint8_t chal[8])
-{
- NTSTATUS nt_status;
- if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(mem_ctx, auth_context))) {
- return nt_status;
- }
-
- (*auth_context)->challenge = data_blob_talloc(*auth_context, chal, 8);
- (*auth_context)->challenge_set_by = "fixed";
- return nt_status;
+ return NT_STATUS_OK;
}
/* the list of currently registered AUTH backends */
@@ -423,7 +266,6 @@ NTSTATUS auth_register(const void *_ops)
return NT_STATUS_OBJECT_NAME_COLLISION;
}
-
backends = realloc_p(backends, struct auth_backend, num_backends+1);
if (!backends) {
smb_panic("out of memory in auth_register");
@@ -468,11 +310,10 @@ const struct auth_critical_sizes *auth_interface_version(void)
static const struct auth_critical_sizes critical_sizes = {
AUTH_INTERFACE_VERSION,
sizeof(struct auth_operations),
- sizeof(struct auth_methods),
+ sizeof(struct auth_method_context),
sizeof(struct auth_context),
sizeof(struct auth_usersupplied_info),
- sizeof(struct auth_serversupplied_info),
- sizeof(struct auth_str),
+ sizeof(struct auth_serversupplied_info)
};
return &critical_sizes;