diff options
Diffstat (limited to 'source3/auth/auth_sam.c')
-rw-r--r-- | source3/auth/auth_sam.c | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c new file mode 100644 index 0000000..a2ce101 --- /dev/null +++ b/source3/auth/auth_sam.c @@ -0,0 +1,315 @@ +/* + Unix SMB/CIFS implementation. + Password and authentication handling + Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000 + Copyright (C) Andrew Bartlett 2001-2003 + Copyright (C) Gerald Carter 2003 + + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "auth.h" +#include "passdb.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_AUTH + +static NTSTATUS auth_sam_ignoredomain_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) +{ + if (!user_info || !auth_context) { + return NT_STATUS_UNSUCCESSFUL; + } + + if (user_info->mapped.account_name == NULL || + user_info->mapped.account_name[0] == '\0') + { + return NT_STATUS_NOT_IMPLEMENTED; + } + + DBG_DEBUG("Check auth for: [%s]\\[%s]\n", + user_info->mapped.domain_name, + user_info->mapped.account_name); + + return check_sam_security(&auth_context->challenge, mem_ctx, + user_info, server_info); +} + +/* module initialisation */ +static NTSTATUS auth_init_sam_ignoredomain( + struct auth_context *auth_context, + const char *param, + struct auth_methods **auth_method) +{ + struct auth_methods *result; + + result = talloc_zero(auth_context, struct auth_methods); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } + result->auth = auth_sam_ignoredomain_auth; + result->name = "sam_ignoredomain"; + + *auth_method = result; + return NT_STATUS_OK; +} + + +/**************************************************************************** +Check SAM security (above) but with a few extra checks. +****************************************************************************/ + +static NTSTATUS auth_samstrict_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) +{ + const char *effective_domain = NULL; + bool is_local_name, is_my_domain; + + if (!user_info || !auth_context) { + return NT_STATUS_LOGON_FAILURE; + } + effective_domain = user_info->mapped.domain_name; + + if (user_info->mapped.account_name == NULL || + user_info->mapped.account_name[0] == '\0') + { + return NT_STATUS_NOT_IMPLEMENTED; + } + + if (lp_server_role() == ROLE_DOMAIN_MEMBER) { + const char *p = NULL; + + p = strchr_m(user_info->mapped.account_name, '@'); + if (p != NULL) { + /* + * This needs to go to the DC, + * even if @ is the last character + */ + return NT_STATUS_NOT_IMPLEMENTED; + } + } + + if (effective_domain == NULL) { + effective_domain = ""; + } + + DBG_DEBUG("Check auth for: [%s]\\[%s]\n", + effective_domain, + user_info->mapped.account_name); + + + if (strequal(effective_domain, "") || strequal(effective_domain, ".")) { + /* + * An empty domain name or '.' should be handled + * as the local SAM name. + */ + effective_domain = lp_netbios_name(); + } + + is_local_name = is_myname(effective_domain); + is_my_domain = strequal(effective_domain, lp_workgroup()); + + /* check whether or not we service this domain/workgroup name */ + + switch ( lp_server_role() ) { + case ROLE_STANDALONE: + case ROLE_DOMAIN_MEMBER: + if ( !is_local_name ) { + DEBUG(6,("check_samstrict_security: %s is not one of my local names (%s)\n", + effective_domain, (lp_server_role() == ROLE_DOMAIN_MEMBER + ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") )); + return NT_STATUS_NOT_IMPLEMENTED; + } + + break; + case ROLE_DOMAIN_PDC: + case ROLE_DOMAIN_BDC: + case ROLE_IPA_DC: + if (!is_local_name && !is_my_domain) { + /* If we are running on a DC that has PASSDB module with domain + * information, check if DNS forest name is matching the domain + * name. This is the case of IPA domain controller when + * trusted AD DCs attempt to authenticate IPA users using + * the forest root domain (which is the only domain in IPA). + */ + struct pdb_domain_info *dom_info = NULL; + + dom_info = pdb_get_domain_info(mem_ctx); + if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) { + is_my_domain = strequal(user_info->mapped.domain_name, + dom_info->dns_forest); + } + + TALLOC_FREE(dom_info); + if (!is_my_domain) { + DEBUG(6,("check_samstrict_security: %s is not one " + "of my local names or domain name (DC)\n", + effective_domain)); + return NT_STATUS_NOT_IMPLEMENTED; + } + } + + break; + default: /* name is ok */ + break; + } + + return check_sam_security(&auth_context->challenge, mem_ctx, + user_info, server_info); +} + +/* module initialisation */ +static NTSTATUS auth_init_sam( + struct auth_context *auth_context, + const char *param, + struct auth_methods **auth_method) +{ + struct auth_methods *result; + + if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC + && !lp_parm_bool(-1, "server role check", "inhibit", false)) { + DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the auth_sam module. \n")); + DEBUGADD(0, ("You should not set 'auth methods' when running the AD DC.\n")); + exit(1); + } + + result = talloc_zero(auth_context, struct auth_methods); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } + result->auth = auth_samstrict_auth; + result->name = "sam"; + *auth_method = result; + return NT_STATUS_OK; +} + +static NTSTATUS auth_sam_netlogon3_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) +{ + const char *effective_domain = NULL; + bool is_my_domain; + + if (!user_info || !auth_context) { + return NT_STATUS_LOGON_FAILURE; + } + effective_domain = user_info->mapped.domain_name; + + if (user_info->mapped.account_name == NULL || + user_info->mapped.account_name[0] == '\0') + { + return NT_STATUS_NOT_IMPLEMENTED; + } + + if (effective_domain == NULL) { + effective_domain = ""; + } + + DBG_DEBUG("Check auth for: [%s]\\[%s]\n", + effective_domain, + user_info->mapped.account_name); + + /* check whether or not we service this domain/workgroup name */ + + switch (lp_server_role()) { + case ROLE_DOMAIN_PDC: + case ROLE_DOMAIN_BDC: + case ROLE_IPA_DC: + break; + default: + DBG_ERR("Invalid server role\n"); + return NT_STATUS_INVALID_SERVER_STATE; + } + + if (strequal(effective_domain, "") || strequal(effective_domain, ".")) { + /* + * An empty domain name or '.' should be handled + * as the local SAM name. + */ + effective_domain = lp_workgroup(); + } + + is_my_domain = strequal(user_info->mapped.domain_name, lp_workgroup()); + if (!is_my_domain) { + /* If we are running on a DC that has PASSDB module with domain + * information, check if DNS forest name is matching the domain + * name. This is the case of IPA domain controller when + * trusted AD DCs attempt to authenticate IPA users using + * the forest root domain (which is the only domain in IPA). + */ + struct pdb_domain_info *dom_info = NULL; + dom_info = pdb_get_domain_info(mem_ctx); + + if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) { + is_my_domain = strequal(user_info->mapped.domain_name, + dom_info->dns_forest); + } + + TALLOC_FREE(dom_info); + } + + if (!is_my_domain) { + DBG_INFO("%s is not our domain name (DC for %s)\n", + effective_domain, lp_workgroup()); + return NT_STATUS_NOT_IMPLEMENTED; + } + + return check_sam_security(&auth_context->challenge, mem_ctx, + user_info, server_info); +} + +/* module initialisation */ +static NTSTATUS auth_init_sam_netlogon3( + struct auth_context *auth_context, + const char *param, + struct auth_methods **auth_method) +{ + struct auth_methods *result; + + if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC + && !lp_parm_bool(-1, "server role check", "inhibit", false)) { + DEBUG(0, ("server role = 'active directory domain controller' " + "not compatible with running the auth_sam module.\n")); + DEBUGADD(0, ("You should not set 'auth methods' when " + "running the AD DC.\n")); + exit(1); + } + + result = talloc_zero(auth_context, struct auth_methods); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } + result->auth = auth_sam_netlogon3_auth; + result->name = "sam_netlogon3"; + *auth_method = result; + return NT_STATUS_OK; +} + +NTSTATUS auth_sam_init(TALLOC_CTX *mem_ctx) +{ + smb_register_auth(AUTH_INTERFACE_VERSION, "sam", auth_init_sam); + smb_register_auth(AUTH_INTERFACE_VERSION, "sam_ignoredomain", auth_init_sam_ignoredomain); + smb_register_auth(AUTH_INTERFACE_VERSION, "sam_netlogon3", auth_init_sam_netlogon3); + return NT_STATUS_OK; +} |