1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00

r1731: Add server-side SPNEGO support to Samba (disabled, until SMB signing

is reworked).

Andrew Bartlett
(This used to be commit 73ee549b8c)
This commit is contained in:
Andrew Bartlett 2004-08-11 18:09:40 +00:00 committed by Gerald (Jerry) Carter
parent 86d4ec7212
commit 1c9216f36c
3 changed files with 356 additions and 171 deletions

View File

@ -66,6 +66,28 @@ static NTSTATUS gensec_spnego_client_start(struct gensec_security *gensec_securi
return NT_STATUS_OK;
}
static NTSTATUS gensec_spnego_server_start(struct gensec_security *gensec_security)
{
struct spnego_state *spnego_state;
TALLOC_CTX *mem_ctx = talloc_init("gensec_spnego_server_start");
if (!mem_ctx) {
return NT_STATUS_NO_MEMORY;
}
spnego_state = talloc_p(mem_ctx, struct spnego_state);
if (!spnego_state) {
return NT_STATUS_NO_MEMORY;
}
spnego_state->expected_packet = SPNEGO_NEG_TOKEN_INIT;
spnego_state->state_position = SPNEGO_SERVER_START;
spnego_state->mem_ctx = mem_ctx;
spnego_state->sub_sec_security = NULL;
gensec_security->private_data = spnego_state;
return NT_STATUS_OK;
}
/*
wrappers for the spnego_*() functions
*/
@ -146,6 +168,18 @@ static NTSTATUS gensec_spnego_session_key(struct gensec_security *gensec_securit
session_key);
}
static NTSTATUS gensec_spnego_session_info(struct gensec_security *gensec_security,
struct auth_session_info **session_info)
{
struct spnego_state *spnego_state = gensec_security->private_data;
if (!spnego_state->sub_sec_security) {
return NT_STATUS_INVALID_PARAMETER;
}
return gensec_session_info(spnego_state->sub_sec_security,
session_info);
}
/** Fallback to another GENSEC mechanism, based on magic strings
*
* This is the 'fallback' case, where we don't get SPNEGO, and have to
@ -191,22 +225,69 @@ static NTSTATUS gensec_spnego_server_try_fallback(struct gensec_security *gensec
}
/** create a client netTokenInit
static NTSTATUS gensec_spnego_parse_negTokenInit(struct gensec_security *gensec_security,
struct spnego_state *spnego_state,
TALLOC_CTX *out_mem_ctx,
const char **mechType,
const DATA_BLOB unwrapped_in, DATA_BLOB *unwrapped_out)
{
int i;
NTSTATUS nt_status;
DATA_BLOB null_data_blob = data_blob(NULL,0);
for (i=0; mechType && mechType[i]; i++) {
nt_status = gensec_subcontext_start(gensec_security,
&spnego_state->sub_sec_security);
if (!NT_STATUS_IS_OK(nt_status)) {
break;
}
/* select the sub context */
nt_status = gensec_start_mech_by_oid(spnego_state->sub_sec_security,
mechType[i]);
if (!NT_STATUS_IS_OK(nt_status)) {
gensec_end(&spnego_state->sub_sec_security);
continue;
}
if (i == 0) {
nt_status = gensec_update(spnego_state->sub_sec_security,
out_mem_ctx,
unwrapped_in,
unwrapped_out);
} else {
/* only get the helping start blob for the first OID */
nt_status = gensec_update(spnego_state->sub_sec_security,
out_mem_ctx,
null_data_blob,
unwrapped_out);
}
if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(nt_status)) {
DEBUG(1, ("SPNEGO(%s) NEG_TOKEN_INIT failed: %s\n",
spnego_state->sub_sec_security->ops->name, nt_errstr(nt_status)));
gensec_end(&spnego_state->sub_sec_security);
} else {
break;
}
}
if (!mechType || !mechType[i]) {
DEBUG(1, ("SPNEGO: Could not find a suitable mechtype in NEG_TOKEN_INIT\n"));
}
return nt_status;
}
/** create a client negTokenInit
*
* This is the case, where the client is the first one who sends data
*/
static NTSTATUS gensec_spnego_client_netTokenInit(struct gensec_security *gensec_security,
static NTSTATUS gensec_spnego_client_negTokenInit(struct gensec_security *gensec_security,
struct spnego_state *spnego_state,
TALLOC_CTX *out_mem_ctx,
const DATA_BLOB in, DATA_BLOB *out)
{
NTSTATUS nt_status;
int i;
int num_ops;
char **mechTypes = NULL;
const struct gensec_security_ops **all_ops = gensec_security_all(&num_ops);
DATA_BLOB null_data_blob = data_blob(NULL,0);
const char **mechTypes = NULL;
DATA_BLOB unwrapped_out = data_blob(NULL,0);
if (num_ops < 1) {
@ -214,31 +295,13 @@ static NTSTATUS gensec_spnego_client_netTokenInit(struct gensec_security *gensec
return NT_STATUS_INVALID_PARAMETER;
}
/* build a mechTypes list we want to offer */
for (i=0; i < num_ops; i++) {
if (!all_ops[i]->oid) {
continue;
}
/* skip SPNEGO itself */
if (strcmp(OID_SPNEGO,all_ops[i]->oid)==0) {
continue;
}
mechTypes = talloc_realloc_p(out_mem_ctx, mechTypes, char *, i+2);
if (!mechTypes) {
DEBUG(1, ("talloc_realloc_p(out_mem_ctx, mechTypes, char *, i+1) failed\n"));
return NT_STATUS_NO_MEMORY;
}
mechTypes[i] = all_ops[i]->oid;
mechTypes[i+1] = NULL;
}
mechTypes = gensec_security_oids(out_mem_ctx, OID_SPNEGO);
if (!mechTypes) {
DEBUG(1, ("no GENSEC OID backends available\n"));
return NT_STATUS_INVALID_PARAMETER;
}
DATA_BLOB null_data_blob = data_blob(NULL,0);
nt_status = gensec_subcontext_start(gensec_security,
&spnego_state->sub_sec_security);
@ -278,6 +341,53 @@ static NTSTATUS gensec_spnego_client_netTokenInit(struct gensec_security *gensec
return NT_STATUS_INVALID_PARAMETER;
}
/** create a client negTokenTarg
*
* This is the case, where the client is the first one who sends data
*/
static NTSTATUS gensec_spnego_server_negTokenTarg(struct gensec_security *gensec_security,
struct spnego_state *spnego_state,
TALLOC_CTX *out_mem_ctx,
NTSTATUS nt_status,
const DATA_BLOB unwrapped_out, DATA_BLOB *out)
{
struct spnego_data spnego_out;
DATA_BLOB null_data_blob = data_blob(NULL, 0);
/* compose reply */
spnego_out.type = SPNEGO_NEG_TOKEN_TARG;
spnego_out.negTokenTarg.supportedMech
= spnego_state->sub_sec_security->ops->oid;
spnego_out.negTokenTarg.responseToken = unwrapped_out;
spnego_out.negTokenTarg.mechListMIC = null_data_blob;
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
spnego_state->state_position = SPNEGO_SERVER_TARG;
} else if (NT_STATUS_IS_OK(nt_status)) {
spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED;
spnego_state->state_position = SPNEGO_DONE;
} else {
spnego_out.negTokenTarg.negResult = SPNEGO_REJECT;
DEBUG(1, ("SPNEGO(%s) login failed: %s\n",
spnego_state->sub_sec_security->ops->name,
nt_errstr(nt_status)));
spnego_state->state_position = SPNEGO_DONE;
}
if (spnego_write_data(out_mem_ctx, out, &spnego_out) == -1) {
DEBUG(1, ("Failed to write SPNEGO reply to NEG_TOKEN_TARG\n"));
return NT_STATUS_INVALID_PARAMETER;
}
spnego_state->expected_packet = SPNEGO_NEG_TOKEN_TARG;
return nt_status;
}
static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
const DATA_BLOB in, DATA_BLOB *out)
{
@ -289,6 +399,8 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
ssize_t len;
*out = data_blob(NULL, 0);
if (!out_mem_ctx) {
out_mem_ctx = spnego_state->mem_ctx;
}
@ -302,30 +414,72 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
case SPNEGO_SERVER_START:
{
if (in.length) {
NTSTATUS nt_status;
len = spnego_read_data(in, &spnego);
if (len == -1) {
return gensec_spnego_server_try_fallback(gensec_security, spnego_state, out_mem_ctx, in, out);
} else {
/* client sent NegTargetInit */
}
/* client sent NegTargetInit, we send NegTokenTarg */
/* OK, so it's real SPNEGO, check the packet's the one we expect */
if (spnego.type != spnego_state->expected_packet) {
DEBUG(1, ("Invalid SPNEGO request: %d, expected %d\n", spnego.type,
spnego_state->expected_packet));
dump_data(1, (const char *)in.data, in.length);
spnego_free_data(&spnego);
return NT_STATUS_INVALID_PARAMETER;
}
nt_status = gensec_spnego_parse_negTokenInit(gensec_security,
spnego_state,
out_mem_ctx,
spnego.negTokenInit.mechTypes,
spnego.negTokenInit.mechToken,
&unwrapped_out);
nt_status = gensec_spnego_server_negTokenTarg(gensec_security,
spnego_state,
out_mem_ctx,
nt_status,
unwrapped_out,
out);
spnego_free_data(&spnego);
return nt_status;
} else {
/* server needs to send NegTargetInit */
const char **mechlist = gensec_security_oids(out_mem_ctx, OID_SPNEGO);
spnego_out.type = SPNEGO_NEG_TOKEN_INIT;
spnego_out.negTokenInit.mechTypes = mechlist;
spnego_out.negTokenInit.reqFlags = 0;
spnego_out.negTokenInit.mechListMIC = null_data_blob;
spnego_out.negTokenInit.mechToken = unwrapped_out;
if (spnego_write_data(out_mem_ctx, out, &spnego_out) == -1) {
DEBUG(1, ("Failed to write SPNEGO reply to NEG_TOKEN_INIT\n"));
return NT_STATUS_INVALID_PARAMETER;
}
/* set next state */
spnego_state->expected_packet = SPNEGO_NEG_TOKEN_TARG;
spnego_state->state_position = SPNEGO_SERVER_TARG;
return NT_STATUS_MORE_PROCESSING_REQUIRED;
}
return NT_STATUS_INVALID_PARAMETER;
}
case SPNEGO_CLIENT_START:
{
/* The server offers a list of mechanisms */
char **mechType;
char *my_mechs[] = {NULL, NULL};
int i;
NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
if (!in.length) {
/* client to produce negTokenInit */
return gensec_spnego_client_netTokenInit(gensec_security, spnego_state, out_mem_ctx, in, out);
return gensec_spnego_client_negTokenInit(gensec_security, spnego_state, out_mem_ctx, in, out);
}
len = spnego_read_data(in, &spnego);
@ -354,50 +508,17 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
}
}
mechType = spnego.negTokenInit.mechTypes;
for (i=0; mechType && mechType[i]; i++) {
nt_status = gensec_subcontext_start(gensec_security,
&spnego_state->sub_sec_security);
if (!NT_STATUS_IS_OK(nt_status)) {
break;
}
/* select the sub context */
nt_status = gensec_start_mech_by_oid(spnego_state->sub_sec_security,
mechType[i]);
if (!NT_STATUS_IS_OK(nt_status)) {
gensec_end(&spnego_state->sub_sec_security);
continue;
}
if (i == 0) {
nt_status = gensec_update(spnego_state->sub_sec_security,
out_mem_ctx,
spnego.negTokenInit.mechToken,
&unwrapped_out);
} else {
/* only get the helping start blob for the first OID */
nt_status = gensec_update(spnego_state->sub_sec_security,
out_mem_ctx,
null_data_blob,
&unwrapped_out);
}
if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(nt_status)) {
DEBUG(1, ("SPNEGO(%s) NEG_TOKEN_INIT failed: %s\n",
spnego_state->sub_sec_security->ops->name, nt_errstr(nt_status)));
gensec_end(&spnego_state->sub_sec_security);
} else {
break;
}
}
if (!mechType || !mechType[i]) {
DEBUG(1, ("SPNEGO: Could not find a suitable mechtype in NEG_TOKEN_INIT\n"));
}
spnego_free_data(&spnego);
nt_status = gensec_spnego_parse_negTokenInit(gensec_security,
spnego_state,
out_mem_ctx,
spnego.negTokenInit.mechTypes,
spnego.negTokenInit.mechToken,
&unwrapped_out);
if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
/* compose reply */
my_mechs[0] = spnego_state->sub_sec_security->ops->oid;
@ -441,40 +562,21 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
spnego_free_data(&spnego);
return NT_STATUS_INVALID_PARAMETER;
}
nt_status = gensec_update(spnego_state->sub_sec_security,
out_mem_ctx,
spnego.negTokenTarg.responseToken,
spnego.negTokenTarg.responseToken,
&unwrapped_out);
nt_status = gensec_spnego_server_negTokenTarg(gensec_security,
spnego_state,
out_mem_ctx,
nt_status,
unwrapped_out,
out);
spnego_free_data(&spnego);
/* compose reply */
spnego_out.type = SPNEGO_NEG_TOKEN_TARG;
spnego_out.negTokenTarg.supportedMech
= spnego_state->sub_sec_security->ops->oid;
spnego_out.negTokenTarg.responseToken = unwrapped_out;
spnego_out.negTokenTarg.mechListMIC = null_data_blob;
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
spnego_state->state_position = SPNEGO_SERVER_TARG;
} else if (NT_STATUS_IS_OK(nt_status)) {
spnego_out.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED;
spnego_state->state_position = SPNEGO_DONE;
} else {
spnego_out.negTokenTarg.negResult = SPNEGO_REJECT;
DEBUG(1, ("SPNEGO(%s) login failed: %s\n",
spnego_state->sub_sec_security->ops->name,
nt_errstr(nt_status)));
spnego_state->state_position = SPNEGO_DONE;
}
if (spnego_write_data(out_mem_ctx, out, &spnego_out) == -1) {
DEBUG(1, ("Failed to write SPNEGO reply to NEG_TOKEN_TARG\n"));
return NT_STATUS_INVALID_PARAMETER;
}
return nt_status;
}
case SPNEGO_CLIENT_TARG:
@ -584,12 +686,14 @@ static const struct gensec_security_ops gensec_spnego_security_ops = {
.auth_type = DCERPC_AUTH_TYPE_SPNEGO,
.oid = OID_SPNEGO,
.client_start = gensec_spnego_client_start,
.server_start = gensec_spnego_server_start,
.update = gensec_spnego_update,
.seal_packet = gensec_spnego_seal_packet,
.sign_packet = gensec_spnego_sign_packet,
.check_packet = gensec_spnego_check_packet,
.unseal_packet = gensec_spnego_unseal_packet,
.session_key = gensec_spnego_session_key,
.session_info = gensec_spnego_session_info,
.end = gensec_spnego_end
};

View File

@ -171,55 +171,10 @@ static void reply_lanman2(struct smbsrv_request *req, uint16_t choice)
req_push_str(req, NULL, lp_workgroup(), -1, STR_TERMINATE);
req_send_reply(req);
}
#if 0
/****************************************************************************
Generate the spnego negprot reply blob. Return the number of bytes used.
****************************************************************************/
static DATA_BLOB negprot_spnego(struct smbsrv_connection *smb_conn)
{
DATA_BLOB blob;
uint8_t guid[16];
const char *OIDs_krb5[] = {OID_KERBEROS5,
OID_KERBEROS5_OLD,
OID_NTLMSSP,
NULL};
const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
char *principal;
smb_conn->negotiate.spnego_negotiated = True;
memset(guid, 0, 16);
safe_strcpy((char *)guid, lp_netbios_name(), 16);
strlower((char *)guid);
#if 0
/* strangely enough, NT does not send the single OID NTLMSSP when
not a ADS member, it sends no OIDs at all
we can't do this until we teach our sesssion setup parser to know
about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
*/
if (lp_security() != SEC_ADS) {
memcpy(p, guid, 16);
return 16;
}
#endif
if (lp_security() != SEC_ADS) {
blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
} else {
asprintf(&principal, "%s$@%s", guid, lp_realm());
blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
free(principal);
}
return blob;
}
#endif
/****************************************************************************
Reply for the nt protocol.
****************************************************************************/
@ -243,13 +198,12 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice)
/* do spnego in user level security if the client
supports it and we can do encrypted passwords */
if (req->smb_conn->negotiate.encrypted_passwords &&
if (0 && req->smb_conn->negotiate.encrypted_passwords &&
(lp_security() != SEC_SHARE) &&
lp_use_spnego() &&
(req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
/* REWRITE negotiate_spnego = True;
negotiate_spnego = True;
capabilities |= CAP_EXTENDED_SECURITY;
*/
}
if (lp_unix_extensions()) {
@ -335,15 +289,51 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice)
req_push_str(req, NULL, lp_netbios_name(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
DEBUG(3,("not using SPNEGO\n"));
} else {
#if 0
DATA_BLOB blob = negprot_spnego(req->smb_conn);
struct gensec_security *gensec_security;
DATA_BLOB null_data_blob = data_blob(NULL, 0);
DATA_BLOB blob;
NTSTATUS nt_status = gensec_server_start(&gensec_security);
if (req->smb_conn->negotiate.auth_context) {
smbsrv_terminate_connection(req->smb_conn, "reply_nt1: is this a secondary negprot? auth_context is non-NULL!\n");
return;
}
req->smb_conn->negotiate.auth_context = NULL;
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("Failed to start GENSEC: %s\n", nt_errstr(nt_status)));
smbsrv_terminate_connection(req->smb_conn, "Failed to start GENSEC\n");
return;
}
nt_status = gensec_start_mech_by_oid(gensec_security, OID_SPNEGO);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("Failed to start SPNEGO: %s\n", nt_errstr(nt_status)));
smbsrv_terminate_connection(req->smb_conn, "Failed to start SPNEGO\n");
return;
}
nt_status = gensec_update(gensec_security, req->mem_ctx, null_data_blob, &blob);
if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
DEBUG(0, ("Failed to get SPNEGO to give us the first token: %s\n", nt_errstr(nt_status)));
smbsrv_terminate_connection(req->smb_conn, "Failed to start SPNEGO - no first token\n");
return;
}
req->smb_conn->negotiate.spnego_negotiated = True;
req_grow_data(req, blob.length + 16);
/* a NOT very random guid */
memset(req->out.ptr, '\0', 16);
req->out.ptr += 16;
req_grow_data(req, blob.length);
memcpy(req->out.ptr, blob.data, blob.length);
SCVAL(req->out.vwv+1, VWV(16), blob.length + 16);
req->out.ptr += blob.length;
DEBUG(3,("using SPNEGO\n"));
#else
smbsrv_terminate_connection(req->smb_conn, "no SPNEGO please");
#endif
}
req_send_reply_nosign(req);

View File

@ -103,19 +103,41 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s
req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities;
}
status = make_user_info_for_reply_enc(&user_info,
sess->nt1.in.user, sess->nt1.in.domain,
sess->nt1.in.password1,
sess->nt1.in.password2);
if (!NT_STATUS_IS_OK(status)) {
return NT_STATUS_ACCESS_DENIED;
if (req->smb_conn->negotiate.spnego_negotiated) {
struct auth_context *auth_context;
status = make_auth_context_subsystem(&auth_context);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (!sess->nt1.in.user || !*sess->nt1.in.user) {
make_user_info_guest(&user_info);
}
status = auth_context->check_ntlm_password(auth_context,
user_info,
&server_info);
free_auth_context(&auth_context);
} else {
status = make_user_info_for_reply_enc(&user_info,
sess->nt1.in.user, sess->nt1.in.domain,
sess->nt1.in.password1,
sess->nt1.in.password2);
if (!NT_STATUS_IS_OK(status)) {
return NT_STATUS_ACCESS_DENIED;
}
status = req->smb_conn->negotiate
.auth_context->check_ntlm_password(req->smb_conn->negotiate
.auth_context,
user_info,
&server_info);
}
status = req->smb_conn->negotiate
.auth_context->check_ntlm_password(req->smb_conn->negotiate
.auth_context,
user_info,
&server_info);
if (!NT_STATUS_IS_OK(status)) {
return nt_status_squash(status);
}
@ -149,8 +171,74 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s
*/
static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup *sess)
{
/* defer this one for now */
return NT_STATUS_INVALID_LEVEL;
NTSTATUS status = NT_STATUS_ACCESS_DENIED;
struct smbsrv_session *smb_sess;
struct gensec_security *gensec_ctx = NULL;
struct auth_session_info *session_info = NULL;
uint16_t vuid;
if (!req->smb_conn->negotiate.done_sesssetup) {
req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize;
req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities;
}
vuid = SVAL(req->in.hdr,HDR_UID);
smb_sess = smbsrv_session_find(req->smb_conn, vuid);
if (smb_sess) {
if (!smb_sess->gensec_ctx) {
return NT_STATUS_INVALID_HANDLE;
}
/* what is when the client is already successful authentificated? */
if (smb_sess->session_info) {
return NT_STATUS_ACCESS_DENIED;
}
status = gensec_update(smb_sess->gensec_ctx, req->mem_ctx, sess->spnego.in.secblob, &sess->spnego.out.secblob);
} else {
status = gensec_server_start(&gensec_ctx);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
return status;
}
status = gensec_start_mech_by_oid(gensec_ctx, OID_SPNEGO);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start GENSEC SPNEGO server code: %s\n", nt_errstr(status)));
return status;
}
status = gensec_update(gensec_ctx, req->mem_ctx, sess->spnego.in.secblob, &sess->spnego.out.secblob);
}
if (NT_STATUS_IS_OK(status)) {
DATA_BLOB session_key;
DATA_BLOB null_data_blob = data_blob(NULL, 0);
status = gensec_session_info(smb_sess->gensec_ctx, &smb_sess->session_info);
if (NT_STATUS_IS_OK(gensec_session_key(smb_sess->gensec_ctx,
&session_key))) {
srv_setup_signing(req->smb_conn, &session_key, &null_data_blob);
req->seq_num = 0;
req->smb_conn->signing.next_seq_num = 2;
}
}
if (!smb_sess) {
vuid = smbsrv_register_session(req->smb_conn, session_info, gensec_ctx);
if (vuid == UID_FIELD_INVALID) {
return NT_STATUS_ACCESS_DENIED;
}
}
sess->spnego.out.action = 0;
sess->spnego.out.vuid = vuid;
sesssetup_common_strings(req,
&sess->spnego.out.os,
&sess->spnego.out.lanman,
&sess->spnego.out.domain);
return status;
}
/*
@ -162,6 +250,9 @@ NTSTATUS sesssetup_backend(struct smbsrv_request *req,
NTSTATUS status = NT_STATUS_INVALID_LEVEL;
switch (sess->generic.level) {
case RAW_SESSSETUP_GENERIC:
status = NT_STATUS_INVALID_LEVEL;
break;
case RAW_SESSSETUP_OLD:
status = sesssetup_old(req, sess);
break;