1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-23 09:57:40 +03:00
samba-mirror/source/auth/auth_info.c

292 lines
8.9 KiB
C

/*
Unix SMB/Netbios implementation.
Version 3.0.
Authentication utility functions
Copyright (C) Andrew Bartlett 2001
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
const struct auth_init_function builtin_auth_init_functions[] = {
{ "guest", auth_init_guest },
{ "rhosts", auth_init_rhosts },
{ "hostsequiv", auth_init_hostsequiv },
{ "sam", auth_init_sam },
{ "samstrict", auth_init_samstrict },
{ "unix", auth_init_unix },
{ "smbserver", auth_init_smbserver },
{ "ntdomain", auth_init_ntdomain },
{ "winbind", auth_init_winbind },
#ifdef DEVELOPER
{ "name_to_ntstatus", auth_init_name_to_ntstatus },
#endif
{ NULL, NULL}
};
/***************************************************************************
Make a auth_info struct
***************************************************************************/
static BOOL make_auth_info(auth_authsupplied_info **auth_info)
{
*auth_info = malloc(sizeof(**auth_info));
if (!*auth_info) {
DEBUG(0,("make_auth_info: malloc failed!\n"));
return False;
}
ZERO_STRUCTP(*auth_info);
return True;
}
/***************************************************************************
Make a auth_info struct with a specified list.
***************************************************************************/
BOOL make_auth_info_list(auth_authsupplied_info **auth_info, auth_methods *list)
{
if (!make_auth_info(auth_info)) {
return False;
}
(*auth_info)->auth_method_list = list;
return True;
}
/***************************************************************************
Make a auth_info struct for the auth subsystem
***************************************************************************/
static BOOL make_auth_info_text_list(auth_authsupplied_info **auth_info, char **text_list)
{
auth_methods *list = NULL;
auth_methods *t = NULL;
auth_methods *tmp;
int i;
if (!text_list) {
DEBUG(2,("No auth method list!?\n"));
return False;
}
for (;*text_list; text_list++)
{
DEBUG(5,("Attempting to find an auth method to match %s\n", *text_list));
for (i = 0; builtin_auth_init_functions[i].name; i++)
{
if (strequal(builtin_auth_init_functions[i].name, *text_list))
{
DEBUG(5,("Found auth method %s (at pos %d)\n", *text_list, i));
if (builtin_auth_init_functions[i].init(&t)) {
DEBUG(5,("auth method %s has a valid init\n", *text_list));
t->name = builtin_auth_init_functions[i].name;
DLIST_ADD_END(list, t, tmp);
} else {
DEBUG(5,("auth method %s DOES NOT have a valid init\n", *text_list));
}
break;
}
}
}
make_auth_info_list(auth_info, list);
return True;
}
/***************************************************************************
Make a auth_info struct for the auth subsystem
***************************************************************************/
BOOL make_auth_info_subsystem(auth_authsupplied_info **auth_info)
{
char **auth_method_list = NULL;
if (lp_auth_methods() && !lp_list_copy(&auth_method_list, lp_auth_methods())) {
return False;
}
if (auth_method_list == NULL) {
switch (lp_security())
{
case SEC_DOMAIN:
DEBUG(5,("Making default auth method list for security=domain\n"));
auth_method_list = lp_list_make("guest samstrict ntdomain");
break;
case SEC_SERVER:
DEBUG(5,("Making default auth method list for security=server\n"));
auth_method_list = lp_list_make("guest samstrict smbserver");
break;
case SEC_USER:
if (lp_encrypted_passwords()) {
DEBUG(5,("Making default auth method list for security=user, encrypt passwords = yes\n"));
auth_method_list = lp_list_make("guest sam");
} else {
DEBUG(5,("Making default auth method list for security=user, encrypt passwords = no\n"));
auth_method_list = lp_list_make("guest unix");
}
break;
case SEC_SHARE:
if (lp_encrypted_passwords()) {
DEBUG(5,("Making default auth method list for security=share, encrypt passwords = yes\n"));
auth_method_list = lp_list_make("guest sam");
} else {
DEBUG(5,("Making default auth method list for security=share, encrypt passwords = no\n"));
auth_method_list = lp_list_make("guest unix");
}
break;
case SEC_ADS:
DEBUG(5,("Making default auth method list for security=ADS\n"));
auth_method_list = lp_list_make("guest samstrict ads ntdomain");
break;
default:
DEBUG(5,("Unknown auth method!\n"));
return False;
}
} else {
DEBUG(5,("Using specified auth order\n"));
}
if (!make_auth_info_text_list(auth_info, auth_method_list)) {
lp_list_free(&auth_method_list);
return False;
}
lp_list_free(&auth_method_list);
return True;
}
/***************************************************************************
Make a auth_info struct with a random challenge
***************************************************************************/
BOOL make_auth_info_random(auth_authsupplied_info **auth_info)
{
uchar chal[8];
if (!make_auth_info_subsystem(auth_info)) {
return False;
}
generate_random_buffer(chal, sizeof(chal), False);
(*auth_info)->challenge = data_blob(chal, sizeof(chal));
(*auth_info)->challenge_set_by = "random";
return True;
}
/***************************************************************************
Make a auth_info struct with a fixed challenge
***************************************************************************/
BOOL make_auth_info_fixed(auth_authsupplied_info **auth_info, uchar chal[8])
{
if (!make_auth_info_subsystem(auth_info)) {
return False;
}
(*auth_info)->challenge = data_blob(chal, 8);
return True;
}
/***************************************************************************
Clear out a auth_info struct that has been allocated
***************************************************************************/
void free_auth_info(auth_authsupplied_info **auth_info)
{
auth_methods *list;
if (*auth_info != NULL) {
list = (*auth_info)->auth_method_list;
while (list) {
auth_methods *old_head = list;
if (list->free_private_data) {
list->free_private_data(&(list->private_data));
}
DLIST_REMOVE(list, list);
SAFE_FREE(old_head);
}
data_blob_free(&(*auth_info)->challenge);
ZERO_STRUCT(**auth_info);
}
SAFE_FREE(*auth_info);
}
/****************************************************************************
Try to get a challenge out of the various authenticaion modules.
It is up to the caller to free it.
****************************************************************************/
DATA_BLOB auth_get_challenge(auth_authsupplied_info *auth_info)
{
DATA_BLOB challenge = data_blob(NULL, 0);
char *challenge_set_by = NULL;
auth_methods *auth_method;
if (auth_info->challenge.length) {
DEBUG(5, ("auth_get_challenge: returning previous challenge (normal)\n"));
return data_blob(auth_info->challenge.data, auth_info->challenge.length);
}
for (auth_method = auth_info->auth_method_list; auth_method; auth_method = auth_method->next)
{
if (auth_method->get_chal) {
DEBUG(5, ("auth_get_challenge: getting challenge from module %s\n", auth_method->name));
if (challenge_set_by) {
DEBUG(1, ("auth_get_challenge: CONFIGURATION ERROR: authenticaion method %s has already specified a challenge. Challenge by %s ignored.\n",
challenge_set_by, auth_method->name));
} else {
challenge = auth_method->get_chal(&auth_method->private_data, auth_info);
if (challenge.length) {
DEBUG(5, ("auth_get_challenge: sucessfully got challenge from module %s\n", auth_method->name));
auth_info->challenge = challenge;
challenge_set_by = auth_method->name;
auth_info->challenge_set_method = auth_method;
} else {
DEBUG(3, ("auth_get_challenge: getting challenge from authenticaion method %s FAILED.\n",
auth_method->name));
}
}
} else {
DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name));
}
}
if (!challenge_set_by) {
uchar chal[8];
generate_random_buffer(chal, sizeof(chal), False);
auth_info->challenge = data_blob(chal, sizeof(chal));
challenge_set_by = "random";
}
DEBUG(5, ("auth_info challenge created by %s\n", challenge_set_by));
DEBUG(5, ("challenge is: \n"));
dump_data(5, auth_info->challenge.data, (auth_info)->challenge.length);
SMB_ASSERT(auth_info->challenge.length == 8);
auth_info->challenge_set_by=challenge_set_by;
return data_blob(auth_info->challenge.data, auth_info->challenge.length);
}