mirror of
https://github.com/samba-team/samba.git
synced 2025-02-02 09:47:23 +03:00
r6270: Move the VUID handling to a IDR tree. This should avoid O(n)
behaviour on session setups, and because we no longer need do deal with the linked list as much, the code is much simpiler too. We may be able to compleatly remove the tid and vuid linked lists, but I need to check. This patch also tries to clean up the VUID handling and session setups in general. To avoid security issues, we now have a distinction between VUIDs allocated for the session setup (to tie togeather the multiple round trips) and those used after authentication. Andrew Bartlett (This used to be commit 3e5775146d9ce6f0ac43aecae7e899b5324399ad)
This commit is contained in:
parent
ce7eb41930
commit
20841a25ad
@ -2,6 +2,7 @@
|
|||||||
Unix SMB/CIFS implementation.
|
Unix SMB/CIFS implementation.
|
||||||
Password and authentication handling
|
Password and authentication handling
|
||||||
Copyright (C) Andrew Tridgell 1992-1998
|
Copyright (C) Andrew Tridgell 1992-1998
|
||||||
|
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -24,39 +25,45 @@
|
|||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
check if a uid has been validated, and return an pointer to the user_struct
|
init the tcon structures
|
||||||
if it has. NULL if not. vuid is biased by an offset. This allows us to
|
****************************************************************************/
|
||||||
tell random client vuid's (normally zero) from valid vuids.
|
void smbsrv_vuid_init(struct smbsrv_connection *smb_conn)
|
||||||
|
{
|
||||||
|
smb_conn->sessions.idtree_vuid = idr_init(smb_conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
Find the session structure assoicated with a VUID (not one from an in-progress session setup)
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
struct smbsrv_session *smbsrv_session_find(struct smbsrv_connection *smb_conn, uint16_t vuid)
|
struct smbsrv_session *smbsrv_session_find(struct smbsrv_connection *smb_conn, uint16_t vuid)
|
||||||
{
|
{
|
||||||
struct smbsrv_session *sess;
|
struct smbsrv_session *sess = idr_find(smb_conn->sessions.idtree_vuid, vuid);
|
||||||
int count=0;
|
if (sess && sess->finished_sesssetup) {
|
||||||
|
return sess;
|
||||||
if (vuid == UID_FIELD_INVALID)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (sess=smb_conn->sessions.session_list; sess; sess=sess->next,count++) {
|
|
||||||
if (vuid == sess->vuid) {
|
|
||||||
if (count > 10) {
|
|
||||||
DLIST_PROMOTE(smb_conn->sessions.session_list, sess);
|
|
||||||
}
|
|
||||||
return sess;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
invalidate a uid
|
Find a VUID assoicated with an in-progress session setup
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void smbsrv_invalidate_vuid(struct smbsrv_connection *smb_conn, uint16_t vuid)
|
struct smbsrv_session *smbsrv_session_find_sesssetup(struct smbsrv_connection *smb_conn, uint16_t vuid)
|
||||||
{
|
{
|
||||||
struct smbsrv_session *sess = smbsrv_session_find(smb_conn, vuid);
|
struct smbsrv_session *sess = idr_find(smb_conn->sessions.idtree_vuid, vuid);
|
||||||
|
if (sess && !sess->finished_sesssetup) {
|
||||||
|
return sess;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (sess == NULL)
|
/****************************************************************************
|
||||||
return;
|
invalidate a session
|
||||||
|
****************************************************************************/
|
||||||
|
static int smbsrv_session_destructor(void *p)
|
||||||
|
{
|
||||||
|
struct smbsrv_session *sess = p;
|
||||||
|
struct smbsrv_connection *smb_conn = sess->smb_conn;
|
||||||
|
|
||||||
DLIST_REMOVE(smb_conn->sessions.session_list, sess);
|
DLIST_REMOVE(smb_conn->sessions.session_list, sess);
|
||||||
|
|
||||||
@ -65,20 +72,18 @@ void smbsrv_invalidate_vuid(struct smbsrv_connection *smb_conn, uint16_t vuid)
|
|||||||
/* REWRITE: conn_clear_vuid_cache(smb, vuid); */
|
/* REWRITE: conn_clear_vuid_cache(smb, vuid); */
|
||||||
|
|
||||||
smb_conn->sessions.num_validated_vuids--;
|
smb_conn->sessions.num_validated_vuids--;
|
||||||
|
|
||||||
|
idr_remove(smb_conn->sessions.idtree_vuid, sess->vuid);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
invalidate all vuid entries for this process
|
invalidate a uid
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void smbsrv_invalidate_all_vuids(struct smbsrv_connection *smb_conn)
|
void smbsrv_invalidate_vuid(struct smbsrv_connection *smb_conn, uint16_t vuid)
|
||||||
{
|
{
|
||||||
struct smbsrv_session *sess,*next=NULL;
|
struct smbsrv_session *sess = smbsrv_session_find(smb_conn, vuid);
|
||||||
|
talloc_free(sess);
|
||||||
for (sess=smb_conn->sessions.session_list; sess; sess=next) {
|
|
||||||
next = sess->next;
|
|
||||||
|
|
||||||
smbsrv_invalidate_vuid(smb_conn, sess->vuid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,56 +98,45 @@ void smbsrv_invalidate_all_vuids(struct smbsrv_connection *smb_conn)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint16_t smbsrv_register_session(struct smbsrv_connection *smb_conn,
|
struct smbsrv_session *smbsrv_register_session(struct smbsrv_connection *smb_conn,
|
||||||
struct auth_session_info *session_info,
|
struct auth_session_info *session_info,
|
||||||
struct gensec_security *gensec_ctx)
|
struct gensec_security *gensec_ctx)
|
||||||
{
|
{
|
||||||
struct smbsrv_session *sess = NULL;
|
struct smbsrv_session *sess = NULL;
|
||||||
|
int i;
|
||||||
sess = talloc(smb_conn, struct smbsrv_session);
|
|
||||||
if(sess == NULL) {
|
|
||||||
DEBUG(0,("talloc(smb_conn->mem_ctx, struct smbsrv_session) failed\n"));
|
|
||||||
return UID_FIELD_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZERO_STRUCTP(sess);
|
|
||||||
sess->vuid = UID_FIELD_INVALID;
|
|
||||||
|
|
||||||
/* Ensure no vuid gets registered in share level security. */
|
/* Ensure no vuid gets registered in share level security. */
|
||||||
/* TODO: replace lp_security with a flag in smbsrv_connection */
|
/* TODO: replace lp_security with a flag in smbsrv_connection */
|
||||||
if(lp_security() == SEC_SHARE)
|
if (lp_security() == SEC_SHARE)
|
||||||
return sess->vuid;
|
return UID_FIELD_INVALID;
|
||||||
|
|
||||||
/* Limit allowed vuids to 16bits - VUID_OFFSET. */
|
sess = talloc(smb_conn, struct smbsrv_session);
|
||||||
if (smb_conn->sessions.num_validated_vuids >= 0xFFFF-VUID_OFFSET)
|
if (sess == NULL) {
|
||||||
return sess->vuid;
|
DEBUG(0,("talloc(smb_conn->mem_ctx, struct smbsrv_session) failed\n"));
|
||||||
|
return sess;
|
||||||
/* Allocate a free vuid. Yes this is a linear search... :-) */
|
|
||||||
while (smbsrv_session_find(smb_conn, smb_conn->sessions.next_vuid) != NULL ) {
|
|
||||||
smb_conn->sessions.next_vuid++;
|
|
||||||
/* Check for vuid wrap. */
|
|
||||||
if (smb_conn->sessions.next_vuid == UID_FIELD_INVALID)
|
|
||||||
smb_conn->sessions.next_vuid = VUID_OFFSET;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(10,("register_vuid: allocated vuid = %u\n",
|
ZERO_STRUCTP(sess);
|
||||||
(uint_t)smb_conn->sessions.next_vuid));
|
|
||||||
|
i = idr_get_new_above(smb_conn->sessions.idtree_vuid, sess, VUID_OFFSET, UINT16_MAX);
|
||||||
|
if (i == -1) {
|
||||||
|
DEBUG(1,("ERROR! Out of connection structures\n"));
|
||||||
|
talloc_free(sess);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
sess->vuid = i;
|
||||||
|
|
||||||
sess->vuid = smb_conn->sessions.next_vuid;
|
|
||||||
smb_conn->sessions.next_vuid++;
|
|
||||||
smb_conn->sessions.num_validated_vuids++;
|
smb_conn->sessions.num_validated_vuids++;
|
||||||
|
|
||||||
/* use this to keep tabs on all our info from the authentication */
|
/* use this to keep tabs on all our info from the authentication */
|
||||||
if (session_info) {
|
sess->session_info = talloc_reference(sess, session_info);
|
||||||
sess->session_info = talloc_reference(sess, session_info);
|
|
||||||
}
|
sess->gensec_ctx = talloc_reference(sess, gensec_ctx);
|
||||||
|
|
||||||
if (gensec_ctx) {
|
|
||||||
sess->gensec_ctx = talloc_reference(sess, gensec_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
sess->smb_conn = smb_conn;
|
sess->smb_conn = smb_conn;
|
||||||
DLIST_ADD(smb_conn->sessions.session_list, sess);
|
DLIST_ADD(smb_conn->sessions.session_list, sess);
|
||||||
|
|
||||||
return sess->vuid;
|
talloc_set_destructor(sess, smbsrv_session_destructor);
|
||||||
|
|
||||||
|
return sess;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
Unix SMB/CIFS implementation.
|
Unix SMB/CIFS implementation.
|
||||||
handle SMBsessionsetup
|
handle SMBsessionsetup
|
||||||
Copyright (C) Andrew Tridgell 1998-2001
|
Copyright (C) Andrew Tridgell 1998-2001
|
||||||
Copyright (C) Andrew Bartlett 2001
|
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005
|
||||||
Copyright (C) Jim McDonough 2002
|
Copyright (C) Jim McDonough 2002
|
||||||
Copyright (C) Luke Howard 2003
|
Copyright (C) Luke Howard 2003
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -26,7 +26,7 @@
|
|||||||
#include "auth/auth.h"
|
#include "auth/auth.h"
|
||||||
#include "smb_server/smb_server.h"
|
#include "smb_server/smb_server.h"
|
||||||
#include "smbd/service_stream.h"
|
#include "smbd/service_stream.h"
|
||||||
|
#include "libcli/nbt/libnbt.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
setup the OS, Lanman and domain portions of a session setup reply
|
setup the OS, Lanman and domain portions of a session setup reply
|
||||||
@ -49,9 +49,13 @@ static NTSTATUS sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *s
|
|||||||
struct auth_usersupplied_info *user_info = NULL;
|
struct auth_usersupplied_info *user_info = NULL;
|
||||||
struct auth_serversupplied_info *server_info = NULL;
|
struct auth_serversupplied_info *server_info = NULL;
|
||||||
struct auth_session_info *session_info;
|
struct auth_session_info *session_info;
|
||||||
|
struct smbsrv_session *smb_sess;
|
||||||
char *remote_machine;
|
char *remote_machine;
|
||||||
TALLOC_CTX *mem_ctx;
|
TALLOC_CTX *mem_ctx;
|
||||||
|
|
||||||
|
sess->old.out.vuid = UID_FIELD_INVALID;
|
||||||
|
sess->old.out.action = 0;
|
||||||
|
|
||||||
mem_ctx = talloc_named(req, 0, "OLD session setup");
|
mem_ctx = talloc_named(req, 0, "OLD session setup");
|
||||||
NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
|
NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
|
||||||
|
|
||||||
@ -85,18 +89,25 @@ static NTSTATUS sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *s
|
|||||||
return auth_nt_status_squash(status);
|
return auth_nt_status_squash(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
sess->old.out.action = 0;
|
smb_sess = smbsrv_register_session(req->smb_conn, session_info, NULL);
|
||||||
sess->old.out.vuid = smbsrv_register_session(req->smb_conn, session_info, NULL);
|
if (!smb_sess) {
|
||||||
if (sess->old.out.vuid == UID_FIELD_INVALID) {
|
|
||||||
return NT_STATUS_ACCESS_DENIED;
|
return NT_STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure this is marked as a 'real' vuid, not one
|
||||||
|
* simply valid for the session setup leg */
|
||||||
|
smb_sess->finished_sesssetup = True;
|
||||||
|
|
||||||
|
/* To correctly process any AndX packet (like a tree connect)
|
||||||
|
* we need to fill in the session on the request here */
|
||||||
|
req->session = smb_sess;
|
||||||
|
sess->old.out.vuid = smb_sess->vuid;
|
||||||
|
|
||||||
sesssetup_common_strings(req,
|
sesssetup_common_strings(req,
|
||||||
&sess->old.out.os,
|
&sess->old.out.os,
|
||||||
&sess->old.out.lanman,
|
&sess->old.out.lanman,
|
||||||
&sess->old.out.domain);
|
&sess->old.out.domain);
|
||||||
|
|
||||||
req->session = smbsrv_session_find(req->smb_conn, sess->old.out.vuid);
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
return NT_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,11 +118,15 @@ static NTSTATUS sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *s
|
|||||||
static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
|
static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
struct smbsrv_session *smb_sess;
|
||||||
struct auth_usersupplied_info *user_info = NULL;
|
struct auth_usersupplied_info *user_info = NULL;
|
||||||
struct auth_serversupplied_info *server_info = NULL;
|
struct auth_serversupplied_info *server_info = NULL;
|
||||||
struct auth_session_info *session_info;
|
struct auth_session_info *session_info;
|
||||||
TALLOC_CTX *mem_ctx;
|
TALLOC_CTX *mem_ctx;
|
||||||
|
|
||||||
|
sess->nt1.out.vuid = UID_FIELD_INVALID;
|
||||||
|
sess->nt1.out.action = 0;
|
||||||
|
|
||||||
mem_ctx = talloc_named(req, 0, "NT1 session setup");
|
mem_ctx = talloc_named(req, 0, "NT1 session setup");
|
||||||
NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
|
NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
|
||||||
|
|
||||||
@ -143,9 +158,15 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s
|
|||||||
status = auth_check_password(auth_context, mem_ctx,
|
status = auth_check_password(auth_context, mem_ctx,
|
||||||
user_info, &server_info);
|
user_info, &server_info);
|
||||||
} else {
|
} else {
|
||||||
char *remote_machine;
|
const char *remote_machine = NULL;
|
||||||
|
|
||||||
remote_machine = socket_get_peer_addr(req->smb_conn->connection->socket, mem_ctx);
|
if (req->smb_conn->negotiate.called_name) {
|
||||||
|
remote_machine = req->smb_conn->negotiate.called_name->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!remote_machine) {
|
||||||
|
remote_machine = socket_get_peer_addr(req->smb_conn->connection->socket, mem_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
status = make_user_info_for_reply_enc(req->smb_conn,
|
status = make_user_info_for_reply_enc(req->smb_conn,
|
||||||
sess->nt1.in.user, sess->nt1.in.domain,
|
sess->nt1.in.user, sess->nt1.in.domain,
|
||||||
@ -174,12 +195,21 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s
|
|||||||
return auth_nt_status_squash(status);
|
return auth_nt_status_squash(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
sess->nt1.out.action = 0;
|
smb_sess = smbsrv_register_session(req->smb_conn, session_info, NULL);
|
||||||
sess->nt1.out.vuid = smbsrv_register_session(req->smb_conn, session_info, NULL);
|
|
||||||
talloc_free(mem_ctx);
|
talloc_free(mem_ctx);
|
||||||
if (sess->nt1.out.vuid == UID_FIELD_INVALID) {
|
if (!smb_sess) {
|
||||||
return NT_STATUS_ACCESS_DENIED;
|
return NT_STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure this is marked as a 'real' vuid, not one
|
||||||
|
* simply valid for the session setup leg */
|
||||||
|
smb_sess->finished_sesssetup = True;
|
||||||
|
|
||||||
|
/* To correctly process any AndX packet (like a tree connect)
|
||||||
|
* we need to fill in the session on the request here */
|
||||||
|
req->session = smb_sess;
|
||||||
|
sess->nt1.out.vuid = smb_sess->vuid;
|
||||||
|
|
||||||
sesssetup_common_strings(req,
|
sesssetup_common_strings(req,
|
||||||
&sess->nt1.out.os,
|
&sess->nt1.out.os,
|
||||||
&sess->nt1.out.lanman,
|
&sess->nt1.out.lanman,
|
||||||
@ -190,7 +220,8 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s
|
|||||||
return NT_STATUS_OK;
|
return NT_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!srv_setup_signing(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2)) {
|
|
||||||
|
if (!srv_setup_signing(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2)) {
|
||||||
/* Already signing, or disabled */
|
/* Already signing, or disabled */
|
||||||
return NT_STATUS_OK;
|
return NT_STATUS_OK;
|
||||||
}
|
}
|
||||||
@ -198,6 +229,9 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s
|
|||||||
/* Force check of the request packet, now we know the session key */
|
/* Force check of the request packet, now we know the session key */
|
||||||
req_signing_check_incoming(req);
|
req_signing_check_incoming(req);
|
||||||
|
|
||||||
|
/* Unfortunetly win2k3 as a client doesn't sign the request
|
||||||
|
* packet here, so we have to force signing to start again */
|
||||||
|
|
||||||
srv_signing_restart(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2);
|
srv_signing_restart(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2);
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
return NT_STATUS_OK;
|
||||||
@ -211,26 +245,29 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup
|
|||||||
{
|
{
|
||||||
NTSTATUS status = NT_STATUS_ACCESS_DENIED;
|
NTSTATUS status = NT_STATUS_ACCESS_DENIED;
|
||||||
struct smbsrv_session *smb_sess;
|
struct smbsrv_session *smb_sess;
|
||||||
struct gensec_security *gensec_ctx = NULL;
|
struct gensec_security *gensec_ctx ;
|
||||||
struct auth_session_info *session_info = NULL;
|
struct auth_session_info *session_info = NULL;
|
||||||
uint16_t vuid;
|
uint16_t vuid;
|
||||||
|
|
||||||
|
sess->spnego.out.vuid = UID_FIELD_INVALID;
|
||||||
|
sess->spnego.out.action = 0;
|
||||||
|
|
||||||
|
sesssetup_common_strings(req,
|
||||||
|
&sess->spnego.out.os,
|
||||||
|
&sess->spnego.out.lanman,
|
||||||
|
&sess->spnego.out.workgroup);
|
||||||
|
|
||||||
if (!req->smb_conn->negotiate.done_sesssetup) {
|
if (!req->smb_conn->negotiate.done_sesssetup) {
|
||||||
req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize;
|
req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize;
|
||||||
req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities;
|
req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
vuid = SVAL(req->in.hdr,HDR_UID);
|
vuid = SVAL(req->in.hdr,HDR_UID);
|
||||||
smb_sess = smbsrv_session_find(req->smb_conn, vuid);
|
smb_sess = smbsrv_session_find_sesssetup(req->smb_conn, vuid);
|
||||||
if (smb_sess && !smb_sess->session_info) {
|
if (smb_sess) {
|
||||||
if (!smb_sess->gensec_ctx) {
|
gensec_ctx = smb_sess->gensec_ctx;
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
status = gensec_update(gensec_ctx, req, sess->spnego.in.secblob, &sess->spnego.out.secblob);
|
||||||
}
|
|
||||||
|
|
||||||
status = gensec_update(smb_sess->gensec_ctx, req, sess->spnego.in.secblob, &sess->spnego.out.secblob);
|
|
||||||
} else {
|
} else {
|
||||||
smb_sess = NULL;
|
|
||||||
|
|
||||||
status = gensec_server_start(req->smb_conn, &gensec_ctx);
|
status = gensec_server_start(req->smb_conn, &gensec_ctx);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
|
DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
|
||||||
@ -248,55 +285,55 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup
|
|||||||
}
|
}
|
||||||
|
|
||||||
status = gensec_update(gensec_ctx, req, sess->spnego.in.secblob, &sess->spnego.out.secblob);
|
status = gensec_update(gensec_ctx, req, sess->spnego.in.secblob, &sess->spnego.out.secblob);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!smb_sess) {
|
|
||||||
vuid = smbsrv_register_session(req->smb_conn,
|
|
||||||
session_info, gensec_ctx);
|
|
||||||
if (vuid == UID_FIELD_INVALID) {
|
|
||||||
return NT_STATUS_ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
smb_sess = smbsrv_session_find(req->smb_conn, vuid);
|
|
||||||
if (!smb_sess) {
|
|
||||||
return NT_STATUS_FOOBAR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NT_STATUS_IS_OK(status)) {
|
if (NT_STATUS_IS_OK(status)) {
|
||||||
DATA_BLOB session_key;
|
DATA_BLOB session_key;
|
||||||
|
|
||||||
status = gensec_session_info(smb_sess->gensec_ctx, &smb_sess->session_info);
|
status = gensec_session_info(gensec_ctx, &session_info);
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
talloc_free(smb_sess);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = gensec_session_key(smb_sess->gensec_ctx,
|
status = gensec_session_key(gensec_ctx,
|
||||||
&session_key);
|
&session_key);
|
||||||
|
|
||||||
if (NT_STATUS_IS_OK(status)
|
if (NT_STATUS_IS_OK(status)
|
||||||
&& smb_sess->session_info->server_info->authenticated
|
&& session_info->server_info->authenticated
|
||||||
&& srv_setup_signing(req->smb_conn, &session_key, NULL)) {
|
&& srv_setup_signing(req->smb_conn, &session_key, NULL)) {
|
||||||
/* Force check of the request packet, now we know the session key */
|
/* Force check of the request packet, now we know the session key */
|
||||||
req_signing_check_incoming(req);
|
req_signing_check_incoming(req);
|
||||||
|
|
||||||
srv_signing_restart(req->smb_conn, &session_key, NULL);
|
srv_signing_restart(req->smb_conn, &session_key, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
|
||||||
} else {
|
} else {
|
||||||
status = auth_nt_status_squash(status);
|
status = auth_nt_status_squash(status);
|
||||||
if (smb_sess->gensec_ctx &&
|
|
||||||
!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
|
/* This invalidates the VUID of the failed login */
|
||||||
talloc_free(smb_sess->gensec_ctx);
|
talloc_free(smb_sess);
|
||||||
smb_sess->gensec_ctx = NULL;
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!smb_sess) {
|
||||||
|
smb_sess = smbsrv_register_session(req->smb_conn,
|
||||||
|
session_info, gensec_ctx);
|
||||||
|
if (!smb_sess) {
|
||||||
|
return NT_STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
req->session = smb_sess;
|
||||||
|
} else {
|
||||||
|
smb_sess->session_info = talloc_reference(smb_sess, session_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
sess->spnego.out.action = 0;
|
if (NT_STATUS_IS_OK(status)) {
|
||||||
sess->spnego.out.vuid = vuid;
|
/* Ensure this is marked as a 'real' vuid, not one
|
||||||
sesssetup_common_strings(req,
|
* simply valid for the session setup leg */
|
||||||
&sess->spnego.out.os,
|
smb_sess->finished_sesssetup = True;
|
||||||
&sess->spnego.out.lanman,
|
}
|
||||||
&sess->spnego.out.workgroup);
|
sess->spnego.out.vuid = smb_sess->vuid;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -737,7 +737,7 @@ static void smbsrv_accept(struct stream_connection *conn)
|
|||||||
|
|
||||||
smb_conn->negotiate.zone_offset = get_time_zone(time(NULL));
|
smb_conn->negotiate.zone_offset = get_time_zone(time(NULL));
|
||||||
|
|
||||||
smb_conn->sessions.next_vuid = VUID_OFFSET;
|
smbsrv_vuid_init(smb_conn);
|
||||||
|
|
||||||
srv_init_signing(smb_conn);
|
srv_init_signing(smb_conn);
|
||||||
|
|
||||||
|
@ -47,6 +47,10 @@ struct smbsrv_session {
|
|||||||
struct gensec_security *gensec_ctx;
|
struct gensec_security *gensec_ctx;
|
||||||
|
|
||||||
struct auth_session_info *session_info;
|
struct auth_session_info *session_info;
|
||||||
|
|
||||||
|
/* Distinguish between a VUID allocated for the multi-pass
|
||||||
|
* extended secrity session setup and one that is finished */
|
||||||
|
BOOL finished_sesssetup;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* we need a forward declaration of the ntvfs_ops strucutre to prevent
|
/* we need a forward declaration of the ntvfs_ops strucutre to prevent
|
||||||
@ -216,8 +220,11 @@ struct smbsrv_connection {
|
|||||||
struct {
|
struct {
|
||||||
/* this holds info on session vuids that are already validated for this VC */
|
/* this holds info on session vuids that are already validated for this VC */
|
||||||
struct smbsrv_session *session_list;
|
struct smbsrv_session *session_list;
|
||||||
uint16_t next_vuid; /* initialise to VUID_OFFSET */
|
|
||||||
int num_validated_vuids;
|
int num_validated_vuids;
|
||||||
|
|
||||||
|
/* an id tree used to allocate vuids */
|
||||||
|
struct idr_context *idtree_vuid;
|
||||||
} sessions;
|
} sessions;
|
||||||
|
|
||||||
/* the server_context holds a linked list of pending requests,
|
/* the server_context holds a linked list of pending requests,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user