ntlm_auth.c

来自「samba最新软件」· C语言 代码 · 共 1,160 行 · 第 1/3 页

C
1,160
字号
/*    Unix SMB/CIFS implementation.   Winbind status program.   Copyright (C) Tim Potter      2000-2003   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004   Copyright (C) Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> 2000    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 "system/filesys.h"#include "lib/cmdline/popt_common.h"#include "lib/ldb/include/ldb.h"#include "auth/credentials/credentials.h"#include "auth/gensec/gensec.h"#include "auth/auth.h"#include "librpc/gen_ndr/ndr_netlogon.h"#include "auth/auth_sam.h"#include "auth/ntlm/ntlm_check.h"#include "pstring.h"#include "libcli/auth/libcli_auth.h"#include "libcli/security/security.h"#include "lib/events/events.h"#include "lib/messaging/messaging.h"#include "lib/messaging/irpc.h"#include "auth/ntlmssp/ntlmssp.h"#include "param/param.h"#define INITIAL_BUFFER_SIZE 300#define MAX_BUFFER_SIZE 63000enum stdio_helper_mode {	SQUID_2_4_BASIC,	SQUID_2_5_BASIC,	SQUID_2_5_NTLMSSP,	NTLMSSP_CLIENT_1,	GSS_SPNEGO_CLIENT,	GSS_SPNEGO_SERVER,	NTLM_SERVER_1,	NUM_HELPER_MODES};#define NTLM_AUTH_FLAG_USER_SESSION_KEY     0x0004#define NTLM_AUTH_FLAG_LMKEY                0x0008typedef void (*stdio_helper_function)(enum stdio_helper_mode stdio_helper_mode, 				      struct loadparm_context *lp_ctx,				      char *buf, int length, void **private,				      unsigned int mux_id, void **private2);static void manage_squid_basic_request (enum stdio_helper_mode stdio_helper_mode, 					struct loadparm_context *lp_ctx,					char *buf, int length, void **private,					unsigned int mux_id, void **private2);static void manage_gensec_request (enum stdio_helper_mode stdio_helper_mode, 				   struct loadparm_context *lp_ctx,				   char *buf, int length, void **private,				   unsigned int mux_id, void **private2);static void manage_ntlm_server_1_request (enum stdio_helper_mode stdio_helper_mode, 					  struct loadparm_context *lp_ctx,					  char *buf, int length, void **private,					  unsigned int mux_id, void **private2);static void manage_squid_request(struct loadparm_context *lp_ctx,				 enum stdio_helper_mode helper_mode, 				 stdio_helper_function fn, void **private2);static const struct {	enum stdio_helper_mode mode;	const char *name;	stdio_helper_function fn;} stdio_helper_protocols[] = {	{ SQUID_2_4_BASIC, "squid-2.4-basic", manage_squid_basic_request},	{ SQUID_2_5_BASIC, "squid-2.5-basic", manage_squid_basic_request},	{ SQUID_2_5_NTLMSSP, "squid-2.5-ntlmssp", manage_gensec_request},	{ GSS_SPNEGO_CLIENT, "gss-spnego-client", manage_gensec_request},	{ GSS_SPNEGO_SERVER, "gss-spnego", manage_gensec_request},	{ NTLMSSP_CLIENT_1, "ntlmssp-client-1", manage_gensec_request},	{ NTLM_SERVER_1, "ntlm-server-1", manage_ntlm_server_1_request},	{ NUM_HELPER_MODES, NULL, NULL}};extern int winbindd_fd;static const char *opt_username;static const char *opt_domain;static const char *opt_workstation;static const char *opt_password;static int opt_multiplex;static int use_cached_creds;static void mux_printf(unsigned int mux_id, const char *format, ...) PRINTF_ATTRIBUTE(2, 3);static void mux_printf(unsigned int mux_id, const char *format, ...){	va_list ap;	if (opt_multiplex) {		x_fprintf(x_stdout, "%d ", mux_id);	}	va_start(ap, format);	x_vfprintf(x_stdout, format, ap);	va_end(ap);}/* Copy of parse_domain_user from winbindd_util.c.  Parse a string of the   form DOMAIN/user into a domain and a user */static bool parse_ntlm_auth_domain_user(const char *domuser, fstring domain, 					fstring user, char winbind_separator){	char *p = strchr(domuser, winbind_separator);	if (!p) {		return false;	}        	fstrcpy(user, p+1);	fstrcpy(domain, domuser);	domain[PTR_DIFF(p, domuser)] = 0;	return true;}/** * Decode a base64 string into a DATA_BLOB - simple and slow algorithm **/static DATA_BLOB base64_decode_data_blob(TALLOC_CTX *mem_ctx, const char *s){	DATA_BLOB ret = data_blob_talloc(mem_ctx, s, strlen(s)+1);	ret.length = ldb_base64_decode((char *)ret.data);	return ret;}/** * Encode a base64 string into a talloc()ed string caller to free. **/static char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data){	return ldb_base64_encode(mem_ctx, (const char *)data.data, data.length);}/** * Decode a base64 string in-place - wrapper for the above **/static void base64_decode_inplace(char *s){	ldb_base64_decode(s);}/* Authenticate a user with a plaintext password */static bool check_plaintext_auth(const char *user, const char *pass, 				 bool stdout_diagnostics){        return (strcmp(pass, opt_password) == 0);}/* authenticate a user with an encrypted username/password */static NTSTATUS local_pw_check_specified(struct loadparm_context *lp_ctx,					 const char *username, 					 const char *domain, 					 const char *workstation,					 const DATA_BLOB *challenge, 					 const DATA_BLOB *lm_response, 					 const DATA_BLOB *nt_response, 					 uint32_t flags, 					 DATA_BLOB *lm_session_key, 					 DATA_BLOB *user_session_key, 					 char **error_string, 					 char **unix_name) {	NTSTATUS nt_status;	struct samr_Password lm_pw, nt_pw;	struct samr_Password *lm_pwd, *nt_pwd;	TALLOC_CTX *mem_ctx = talloc_init("local_pw_check_specified");	if (!mem_ctx) {		nt_status = NT_STATUS_NO_MEMORY;	} else {				E_md4hash(opt_password, nt_pw.hash);		if (E_deshash(opt_password, lm_pw.hash)) {			lm_pwd = &lm_pw;		} else {			lm_pwd = NULL;		}		nt_pwd = &nt_pw;						nt_status = ntlm_password_check(mem_ctx, 						lp_ctx,						MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |						MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT,						challenge,						lm_response,						nt_response,						username,						username,						domain,						lm_pwd, nt_pwd, user_session_key, lm_session_key);				if (NT_STATUS_IS_OK(nt_status)) {			if (unix_name) {				asprintf(unix_name, 					 "%s%c%s", domain,					 *lp_winbind_separator(lp_ctx), 					 username);			}		} else {			DEBUG(3, ("Login for user [%s]\\[%s]@[%s] failed due to [%s]\n", 				  domain, username, workstation, 				  nt_errstr(nt_status)));		}		talloc_free(mem_ctx);	}	if (error_string) {		*error_string = strdup(nt_errstr(nt_status));	}	return nt_status;		}static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode, 				       struct loadparm_context *lp_ctx,				       char *buf, int length, void **private,				       unsigned int mux_id, void **private2) {	char *user, *pass;		user=buf;		pass = memchr(buf, ' ', length);	if (!pass) {		DEBUG(2, ("Password not found. Denying access\n"));		mux_printf(mux_id, "ERR\n");		return;	}	*pass='\0';	pass++;		if (stdio_helper_mode == SQUID_2_5_BASIC) {		rfc1738_unescape(user);		rfc1738_unescape(pass);	}		if (check_plaintext_auth(user, pass, false)) {		mux_printf(mux_id, "OK\n");	} else {		mux_printf(mux_id, "ERR\n");	}}/* This is a bit hairy, but the basic idea is to do a password callback   to the calling application.  The callback comes from within gensec */static void manage_gensec_get_pw_request(enum stdio_helper_mode stdio_helper_mode, 					 struct loadparm_context *lp_ctx,					 char *buf, int length, void **private,					 unsigned int mux_id, void **password)  {	DATA_BLOB in;	if (strlen(buf) < 2) {		DEBUG(1, ("query [%s] invalid", buf));		mux_printf(mux_id, "BH Query invalid\n");		return;	}	if (strlen(buf) > 3) {		in = base64_decode_data_blob(NULL, buf + 3);	} else {		in = data_blob(NULL, 0);	}	if (strncmp(buf, "PW ", 3) == 0) {		*password = talloc_strndup(*private /* hopefully the right gensec context, useful to use for talloc */,					   (const char *)in.data, in.length);				if (*password == NULL) {			DEBUG(1, ("Out of memory\n"));			mux_printf(mux_id, "BH Out of memory\n");			data_blob_free(&in);			return;		}		mux_printf(mux_id, "OK\n");		data_blob_free(&in);		return;	}	DEBUG(1, ("Asked for (and expected) a password\n"));	mux_printf(mux_id, "BH Expected a password\n");	data_blob_free(&in);}/**  * Callback for password credentials.  This is not async, and when * GENSEC and the credentials code is made async, it will look rather * different. */static const char *get_password(struct cli_credentials *credentials) {	char *password = NULL;		/* Ask for a password */	mux_printf((unsigned int)credentials->priv_data, "PW\n");	credentials->priv_data = NULL;	manage_squid_request(cmdline_lp_ctx, NUM_HELPER_MODES /* bogus */, manage_gensec_get_pw_request, (void **)&password);	return password;}/** Check if a string is part of a list.**/static bool in_list(const char *s, const char *list, bool casesensitive){	char *tok;	size_t tok_len = 1024;	const char *p=list;	if (!list)		return false;	tok = (char *)malloc(tok_len);	if (!tok) {		return false;	}	while (next_token(&p, tok, LIST_SEP, tok_len)) {		if ((casesensitive?strcmp:strcasecmp_m)(tok,s) == 0) {			free(tok);			return true;		}	}	free(tok);	return false;}static void gensec_want_feature_list(struct gensec_security *state, char* feature_list){	if (in_list("NTLMSSP_FEATURE_SESSION_KEY", feature_list, true)) {		DEBUG(10, ("want GENSEC_FEATURE_SESSION_KEY\n"));		gensec_want_feature(state, GENSEC_FEATURE_SESSION_KEY);	}	if (in_list("NTLMSSP_FEATURE_SIGN", feature_list, true)) {		DEBUG(10, ("want GENSEC_FEATURE_SIGN\n"));		gensec_want_feature(state, GENSEC_FEATURE_SIGN);	}	if (in_list("NTLMSSP_FEATURE_SEAL", feature_list, true)) {		DEBUG(10, ("want GENSEC_FEATURE_SEAL\n"));		gensec_want_feature(state, GENSEC_FEATURE_SEAL);	}}static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, 				  struct loadparm_context *lp_ctx,				  char *buf, int length, void **private,				  unsigned int mux_id, void **private2) {	DATA_BLOB in;	DATA_BLOB out = data_blob(NULL, 0);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?