sesssetup.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,115 行 · 第 1/3 页

C
1,115
字号
****************************************************************************/static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,				void *p){	struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;	const char *ip = (const char *)p;	if (!process_exists(pid_to_procid(sessionid->pid))) {		return 0;	}	if (sessionid->pid == sys_getpid()) {		return 0;	}	if (strcmp(ip, sessionid->ip_addr) != 0) {		return 0;	}	message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,			 NULL, 0, True);	return 0;}static void setup_new_vc_session(void){	DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));#if 0	conn_close_all();	invalidate_all_vuids();#endif	if (lp_reset_on_zero_vc()) {		session_traverse(shutdown_other_smbds, client_addr());	}}/**************************************************************************** Reply to a session setup command.****************************************************************************/int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,			  int length,int bufsize){	int sess_vuid;	int   smb_bufsize;    	DATA_BLOB lm_resp;	DATA_BLOB nt_resp;	DATA_BLOB plaintext_password;	fstring user;	fstring sub_user; /* Sainitised username for substituion */	fstring domain;	fstring native_os;	fstring native_lanman;	fstring primary_domain;	static BOOL done_sesssetup = False;	extern BOOL global_encrypted_passwords_negotiated;	extern BOOL global_spnego_negotiated;	extern enum protocol_types Protocol;	extern int max_send;	auth_usersupplied_info *user_info = NULL;	extern struct auth_context *negprot_global_auth_context;	auth_serversupplied_info *server_info = NULL;	NTSTATUS nt_status;	BOOL doencrypt = global_encrypted_passwords_negotiated;	DATA_BLOB session_key;		START_PROFILE(SMBsesssetupX);	ZERO_STRUCT(lm_resp);	ZERO_STRUCT(nt_resp);	ZERO_STRUCT(plaintext_password);	DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));	/* a SPNEGO session setup has 12 command words, whereas a normal	   NT1 session setup has 13. See the cifs spec. */	if (CVAL(inbuf, smb_wct) == 12 &&	    (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {		if (!global_spnego_negotiated) {			DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));			return ERROR_NT(NT_STATUS_LOGON_FAILURE);		}		if (SVAL(inbuf,smb_vwv4) == 0) {			setup_new_vc_session();		}		return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);	}	smb_bufsize = SVAL(inbuf,smb_vwv2);	if (Protocol < PROTOCOL_NT1) {		uint16 passlen1 = SVAL(inbuf,smb_vwv7);		/* Never do NT status codes with protocols before NT1 as we don't get client caps. */		remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);		if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);		}		if (doencrypt) {			lm_resp = data_blob(smb_buf(inbuf), passlen1);		} else {			plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);			/* Ensure null termination */			plaintext_password.data[passlen1] = 0;		}		srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);		*domain = 0;	} else {		uint16 passlen1 = SVAL(inbuf,smb_vwv7);		uint16 passlen2 = SVAL(inbuf,smb_vwv8);		enum remote_arch_types ra_type = get_remote_arch();		char *p = smb_buf(inbuf);    		char *save_p = smb_buf(inbuf);		uint16 byte_count;					if(global_client_caps == 0) {			global_client_caps = IVAL(inbuf,smb_vwv11);					if (!(global_client_caps & CAP_STATUS32)) {				remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);			}			/* client_caps is used as final determination if client is NT or Win95. 			   This is needed to return the correct error codes in some			   circumstances.			*/					if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {				if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {					set_remote_arch( RA_WIN95);				}			}		}		if (!doencrypt) {			/* both Win95 and WinNT stuff up the password lengths for			   non-encrypting systems. Uggh. 			   			   if passlen1==24 its a win95 system, and its setting the			   password length incorrectly. Luckily it still works with the			   default code because Win95 will null terminate the password			   anyway 			   			   if passlen1>0 and passlen2>0 then maybe its a NT box and its			   setting passlen2 to some random value which really stuffs			   things up. we need to fix that one.  */						if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)				passlen2 = 0;		}				/* check for nasty tricks */		if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);		}		if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);		}		/* Save the lanman2 password and the NT md4 password. */				if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {			doencrypt = False;		}		if (doencrypt) {			lm_resp = data_blob(p, passlen1);			nt_resp = data_blob(p+passlen1, passlen2);		} else {			pstring pass;			BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;#if 0			/* This was the previous fix. Not sure if it's still valid. JRA. */			if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {				/* NT4.0 stuffs up plaintext unicode password lengths... */				srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,					sizeof(pass), passlen1, STR_TERMINATE);#endif			if (unic && (passlen2 == 0) && passlen1) {				/* Only a ascii plaintext password was sent. */				srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),					passlen1, STR_TERMINATE|STR_ASCII);			} else {				srvstr_pull(inbuf, pass, smb_buf(inbuf), 					sizeof(pass),  unic ? passlen2 : passlen1, 					STR_TERMINATE);			}			plaintext_password = data_blob(pass, strlen(pass)+1);		}				p += passlen1 + passlen2;		p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);		p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);		p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);		p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);		/* not documented or decoded by Ethereal but there is one more string 		   in the extra bytes which is the same as the PrimaryDomain when using 		   extended security.  Windows NT 4 and 2003 use this string to store 		   the native lanman string. Windows 9x does not include a string here 		   at all so we have to check if we have any extra bytes left */				byte_count = SVAL(inbuf, smb_vwv13);		if ( PTR_DIFF(p, save_p) < byte_count)			p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);		else 			fstrcpy( primary_domain, "null" );		DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",			 domain, native_os, native_lanman, primary_domain));		if ( ra_type == RA_WIN2K ) {			if ( strlen(native_lanman) == 0 )				ra_lanman_string( primary_domain );			else				ra_lanman_string( native_lanman );		}	}	if (SVAL(inbuf,smb_vwv4) == 0) {		setup_new_vc_session();	}	DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));	if (*user) {		if (global_spnego_negotiated) {						/* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */						DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));			return ERROR_NT(NT_STATUS_LOGON_FAILURE);		}		fstrcpy(sub_user, user);	} else {		fstrcpy(sub_user, lp_guestaccount());	}	sub_set_smb_name(sub_user);	reload_services(True);		if (lp_security() == SEC_SHARE) {		/* in share level we should ignore any passwords */		data_blob_free(&lm_resp);		data_blob_free(&nt_resp);		data_blob_clear_free(&plaintext_password);		map_username(sub_user);		add_session_user(sub_user);		/* Then force it to null for the benfit of the code below */		*user = 0;	}		if (!*user) {		nt_status = check_guest_password(&server_info);	} else if (doencrypt) {		if (!negprot_global_auth_context) {			DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted session setup without negprot denied!\n"));			return ERROR_NT(NT_STATUS_LOGON_FAILURE);		}		nt_status = make_user_info_for_reply_enc(&user_info, user, domain,		                                         lm_resp, nt_resp);		if (NT_STATUS_IS_OK(nt_status)) {			nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 										     user_info, 										     &server_info);		}	} else {		struct auth_context *plaintext_auth_context = NULL;		const uint8 *chal;		if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {			chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);						if (!make_user_info_for_reply(&user_info, 						      user, domain, chal,						      plaintext_password)) {				nt_status = NT_STATUS_NO_MEMORY;			}					if (NT_STATUS_IS_OK(nt_status)) {				nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, 											user_info, 											&server_info); 								(plaintext_auth_context->free)(&plaintext_auth_context);			}		}	}	free_user_info(&user_info);		if (!NT_STATUS_IS_OK(nt_status)) {		nt_status = do_map_to_guest(nt_status, &server_info, user, domain);	}		if (!NT_STATUS_IS_OK(nt_status)) {		data_blob_free(&nt_resp);		data_blob_free(&lm_resp);		data_blob_clear_free(&plaintext_password);		return ERROR_NT(nt_status_squash(nt_status));	}	if (server_info->user_session_key.data) {		session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);	} else {		session_key = data_blob(NULL, 0);	}	data_blob_clear_free(&plaintext_password);		/* it's ok - setup a reply */	set_message(outbuf,3,0,True);	if (Protocol >= PROTOCOL_NT1) {		char *p = smb_buf( outbuf );		p += add_signature( outbuf, p );		set_message_end( outbuf, p );		/* perhaps grab OS version here?? */	}		if (server_info->guest) {		SSVAL(outbuf,smb_vwv2,1);	}	/* register the name and uid as being validated, so further connections	   to a uid can get through without a password, on the same VC */	/* register_vuid keeps the server info */	sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);	data_blob_free(&nt_resp);	data_blob_free(&lm_resp);	if (sess_vuid == -1) {		return ERROR_NT(NT_STATUS_LOGON_FAILURE);	}	/* current_user_info is changed on new vuid */	reload_services( True );	sessionsetup_start_signing_engine(server_info, inbuf);	SSVAL(outbuf,smb_uid,sess_vuid);	SSVAL(inbuf,smb_uid,sess_vuid);		if (!done_sesssetup)		max_send = MIN(max_send,smb_bufsize);		done_sesssetup = True;		END_PROFILE(SMBsesssetupX);	return chain_reply(inbuf,outbuf,length,bufsize);}

⌨️ 快捷键说明

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