Ejemplo n.º 1
0
static struct passwd *getpwnam_alloc_cached(TALLOC_CTX *mem_ctx, const char *name)
{
	struct passwd *pw, *for_cache;

	pw = (struct passwd *)memcache_lookup_talloc(
		NULL, GETPWNAM_CACHE, data_blob_string_const_null(name));
	if (pw != NULL) {
		return tcopy_passwd(mem_ctx, pw);
	}

	pw = getpwnam(name);
	if (pw == NULL) {
		return NULL;
	}

	for_cache = tcopy_passwd(talloc_tos(), pw);
	if (for_cache == NULL) {
		return NULL;
	}

	memcache_add_talloc(NULL, GETPWNAM_CACHE,
			data_blob_string_const_null(name), &for_cache);

	return tcopy_passwd(mem_ctx, pw);
}
Ejemplo n.º 2
0
static bool delete_getpwnam_cache(const char *username)
{
	DATA_BLOB name = data_blob_string_const_null(username);
	DEBUG(6, ("Delete passwd struct for %s from memcache\n",
		  username));
	memcache_delete(NULL, GETPWNAM_CACHE, name);
	return true;
}
Ejemplo n.º 3
0
static bool test_string_null(struct torture_context *tctx)
{
	DATA_BLOB blob = data_blob_string_const_null("bla");	

	torture_assert_int_equal(tctx, blob.length, 4, "blob length");
	torture_assert_str_equal(tctx, (char *)blob.data, "bla", "blob data");

	return true;
}
Ejemplo n.º 4
0
/* string_match - match string s against token tok */
static bool string_match(const char *tok,const char *s)
{
	size_t     tok_len;
	size_t     str_len;
	const char   *cut;

	/* Return true if a token has the magic value "ALL". Return
	 * true if the token is "FAIL". If the token starts with a "."
	 * (domain name), return true if it matches the last fields of
	 * the string. If the token has the magic value "LOCAL",
	 * return true if the string does not contain a "."
	 * character. If the token ends on a "." (network number),
	 * return true if it matches the first fields of the
	 * string. If the token begins with a "@" (netgroup name),
	 * return true if the string is a (host) member of the
	 * netgroup. Return true if the token fully matches the
	 * string. If the token is a netnumber/netmask pair, return
	 * true if the address is a member of the specified subnet.
	 */

	if (tok[0] == '.') {			/* domain: match last fields */
		if ((str_len = strlen(s)) > (tok_len = strlen(tok))
		    && strequal(tok, s + str_len - tok_len)) {
			return true;
		}
	} else if (tok[0] == '@') { /* netgroup: look it up */
#ifdef	HAVE_NETGROUP
		DATA_BLOB tmp;
		char *mydomain = NULL;
		char *hostname = NULL;
		bool netgroup_ok = false;

		if (memcache_lookup(
			    NULL, SINGLETON_CACHE,
			    data_blob_string_const_null("yp_default_domain"),
			    &tmp)) {

			SMB_ASSERT(tmp.length > 0);
			mydomain = (tmp.data[0] == '\0')
				? NULL : (char *)tmp.data;
		}
		else {
			yp_get_default_domain(&mydomain);

			memcache_add(
				NULL, SINGLETON_CACHE,
				data_blob_string_const_null("yp_default_domain"),
				data_blob_string_const_null(mydomain?mydomain:""));
		}

		if (!mydomain) {
			DEBUG(0,("Unable to get default yp domain. "
				"Try without it.\n"));
		}
		if (!(hostname = SMB_STRDUP(s))) {
			DEBUG(1,("out of memory for strdup!\n"));
			return false;
		}

		netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain);

		DEBUG(5,("looking for %s of domain %s in netgroup %s gave %s\n",
			 hostname,
			 mydomain?mydomain:"(ANY)",
			 tok+1,
			 BOOLSTR(netgroup_ok)));

		SAFE_FREE(hostname);

		if (netgroup_ok)
			return true;
#else
		DEBUG(0,("access: netgroup support is not configured\n"));
		return false;
#endif
	} else if (strequal(tok, "ALL")) {	/* all: match any */
		return true;
	} else if (strequal(tok, "FAIL")) {	/* fail: match any */
		return true;
	} else if (strequal(tok, "LOCAL")) {	/* local: no dots */
		if (strchr_m(s, '.') == 0 && !strequal(s, "unknown")) {
			return true;
		}
	} else if (strequal(tok, s)) {   /* match host name or address */
		return true;
	} else if (tok[(tok_len = strlen(tok)) - 1] == '.') {	/* network */
		if (strncmp(tok, s, tok_len) == 0) {
			return true;
		}
	} else if ((cut = strchr_m(tok, '/')) != 0) {	/* netnumber/netmask */
		if ((isdigit(s[0]) && strchr_m(tok, '.') != NULL) ||
			(tok[0] == '[' && cut > tok && cut[-1] == ']') ||
			((isxdigit(s[0]) || s[0] == ':') &&
				strchr_m(tok, ':') != NULL)) {
			/* IPv4/netmask or
			 * [IPv6:addr]/netmask or IPv6:addr/netmask */
			return masked_match(tok, cut, s);
		}
	} else if (strchr_m(tok, '*') != 0 || strchr_m(tok, '?')) {
		return unix_wild_match(tok, s);
	}
	return false;
}
Ejemplo n.º 5
0
static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
					struct smbd_smb2_request *smb2req,
					uint8_t in_security_mode,
					struct auth_session_info *session_info,
					uint16_t *out_session_flags,
					uint64_t *out_session_id)
{
	NTSTATUS status;
	bool guest = false;
	uint8_t session_key[16];
	struct smbXsrv_session *x = session;
	struct smbXsrv_connection *xconn = smb2req->xconn;
	struct _derivation {
		DATA_BLOB label;
		DATA_BLOB context;
	};
	struct {
		struct _derivation signing;
		struct _derivation encryption;
		struct _derivation decryption;
		struct _derivation application;
	} derivation = { };

	if (xconn->protocol >= PROTOCOL_SMB3_10) {
		struct smbXsrv_preauth *preauth;
		struct _derivation *d;
		DATA_BLOB p;
		struct hc_sha512state sctx;
		size_t i;

		preauth = talloc_move(smb2req, &session->preauth);

		samba_SHA512_Init(&sctx);
		samba_SHA512_Update(&sctx, preauth->sha512_value,
				    sizeof(preauth->sha512_value));
		for (i = 1; i < smb2req->in.vector_count; i++) {
			samba_SHA512_Update(&sctx,
					    smb2req->in.vector[i].iov_base,
					    smb2req->in.vector[i].iov_len);
		}
		samba_SHA512_Final(preauth->sha512_value, &sctx);

		p = data_blob_const(preauth->sha512_value,
				    sizeof(preauth->sha512_value));

		d = &derivation.signing;
		d->label = data_blob_string_const_null("SMBSigningKey");
		d->context = p;

		d = &derivation.decryption;
		d->label = data_blob_string_const_null("SMBC2SCipherKey");
		d->context = p;

		d = &derivation.encryption;
		d->label = data_blob_string_const_null("SMBS2CCipherKey");
		d->context = p;

		d = &derivation.application;
		d->label = data_blob_string_const_null("SMBAppKey");
		d->context = p;

	} else if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d;

		d = &derivation.signing;
		d->label = data_blob_string_const_null("SMB2AESCMAC");
		d->context = data_blob_string_const_null("SmbSign");

		d = &derivation.decryption;
		d->label = data_blob_string_const_null("SMB2AESCCM");
		d->context = data_blob_string_const_null("ServerIn ");

		d = &derivation.encryption;
		d->label = data_blob_string_const_null("SMB2AESCCM");
		d->context = data_blob_string_const_null("ServerOut");

		d = &derivation.application;
		d->label = data_blob_string_const_null("SMB2APP");
		d->context = data_blob_string_const_null("SmbRpc");
	}

	if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
	    (xconn->smb2.server.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
	{
		x->global->signing_required = true;
	}

	if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED) &&
	    (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
		x->encryption_desired = true;
	}

	if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
		x->encryption_desired = true;
		x->global->encryption_required = true;
	}

	if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
		/* we map anonymous to guest internally */
		*out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
		*out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
		/* force no signing */
		x->global->signing_required = false;
		guest = true;
	}

	if (guest && x->global->encryption_required) {
		DEBUG(1,("reject guest session as encryption is required\n"));
		return NT_STATUS_ACCESS_DENIED;
	}

	if (xconn->smb2.server.cipher == 0) {
		if (x->global->encryption_required) {
			DEBUG(1,("reject session with dialect[0x%04X] "
				 "as encryption is required\n",
				 xconn->smb2.server.dialect));
			return NT_STATUS_ACCESS_DENIED;
		}
	}

	if (x->encryption_desired) {
		*out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
	}

	ZERO_STRUCT(session_key);
	memcpy(session_key, session_info->session_key.data,
	       MIN(session_info->session_key.length, sizeof(session_key)));

	x->global->signing_key = data_blob_talloc(x->global,
						  session_key,
						  sizeof(session_key));
	if (x->global->signing_key.data == NULL) {
		ZERO_STRUCT(session_key);
		return NT_STATUS_NO_MEMORY;
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.signing;

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->signing_key.data);
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.decryption;

		x->global->decryption_key = data_blob_talloc(x->global,
							     session_key,
							     sizeof(session_key));
		if (x->global->decryption_key.data == NULL) {
			ZERO_STRUCT(session_key);
			return NT_STATUS_NO_MEMORY;
		}

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->decryption_key.data);
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.encryption;
		size_t nonce_size;

		x->global->encryption_key = data_blob_talloc(x->global,
							     session_key,
							     sizeof(session_key));
		if (x->global->encryption_key.data == NULL) {
			ZERO_STRUCT(session_key);
			return NT_STATUS_NO_MEMORY;
		}

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->encryption_key.data);

		/*
		 * CCM and GCM algorithms must never have their
		 * nonce wrap, or the security of the whole
		 * communication and the keys is destroyed.
		 * We must drop the connection once we have
		 * transfered too much data.
		 *
		 * NOTE: We assume nonces greater than 8 bytes.
		 */
		generate_random_buffer((uint8_t *)&x->nonce_high_random,
				       sizeof(x->nonce_high_random));
		switch (xconn->smb2.server.cipher) {
		case SMB2_ENCRYPTION_AES128_CCM:
			nonce_size = AES_CCM_128_NONCE_SIZE;
			break;
		case SMB2_ENCRYPTION_AES128_GCM:
			nonce_size = AES_GCM_128_IV_SIZE;
			break;
		default:
			nonce_size = 0;
			break;
		}
		x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
		x->nonce_high = 0;
		x->nonce_low = 0;
	}

	x->global->application_key = data_blob_dup_talloc(x->global,
						x->global->signing_key);
	if (x->global->application_key.data == NULL) {
		ZERO_STRUCT(session_key);
		return NT_STATUS_NO_MEMORY;
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.application;

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->application_key.data);
	}
	ZERO_STRUCT(session_key);

	x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
						x->global->signing_key);
	if (x->global->channels[0].signing_key.data == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	data_blob_clear_free(&session_info->session_key);
	session_info->session_key = data_blob_dup_talloc(session_info,
						x->global->application_key);
	if (session_info->session_key.data == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	session->compat = talloc_zero(session, struct user_struct);
	if (session->compat == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	session->compat->session = session;
	session->compat->homes_snum = -1;
	session->compat->session_info = session_info;
	session->compat->session_keystr = NULL;
	session->compat->vuid = session->global->session_wire_id;
	DLIST_ADD(smb2req->sconn->users, session->compat);
	smb2req->sconn->num_users++;

	if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
		session->compat->homes_snum =
			register_homes_share(session_info->unix_info->unix_name);
	}

	set_current_user_info(session_info->unix_info->sanitized_username,
			      session_info->unix_info->unix_name,
			      session_info->info->domain_name);

	reload_services(smb2req->sconn, conn_snum_used, true);

	session->status = NT_STATUS_OK;
	session->global->auth_session_info = session_info;
	session->global->auth_session_info_seqnum += 1;
	session->global->channels[0].auth_session_info_seqnum =
		session->global->auth_session_info_seqnum;
	session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
	session->global->expiration_time = gensec_expire_time(session->gensec);

	if (!session_claim(session)) {
		DEBUG(1, ("smb2: Failed to claim session "
			"for vuid=%llu\n",
			(unsigned long long)session->compat->vuid));
		return NT_STATUS_LOGON_FAILURE;
	}

	status = smbXsrv_session_update(session);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
			  (unsigned long long)session->compat->vuid,
			  nt_errstr(status)));
		return NT_STATUS_LOGON_FAILURE;
	}

	/*
	 * we attach the session to the request
	 * so that the response can be signed
	 */
	if (!guest) {
		smb2req->do_signing = true;
	}

	global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);

	*out_session_id = session->global->session_wire_id;

	return NT_STATUS_OK;
}
Ejemplo n.º 6
0
static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session,
					   struct smbXsrv_session_auth0 **_auth,
					   struct smbd_smb2_request *smb2req,
					   struct auth_session_info *session_info,
					   uint16_t *out_session_flags,
					   uint64_t *out_session_id)
{
	NTSTATUS status;
	struct smbXsrv_session *x = session;
	struct smbXsrv_session_auth0 *auth = *_auth;
	struct smbXsrv_connection *xconn = smb2req->xconn;
	struct smbXsrv_channel_global0 *c = NULL;
	uint8_t session_key[16];
	size_t i;
	struct _derivation {
		DATA_BLOB label;
		DATA_BLOB context;
	};
	struct {
		struct _derivation signing;
	} derivation = { };
	bool ok;

	*_auth = NULL;

	if (xconn->protocol >= PROTOCOL_SMB3_10) {
		struct smbXsrv_preauth *preauth;
		struct _derivation *d;
		DATA_BLOB p;
		struct hc_sha512state sctx;

		preauth = talloc_move(smb2req, &auth->preauth);

		samba_SHA512_Init(&sctx);
		samba_SHA512_Update(&sctx, preauth->sha512_value,
				    sizeof(preauth->sha512_value));
		for (i = 1; i < smb2req->in.vector_count; i++) {
			samba_SHA512_Update(&sctx,
					    smb2req->in.vector[i].iov_base,
					    smb2req->in.vector[i].iov_len);
		}
		samba_SHA512_Final(preauth->sha512_value, &sctx);

		p = data_blob_const(preauth->sha512_value,
				    sizeof(preauth->sha512_value));

		d = &derivation.signing;
		d->label = data_blob_string_const_null("SMBSigningKey");
		d->context = p;

	} else if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d;

		d = &derivation.signing;
		d->label = data_blob_string_const_null("SMB2AESCMAC");
		d->context = data_blob_string_const_null("SmbSign");
	}

	status = smbXsrv_session_find_channel(session, xconn, &c);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	ok = security_token_is_sid(session_info->security_token,
			&x->global->auth_session_info->security_token->sids[0]);
	if (!ok) {
		return NT_STATUS_NOT_SUPPORTED;
	}

	if (session_info->session_key.length == 0) {
		/* See [MS-SMB2] 3.3.5.2.4 for the return code. */
		return NT_STATUS_NOT_SUPPORTED;
	}

	ZERO_STRUCT(session_key);
	memcpy(session_key, session_info->session_key.data,
	       MIN(session_info->session_key.length, sizeof(session_key)));

	c->signing_key = data_blob_talloc(x->global,
					  session_key,
					  sizeof(session_key));
	if (c->signing_key.data == NULL) {
		ZERO_STRUCT(session_key);
		return NT_STATUS_NO_MEMORY;
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.signing;

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    c->signing_key.data);
	}
	ZERO_STRUCT(session_key);

	TALLOC_FREE(auth);
	status = smbXsrv_session_update(session);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
			  (unsigned long long)session->compat->vuid,
			  nt_errstr(status)));
		return NT_STATUS_LOGON_FAILURE;
	}

	*out_session_id = session->global->session_wire_id;

	return NT_STATUS_OK;
}
Ejemplo n.º 7
0
static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
					struct smbd_smb2_request *smb2req,
					uint8_t in_security_mode,
					struct auth_session_info *session_info,
					uint16_t *out_session_flags,
					uint64_t *out_session_id)
{
	NTSTATUS status;
	bool guest = false;
	uint8_t session_key[16];
	struct smbXsrv_session *x = session;
	struct smbXsrv_connection *xconn = smb2req->xconn;

	if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
	    lp_server_signing() == SMB_SIGNING_REQUIRED) {
		x->global->signing_required = true;
	}

	if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
		x->global->encryption_required = true;
	}

	if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
		/* we map anonymous to guest internally */
		*out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
		*out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
		/* force no signing */
		x->global->signing_required = false;
		guest = true;
	}

	if (guest && x->global->encryption_required) {
		DEBUG(1,("reject guest session as encryption is required\n"));
		return NT_STATUS_ACCESS_DENIED;
	}

	if (xconn->smb2.server.cipher == 0) {
		if (x->global->encryption_required) {
			DEBUG(1,("reject session with dialect[0x%04X] "
				 "as encryption is required\n",
				 xconn->smb2.server.dialect));
			return NT_STATUS_ACCESS_DENIED;
		}
	}

	if (x->global->encryption_required) {
		*out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
	}

	ZERO_STRUCT(session_key);
	memcpy(session_key, session_info->session_key.data,
	       MIN(session_info->session_key.length, sizeof(session_key)));

	x->global->signing_key = data_blob_talloc(x->global,
						  session_key,
						  sizeof(session_key));
	if (x->global->signing_key.data == NULL) {
		ZERO_STRUCT(session_key);
		return NT_STATUS_NO_MEMORY;
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		const DATA_BLOB label = data_blob_string_const_null("SMB2AESCMAC");
		const DATA_BLOB context = data_blob_string_const_null("SmbSign");

		smb2_key_derivation(session_key, sizeof(session_key),
				    label.data, label.length,
				    context.data, context.length,
				    x->global->signing_key.data);
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		const DATA_BLOB label = data_blob_string_const_null("SMB2AESCCM");
		const DATA_BLOB context = data_blob_string_const_null("ServerIn ");

		x->global->decryption_key = data_blob_talloc(x->global,
							     session_key,
							     sizeof(session_key));
		if (x->global->decryption_key.data == NULL) {
			ZERO_STRUCT(session_key);
			return NT_STATUS_NO_MEMORY;
		}

		smb2_key_derivation(session_key, sizeof(session_key),
				    label.data, label.length,
				    context.data, context.length,
				    x->global->decryption_key.data);
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		const DATA_BLOB label = data_blob_string_const_null("SMB2AESCCM");
		const DATA_BLOB context = data_blob_string_const_null("ServerOut");

		x->global->encryption_key = data_blob_talloc(x->global,
							     session_key,
							     sizeof(session_key));
		if (x->global->encryption_key.data == NULL) {
			ZERO_STRUCT(session_key);
			return NT_STATUS_NO_MEMORY;
		}

		smb2_key_derivation(session_key, sizeof(session_key),
				    label.data, label.length,
				    context.data, context.length,
				    x->global->encryption_key.data);

		generate_random_buffer((uint8_t *)&x->nonce_high, sizeof(x->nonce_high));
		x->nonce_low = 1;
	}

	x->global->application_key = data_blob_dup_talloc(x->global,
						x->global->signing_key);
	if (x->global->application_key.data == NULL) {
		ZERO_STRUCT(session_key);
		return NT_STATUS_NO_MEMORY;
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		const DATA_BLOB label = data_blob_string_const_null("SMB2APP");
		const DATA_BLOB context = data_blob_string_const_null("SmbRpc");

		smb2_key_derivation(session_key, sizeof(session_key),
				    label.data, label.length,
				    context.data, context.length,
				    x->global->application_key.data);
	}
	ZERO_STRUCT(session_key);

	x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
						x->global->signing_key);
	if (x->global->channels[0].signing_key.data == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	data_blob_clear_free(&session_info->session_key);
	session_info->session_key = data_blob_dup_talloc(session_info,
						x->global->application_key);
	if (session_info->session_key.data == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	session->compat = talloc_zero(session, struct user_struct);
	if (session->compat == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	session->compat->session = session;
	session->compat->homes_snum = -1;
	session->compat->session_info = session_info;
	session->compat->session_keystr = NULL;
	session->compat->vuid = session->global->session_wire_id;
	DLIST_ADD(smb2req->sconn->users, session->compat);
	smb2req->sconn->num_users++;

	if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
		session->compat->homes_snum =
			register_homes_share(session_info->unix_info->unix_name);
	}

	set_current_user_info(session_info->unix_info->sanitized_username,
			      session_info->unix_info->unix_name,
			      session_info->info->domain_name);

	reload_services(smb2req->sconn, conn_snum_used, true);

	session->status = NT_STATUS_OK;
	session->global->auth_session_info = session_info;
	session->global->auth_session_info_seqnum += 1;
	session->global->channels[0].auth_session_info_seqnum =
		session->global->auth_session_info_seqnum;
	session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
	session->global->expiration_time = gensec_expire_time(session->gensec);

	if (!session_claim(session)) {
		DEBUG(1, ("smb2: Failed to claim session "
			"for vuid=%llu\n",
			(unsigned long long)session->compat->vuid));
		return NT_STATUS_LOGON_FAILURE;
	}

	status = smbXsrv_session_update(session);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
			  (unsigned long long)session->compat->vuid,
			  nt_errstr(status)));
		return NT_STATUS_LOGON_FAILURE;
	}

	/*
	 * we attach the session to the request
	 * so that the response can be signed
	 */
	smb2req->session = session;
	if (!guest) {
		smb2req->do_signing = true;
	}

	global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);

	*out_session_id = session->global->session_wire_id;

	return NT_STATUS_OK;
}