Beispiel #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;
}
Beispiel #2
0
static NTSTATUS smbd_smb2_spnego_auth(struct smbd_smb2_session *session,
					struct smbd_smb2_request *smb2req,
					uint8_t in_security_mode,
					DATA_BLOB in_security_buffer,
					uint16_t *out_session_flags,
					DATA_BLOB *out_security_buffer,
					uint64_t *out_session_id)
{
	DATA_BLOB auth = data_blob_null;
	DATA_BLOB auth_out = data_blob_null;
	NTSTATUS status;

	if (!spnego_parse_auth(talloc_tos(), in_security_buffer, &auth)) {
		TALLOC_FREE(session);
		return NT_STATUS_LOGON_FAILURE;
	}

	if (auth.data[0] == ASN1_APPLICATION(0)) {
		/* Might be a second negTokenTarg packet */
		DATA_BLOB secblob_in = data_blob_null;
		char *kerb_mech = NULL;

		status = parse_spnego_mechanisms(talloc_tos(),
				in_security_buffer,
				&secblob_in, &kerb_mech);
		if (!NT_STATUS_IS_OK(status)) {
			TALLOC_FREE(session);
			return status;
		}

#ifdef HAVE_KRB5
		if (kerb_mech && ((lp_security()==SEC_ADS) ||
					USE_KERBEROS_KEYTAB) ) {
			status = smbd_smb2_session_setup_krb5(session,
					smb2req,
					in_security_mode,
					&secblob_in,
					kerb_mech,
					out_session_flags,
					out_security_buffer,
					out_session_id);

			data_blob_free(&secblob_in);
			TALLOC_FREE(kerb_mech);
			if (!NT_STATUS_IS_OK(status)) {
				TALLOC_FREE(session);
			}
			return status;
		}
#endif

		/* Can't blunder into NTLMSSP auth if we have
		 * a krb5 ticket. */

		if (kerb_mech) {
			DEBUG(3,("smb2: network "
				"misconfiguration, client sent us a "
				"krb5 ticket and kerberos security "
				"not enabled\n"));
			TALLOC_FREE(session);
			data_blob_free(&secblob_in);
			TALLOC_FREE(kerb_mech);
			return NT_STATUS_LOGON_FAILURE;
		}

		data_blob_free(&secblob_in);
	}

	if (session->auth_ntlmssp_state == NULL) {
		status = auth_ntlmssp_prepare(session->sconn->remote_address,
					    &session->auth_ntlmssp_state);
		if (!NT_STATUS_IS_OK(status)) {
			data_blob_free(&auth);
			TALLOC_FREE(session);
			return status;
		}

		auth_ntlmssp_want_feature(session->auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);

		status = auth_ntlmssp_start(session->auth_ntlmssp_state);
		if (!NT_STATUS_IS_OK(status)) {
			data_blob_free(&auth);
			TALLOC_FREE(session);
			return status;
		}
	}

	status = auth_ntlmssp_update(session->auth_ntlmssp_state,
				     talloc_tos(), auth,
				     &auth_out);
	/* If status is NT_STATUS_OK then we need to get the token.
	 * Map to guest is now internal to auth_ntlmssp */
	if (NT_STATUS_IS_OK(status)) {
		status = auth_ntlmssp_session_info(session,
						   session->auth_ntlmssp_state,
						   &session->session_info);
	}

	if (!NT_STATUS_IS_OK(status) &&
			!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		TALLOC_FREE(session->auth_ntlmssp_state);
		data_blob_free(&auth);
		TALLOC_FREE(session);
		return status;
	}

	data_blob_free(&auth);

	*out_security_buffer = spnego_gen_auth_response(smb2req,
				&auth_out, status, NULL);

	if (out_security_buffer->data == NULL) {
		TALLOC_FREE(session->auth_ntlmssp_state);
		TALLOC_FREE(session);
		return NT_STATUS_NO_MEMORY;
	}

	*out_session_id = session->vuid;

	if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		return NT_STATUS_MORE_PROCESSING_REQUIRED;
	}

	/* We're done - claim the session. */
	return smbd_smb2_common_ntlmssp_auth_return(session,
						smb2req,
						in_security_mode,
						in_security_buffer,
						out_session_flags,
						out_session_id);
}
Beispiel #3
0
static NTSTATUS smbd_smb2_spnego_negotiate(struct smbd_smb2_session *session,
					struct smbd_smb2_request *smb2req,
					uint8_t in_security_mode,
					DATA_BLOB in_security_buffer,
					uint16_t *out_session_flags,
					DATA_BLOB *out_security_buffer,
					uint64_t *out_session_id)
{
	DATA_BLOB secblob_in = data_blob_null;
	DATA_BLOB chal_out = data_blob_null;
	char *kerb_mech = NULL;
	NTSTATUS status;

	/* Ensure we have no old NTLM state around. */
	TALLOC_FREE(session->auth_ntlmssp_state);

	status = parse_spnego_mechanisms(talloc_tos(), in_security_buffer,
			&secblob_in, &kerb_mech);
	if (!NT_STATUS_IS_OK(status)) {
		goto out;
	}

#ifdef HAVE_KRB5
	if (kerb_mech && ((lp_security()==SEC_ADS) ||
				USE_KERBEROS_KEYTAB) ) {
		status = smbd_smb2_session_setup_krb5(session,
				smb2req,
				in_security_mode,
				&secblob_in,
				kerb_mech,
				out_session_flags,
				out_security_buffer,
				out_session_id);

		goto out;
	}
#endif

	if (kerb_mech) {
		/* The mechtoken is a krb5 ticket, but
		 * we need to fall back to NTLM. */

		DEBUG(3,("smb2: Got krb5 ticket in SPNEGO "
			"but set to downgrade to NTLMSSP\n"));

		status = NT_STATUS_MORE_PROCESSING_REQUIRED;
	} else {
		/* Fall back to NTLMSSP. */
		status = auth_ntlmssp_prepare(session->sconn->remote_address,
					    &session->auth_ntlmssp_state);
		if (!NT_STATUS_IS_OK(status)) {
			goto out;
		}

		auth_ntlmssp_want_feature(session->auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);

		status = auth_ntlmssp_start(session->auth_ntlmssp_state);
		if (!NT_STATUS_IS_OK(status)) {
			goto out;
		}

		status = auth_ntlmssp_update(session->auth_ntlmssp_state,
					     talloc_tos(),
					     secblob_in,
					     &chal_out);
	}

	if (!NT_STATUS_IS_OK(status) &&
			!NT_STATUS_EQUAL(status,
				NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		goto out;
	}

	*out_security_buffer = spnego_gen_auth_response(smb2req,
						&chal_out,
						status,
						OID_NTLMSSP);
	if (out_security_buffer->data == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}
	*out_session_id = session->vuid;

  out:

	data_blob_free(&secblob_in);
	data_blob_free(&chal_out);
	TALLOC_FREE(kerb_mech);
	if (!NT_STATUS_IS_OK(status) &&
			!NT_STATUS_EQUAL(status,
				NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		TALLOC_FREE(session->auth_ntlmssp_state);
		TALLOC_FREE(session);
	}
	return status;
}
Beispiel #4
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;
}