From 1c798aba40fb0e389c7a54ad3d8f7d45876f2809 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 3 Feb 2004 11:10:56 +0000 Subject: - port AUTH and PASSDB subsystems to new SMB_SUBSYSTEM() scheme - some const fixes in ntvfs metze (This used to be commit af89a78123068767b1d134969c5651a0fd978b0d) --- source4/auth/auth.c | 174 +++++++++++++++++++++++++++++++------------ source4/auth/auth.h | 175 ++++++++++++++++++++++++++++++++++++++++++++ source4/auth/auth_builtin.c | 76 ++++++++----------- source4/auth/auth_sam.c | 41 ++++++++++- source4/auth/auth_unix.c | 18 ++++- source4/auth/config.m4 | 9 +++ 6 files changed, 397 insertions(+), 96 deletions(-) create mode 100644 source4/auth/auth.h create mode 100644 source4/auth/config.m4 (limited to 'source4/auth') diff --git a/source4/auth/auth.c b/source4/auth/auth.c index 2dc14248f9..a41cf72b1f 100644 --- a/source4/auth/auth.c +++ b/source4/auth/auth.c @@ -23,28 +23,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH -/** List of various built-in authentication modules */ - -static const struct auth_init_function_entry builtin_auth_init_functions[] = { - { "guest", auth_init_guest }, -/* { "rhosts", auth_init_rhosts }, */ -/* { "hostsequiv", auth_init_hostsequiv }, */ - { "sam", auth_init_sam }, - { "samstrict", auth_init_samstrict }, - { "samstrict_dc", auth_init_samstrict_dc }, - { "unix", auth_init_unix }, -/* { "smbserver", auth_init_smbserver }, */ -/* { "ntdomain", auth_init_ntdomain }, */ -/* { "trustdomain", auth_init_trustdomain }, */ -/* { "winbind", auth_init_winbind }, */ -#ifdef DEVELOPER - { "name_to_ntstatus", auth_init_name_to_ntstatus }, - { "fixed_challenge", auth_init_fixed_challenge }, -#endif - { "plugin", auth_init_plugin }, - { NULL, NULL} -}; - /**************************************************************************** Try to get a challenge out of the various authentication modules. Returns a const char of length 8 bytes. @@ -335,37 +313,40 @@ static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context, if (!NT_STATUS_IS_OK(nt_status = make_auth_context(auth_context))) return nt_status; - for (;*text_list; text_list++) { + 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)); - for (i = 0; builtin_auth_init_functions[i].name; i++) { - char *module_name = smb_xstrdup(*text_list); - char *module_params = NULL; - char *p; - - p = strchr(module_name, ':'); - if (p) { - *p = 0; - module_params = p+1; - trim_string(module_params, " ", " "); - } - trim_string(module_name, " ", " "); - - if (strequal(builtin_auth_init_functions[i].name, module_name)) { - DEBUG(5,("make_auth_context_text_list: Found auth method %s (at pos %d)\n", *text_list, i)); - if (NT_STATUS_IS_OK(builtin_auth_init_functions[i].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, auth_methods *); - } else { - DEBUG(0,("make_auth_context_text_list: auth method %s did not correctly init\n", - *text_list)); - } - break; - } + 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 (at pos %d)\n", *text_list, i)); 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, 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; @@ -452,4 +433,101 @@ NTSTATUS make_auth_context_fixed(struct auth_context **auth_context, uchar chal[ return nt_status; } +/* the list of currently registered AUTH backends */ +static struct { + const struct auth_operations *ops; +} *backends = NULL; +static int num_backends; + +/* + register a AUTH backend. + + The 'name' can be later used by other backends to find the operations + structure for this backend. +*/ +static NTSTATUS auth_register(void *_ops) +{ + const struct auth_operations *ops = _ops; + struct auth_operations *new_ops; + + if (auth_backend_byname(ops->name) != NULL) { + /* its already registered! */ + DEBUG(0,("AUTH backend '%s' already registered\n", + ops->name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + backends = Realloc(backends, sizeof(backends[0]) * (num_backends+1)); + if (!backends) { + smb_panic("out of memory in auth_register"); + } + + new_ops = smb_xmemdup(ops, sizeof(*ops)); + new_ops->name = smb_xstrdup(ops->name); + + backends[num_backends].ops = new_ops; + + num_backends++; + + DEBUG(3,("AUTH backend '%s' registered\n", + ops->name)); + + return NT_STATUS_OK; +} + +/* + return the operations structure for a named backend of the specified type +*/ +const struct auth_operations *auth_backend_byname(const char *name) +{ + int i; + + for (i=0;iname, name) == 0) { + return backends[i].ops; + } + } + + return NULL; +} + +/* + return the AUTH interface version, and the size of some critical types + This can be used by backends to either detect compilation errors, or provide + multiple implementations for different smbd compilation options in one module +*/ +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_context), + sizeof(struct auth_ntlmssp_state), + sizeof(struct auth_usersupplied_info), + sizeof(struct auth_serversupplied_info), + sizeof(struct auth_str), + sizeof(struct auth_unistr) + }; + + return &critical_sizes; +} + +/* + initialise the AUTH subsystem +*/ +BOOL auth_init(void) +{ + NTSTATUS status; + + status = register_subsystem("auth", auth_register); + if (!NT_STATUS_IS_OK(status)) { + return False; + } + + /* FIXME: Perhaps panic if a basic backend, such as SAM, fails to initialise? */ + static_init_auth; + DEBUG(3,("AUTH subsystem version %d initialised\n", AUTH_INTERFACE_VERSION)); + return True; +} diff --git a/source4/auth/auth.h b/source4/auth/auth.h new file mode 100644 index 0000000000..dc12d8196f --- /dev/null +++ b/source4/auth/auth.h @@ -0,0 +1,175 @@ +/* + Unix SMB/CIFS implementation. + Standardised Authentication types + 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. +*/ + +#ifndef _SAMBA_AUTH_H +#define _SAMBA_AUTH_H + +/* modules can use the following to determine if the interface has changed + * please increment the version number after each interface change + * with a comment and maybe update struct auth_critical_sizes. + */ +/* version 1 - version from samba 3.0 - metze */ +/* version 2 - initial samba4 version - metze */ +#define AUTH_INTERFACE_VERSION 2 + +/* AUTH_STR - string */ +typedef struct auth_str +{ + int len; + char *str; +} AUTH_STR; + +/* AUTH_UNISTR - unicode string or buffer */ +typedef struct auth_unistr +{ + int len; + uchar *unistr; +} AUTH_UNISTR; + +#define AUTH_FLAG_NONE 0x000000 +#define AUTH_FLAG_PLAINTEXT 0x000001 +#define AUTH_FLAG_LM_RESP 0x000002 +#define AUTH_FLAG_NTLM_RESP 0x000004 +#define AUTH_FLAG_NTLMv2_RESP 0x000008 + +typedef struct auth_usersupplied_info +{ + DATA_BLOB lm_resp; + DATA_BLOB nt_resp; + DATA_BLOB plaintext_password; + + BOOL encrypted; + + uint32 auth_flags; + + AUTH_STR client_domain; /* domain name string */ + AUTH_STR domain; /* domain name after mapping */ + AUTH_STR internal_username; /* username after mapping */ + AUTH_STR smb_name; /* username before mapping */ + AUTH_STR wksta_name; /* workstation name (netbios calling name) unicode string */ +} auth_usersupplied_info; + +#define SAM_FILL_NAME 0x01 +#define SAM_FILL_INFO3 0x02 +#define SAM_FILL_SAM 0x04 +#define SAM_FILL_UNIX 0x08 +#define SAM_FILL_ALL (SAM_FILL_NAME | SAM_FILL_INFO3 | SAM_FILL_SAM | SAM_FILL_UNIX) + +typedef struct auth_serversupplied_info +{ + BOOL guest; + + /* This groups info is needed for when we become_user() for this uid */ + int n_groups; + gid_t *groups; + + /* NT group information taken from the info3 structure */ + + NT_USER_TOKEN *ptok; + + uint8 session_key[16]; + uint8 first_8_lm_hash[8]; + DATA_BLOB nt_session_key; + DATA_BLOB lm_session_key; + + uint32 sam_fill_level; /* How far is this structure filled? */ + + SAM_ACCOUNT *sam_account; + + void *pam_handle; +} auth_serversupplied_info; + +struct auth_context { + DATA_BLOB challenge; + + /* Who set this up in the first place? */ + const char *challenge_set_by; + + BOOL challenge_may_be_modified; + + struct auth_methods *challenge_set_method; + /* What order are the various methods in? Try to stop it changing under us */ + struct auth_methods *auth_method_list; + + TALLOC_CTX *mem_ctx; + const uint8 *(*get_ntlm_challenge)(struct auth_context *auth_context); + NTSTATUS (*check_ntlm_password)(const struct auth_context *auth_context, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info); + NTSTATUS (*nt_status_squash)(NTSTATUS nt_status); + void (*free)(struct auth_context **auth_context); +}; + +typedef struct auth_methods +{ + struct auth_methods *prev, *next; + const char *name; /* What name got this module */ + + NTSTATUS (*auth)(const struct auth_context *auth_context, + void *my_private_data, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info); + + DATA_BLOB (*get_chal)(const struct auth_context *auth_context, + void **my_private_data, + TALLOC_CTX *mem_ctx); + + /* Used to keep tabs on things like the cli for SMB server authentication */ + void *private_data; + + /* Function to clean up the above arbitary structure */ + void (*free_private_data)(void **private_data); + + /* Function to send a keepalive message on the above structure */ + void (*send_keepalive)(void **private_data); +} auth_methods; + +typedef struct auth_ntlmssp_state +{ + TALLOC_CTX *mem_ctx; + struct auth_context *auth_context; + struct auth_serversupplied_info *server_info; + struct ntlmssp_state *ntlmssp_state; +} AUTH_NTLMSSP_STATE; + +#define auth_ops __XXX_ERROR_BLA +struct auth_operations { + /* the name of the backend */ + const char *name; + + /* Function to create a member of the authmethods list */ + NTSTATUS (*init)(struct auth_context *, const char *, struct auth_methods **); +}; + +/* this structure is used by backends to determine the size of some critical types */ +struct auth_critical_sizes { + int interface_version; + int sizeof_auth_operations; + int sizeof_auth_methods; + int sizeof_auth_context; + int sizeof_auth_ntlmssp_state; + int sizeof_auth_usersupplied_info; + int sizeof_auth_serversupplied_info; + int sizeof_auth_str; + int sizeof_auth_unistr; +}; + +#endif /* _SAMBA_AUTH_H */ diff --git a/source4/auth/auth_builtin.c b/source4/auth/auth_builtin.c index 61270fca10..d82a1ab56b 100644 --- a/source4/auth/auth_builtin.c +++ b/source4/auth/auth_builtin.c @@ -50,7 +50,7 @@ static NTSTATUS check_guest_security(const struct auth_context *auth_context, /* Guest modules initialisation */ -NTSTATUS auth_init_guest(struct auth_context *auth_context, const char *options, auth_methods **auth_method) +static NTSTATUS auth_init_guest(struct auth_context *auth_context, const char *options, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) return NT_STATUS_NO_MEMORY; @@ -101,7 +101,7 @@ static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_ /** Module initailisation function */ -NTSTATUS auth_init_name_to_ntstatus(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_name_to_ntstatus(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) return NT_STATUS_NO_MEMORY; @@ -150,7 +150,7 @@ static DATA_BLOB auth_get_fixed_challenge(const struct auth_context *auth_contex /** Module initailisation function */ -NTSTATUS auth_init_fixed_challenge(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_fixed_challenge(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) return NT_STATUS_NO_MEMORY; @@ -161,50 +161,38 @@ NTSTATUS auth_init_fixed_challenge(struct auth_context *auth_context, const char return NT_STATUS_OK; } -/** - * Outsorce an auth module to an external loadable .so - * - * Only works on systems with dlopen() etc. - **/ - -/* Plugin modules initialisation */ - -NTSTATUS auth_init_plugin(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +NTSTATUS auth_builtin_init(void) { - void * dl_handle; - char *plugin_param, *plugin_name, *p; - auth_init_function plugin_init; - - if (param == NULL) { - DEBUG(0, ("auth_init_plugin: The plugin module needs an argument!\n")); - return NT_STATUS_UNSUCCESSFUL; + NTSTATUS ret; + struct auth_operations ops; + + ops.name = "guest"; + ops.init = auth_init_guest; + ret = register_backend("auth", &ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' auth backend!\n", + ops.name)); + return ret; } - plugin_name = smb_xstrdup(param); - p = strchr(plugin_name, ':'); - if (p) { - *p = 0; - plugin_param = p+1; - trim_string(plugin_param, " ", " "); - } else plugin_param = NULL; - - trim_string(plugin_name, " ", " "); - - DEBUG(5, ("auth_init_plugin: Trying to load auth plugin %s\n", plugin_name)); - dl_handle = sys_dlopen(plugin_name, RTLD_NOW ); - if (!dl_handle) { - DEBUG(0, ("auth_init_plugin: Failed to load auth plugin %s using sys_dlopen (%s)\n", - plugin_name, sys_dlerror())); - return NT_STATUS_UNSUCCESSFUL; - } - - plugin_init = (auth_init_function)sys_dlsym(dl_handle, "auth_init"); - if (!plugin_init){ - DEBUG(0, ("Failed to find function 'auth_init' using sys_dlsym in sam plugin %s (%s)\n", - plugin_name, sys_dlerror())); - return NT_STATUS_UNSUCCESSFUL; +#ifdef DEVELOPER + ops.name = "name_to_ntstatus"; + ops.init = auth_init_name_to_ntstatus; + ret = register_backend("auth", &ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' auth backend!\n", + ops.name)); + return ret; } - DEBUG(5, ("Starting sam plugin %s with paramater %s\n", plugin_name, plugin_param?plugin_param:"(null)")); - return plugin_init(auth_context, plugin_param, auth_method); + ops.name = "fixed_challenge"; + ops.init = auth_init_fixed_challenge; + ret = register_backend("auth", &ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' auth backend!\n", + ops.name)); + return ret; + } +#endif /* DEVELOPER */ + return ret; } diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c index 51462555f9..f25a5e4691 100644 --- a/source4/auth/auth_sam.c +++ b/source4/auth/auth_sam.c @@ -468,7 +468,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, } /* module initialisation */ -NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; @@ -509,7 +509,7 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context } /* module initialisation */ -NTSTATUS auth_init_samstrict(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_samstrict(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; @@ -552,7 +552,7 @@ static NTSTATUS check_samstrict_dc_security(const struct auth_context *auth_cont } /* module initialisation */ -NTSTATUS auth_init_samstrict_dc(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_samstrict_dc(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; @@ -562,3 +562,38 @@ NTSTATUS auth_init_samstrict_dc(struct auth_context *auth_context, const char *p (*auth_method)->name = "samstrict_dc"; return NT_STATUS_OK; } + +NTSTATUS auth_sam_init(void) +{ + NTSTATUS ret; + struct auth_operations ops; + + ops.name = "sam"; + ops.init = auth_init_sam; + ret = register_backend("auth", &ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' auth backend!\n", + ops.name)); + return ret; + } + + ops.name = "samstrict"; + ops.init = auth_init_samstrict; + ret = register_backend("auth", &ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' auth backend!\n", + ops.name)); + return ret; + } + + ops.name = "samstrict_dc"; + ops.init = auth_init_samstrict_dc; + ret = register_backend("auth", &ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' auth backend!\n", + ops.name)); + return ret; + } + + return ret; +} diff --git a/source4/auth/auth_unix.c b/source4/auth/auth_unix.c index 4f44767a81..b7c3475e55 100644 --- a/source4/auth/auth_unix.c +++ b/source4/auth/auth_unix.c @@ -119,7 +119,7 @@ static NTSTATUS check_unix_security(const struct auth_context *auth_context, } /* module initialisation */ -NTSTATUS auth_init_unix(struct auth_context *auth_context, const char* param, auth_methods **auth_method) +static NTSTATUS auth_init_unix(struct auth_context *auth_context, const char* param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; @@ -130,3 +130,19 @@ NTSTATUS auth_init_unix(struct auth_context *auth_context, const char* param, au return NT_STATUS_OK; } +NTSTATUS auth_unix_init(void) +{ + NTSTATUS ret; + struct auth_operations ops; + + ops.name = "unix"; + ops.init = auth_init_unix; + ret = register_backend("auth", &ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' auth backend!\n", + ops.name)); + return ret; + } + + return ret; +} diff --git a/source4/auth/config.m4 b/source4/auth/config.m4 new file mode 100644 index 0000000000..cb547301f5 --- /dev/null +++ b/source4/auth/config.m4 @@ -0,0 +1,9 @@ +dnl # AUTH Server subsystem + +SMB_MODULE(auth_sam,AUTH,STATIC,[auth/auth_sam.o]) +SMB_MODULE(auth_builtin,AUTH,STATIC,[auth/auth_builtin.o]) +SMB_MODULE(auth_unix,AUTH,STATIC,[auth/auth_unix.o]) + +SMB_SUBSYSTEM(AUTH,auth/auth.o, + [auth/auth_ntlmssp.o auth/auth_util.o auth/pampass.o auth/pass_check.o auth/auth_compat.o], + auth/auth_public_proto.h) -- cgit