예제 #1
0
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)
{
	DATA_BLOB secblob;
	DATA_BLOB chal;
	BOOL got_kerberos_mechanism = False;
	NTSTATUS status;

	status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism);
	if (!NT_STATUS_IS_OK(status)) {
		/* Kill the intermediate vuid */
		invalidate_vuid(vuid);
		return ERROR_NT(nt_status_squash(status));
	}

	DEBUG(3,("reply_spnego_negotiate: 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()) ) {
		BOOL destroy_vuid = True;
		int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
						length, bufsize, &secblob, &destroy_vuid);
		data_blob_free(&secblob);
		if (destroy_vuid) {
			/* Kill the intermediate vuid */
			invalidate_vuid(vuid);
		}
		return ret;
	}
#endif

	if (*auth_ntlmssp_state) {
		auth_ntlmssp_end(auth_ntlmssp_state);
	}

	status = auth_ntlmssp_start(auth_ntlmssp_state);
	if (!NT_STATUS_IS_OK(status)) {
		/* Kill the intermediate vuid */
		invalidate_vuid(vuid);
		return ERROR_NT(nt_status_squash(status));
	}

	status = auth_ntlmssp_update(*auth_ntlmssp_state, 
					secblob, &chal);

	data_blob_free(&secblob);

	reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
			     &chal, status, True);

	data_blob_free(&chal);

	/* already replied */
	return -1;
}
예제 #2
0
static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
			     int length, int bufsize,
			     DATA_BLOB blob1)
{
	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
		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
	}
	
	if (!global_ntlmssp_state) {
		/* auth before negotiatiate? */
		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
	}
	
	nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
						auth, &auth_reply);

	data_blob_free(&auth);

	reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
			     &auth_reply, nt_status);
		
	data_blob_free(&auth_reply);

	/* and tell smbd that we have already replied to this packet */
	return -1;
}
예제 #3
0
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 = data_blob(NULL,0);
	DATA_BLOB auth_reply = data_blob(NULL,0);
	DATA_BLOB secblob = data_blob(NULL,0);
	NTSTATUS 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_squash(NT_STATUS_INVALID_PARAMETER));
	}

	if (auth.data[0] == ASN1_APPLICATION(0)) {
		/* Might be a second negTokenTarg packet */

		BOOL got_krb5_mechanism = False;
		status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism);
		if (NT_STATUS_IS_OK(status)) {
			DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length));
#ifdef HAVE_KRB5
			if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
				BOOL destroy_vuid = True;
				int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
								length, bufsize, &secblob, &destroy_vuid);
				data_blob_free(&secblob);
				data_blob_free(&auth);
				if (destroy_vuid) {
					/* Kill the intermediate vuid */
					invalidate_vuid(vuid);
				}
				return ret;
			}
#endif
		}
	}

	/* If we get here it wasn't a negTokenTarg auth packet. */
	data_blob_free(&secblob);
	
	if (!*auth_ntlmssp_state) {
		/* Kill the intermediate vuid */
		invalidate_vuid(vuid);

		/* auth before negotiatiate? */
		return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
	}
	
	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, status, True);
		
	data_blob_free(&auth_reply);

	/* and tell smbd that we have already replied to this packet */
	return -1;
}
예제 #4
0
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;
	NTSTATUS status = NT_STATUS_OK;
	uint16 smbpid = SVAL(inbuf,smb_pid);

	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_squash(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 ) {
		/* Vista sets neither the OS or lanman strings */

		if ( !strlen(native_os) && !strlen(native_lanman) )
			set_remote_arch(RA_VISTA);
		
		/* 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) {
		struct pending_auth_data *pad = get_pending_auth_data(smbpid);
		if (pad) {
			DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
				(unsigned int)pad->vuid ));
			vuid = pad->vuid;
			vuser = get_partial_auth_user_struct(vuid);
		}
	}

	if (!vuser) {
		vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
		if (vuid == UID_FIELD_INVALID ) {
			data_blob_free(&blob1);
			return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
		}
	
		vuser = get_partial_auth_user_struct(vuid);
	}

	if (!vuser) {
		data_blob_free(&blob1);
		return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
	}
	
	SSVAL(outbuf,smb_uid,vuid);

	/* Large (greater than 4k) SPNEGO blobs are split into multiple
	 * sessionsetup requests as the Windows limit on the security blob
	 * field is 4k. Bug #4400. JRA.
	 */

	status = check_spnego_blob_complete(smbpid, vuid, &blob1);
	if (!NT_STATUS_IS_OK(status)) {
		if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
			/* Real error - kill the intermediate vuid */
			invalidate_vuid(vuid);
		}
		data_blob_free(&blob1);
		return ERROR_NT(nt_status_squash(status));
	}

	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;
		if (!vuser->auth_ntlmssp_state) {
			status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
			if (!NT_STATUS_IS_OK(status)) {
				/* Kill the intermediate vuid */
				invalidate_vuid(vuid);
				data_blob_free(&blob1);
				return ERROR_NT(nt_status_squash(status));
			}
		}

		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, 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_squash(NT_STATUS_LOGON_FAILURE));
}
예제 #5
0
static int reply_spnego_negotiate(connection_struct *conn, 
				  char *inbuf,
				  char *outbuf,
				  int length, int bufsize,
				  DATA_BLOB blob1)
{
	char *OIDs[ASN1_MAX_OIDS];
	DATA_BLOB secblob;
	int i;
	DATA_BLOB chal;
	BOOL got_kerberos = False;
	NTSTATUS nt_status;

	/* parse out the OIDs and the first sec blob */
	if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
		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              */
	
	if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
	    strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
		got_kerberos = True;
	}
		
	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 && (SEC_ADS == lp_security())) {
		int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
						length, bufsize, &secblob);
		data_blob_free(&secblob);
		return ret;
	}
#endif

	if (global_ntlmssp_state) {
		auth_ntlmssp_end(&global_ntlmssp_state);
	}

	nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return ERROR_NT(nt_status);
	}

	nt_status = auth_ntlmssp_update(global_ntlmssp_state, 
					secblob, &chal);

	data_blob_free(&secblob);

	reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state,
			     &chal, nt_status);
		
	data_blob_free(&chal);

	/* already replied */
	return -1;
}
예제 #6
0
파일: sesssetup.c 프로젝트: hajuuk/R7000
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();

	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 );
	}
		
	if (blob1.data[0] == ASN1_APPLICATION(0)) {
		/* its a negTokenTarg packet */
		ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
		data_blob_free(&blob1);
		return ret;
	}

	if (blob1.data[0] == ASN1_CONTEXT(1)) {
		/* its a auth packet */
		ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
		data_blob_free(&blob1);
		return ret;
	}

	/* Foxconn modified start pling 12/29/2011 */
	/* Fix Android partial auth issue.
	 * Port from Samba 3.0.24 (used by WNDR3800) */
	if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
		DATA_BLOB chal;
		NTSTATUS nt_status;
		if (!global_ntlmssp_state) {
	    	nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
			if (!NT_STATUS_IS_OK(nt_status)) {
				return ERROR_NT(nt_status_squash(nt_status));
			}
		}

		nt_status = auth_ntlmssp_update(global_ntlmssp_state,
						blob1, &chal);
		
		data_blob_free(&blob1);
		
		reply_spnego_ntlmssp(conn, inbuf, outbuf, 
					   &global_ntlmssp_state,
					   &chal, nt_status, False);
		data_blob_free(&chal);
		return -1;
	}
    /* Foxconn added end pling 12/29/2011 */

	/* 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);
}