ntlm_auth.c

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

C
1,160
字号
				flags |= NTLM_AUTH_FLAG_LMKEY;						if (ntlm_server_1_user_session_key) 				flags |= NTLM_AUTH_FLAG_USER_SESSION_KEY;			if (!NT_STATUS_IS_OK(				    local_pw_check_specified(lp_ctx,							     username, 							      domain, 							      lp_netbios_name(lp_ctx),							      &challenge, 							      &lm_response, 							      &nt_response, 							      flags, 							      &lm_key, 							      &user_session_key,							      &error_string,							      NULL))) {				mux_printf(mux_id, "Authenticated: No\n");				mux_printf(mux_id, "Authentication-Error: %s\n.\n", error_string);				SAFE_FREE(error_string);			} else {				static char zeros[16];				char *hex_lm_key;				char *hex_user_session_key;				mux_printf(mux_id, "Authenticated: Yes\n");				if (ntlm_server_1_lm_session_key 				    && lm_key.length 				    && (memcmp(zeros, lm_key.data, 								lm_key.length) != 0)) {					hex_encode(lm_key.data,						   lm_key.length,						   &hex_lm_key);					mux_printf(mux_id, "LANMAN-Session-Key: %s\n", hex_lm_key);					SAFE_FREE(hex_lm_key);				}				if (ntlm_server_1_user_session_key 				    && user_session_key.length 				    && (memcmp(zeros, user_session_key.data, 					       user_session_key.length) != 0)) {					hex_encode(user_session_key.data, 						   user_session_key.length, 						   &hex_user_session_key);					mux_printf(mux_id, "User-Session-Key: %s\n", hex_user_session_key);					SAFE_FREE(hex_user_session_key);				}			}		}		/* clear out the state */		challenge = data_blob(NULL, 0);		nt_response = data_blob(NULL, 0);		lm_response = data_blob(NULL, 0);		SAFE_FREE(full_username);		SAFE_FREE(username);		SAFE_FREE(domain);		SAFE_FREE(plaintext_password);		ntlm_server_1_user_session_key = false;		ntlm_server_1_lm_session_key = false;		mux_printf(mux_id, ".\n");		return;	}	request = buf;	/* Indicates a base64 encoded structure */	parameter = strstr(request, ":: ");	if (!parameter) {		parameter = strstr(request, ": ");				if (!parameter) {			DEBUG(0, ("Parameter not found!\n"));			mux_printf(mux_id, "Error: Parameter not found!\n.\n");			return;		}				parameter[0] ='\0';		parameter++;		parameter[0] ='\0';		parameter++;	} else {		parameter[0] ='\0';		parameter++;		parameter[0] ='\0';		parameter++;		parameter[0] ='\0';		parameter++;		base64_decode_inplace(parameter);	}	if (strequal(request, "LANMAN-Challenge")) {		challenge = strhex_to_data_blob(parameter);		if (challenge.length != 8) {			mux_printf(mux_id, "Error: hex decode of %s failed! (got %d bytes, expected 8)\n.\n", 				  parameter,				  (int)challenge.length);			challenge = data_blob(NULL, 0);		}	} else if (strequal(request, "NT-Response")) {		nt_response = strhex_to_data_blob(parameter);		if (nt_response.length < 24) {			mux_printf(mux_id, "Error: hex decode of %s failed! (only got %d bytes, needed at least 24)\n.\n", 				  parameter,				  (int)nt_response.length);			nt_response = data_blob(NULL, 0);		}	} else if (strequal(request, "LANMAN-Response")) {		lm_response = strhex_to_data_blob(parameter);		if (lm_response.length != 24) {			mux_printf(mux_id, "Error: hex decode of %s failed! (got %d bytes, expected 24)\n.\n", 				  parameter,				  (int)lm_response.length);			lm_response = data_blob(NULL, 0);		}	} else if (strequal(request, "Password")) {		plaintext_password = smb_xstrdup(parameter);	} else if (strequal(request, "NT-Domain")) {		domain = smb_xstrdup(parameter);	} else if (strequal(request, "Username")) {		username = smb_xstrdup(parameter);	} else if (strequal(request, "Full-Username")) {		full_username = smb_xstrdup(parameter);	} else if (strequal(request, "Request-User-Session-Key")) {		ntlm_server_1_user_session_key = strequal(parameter, "Yes");	} else if (strequal(request, "Request-LanMan-Session-Key")) {		ntlm_server_1_lm_session_key = strequal(parameter, "Yes");	} else {		mux_printf(mux_id, "Error: Unknown request %s\n.\n", request);	}}static void manage_squid_request(struct loadparm_context *lp_ctx, enum stdio_helper_mode helper_mode, 				 stdio_helper_function fn, void **private2) {	char *buf;	char tmp[INITIAL_BUFFER_SIZE+1];	unsigned int mux_id = 0;	int length, buf_size = 0;	char *c;	struct mux_private {		unsigned int max_mux;		void **private_pointers;	};	static struct mux_private *mux_private;	static void *normal_private;	void **private;	buf = talloc_strdup(NULL, "");	if (buf == NULL) {		DEBUG(0, ("Failed to allocate memory for reading the input "			  "buffer.\n"));		x_fprintf(x_stdout, "ERR\n");		return;	}	do {		/* this is not a typo - x_fgets doesn't work too well under		 * squid */		if (fgets(tmp, INITIAL_BUFFER_SIZE, stdin) == NULL) {			if (ferror(stdin)) {				DEBUG(1, ("fgets() failed! dying..... errno=%d "					  "(%s)\n", ferror(stdin),					  strerror(ferror(stdin))));				exit(1);    /* BIIG buffer */			}			exit(0);		}		buf = talloc_strdup_append_buffer(buf, tmp);		buf_size += INITIAL_BUFFER_SIZE;		if (buf_size > MAX_BUFFER_SIZE) {			DEBUG(0, ("Invalid Request (too large)\n"));			x_fprintf(x_stdout, "ERR\n");			talloc_free(buf);			return;		}		c = strchr(buf, '\n');	} while (c == NULL);	*c = '\0';	length = c-buf;	DEBUG(10, ("Got '%s' from squid (length: %d).\n",buf,length));	if (buf[0] == '\0') {		DEBUG(0, ("Invalid Request (empty)\n"));		x_fprintf(x_stdout, "ERR\n");		talloc_free(buf);		return;	}	if (opt_multiplex) {		if (sscanf(buf, "%u ", &mux_id) != 1) {			DEBUG(0, ("Invalid Request - no multiplex id\n"));			x_fprintf(x_stdout, "ERR\n");			talloc_free(buf);			return;		}		if (!mux_private) {			mux_private = talloc(NULL, struct mux_private);			mux_private->max_mux = 0;			mux_private->private_pointers = NULL;		}				c=strchr(buf,' ');		if (!c) {			DEBUG(0, ("Invalid Request - no data after multiplex id\n"));			x_fprintf(x_stdout, "ERR\n");			talloc_free(buf);			return;		}		c++;		if (mux_id >= mux_private->max_mux) {			unsigned int prev_max = mux_private->max_mux;			mux_private->max_mux = mux_id + 1;			mux_private->private_pointers				= talloc_realloc(mux_private, 						   mux_private->private_pointers, 						   void *, mux_private->max_mux);			memset(&mux_private->private_pointers[prev_max], '\0',  			       (sizeof(*mux_private->private_pointers) * (mux_private->max_mux - prev_max))); 		};		private = &mux_private->private_pointers[mux_id];	} else {		c = buf;		private = &normal_private;	}	fn(helper_mode, lp_ctx, c, length, private, mux_id, private2);	talloc_free(buf);}static void squid_stream(struct loadparm_context *lp_ctx, 			 enum stdio_helper_mode stdio_mode, 			 stdio_helper_function fn) {	/* initialize FDescs */	x_setbuf(x_stdout, NULL);	x_setbuf(x_stderr, NULL);	while(1) {		manage_squid_request(lp_ctx, stdio_mode, fn, NULL);	}}/* Main program */enum {	OPT_USERNAME = 1000,	OPT_DOMAIN,	OPT_WORKSTATION,	OPT_CHALLENGE,	OPT_RESPONSE,	OPT_LM,	OPT_NT,	OPT_PASSWORD,	OPT_LM_KEY,	OPT_USER_SESSION_KEY,	OPT_DIAGNOSTICS,	OPT_REQUIRE_MEMBERSHIP,	OPT_MULTIPLEX,	OPT_USE_CACHED_CREDS,};int main(int argc, const char **argv){	static const char *helper_protocol;	int opt;	poptContext pc;	/* NOTE: DO NOT change this interface without considering the implications!	   This is an external interface, which other programs will use to interact 	   with this helper.	*/	/* We do not use single-letter command abbreviations, because they harm future 	   interface stability. */	struct poptOption long_options[] = {		POPT_AUTOHELP		{ "helper-protocol", 0, POPT_ARG_STRING, &helper_protocol, OPT_DOMAIN, "operate as a stdio-based helper", "helper protocol to use"}, 		{ "domain", 0, POPT_ARG_STRING, &opt_domain, OPT_DOMAIN, "domain name"}, 		{ "workstation", 0, POPT_ARG_STRING, &opt_workstation, OPT_WORKSTATION, "workstation"},		{ "username", 0, POPT_ARG_STRING, &opt_username, OPT_PASSWORD, "Username"},				{ "password", 0, POPT_ARG_STRING, &opt_password, OPT_PASSWORD, "User's plaintext password"},				{ "multiplex", 0, POPT_ARG_NONE, &opt_multiplex, OPT_MULTIPLEX, "Multiplex Mode"},		{ "use-cached-creds", 0, POPT_ARG_NONE, &use_cached_creds, OPT_USE_CACHED_CREDS, "silently ignored for compatibility reasons"},		POPT_COMMON_SAMBA		POPT_COMMON_VERSION		{ NULL }	};	/* Samba client initialisation */	setup_logging(NULL, DEBUG_STDERR);	/* Parse options */	pc = poptGetContext("ntlm_auth", argc, argv, long_options, 0);	/* Parse command line options */	if (argc == 1) {		poptPrintHelp(pc, stderr, 0);		return 1;	}	pc = poptGetContext(NULL, argc, (const char **)argv, long_options, 			    POPT_CONTEXT_KEEP_FIRST);	while((opt = poptGetNextOpt(pc)) != -1) {		if (opt < -1) {			break;		}	}	if (opt < -1) {		fprintf(stderr, "%s: %s\n",			poptBadOption(pc, POPT_BADOPTION_NOALIAS),			poptStrerror(opt));		return 1;	}	gensec_init(cmdline_lp_ctx);	if (opt_domain == NULL) {		opt_domain = lp_workgroup(cmdline_lp_ctx);	}	if (helper_protocol) {		int i;		for (i=0; i<NUM_HELPER_MODES; i++) {			if (strcmp(helper_protocol, stdio_helper_protocols[i].name) == 0) {				squid_stream(cmdline_lp_ctx, stdio_helper_protocols[i].mode, stdio_helper_protocols[i].fn);				exit(0);			}		}		x_fprintf(x_stderr, "unknown helper protocol [%s]\n\nValid helper protools:\n\n", helper_protocol);		for (i=0; i<NUM_HELPER_MODES; i++) {			x_fprintf(x_stderr, "%s\n", stdio_helper_protocols[i].name);		}		exit(1);	}	if (!opt_username) {		x_fprintf(x_stderr, "username must be specified!\n\n");		poptPrintHelp(pc, stderr, 0);		exit(1);	}	if (opt_workstation == NULL) {		opt_workstation = lp_netbios_name(cmdline_lp_ctx);	}	if (!opt_password) {		opt_password = getpass("password: ");	}	{		char *user;		asprintf(&user, "%s%c%s", opt_domain, *lp_winbind_separator(cmdline_lp_ctx), opt_username);		if (!check_plaintext_auth(user, opt_password, true)) {			return 1;		}	}	/* Exit code */	poptFreeContext(pc);	return 0;}

⌨️ 快捷键说明

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