sesssetup.c

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

C
1,115
字号
		}				SSVAL(outbuf, smb_uid, sess_vuid);		sessionsetup_start_signing_engine(server_info, inbuf);	}        /* wrap that up in a nice GSS-API wrapping */	if (NT_STATUS_IS_OK(ret)) {		ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);	} else {		ap_rep_wrapped = data_blob(NULL, 0);	}	response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);	reply_sesssetup_blob(conn, outbuf, response, ret);	data_blob_free(&ap_rep);	data_blob_free(&ap_rep_wrapped);	data_blob_free(&response);	talloc_destroy(mem_ctx);	return -1; /* already replied */}#endif/**************************************************************************** Send a session setup reply, wrapped in SPNEGO. Get vuid and check first. End the NTLMSSP exchange context if we are OK/complete fail This should be split into two functions, one to handle each leg of the NTLM auth steps.***************************************************************************/static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,				 uint16 vuid,				 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,				 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status, 				 BOOL wrap) {	BOOL ret;	DATA_BLOB response;	struct auth_serversupplied_info *server_info = NULL;	if (NT_STATUS_IS_OK(nt_status)) {		server_info = (*auth_ntlmssp_state)->server_info;	} else {		nt_status = do_map_to_guest(nt_status, 					    &server_info, 					    (*auth_ntlmssp_state)->ntlmssp_state->user, 					    (*auth_ntlmssp_state)->ntlmssp_state->domain);	}	if (NT_STATUS_IS_OK(nt_status)) {		int sess_vuid;		DATA_BLOB nullblob = data_blob(NULL, 0);		DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);		/* register_vuid keeps the server info */		sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);		(*auth_ntlmssp_state)->server_info = NULL;		if (sess_vuid == -1) {			nt_status = NT_STATUS_LOGON_FAILURE;		} else {						/* current_user_info is changed on new vuid */			reload_services( True );			set_message(outbuf,4,0,True);			SSVAL(outbuf, smb_vwv3, 0);						if (server_info->guest) {				SSVAL(outbuf,smb_vwv2,1);			}						SSVAL(outbuf,smb_uid,sess_vuid);			sessionsetup_start_signing_engine(server_info, inbuf);		}	}	if (wrap) {		response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);	} else {		response = *ntlmssp_blob;	}	ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);	if (wrap) {		data_blob_free(&response);	}	/* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,	   and the other end, that we are not finished yet. */	if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {		/* NB. This is *NOT* an error case. JRA */		auth_ntlmssp_end(auth_ntlmssp_state);		/* Kill the intermediate vuid */		invalidate_vuid(vuid);	}	return ret;}/**************************************************************************** Reply to a session setup spnego negotiate packet.****************************************************************************/static int reply_spnego_negotiate(connection_struct *conn, 				  char *inbuf,				  char *outbuf,				  uint16 vuid,				  int length, int bufsize,				  DATA_BLOB blob1,				  AUTH_NTLMSSP_STATE **auth_ntlmssp_state){	char *OIDs[ASN1_MAX_OIDS];	DATA_BLOB secblob;	int i;	DATA_BLOB chal;#ifdef HAVE_KRB5	BOOL got_kerberos_mechanism = False;#endif	NTSTATUS nt_status;	/* parse out the OIDs and the first sec blob */	if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {		/* Kill the intermediate vuid */		invalidate_vuid(vuid);		return ERROR_NT(NT_STATUS_LOGON_FAILURE);	}	/* only look at the first OID for determining the mechToken --	   accoirding to RFC2478, we should choose the one we want 	   and renegotiate, but i smell a client bug here..  	   	   Problem observed when connecting to a member (samba box) 	   of an AD domain as a user in a Samba domain.  Samba member 	   server sent back krb5/mskrb5/ntlmssp as mechtypes, but the 	   client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an 	   NTLMSSP mechtoken.                 --jerry              */#ifdef HAVE_KRB5		if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||	    strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {		got_kerberos_mechanism = True;	}#endif			for (i=0;OIDs[i];i++) {		DEBUG(3,("Got OID %s\n", OIDs[i]));		free(OIDs[i]);	}	DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));#ifdef HAVE_KRB5	if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {		int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 						length, bufsize, &secblob);		data_blob_free(&secblob);		/* Kill the intermediate vuid */		invalidate_vuid(vuid);		return ret;	}#endif	if (*auth_ntlmssp_state) {		auth_ntlmssp_end(auth_ntlmssp_state);	}	nt_status = auth_ntlmssp_start(auth_ntlmssp_state);	if (!NT_STATUS_IS_OK(nt_status)) {		/* Kill the intermediate vuid */		invalidate_vuid(vuid);		return ERROR_NT(nt_status);	}	nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, 					secblob, &chal);	data_blob_free(&secblob);	reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,			     &chal, nt_status, True);	data_blob_free(&chal);	/* already replied */	return -1;}	/**************************************************************************** Reply to a session setup spnego auth packet.****************************************************************************/static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,			     uint16 vuid,			     int length, int bufsize,			     DATA_BLOB blob1,			     AUTH_NTLMSSP_STATE **auth_ntlmssp_state){	DATA_BLOB auth, auth_reply;	NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;	if (!spnego_parse_auth(blob1, &auth)) {#if 0		file_save("auth.dat", blob1.data, blob1.length);#endif		/* Kill the intermediate vuid */		invalidate_vuid(vuid);		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);	}		if (!*auth_ntlmssp_state) {		/* Kill the intermediate vuid */		invalidate_vuid(vuid);		/* auth before negotiatiate? */		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);	}		nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, 					auth, &auth_reply);	data_blob_free(&auth);	reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, 			     auth_ntlmssp_state,			     &auth_reply, nt_status, True);			data_blob_free(&auth_reply);	/* and tell smbd that we have already replied to this packet */	return -1;}/**************************************************************************** Reply to a session setup command.****************************************************************************/static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,					char *outbuf,					int length,int bufsize){	uint8 *p;	DATA_BLOB blob1;	int ret;	size_t bufrem;	fstring native_os, native_lanman, primary_domain;	char *p2;	uint16 data_blob_len = SVAL(inbuf, smb_vwv7);	enum remote_arch_types ra_type = get_remote_arch();	int vuid = SVAL(inbuf,smb_uid);	user_struct *vuser = NULL;	DEBUG(3,("Doing spnego session setup\n"));	if (global_client_caps == 0) {		global_client_caps = IVAL(inbuf,smb_vwv10);		if (!(global_client_caps & CAP_STATUS32)) {			remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);		}	}			p = (uint8 *)smb_buf(inbuf);	if (data_blob_len == 0) {		/* an invalid request */		return ERROR_NT(NT_STATUS_LOGON_FAILURE);	}	bufrem = smb_bufrem(inbuf, p);	/* pull the spnego blob */	blob1 = data_blob(p, MIN(bufrem, data_blob_len));#if 0	file_save("negotiate.dat", blob1.data, blob1.length);#endif	p2 = inbuf + smb_vwv13 + data_blob_len;	p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);	p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);	p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);	DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", 		native_os, native_lanman, primary_domain));	if ( ra_type == RA_WIN2K ) {		/* Windows 2003 doesn't set the native lanman string, 		   but does set primary domain which is a bug I think */			   		if ( !strlen(native_lanman) )			ra_lanman_string( primary_domain );		else			ra_lanman_string( native_lanman );	}			vuser = get_partial_auth_user_struct(vuid);	if (!vuser) {		vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);		if (vuid == -1) {			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);		}			vuser = get_partial_auth_user_struct(vuid);	}	if (!vuser) {		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);	}		SSVAL(outbuf,smb_uid,vuid);		if (blob1.data[0] == ASN1_APPLICATION(0)) {		/* its a negTokenTarg packet */		ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,					     &vuser->auth_ntlmssp_state);		data_blob_free(&blob1);		return ret;	}	if (blob1.data[0] == ASN1_CONTEXT(1)) {		/* its a auth packet */		ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,					&vuser->auth_ntlmssp_state);		data_blob_free(&blob1);		return ret;	}	if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {		DATA_BLOB chal;		NTSTATUS nt_status;		if (!vuser->auth_ntlmssp_state) {			nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);			if (!NT_STATUS_IS_OK(nt_status)) {				/* Kill the intermediate vuid */				invalidate_vuid(vuid);								return ERROR_NT(nt_status);			}		}		nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,						blob1, &chal);				data_blob_free(&blob1);				reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, 					   &vuser->auth_ntlmssp_state,					   &chal, nt_status, False);		data_blob_free(&chal);		return -1;	}	/* what sort of packet is this? */	DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));	data_blob_free(&blob1);	return ERROR_NT(NT_STATUS_LOGON_FAILURE);}/**************************************************************************** On new VC == 0, shutdown *all* old connections and users. It seems that only NT4.x does this. At W2K and above (XP etc.). a new session setup with VC==0 is ignored.

⌨️ 快捷键说明

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