From 9f084101dd392ceb85f141f55ee56bed344626ef Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 2 May 2004 08:45:00 +0000 Subject: r443: Update Samba4 to the auth and NTLMSSP code from Samba3. Not all the auth code is merged - only those parts that are actually being used in Samba4. There is a lot more work to do in the NTLMSSP area, and I hope to develop that work here. There is a start on this here - splitting NTLMSSP into two parts that my operate in an async fashion (before and after the actual authentication) Andrew Bartlett (This used to be commit 5876c78806e6a6c44613a1354e8d564b427d0c9f) --- source4/auth/auth.c | 77 +++++---- source4/auth/auth.h | 44 ++--- source4/auth/auth_builtin.c | 19 ++- source4/auth/auth_compat.c | 17 +- source4/auth/auth_ntlmssp.c | 47 ++--- source4/auth/auth_sam.c | 406 +++++++------------------------------------- source4/auth/auth_util.c | 238 ++++++++++++-------------- 7 files changed, 268 insertions(+), 580 deletions(-) (limited to 'source4/auth') diff --git a/source4/auth/auth.c b/source4/auth/auth.c index a41cf72b1f..714bb37c6d 100644 --- a/source4/auth/auth.c +++ b/source4/auth/auth.c @@ -41,6 +41,8 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context) return auth_context->challenge.data; } + auth_context->challenge_may_be_modified = False; + 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)); @@ -80,11 +82,12 @@ static const uint8 *get_ntlm_challenge(struct auth_context *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, (const char*)auth_context->challenge.data, auth_context->challenge.length); + dump_data(5, (const char *)auth_context->challenge.data, auth_context->challenge.length); SMB_ASSERT(auth_context->challenge.length == 8); @@ -156,9 +159,8 @@ static 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 = NT_STATUS_LOGON_FAILURE; - const char *pdb_username; + /* if all the modules say 'not for me' this is reasonable */ + NTSTATUS nt_status = NT_STATUS_NO_SUCH_USER; auth_methods *auth_method; TALLOC_CTX *mem_ctx; @@ -181,7 +183,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, auth_context->challenge_set_by)); DEBUG(10, ("challenge is: \n")); - dump_data(5, (const char*)auth_context->challenge.data, auth_context->challenge.length); + dump_data(5, (const char *)auth_context->challenge.data, auth_context->challenge.length); #ifdef DEBUG_PASSWORD DEBUG(100, ("user_info has passwords of length %d and %d\n", @@ -197,12 +199,24 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, return NT_STATUS_LOGON_FAILURE; for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_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); - nt_status = auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); + result = auth_method->auth(auth_context, auth_method->private_data, 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] suceeded\n", + DEBUG(3, ("check_ntlm_password: %s authentication for user [%s] succeeded\n", auth_method->name, user_info->smb_name.str)); } else { DEBUG(5, ("check_ntlm_password: %s authentication for user [%s] FAILED with error %s\n", @@ -211,8 +225,10 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, talloc_destroy(mem_ctx); - if (NT_STATUS_IS_OK(nt_status)) - break; + if ( NT_STATUS_IS_OK(nt_status)) + { + break; + } } /* This is one of the few places the *relies* (rather than just sets defaults @@ -222,29 +238,12 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, smb_user_control(user_info, *server_info, nt_status); if (NT_STATUS_IS_OK(nt_status)) { - pdb_username = pdb_get_username((*server_info)->sam_account); - if (!(*server_info)->guest) { - /* We might not be root if we are an RPC call */ - become_root(); - nt_status = smb_pam_accountcheck(pdb_username); - unbecome_root(); - - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_ntlm_password: PAM Account for user [%s] suceeded\n", - pdb_username)); - } else { - DEBUG(3, ("check_ntlm_password: PAM Account for user [%s] FAILED with error %s\n", - pdb_username, nt_errstr(nt_status))); - } - } - if (NT_STATUS_IS_OK(nt_status)) { DEBUG((*server_info)->guest ? 5 : 2, - ("check_ntlm_password: %sauthentication for user [%s] -> [%s] -> [%s] suceeded\n", + ("check_ntlm_password: %sauthentication for user [%s] -> [%s] succeeded\n", (*server_info)->guest ? "guest " : "", user_info->smb_name.str, - user_info->internal_username.str, - pdb_username)); + user_info->internal_username.str)); } } @@ -263,9 +262,20 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, static void free_auth_context(struct auth_context **auth_context) { - if (*auth_context != NULL) + 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_destroy((*auth_context)->mem_ctx); - *auth_context = NULL; + *auth_context = NULL; + } } /*************************************************************************** @@ -372,7 +382,7 @@ NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context) { case SEC_DOMAIN: DEBUG(5,("Making default auth method list for security=domain\n")); - auth_method_list = str_list_make("guest sam winbind ntdomain", NULL); + auth_method_list = str_list_make("guest sam winbind:ntdomain", NULL); break; case SEC_SERVER: DEBUG(5,("Making default auth method list for security=server\n")); @@ -398,7 +408,7 @@ NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context) break; case SEC_ADS: DEBUG(5,("Making default auth method list for security=ADS\n")); - auth_method_list = str_list_make("guest sam ads winbind ntdomain", NULL); + auth_method_list = str_list_make("guest sam winbind:ntdomain", NULL); break; default: DEBUG(5,("Unknown auth method!\n")); @@ -428,7 +438,7 @@ NTSTATUS make_auth_context_fixed(struct auth_context **auth_context, uchar chal[ return nt_status; } - (*auth_context)->challenge = data_blob(chal, 8); + (*auth_context)->challenge = data_blob_talloc((*auth_context)->mem_ctx, chal, 8); (*auth_context)->challenge_set_by = "fixed"; return nt_status; } @@ -507,7 +517,6 @@ const struct auth_critical_sizes *auth_interface_version(void) sizeof(struct auth_usersupplied_info), sizeof(struct auth_serversupplied_info), sizeof(struct auth_str), - sizeof(struct auth_unistr) }; return &critical_sizes; diff --git a/source4/auth/auth.h b/source4/auth/auth.h index dc12d8196f..22738ffc2c 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -27,7 +27,8 @@ */ /* version 1 - version from samba 3.0 - metze */ /* version 2 - initial samba4 version - metze */ -#define AUTH_INTERFACE_VERSION 2 +/* version 3 - subsequent samba4 version - abartlet */ +#define AUTH_INTERFACE_VERSION 3 /* AUTH_STR - string */ typedef struct auth_str @@ -36,34 +37,23 @@ typedef struct auth_str 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 lm_interactive_pwd; + DATA_BLOB nt_interactive_pwd; 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 @@ -84,11 +74,9 @@ typedef struct auth_serversupplied_info NT_USER_TOKEN *ptok; - uint8 session_key[16]; - uint8 first_8_lm_hash[8]; - DATA_BLOB nt_session_key; + DATA_BLOB user_session_key; DATA_BLOB lm_session_key; - + uint32 sam_fill_level; /* How far is this structure filled? */ SAM_ACCOUNT *sam_account; @@ -126,7 +114,7 @@ typedef struct auth_methods void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info); + auth_serversupplied_info **server_info); DATA_BLOB (*get_chal)(const struct auth_context *auth_context, void **my_private_data, @@ -140,8 +128,20 @@ typedef struct auth_methods /* Function to send a keepalive message on the above structure */ void (*send_keepalive)(void **private_data); + } auth_methods; +typedef NTSTATUS (*auth_init_function)(struct auth_context *, const char *, struct auth_methods **); + +struct auth_init_function_entry { + const char *name; + /* Function to create a member of the authmethods list */ + + auth_init_function init; + + struct auth_init_function_entry *prev, *next; +}; + typedef struct auth_ntlmssp_state { TALLOC_CTX *mem_ctx; @@ -172,4 +172,4 @@ struct auth_critical_sizes { int sizeof_auth_unistr; }; -#endif /* _SAMBA_AUTH_H */ +#endif /* _SMBAUTH_H_ */ diff --git a/source4/auth/auth_builtin.c b/source4/auth/auth_builtin.c index d82a1ab56b..b5f5a101f4 100644 --- a/source4/auth/auth_builtin.c +++ b/source4/auth/auth_builtin.c @@ -1,6 +1,6 @@ /* Unix SMB/CIFS implementation. - Generic authenticaion types + Generic authentication types Copyright (C) Andrew Bartlett 2001-2002 Copyright (C) Jelmer Vernooij 2002 @@ -38,7 +38,8 @@ static NTSTATUS check_guest_security(const struct auth_context *auth_context, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + /* mark this as 'not for me' */ + NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; if (!(user_info->internal_username.str && *user_info->internal_username.str)) { @@ -60,6 +61,7 @@ static NTSTATUS auth_init_guest(struct auth_context *auth_context, const char *o return NT_STATUS_OK; } +#ifdef DEVELOPER /** * Return an error based on username * @@ -84,12 +86,12 @@ static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_ long error_num; fstrcpy(user, user_info->smb_name.str); - if (strncasecmp("NT_STATUS", user, strlen("NT_STATUS")) == 0) { - strupper(user); + if (strnequal("NT_STATUS", user, strlen("NT_STATUS"))) { + strupper_m(user); return nt_status_string_to_code(user); } - strlower(user); + strlower_m(user); error_num = strtoul(user, NULL, 16); DEBUG(5,("check_name_to_ntstatus_security: Error for user %s was %lx\n", user, error_num)); @@ -99,7 +101,7 @@ static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_ return nt_status; } -/** Module initailisation function */ +/** Module initialisation function */ static NTSTATUS auth_init_name_to_ntstatus(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { @@ -112,7 +114,7 @@ static NTSTATUS auth_init_name_to_ntstatus(struct auth_context *auth_context, co } /** - * Return a 'fixed' challenge instead of a varaible one. + * Return a 'fixed' challenge instead of a variable one. * * The idea of this function is to make packet snifs consistant * with a fixed challenge, so as to aid debugging. @@ -132,7 +134,7 @@ static NTSTATUS check_fixed_challenge_security(const struct auth_context *auth_c const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_NOT_IMPLEMENTED; } /**************************************************************************** @@ -160,6 +162,7 @@ static NTSTATUS auth_init_fixed_challenge(struct auth_context *auth_context, con (*auth_method)->name = "fixed_challenge"; return NT_STATUS_OK; } +#endif /* DEVELOPER */ NTSTATUS auth_builtin_init(void) { diff --git a/source4/auth/auth_compat.c b/source4/auth/auth_compat.c index 49cd2e8468..d8c1ad78f0 100644 --- a/source4/auth/auth_compat.c +++ b/source4/auth/auth_compat.c @@ -95,7 +95,6 @@ BOOL password_ok(struct server_context *smb, const char *smb_name, DATA_BLOB pas DATA_BLOB null_password = data_blob(NULL, 0); BOOL encrypted = (smb->negotiate.encrypted_passwords && password_blob.length == 24); - NTSTATUS status; if (encrypted) { /* @@ -103,20 +102,20 @@ BOOL password_ok(struct server_context *smb, const char *smb_name, DATA_BLOB pas * but fall-through as required. * NTLMv2 makes no sense here. */ - status = pass_check_smb(smb, smb_name, lp_workgroup(), null_password, - password_blob, null_password, encrypted); - if (NT_STATUS_IS_OK(status)) { + if (NT_STATUS_IS_OK(pass_check_smb(smb, smb_name, lp_workgroup(), null_password, password_blob, null_password, encrypted))) { return True; } - status = pass_check_smb(smb, smb_name, lp_workgroup(), password_blob, - null_password, null_password, encrypted); + if (NT_STATUS_IS_OK(pass_check_smb(smb, smb_name, lp_workgroup(), password_blob, null_password, null_password, encrypted))) { + return True; + } } else { - status = pass_check_smb(smb, smb_name, lp_workgroup(), null_password, - null_password, password_blob, encrypted); + if (NT_STATUS_IS_OK(pass_check_smb(smb, smb_name, lp_workgroup(), null_password, null_password, password_blob, encrypted))) { + return True; + } } - return NT_STATUS_IS_OK(status); + return False; } diff --git a/source4/auth/auth_ntlmssp.c b/source4/auth/auth_ntlmssp.c index 940630b4c6..a4e0dd5588 100644 --- a/source4/auth/auth_ntlmssp.c +++ b/source4/auth/auth_ntlmssp.c @@ -75,42 +75,33 @@ static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, * Return the session keys used on the connection. */ -static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *nt_session_key, DATA_BLOB *lm_session_key) +static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) { AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context; - uint32 auth_flags = AUTH_FLAG_NONE; auth_usersupplied_info *user_info = NULL; - DATA_BLOB plaintext_password = data_blob(NULL, 0); NTSTATUS nt_status; - if (auth_ntlmssp_state->ntlmssp_state->lm_resp.length) { - auth_flags |= AUTH_FLAG_LM_RESP; - } - - if (auth_ntlmssp_state->ntlmssp_state->nt_resp.length == 24) { - auth_flags |= AUTH_FLAG_NTLM_RESP; - } else if (auth_ntlmssp_state->ntlmssp_state->nt_resp.length > 24) { - auth_flags |= AUTH_FLAG_NTLMv2_RESP; - } - #if 0 /* the client has given us its machine name (which we otherwise would not get on port 445). we need to possibly reload smb.conf if smb.conf includes depend on the machine name */ + set_remote_machine_name(auth_ntlmssp_state->ntlmssp_state->workstation, True); + /* setup the string used by %U */ /* sub_set_smb_name checks for weird internally */ sub_set_smb_name(auth_ntlmssp_state->ntlmssp_state->user); + reload_services(True); -#endif +#endif nt_status = make_user_info_map(&user_info, auth_ntlmssp_state->ntlmssp_state->user, auth_ntlmssp_state->ntlmssp_state->domain, auth_ntlmssp_state->ntlmssp_state->workstation, - auth_ntlmssp_state->ntlmssp_state->lm_resp, - auth_ntlmssp_state->ntlmssp_state->nt_resp, - plaintext_password, - auth_flags, True); + auth_ntlmssp_state->ntlmssp_state->lm_resp.data ? &auth_ntlmssp_state->ntlmssp_state->lm_resp : NULL, + auth_ntlmssp_state->ntlmssp_state->nt_resp.data ? &auth_ntlmssp_state->ntlmssp_state->nt_resp : NULL, + NULL, NULL, NULL, + True); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; @@ -124,19 +115,17 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } - if (auth_ntlmssp_state->server_info->nt_session_key.length) { - DEBUG(5, ("Got NT session key of length %u\n", auth_ntlmssp_state->server_info->nt_session_key.length)); - *nt_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx, - auth_ntlmssp_state->server_info->nt_session_key.data, - auth_ntlmssp_state->server_info->nt_session_key.length); - } else if (auth_ntlmssp_state->server_info->lm_session_key.length) { - DEBUG(5, ("Got LM session key of length %u\n", auth_ntlmssp_state->server_info->lm_session_key.length)); - *lm_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx, + if (auth_ntlmssp_state->server_info->user_session_key.length) { + DEBUG(10, ("Got NT session key of length %u\n", auth_ntlmssp_state->server_info->user_session_key.length)); + *user_session_key = data_blob_talloc(ntlmssp_state->mem_ctx, + auth_ntlmssp_state->server_info->user_session_key.data, + auth_ntlmssp_state->server_info->user_session_key.length); + } + if (auth_ntlmssp_state->server_info->lm_session_key.length) { + DEBUG(10, ("Got LM session key of length %u\n", auth_ntlmssp_state->server_info->lm_session_key.length)); + *lm_session_key = data_blob_talloc(ntlmssp_state->mem_ctx, auth_ntlmssp_state->server_info->lm_session_key.data, auth_ntlmssp_state->server_info->lm_session_key.length); - } else { - *nt_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx, - auth_ntlmssp_state->server_info->session_key, 16); } return nt_status; } diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c index 35635ea474..028fda74fe 100644 --- a/source4/auth/auth_sam.c +++ b/source4/auth/auth_sam.c @@ -3,7 +3,8 @@ Password and authentication handling Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Luke Kenneth Casson Leighton 1996-2000 - Copyright (C) Andrew Bartlett 2001 + 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 @@ -25,291 +26,51 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH -/**************************************************************************** -core of smb password checking routine. -****************************************************************************/ -static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response, - const uchar *part_passwd, - DATA_BLOB sec_blob, - uint8 user_sess_key[16]) -{ - /* Finish the encryption of part_passwd. */ - uchar p24[24]; - - if (part_passwd == NULL) { - DEBUG(10,("No password set - DISALLOWING access\n")); - /* No password set - always false ! */ - return False; - } - - if (sec_blob.length != 8) { - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challenge size (%d)\n", sec_blob.length)); - return False; - } - - if (nt_response.length != 24) { - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", nt_response.length)); - return False; - } - - SMBOWFencrypt(part_passwd, sec_blob.data, p24); - if (user_sess_key != NULL) - { - SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key); - } - - - -#if DEBUG_PASSWORD - DEBUG(100,("Part password (P16) was |")); - dump_data(100, part_passwd, 16); - DEBUG(100,("Password from client was |")); - dump_data(100, nt_response.data, nt_response.length); - DEBUG(100,("Given challenge was |")); - dump_data(100, sec_blob.data, sec_blob.length); - DEBUG(100,("Value from encryption was |")); - dump_data(100, p24, 24); -#endif - return (memcmp(p24, nt_response.data, 24) == 0); -} - - -/**************************************************************************** -core of smb password checking routine. (NTLMv2, LMv2) - -Note: The same code works with both NTLMv2 and LMv2. -****************************************************************************/ -static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, - const uchar *part_passwd, - const DATA_BLOB sec_blob, - const char *user, const char *domain, - uint8 user_sess_key[16]) -{ - /* Finish the encryption of part_passwd. */ - uchar kr[16]; - uchar value_from_encryption[16]; - uchar client_response[16]; - DATA_BLOB client_key_data; - - if (part_passwd == NULL) - { - DEBUG(10,("No password set - DISALLOWING access\n")); - /* No password set - always False */ - return False; - } - - if (ntv2_response.length < 16) { - /* We MUST have more than 16 bytes, or the stuff below will go - crazy... */ - DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%d)\n", - ntv2_response.length)); - return False; - } - - client_key_data = data_blob(ntv2_response.data+16, ntv2_response.length-16); - /* - todo: should we be checking this for anything? We can't for LMv2, - but for NTLMv2 it is meant to contain the current time etc. - */ - - memcpy(client_response, ntv2_response.data, sizeof(client_response)); - - if (!ntv2_owf_gen(part_passwd, user, domain, kr)) { - return False; - } - - SMBOWFencrypt_ntv2(kr, &sec_blob, &client_key_data, value_from_encryption); - if (user_sess_key != NULL) - { - SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key); - } - -#if DEBUG_PASSWORD - DEBUG(100,("Part password (P16) was |")); - dump_data(100, part_passwd, 16); - DEBUG(100,("Password from client was |")); - dump_data(100, ntv2_response.data, ntv2_response.length); - DEBUG(100,("Variable data from client was |")); - dump_data(100, client_key_data.data, client_key_data.length); - DEBUG(100,("Given challenge was |")); - dump_data(100, sec_blob.data, sec_blob.length); - DEBUG(100,("Value from encryption was |")); - dump_data(100, value_from_encryption, 16); -#endif - data_blob_clear_free(&client_key_data); - return (memcmp(value_from_encryption, client_response, 16) == 0); -} - - /**************************************************************************** Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ + static NTSTATUS sam_password_ok(const struct auth_context *auth_context, TALLOC_CTX *mem_ctx, SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, - uint8 user_sess_key[16]) + DATA_BLOB *user_sess_key, + DATA_BLOB *lm_sess_key) { uint16 acct_ctrl; - const uint8 *nt_pw, *lm_pw; - uint32 auth_flags; + const uint8 *lm_pw, *nt_pw; + const char *username = pdb_get_username(sampass); acct_ctrl = pdb_get_acct_ctrl(sampass); - if (acct_ctrl & ACB_PWNOTREQ) - { - if (lp_null_passwords()) - { - DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", pdb_get_username(sampass))); - return(NT_STATUS_OK); - } - else - { - DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", pdb_get_username(sampass))); - return(NT_STATUS_LOGON_FAILURE); - } - } - - auth_flags = user_info->auth_flags; - - if (IS_SAM_DEFAULT(sampass, PDB_NTPASSWD)) { - DEBUG(3,("sam_password_ok: NO NT password stored for user %s.\n", - pdb_get_username(sampass))); - /* No return, we want to check the LM hash below in this case */ - auth_flags &= (~(AUTH_FLAG_NTLMv2_RESP | AUTH_FLAG_NTLM_RESP)); - } - - if (auth_flags & AUTH_FLAG_NTLMv2_RESP) { - nt_pw = pdb_get_nt_passwd(sampass); - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("sam_password_ok: Checking NTLMv2 password with domain [%s]\n", user_info->client_domain.str)); - if (smb_pwd_check_ntlmv2( user_info->nt_resp, - nt_pw, auth_context->challenge, - user_info->smb_name.str, - user_info->client_domain.str, - user_sess_key)) - { - return NT_STATUS_OK; - } - - DEBUG(4,("sam_password_ok: Checking NTLMv2 password without a domain\n")); - if (smb_pwd_check_ntlmv2( user_info->nt_resp, - nt_pw, auth_context->challenge, - user_info->smb_name.str, - "", - user_sess_key)) - { + if (acct_ctrl & ACB_PWNOTREQ) { + if (lp_null_passwords()) { + DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", username)); return NT_STATUS_OK; } else { - DEBUG(3,("sam_password_ok: NTLMv2 password check failed\n")); - return NT_STATUS_WRONG_PASSWORD; - } - } else if (auth_flags & AUTH_FLAG_NTLM_RESP) { - if (lp_ntlm_auth()) { - nt_pw = pdb_get_nt_passwd(sampass); - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - DEBUG(4,("sam_password_ok: Checking NT MD4 password\n")); - if (smb_pwd_check_ntlmv1(user_info->nt_resp, - nt_pw, auth_context->challenge, - user_sess_key)) - { - return NT_STATUS_OK; - } else { - DEBUG(3,("sam_password_ok: NT MD4 password check failed for user %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; - } - } else { - DEBUG(2,("sam_password_ok: NTLMv1 passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); - /* no return, becouse we might pick up LMv2 in the LM feild */ - } + DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", username)); + return NT_STATUS_LOGON_FAILURE; + } } - - if (auth_flags & AUTH_FLAG_LM_RESP) { - if (user_info->lm_resp.length != 24) { - DEBUG(2,("sam_password_ok: invalid LanMan password length (%d) for user %s\n", - user_info->nt_resp.length, pdb_get_username(sampass))); - } - - if (!lp_lanman_auth()) { - DEBUG(3,("sam_password_ok: Lanman passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); - } else if (IS_SAM_DEFAULT(sampass, PDB_LMPASSWD)) { - DEBUG(3,("sam_password_ok: NO LanMan password set for user %s (and no NT password supplied)\n",pdb_get_username(sampass))); - } else { - lm_pw = pdb_get_lanman_passwd(sampass); - - DEBUG(4,("sam_password_ok: Checking LM password\n")); - if (smb_pwd_check_ntlmv1(user_info->lm_resp, - lm_pw, auth_context->challenge, - user_sess_key)) - { - return NT_STATUS_OK; - } - } - if (IS_SAM_DEFAULT(sampass, PDB_NTPASSWD)) { - DEBUG(4,("sam_password_ok: LM password check failed for user, no NT password %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; - } - - nt_pw = pdb_get_nt_passwd(sampass); - - /* This is for 'LMv2' authentication. almost NTLMv2 but limited to 24 bytes. - - related to Win9X, legacy NAS pass-though authentication - */ - DEBUG(4,("sam_password_ok: Checking LMv2 password with domain %s\n", user_info->client_domain.str)); - if (smb_pwd_check_ntlmv2( user_info->lm_resp, - nt_pw, auth_context->challenge, - user_info->smb_name.str, - user_info->client_domain.str, - user_sess_key)) - { - return NT_STATUS_OK; - } - - DEBUG(4,("sam_password_ok: Checking LMv2 password without a domain\n")); - if (smb_pwd_check_ntlmv2( user_info->lm_resp, - nt_pw, auth_context->challenge, - user_info->smb_name.str, - "", - user_sess_key)) - { - return NT_STATUS_OK; - } + lm_pw = pdb_get_lanman_passwd(sampass); + nt_pw = pdb_get_nt_passwd(sampass); - /* Apparently NT accepts NT responses in the LM field - - I think this is related to Win9X pass-though authentication - */ - DEBUG(4,("sam_password_ok: Checking NT MD4 password in LM field\n")); - if (lp_ntlm_auth()) - { - if (smb_pwd_check_ntlmv1(user_info->lm_resp, - nt_pw, auth_context->challenge, - user_sess_key)) - { - return NT_STATUS_OK; - } - DEBUG(3,("sam_password_ok: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; - } else { - DEBUG(3,("sam_password_ok: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; - } - - } - - /* Should not be reached, but if they send nothing... */ - DEBUG(3,("sam_password_ok: NEITHER LanMan nor NT password supplied for user %s\n",pdb_get_username(sampass))); - return NT_STATUS_WRONG_PASSWORD; + return ntlm_password_check(mem_ctx, &auth_context->challenge, + &user_info->lm_resp, &user_info->nt_resp, + &user_info->lm_interactive_pwd, &user_info->nt_interactive_pwd, + username, + user_info->smb_name.str, + user_info->client_domain.str, + lm_pw, nt_pw, user_sess_key, lm_sess_key); } + /**************************************************************************** Do a specific test for a SAM_ACCOUNT being vaild for this connection (ie not disabled, expired and the like). ****************************************************************************/ + static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info) @@ -322,16 +83,22 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, /* Quit if the account was disabled. */ if (acct_ctrl & ACB_DISABLED) { - DEBUG(1,("Account for user '%s' was disabled.\n", pdb_get_username(sampass))); + DEBUG(1,("sam_account_ok: Account for user '%s' was disabled.\n", pdb_get_username(sampass))); return NT_STATUS_ACCOUNT_DISABLED; } + /* Quit if the account was locked out. */ + if (acct_ctrl & ACB_AUTOLOCK) { + DEBUG(1,("sam_account_ok: Account for user %s was locked out.\n", pdb_get_username(sampass))); + return NT_STATUS_ACCOUNT_LOCKED_OUT; + } + /* Test account expire time */ kickoff_time = pdb_get_kickoff_time(sampass); if (kickoff_time != 0 && time(NULL) > kickoff_time) { - DEBUG(1,("Account for user '%s' has expried.\n", pdb_get_username(sampass))); - DEBUG(3,("Account expired at '%ld' unix time.\n", (long)kickoff_time)); + DEBUG(1,("sam_account_ok: Account for user '%s' has expired.\n", pdb_get_username(sampass))); + DEBUG(3,("sam_account_ok: Account expired at '%ld' unix time.\n", (long)kickoff_time)); return NT_STATUS_ACCOUNT_EXPIRED; } @@ -341,14 +108,14 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, /* check for immediate expiry "must change at next logon" */ if (must_change_time == 0 && last_set_time != 0) { - DEBUG(1,("Account for user '%s' password must change!.\n", pdb_get_username(sampass))); + DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", pdb_get_username(sampass))); return NT_STATUS_PASSWORD_MUST_CHANGE; } /* check for expired password */ if (must_change_time < time(NULL) && must_change_time != 0) { - DEBUG(1,("Account for user '%s' password expired!.\n", pdb_get_username(sampass))); - DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", timestring(mem_ctx, must_change_time), (long)must_change_time)); + DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", pdb_get_username(sampass))); + DEBUG(1,("sam_account_ok: Password expired at '%s' (%ld) unix time.\n", timestring(mem_ctx, must_change_time), (long)must_change_time)); return NT_STATUS_PASSWORD_EXPIRED; } } @@ -356,8 +123,8 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, /* Test workstation. Workstation list is comma separated. */ workstation_list = talloc_strdup(mem_ctx, pdb_get_workstations(sampass)); - - if (!workstation_list) return NT_STATUS_NO_MEMORY; + if (!workstation_list) + return NT_STATUS_NO_MEMORY; if (*workstation_list) { BOOL invalid_ws = True; @@ -366,7 +133,7 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, fstring tok; while (next_token(&s, tok, ",", sizeof(tok))) { - DEBUG(10,("checking for workstation match %s and %s (len=%d)\n", + DEBUG(10,("sam_account_ok: checking for workstation match %s and %s (len=%d)\n", tok, user_info->wksta_name.str, user_info->wksta_name.len)); if(strequal(tok, user_info->wksta_name.str)) { invalid_ws = False; @@ -396,7 +163,6 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } - /**************************************************************************** check if a username/password is OK assuming the password is a 24 byte SMB hash supplied in the user_info structure @@ -412,14 +178,14 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, SAM_ACCOUNT *sampass=NULL; BOOL ret; NTSTATUS nt_status; - uint8 user_sess_key[16]; - const uint8* lm_hash; + DATA_BLOB user_sess_key = data_blob(NULL, 0); + DATA_BLOB lm_sess_key = data_blob(NULL, 0); if (!user_info || !auth_context) { return NT_STATUS_UNSUCCESSFUL; } - /* Can't use the talloc version here, becouse the returned struct gets + /* Can't use the talloc version here, because the returned struct gets kept on the server_info */ if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) { return nt_status; @@ -431,21 +197,27 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, ret = pdb_getsampwnam(sampass, user_info->internal_username.str); unbecome_root(); - if (ret == False) - { - DEBUG(3,("Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str)); + if (ret == False) { + DEBUG(3,("check_sam_security: Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str)); pdb_free_sam(&sampass); return NT_STATUS_NO_SUCH_USER; } - nt_status = sam_account_ok(mem_ctx, sampass, user_info); + /* Quit if the account was locked out. */ + if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK) { + DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", pdb_get_username(sampass))); + return NT_STATUS_ACCOUNT_LOCKED_OUT; + } + + nt_status = sam_password_ok(auth_context, mem_ctx, sampass, + user_info, &user_sess_key, &lm_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { pdb_free_sam(&sampass); return nt_status; } - nt_status = sam_password_ok(auth_context, mem_ctx, sampass, user_info, user_sess_key); + nt_status = sam_account_ok(mem_ctx, sampass, user_info); if (!NT_STATUS_IS_OK(nt_status)) { pdb_free_sam(&sampass); @@ -457,25 +229,21 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, return nt_status; } - lm_hash = pdb_get_lanman_passwd((*server_info)->sam_account); - if (lm_hash) { - memcpy((*server_info)->first_8_lm_hash, lm_hash, 8); - } - - memcpy((*server_info)->session_key, user_sess_key, sizeof(user_sess_key)); + (*server_info)->user_session_key = user_sess_key; + (*server_info)->lm_session_key = lm_sess_key; return nt_status; } /* module initialisation */ -static NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_sam_ignoredomain(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; } (*auth_method)->auth = check_sam_security; - (*auth_method)->name = "sam"; + (*auth_method)->name = "sam_ignoredomain"; return NT_STATUS_OK; } @@ -509,57 +277,14 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context } /* module initialisation */ -static NTSTATUS auth_init_samstrict(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; } (*auth_method)->auth = check_samstrict_security; - (*auth_method)->name = "samstrict"; - return NT_STATUS_OK; -} - -/**************************************************************************** -Check SAM security (above) but with a few extra checks if we're a DC. -****************************************************************************/ - -static NTSTATUS check_samstrict_dc_security(const struct auth_context *auth_context, - void *my_private_data, - TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) -{ - - if (!user_info || !auth_context) { - return NT_STATUS_LOGON_FAILURE; - } - - /* If we are a domain member, we must not - attempt to check the password locally, - unless it is one of our aliases, empty - or our domain if we are a logon server.*/ - - - if ((strcasecmp(lp_workgroup(), user_info->domain.str) != 0) && - (!is_myname(user_info->domain.str))) { - DEBUG(7,("The requested user domain is not the local server name or our domain. [%s]\\[%s]\n", - user_info->domain.str,user_info->internal_username.str)); - return NT_STATUS_NO_SUCH_USER; - } - - return check_sam_security(auth_context, my_private_data, mem_ctx, user_info, server_info); -} - -/* module initialisation */ -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; - } - - (*auth_method)->auth = check_samstrict_dc_security; - (*auth_method)->name = "samstrict_dc"; + (*auth_method)->name = "sam"; return NT_STATUS_OK; } @@ -577,17 +302,8 @@ NTSTATUS auth_sam_init(void) 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; + ops.name = "sam_ignoredomain"; + ops.init = auth_init_sam_ignoredomain; ret = register_backend("auth", &ops); if (!NT_STATUS_IS_OK(ret)) { DEBUG(0,("Failed to register '%s' auth backend!\n", diff --git a/source4/auth/auth_util.c b/source4/auth/auth_util.c index db208008ae..db10514c7e 100644 --- a/source4/auth/auth_util.c +++ b/source4/auth/auth_util.c @@ -35,7 +35,8 @@ extern DOM_SID global_sid_Authenticated_Users; /**************************************************************************** Create a UNIX user on demand. ****************************************************************************/ -static int smb_create_user(const char *unix_user, const char *homedir) + +static int smb_create_user(const char *domain, const char *unix_username, const char *homedir) { pstring add_script; int ret; @@ -43,7 +44,9 @@ static int smb_create_user(const char *unix_user, const char *homedir) pstrcpy(add_script, lp_adduser_script()); if (! *add_script) return -1; - all_string_sub(add_script, "%u", unix_user, sizeof(pstring)); + all_string_sub(add_script, "%u", unix_username, sizeof(pstring)); + if (domain) + all_string_sub(add_script, "%D", domain, sizeof(pstring)); if (homedir) all_string_sub(add_script, "%H", homedir, sizeof(pstring)); ret = smbrun(add_script,NULL); @@ -70,7 +73,7 @@ void smb_user_control(const auth_usersupplied_info *user_info, auth_serversuppli */ if(lp_adduser_script() && !(pwd = Get_Pwnam(user_info->internal_username.str))) { - smb_create_user(user_info->internal_username.str, NULL); + smb_create_user(user_info->domain.str, user_info->internal_username.str, NULL); } } } @@ -116,16 +119,17 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info, const char *client_domain, const char *domain, const char *wksta_name, - DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, - DATA_BLOB plaintext, - uint32 auth_flags, BOOL encrypted) + DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd, + DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd, + DATA_BLOB *plaintext, + BOOL encrypted) { DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name)); *user_info = malloc(sizeof(**user_info)); if (!user_info) { - DEBUG(0,("malloc failed for user_info (size %d)\n", sizeof(*user_info))); + DEBUG(0,("malloc failed for user_info (size %lu)\n", (unsigned long)sizeof(*user_info))); return NT_STATUS_NO_MEMORY; } @@ -175,12 +179,19 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info, DEBUG(5,("making blobs for %s's user_info struct\n", internal_username)); - (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length); - (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length); - (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length); + if (lm_pwd) + (*user_info)->lm_resp = data_blob(lm_pwd->data, lm_pwd->length); + if (nt_pwd) + (*user_info)->nt_resp = data_blob(nt_pwd->data, nt_pwd->length); + if (lm_interactive_pwd) + (*user_info)->lm_interactive_pwd = data_blob(lm_interactive_pwd->data, lm_interactive_pwd->length); + if (nt_interactive_pwd) + (*user_info)->nt_interactive_pwd = data_blob(nt_interactive_pwd->data, nt_interactive_pwd->length); + + if (plaintext) + (*user_info)->plaintext_password = data_blob(plaintext->data, plaintext->length); (*user_info)->encrypted = encrypted; - (*user_info)->auth_flags = auth_flags; DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name)); @@ -195,9 +206,10 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, const char *wksta_name, - DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, - DATA_BLOB plaintext, - uint32 ntlmssp_flags, BOOL encrypted) + DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd, + DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd, + DATA_BLOB *plaintext, + BOOL encrypted) { const char *domain; fstring internal_username; @@ -206,58 +218,22 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, DEBUG(5, ("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n", client_domain, smb_name, wksta_name)); - if (lp_allow_trusted_domains() && *client_domain) { - - /* the client could have given us a workstation name - or other crap for the workgroup - we really need a - way of telling if this domain name is one of our - trusted domain names - - Also don't allow "" as a domain, fixes a Win9X bug - where it doens't supply a domain for logon script - 'net use' commands. - - The way I do it here is by checking if the fully - qualified username exists. This is rather reliant - on winbind, but until we have a better method this - will have to do - */ + /* don't allow "" as a domain, fixes a Win9X bug + where it doens't supply a domain for logon script + 'net use' commands. */ + if ( *client_domain ) domain = client_domain; - - if ((smb_name) && (*smb_name)) { /* Don't do this for guests */ - char *user = NULL; - if (asprintf(&user, "%s%s%s", - client_domain, lp_winbind_separator(), - smb_name) < 0) { - DEBUG(0, ("make_user_info_map: asprintf() failed!\n")); - return NT_STATUS_NO_MEMORY; - } - - DEBUG(5, ("make_user_info_map: testing for user %s\n", user)); - - if (Get_Pwnam(user) == NULL) { - DEBUG(5, ("make_user_info_map: test for user %s failed\n", user)); - domain = lp_workgroup(); - DEBUG(5, ("make_user_info_map: trusted domain %s doesn't appear to exist, using %s\n", - client_domain, domain)); - } else { - DEBUG(5, ("make_user_info_map: using trusted domain %s\n", domain)); - } - SAFE_FREE(user); - } - } else { + else domain = lp_workgroup(); - } + + /* we know that it is a trusted domain (and we are allowing them) or it is our domain */ - return make_user_info(user_info, - smb_name, internal_username, - client_domain, domain, - wksta_name, + return make_user_info(user_info, smb_name, internal_username, + client_domain, domain, wksta_name, lm_pwd, nt_pwd, - plaintext, - ntlmssp_flags, encrypted); - + lm_interactive_pwd, nt_interactive_pwd, + plaintext, encrypted); } /**************************************************************************** @@ -276,23 +252,14 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, NTSTATUS nt_status; DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); - DATA_BLOB plaintext_blob = data_blob(NULL, 0); - uint32 auth_flags = AUTH_FLAG_NONE; - - if (lm_pwd_len) - auth_flags |= AUTH_FLAG_LM_RESP; - if (nt_pwd_len == 24) { - auth_flags |= AUTH_FLAG_NTLM_RESP; - } else if (nt_pwd_len != 0) { - auth_flags |= AUTH_FLAG_NTLMv2_RESP; - } nt_status = make_user_info_map(user_info, - smb_name, client_domain, - wksta_name, - lm_blob, nt_blob, - plaintext_blob, - auth_flags, True); + smb_name, client_domain, + wksta_name, + lm_pwd_len ? &lm_blob : NULL, + nt_pwd_len ? &nt_blob : NULL, + NULL, NULL, NULL, + True); ret = NT_STATUS_IS_OK(nt_status) ? True : False; @@ -320,7 +287,6 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; unsigned char key[16]; - uint32 auth_flags = AUTH_FLAG_NONE; ZERO_STRUCT(key); memcpy(key, dc_sess_key, 8); @@ -339,8 +305,11 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, dump_data(100, nt_pwd, sizeof(nt_pwd)); #endif - SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd)); - SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd)); + if (lm_interactive_pwd) + SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd)); + + if (nt_interactive_pwd) + SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd)); #ifdef DEBUG_PASSWORD DEBUG(100,("decrypt of lm owf password:")); @@ -350,37 +319,51 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, dump_data(100, nt_pwd, sizeof(nt_pwd)); #endif - SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response); - SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response); + if (lm_interactive_pwd) + SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response); + + if (nt_interactive_pwd) + SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response); /* Password info paranoia */ - ZERO_STRUCT(lm_pwd); - ZERO_STRUCT(nt_pwd); ZERO_STRUCT(key); { BOOL ret; NTSTATUS nt_status; - DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); - DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); - DATA_BLOB plaintext_blob = data_blob(NULL, 0); + DATA_BLOB local_lm_blob; + DATA_BLOB local_nt_blob; - if (lm_interactive_pwd) - auth_flags |= AUTH_FLAG_LM_RESP; - if (nt_interactive_pwd) - auth_flags |= AUTH_FLAG_NTLM_RESP; + DATA_BLOB lm_interactive_blob; + DATA_BLOB nt_interactive_blob; + + if (lm_interactive_pwd) { + local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); + lm_interactive_blob = data_blob(lm_pwd, sizeof(lm_pwd)); + ZERO_STRUCT(lm_pwd); + } + + if (nt_interactive_pwd) { + local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); + nt_interactive_blob = data_blob(nt_pwd, sizeof(nt_pwd)); + ZERO_STRUCT(nt_pwd); + } nt_status = make_user_info_map(user_info, smb_name, client_domain, wksta_name, - local_lm_blob, - local_nt_blob, - plaintext_blob, - auth_flags, True); - + lm_interactive_pwd ? &local_lm_blob : NULL, + nt_interactive_pwd ? &local_nt_blob : NULL, + lm_interactive_pwd ? &lm_interactive_blob : NULL, + nt_interactive_pwd ? &nt_interactive_blob : NULL, + NULL, + True); + ret = NT_STATUS_IS_OK(nt_status) ? True : False; data_blob_free(&local_lm_blob); data_blob_free(&local_nt_blob); + data_blob_free(&lm_interactive_blob); + data_blob_free(&nt_interactive_blob); return ret; } } @@ -400,7 +383,6 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, DATA_BLOB local_lm_blob; DATA_BLOB local_nt_blob; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - uint32 auth_flags = AUTH_FLAG_NONE; /* * Not encrypted - do so. @@ -416,14 +398,13 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, dump_data(100, plaintext_password.data, plaintext_password.length); #endif - SMBencrypt( (const uchar *)plaintext_password.data, (const uchar*)chal, local_lm_response); + SMBencrypt( (const char *)plaintext_password.data, (const uchar*)chal, local_lm_response); local_lm_blob = data_blob(local_lm_response, 24); /* We can't do an NT hash here, as the password needs to be case insensitive */ local_nt_blob = data_blob(NULL, 0); - auth_flags = (AUTH_FLAG_PLAINTEXT | AUTH_FLAG_LM_RESP); } else { local_lm_blob = data_blob(NULL, 0); local_nt_blob = data_blob(NULL, 0); @@ -432,10 +413,11 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, sub_get_remote_machine(), - local_lm_blob, - local_nt_blob, - plaintext_password, - auth_flags, False); + local_lm_blob.data ? &local_lm_blob : NULL, + local_nt_blob.data ? &local_nt_blob : NULL, + NULL, NULL, + plaintext_password.data ? &plaintext_password : NULL, + False); data_blob_free(&local_lm_blob); return NT_STATUS_IS_OK(ret) ? True : False; @@ -450,27 +432,13 @@ NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, const char *client_domain, DATA_BLOB lm_resp, DATA_BLOB nt_resp) { - uint32 auth_flags = AUTH_FLAG_NONE; - - DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); - - if (lm_resp.length == 24) { - auth_flags |= AUTH_FLAG_LM_RESP; - } - if (nt_resp.length == 0) { - } else if (nt_resp.length == 24) { - auth_flags |= AUTH_FLAG_NTLM_RESP; - } else { - auth_flags |= AUTH_FLAG_NTLMv2_RESP; - } - return make_user_info_map(user_info, smb_name, client_domain, sub_get_remote_machine(), - lm_resp, - nt_resp, - no_plaintext_blob, - auth_flags, True); + lm_resp.data ? &lm_resp : NULL, + nt_resp.data ? &nt_resp : NULL, + NULL, NULL, NULL, + True); } /**************************************************************************** @@ -479,19 +447,16 @@ NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, BOOL make_user_info_guest(auth_usersupplied_info **user_info) { - DATA_BLOB lm_blob = data_blob(NULL, 0); - DATA_BLOB nt_blob = data_blob(NULL, 0); - DATA_BLOB plaintext_blob = data_blob(NULL, 0); - uint32 auth_flags = AUTH_FLAG_NONE; NTSTATUS nt_status; nt_status = make_user_info(user_info, - "","", - "","", - "", - nt_blob, lm_blob, - plaintext_blob, - auth_flags, True); + "","", + "","", + "", + NULL, NULL, + NULL, NULL, + NULL, + True); return NT_STATUS_IS_OK(nt_status) ? True : False; } @@ -512,9 +477,9 @@ void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token) DEBUGC(dbg_class, dbg_lev, ("NT user token of user %s\n", sid_to_string(sid_str, &token->user_sids[0]) )); - DEBUGADDC(dbg_class, dbg_lev, ("contains %i SIDs\n", token->num_sids)); + DEBUGADDC(dbg_class, dbg_lev, ("contains %lu SIDs\n", (unsigned long)token->num_sids)); for (i = 0; i < token->num_sids; i++) - DEBUGADDC(dbg_class, dbg_lev, ("SID[%3i]: %s\n", i, + DEBUGADDC(dbg_class, dbg_lev, ("SID[%3lu]: %s\n", (unsigned long)i, sid_to_string(sid_str, &token->user_sids[i]))); } @@ -633,7 +598,7 @@ struct nt_user_token *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t * return NULL; } - group_sids = malloc(sizeof(DOM_SID) * ngroups); + group_sids = malloc(sizeof(DOM_SID) * ngroups); if (!group_sids) { DEBUG(0, ("create_nt_token: malloc() failed for DOM_SID list!\n")); return NULL; @@ -856,9 +821,16 @@ NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info) nt_status = make_server_info_sam(server_info, sampass); if (NT_STATUS_IS_OK(nt_status)) { + static const char zeros[16]; (*server_info)->guest = True; + + /* annoying, but the Guest really does have a session key, + and it is all zeros! */ + (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros)); + (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros)); } + return nt_status; } -- cgit