mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
d870edce76
- Move rpc_client/cli_trust.c to smbd/change_trust_pw.c - It hasn't been used by anything else since smbpasswd lost its -j - Add a TALLOC_CTX to the auth subsytem. These are only valid for the length of the calls to the individual modules, if you want a longer context hide it in your private data. Similarly, all returns (like the server_info) should still be malloced. - Move the 'ntdomain' module (security=domain in oldspeak) over to use the new libsmb domain logon code. Also rework much of the code to use some better helper functions for the connection - getting us much better error returns (the new code is NTSTATUS). The only remaining thing to do is to figure out if tpot's 0xdead 0xbeef for the LUID feilds is sufficient, or if we should do random LUIDs as per the old code. Similarly, I'll move winbind over to this when I get a chance. This leaves the SPOOLSS code and some cli_pipe code as the only stuff still in rpc_client, at least as far as smbd is concerned. While I've given this a basic rundown, any testing is as always appriciated. Andrew Bartlett
314 lines
9.6 KiB
C
314 lines
9.6 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"
|
|
|
|
/** List of various built-in authenticaion modules */
|
|
|
|
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}
|
|
};
|
|
|
|
/***************************************************************************
|
|
Free a linked list of auth methods
|
|
***************************************************************************/
|
|
|
|
static void free_auth_methods_list(auth_methods **list)
|
|
{
|
|
if (list != NULL) {
|
|
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);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!make_auth_info_list(auth_info, list)) {
|
|
free_auth_methods_list(&list);
|
|
return False;
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (*auth_info != NULL) {
|
|
free_auth_methods_list(&(*auth_info)->auth_method_list);
|
|
|
|
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;
|
|
TALLOC_CTX *mem_ctx;
|
|
|
|
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 {
|
|
mem_ctx = talloc_init_named("auth_get_challange for module %s", auth_method->name);
|
|
if (!mem_ctx) {
|
|
smb_panic("talloc_init_named() failed!");
|
|
}
|
|
|
|
challenge = auth_method->get_chal(&auth_method->private_data, mem_ctx, 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));
|
|
}
|
|
talloc_destroy(mem_ctx);
|
|
}
|
|
} 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);
|
|
}
|
|
|
|
|