r11783: - make the VIUD field in smbsrv_session 64bit, as SMB2 needs it
authorStefan Metzmacher <metze@samba.org>
Fri, 18 Nov 2005 12:57:48 +0000 (12:57 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:46:26 +0000 (13:46 -0500)
- add an idtree_limit to limit the max VUID we give the clients
  it's UINT16_MAX (0xffff) for the SMB protocol
- add auth_time to the smbsrv_session statistics
- use the session_info as marker for finished and non-finished
  session setups

metze

source/librpc/idl/irpc.idl
source/smb_server/management.c
source/smb_server/receive.c
source/smb_server/session.c
source/smb_server/sesssetup.c
source/smb_server/smb_server.h

index 6ca853d6429f3d9566103895b099ddbae65e34ac..d7a727bee7be7705f2a2b706466657f4c45eecce 100644 (file)
        } smbsrv_info_level;
 
        typedef struct {
-               uint16 vuid;
+               hyper vuid;
                astring account_name;
                astring domain_name;
                astring client_ip;
                NTTIME  connect_time;
+               NTTIME  auth_time;
        } smbsrv_session_info;
 
        typedef struct {
index 9f22ee94e865c80e2ca5f1c8d580819389ce4b2e..d158947ba45510e878da06c202d07813ce723545 100644 (file)
@@ -51,8 +51,9 @@ static NTSTATUS smbsrv_session_information(struct irpc_message *msg,
                info->vuid         = sess->vuid;
                info->account_name = sess->session_info->server_info->account_name;
                info->domain_name  = sess->session_info->server_info->domain_name;
-               info->connect_time = timeval_to_nttime(&sess->connect_time);
                info->client_ip    = socket_get_peer_addr(smb_conn->connection->socket, r);
+               info->connect_time = timeval_to_nttime(&sess->statistics.connect_time);
+               info->auth_time    = timeval_to_nttime(&sess->statistics.auth_time);
                i++;
        }       
 
index 3ecd111af634fabe3937f864962026e368f62db0..0ee87698c8a32d852a92f55d7ff0a9e3299ee0ac 100644 (file)
@@ -645,7 +645,7 @@ NTSTATUS smbsrv_init_smb_connection(struct smbsrv_connection *smb_conn)
        smb_conn->config.security = lp_security();
        smb_conn->config.nt_status_support = lp_nt_status_support();
 
-       status = smbsrv_init_sessions(smb_conn);
+       status = smbsrv_init_sessions(smb_conn, UINT16_MAX);
        NT_STATUS_NOT_OK_RETURN(status);
 
        status = smbsrv_init_tcons(smb_conn, UINT16_MAX);
index ba141f96ecff70f81a4a9bf8f1acede5c013174d..967c02bfc9c1cf00630cdc73feb7ce50dbc42815 100644 (file)
 #include "dlinklist.h"
 
 
-/****************************************************************************
-init the session structures
-****************************************************************************/
-NTSTATUS smbsrv_init_sessions(struct smbsrv_connection *smb_conn)
+/*
+ * init the sessions structures
+ */
+NTSTATUS smbsrv_init_sessions(struct smbsrv_connection *smb_conn, uint64_t limit)
 {
-       smb_conn->sessions.idtree_vuid = idr_init(smb_conn);
+       /* 
+        * the idr_* functions take 'int' as limit,
+        * and only work with a max limit 0x00FFFFFF
+        */
+       limit &= 0x00FFFFFF;
+
+       smb_conn->sessions.idtree_vuid  = idr_init(smb_conn);
        NT_STATUS_HAVE_NO_MEMORY(smb_conn->sessions.idtree_vuid);
+       smb_conn->sessions.idtree_limit = limit;
+       smb_conn->sessions.list         = NULL;
+
        return NT_STATUS_OK;
 }
 
-/****************************************************************************
-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)
+/*
+ * 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, uint64_t vuid)
 {
-       struct smbsrv_session *sess = idr_find(smb_conn->sessions.idtree_vuid, vuid);
-       if (sess && sess->finished_sesssetup) {
+       void *p;
+       struct smbsrv_session *sess;
+
+       if (vuid == 0) return NULL;
+
+       if (vuid > smb_conn->sessions.idtree_limit) return NULL;
+
+       p = idr_find(smb_conn->sessions.idtree_vuid, vuid);
+       if (!p) return NULL;
+
+       /* only return a finished session */
+       sess = talloc_get_type(p, struct smbsrv_session);
+       if (sess && sess->session_info) {
                return sess;
        }
+
        return NULL;
 }
 
-/****************************************************************************
- Find a VUID assoicated with an in-progress session setup
-****************************************************************************/
-struct smbsrv_session *smbsrv_session_find_sesssetup(struct smbsrv_connection *smb_conn, uint16_t vuid)
+/*
+ * Find the session structure assoicated with a VUID
+ * (assoicated with an in-progress session setup)
+ */
+struct smbsrv_session *smbsrv_session_find_sesssetup(struct smbsrv_connection *smb_conn, uint64_t vuid)
 {
-       struct smbsrv_session *sess = idr_find(smb_conn->sessions.idtree_vuid, vuid);
-       if (sess && !sess->finished_sesssetup) {
+       void *p;
+       struct smbsrv_session *sess;
+
+       if (vuid == 0) return NULL;
+
+       if (vuid > smb_conn->sessions.idtree_limit) return NULL;
+
+       p = idr_find(smb_conn->sessions.idtree_vuid, vuid);
+       if (!p) return NULL;
+
+       /* only return an unfinished session */
+       sess = talloc_get_type(p, struct smbsrv_session);
+       if (sess && !sess->session_info) {
                return sess;
        }
        return NULL;
 }
 
-/****************************************************************************
-invalidate a session
-****************************************************************************/
-static int smbsrv_session_destructor(void *p) 
+/*
+ * the session will be marked as valid for usage
+ * by attaching a auth_session_info to the session.
+ *
+ * session_info will be talloc_stealed
+ */
+NTSTATUS smbsrv_session_sesssetup_finished(struct smbsrv_session *sess,
+                                          struct auth_session_info *session_info)
 {
-       struct smbsrv_session *sess = talloc_get_type(p, struct smbsrv_session);
-       struct smbsrv_connection *smb_conn = sess->smb_conn;
-
-       /* clear the vuid from the 'cache' on each connection, and
-          from the vuid 'owner' of connections */
-       /* REWRITE: conn_clear_vuid_cache(smb, vuid); */
+       /* this check is to catch programmer errors */
+       if (!session_info) {
+               talloc_free(sess);
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
-       smb_conn->sessions.num_validated_vuids--;
+       /* mark the session as successful authenticated */
+       sess->session_info = talloc_steal(sess, session_info);
 
-       idr_remove(smb_conn->sessions.idtree_vuid, sess->vuid);
+       /* now fill in some statistics */
+       sess->statistics.auth_time = timeval_current();
 
-       DLIST_REMOVE(smb_conn->sessions.list, sess);
-       return 0;
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
-invalidate a uid
+destroy a session structure
 ****************************************************************************/
-void smbsrv_invalidate_vuid(struct smbsrv_connection *smb_conn, uint16_t vuid)
+static int smbsrv_session_destructor(void *p)
 {
-       struct smbsrv_session *sess = smbsrv_session_find(smb_conn, vuid);
-       talloc_free(sess);
+       struct smbsrv_session *sess = talloc_get_type(p, struct smbsrv_session);
+       struct smbsrv_connection *smb_conn = sess->smb_conn;
+
+       idr_remove(smb_conn->sessions.idtree_vuid, sess->vuid);
+       DLIST_REMOVE(smb_conn->sessions.list, sess);
+       return 0;
 }
 
-/**
- *  register that a valid login has been performed, establish 'session'.
- *  @param session_info The token returned from the authentication process (if the authentication has completed)
- *   (now 'owned' by register_vuid)
- *
- *  @param smb_name The untranslated name of the user
- *
- *  @return Newly allocated vuid, biased by an offset. (This allows us to
- *   tell random client vuid's (normally zero) from valid vuids.)
- *
+/*
+ * allocate a new session structure with a VUID.
+ * gensec_ctx is optional, but talloc_steal'ed when present
  */
-
-struct smbsrv_session *smbsrv_register_session(struct smbsrv_connection *smb_conn,
-                                              struct auth_session_info *session_info,
-                                              struct gensec_security *gensec_ctx)
+struct smbsrv_session *smbsrv_session_new(struct smbsrv_connection *smb_conn,
+                                         struct gensec_security *gensec_ctx)
 {
        struct smbsrv_session *sess = NULL;
        int i;
@@ -109,15 +142,11 @@ struct smbsrv_session *smbsrv_register_session(struct smbsrv_connection *smb_con
        /* Ensure no vuid gets registered in share level security. */
        if (smb_conn->config.security == SEC_SHARE) return NULL;
 
-       sess = talloc(smb_conn, struct smbsrv_session);
-       if (sess == NULL) {
-               DEBUG(0,("talloc(smb_conn->mem_ctx, struct smbsrv_session) failed\n"));
-               return sess;
-       }
-
-       ZERO_STRUCTP(sess);
+       sess = talloc_zero(smb_conn, struct smbsrv_session);
+       if (!sess) return NULL;
+       sess->smb_conn = smb_conn;
 
-       i = idr_get_new_random(smb_conn->sessions.idtree_vuid, sess, UINT16_MAX);
+       i = idr_get_new_random(smb_conn->sessions.idtree_vuid, sess, smb_conn->sessions.idtree_limit);
        if (i == -1) {
                DEBUG(1,("ERROR! Out of connection structures\n"));
                talloc_free(sess);
@@ -125,18 +154,14 @@ struct smbsrv_session *smbsrv_register_session(struct smbsrv_connection *smb_con
        }
        sess->vuid = i;
 
-       smb_conn->sessions.num_validated_vuids++;
-
        /* use this to keep tabs on all our info from the authentication */
-       sess->session_info = talloc_reference(sess, session_info);
-       
-       sess->gensec_ctx = talloc_reference(sess, gensec_ctx);
-       sess->smb_conn = smb_conn;
-       sess->connect_time = timeval_current();
+       sess->gensec_ctx = talloc_steal(sess, gensec_ctx);
 
        DLIST_ADD(smb_conn->sessions.list, sess);
-
        talloc_set_destructor(sess, smbsrv_session_destructor);
 
+       /* now fill in some statistics */
+       sess->statistics.connect_time = timeval_current();
+
        return sess;
 }
index 5533eca60787ec3e4e66e6fc10b9dff26e8cd43c..3f09346243a4062b95a64d727b2f1bec8caa277e 100644 (file)
@@ -5,7 +5,8 @@
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005
    Copyright (C) Jim McDonough                        2002
    Copyright (C) Luke Howard                          2003
-
+   Copyright (C) Stefan Metzmacher                    2005
+   
    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
    the Free Software Foundation; either version 2 of the License, or
@@ -95,14 +96,18 @@ static NTSTATUS sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *s
                return auth_nt_status_squash(status);
        }
 
-       smb_sess = smbsrv_register_session(req->smb_conn, session_info, NULL);
+       /* allocate a new session */
+       smb_sess = smbsrv_session_new(req->smb_conn, NULL);
        if (!smb_sess) {
                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;
+       status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               return auth_nt_status_squash(status);
+       }
 
        /* To correctly process any AndX packet (like a tree connect)
         * we need to fill in the session on the request here */
@@ -158,7 +163,7 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s
        if (req->smb_conn->negotiate.calling_name) {
                remote_machine = req->smb_conn->negotiate.calling_name->name;
        }
-       
+
        if (!remote_machine) {
                remote_machine = socket_get_peer_addr(req->smb_conn->connection->socket, req);
        }
@@ -191,14 +196,18 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s
                return auth_nt_status_squash(status);
        }
 
-       smb_sess = smbsrv_register_session(req->smb_conn, session_info, NULL);
+       /* allocate a new session */
+       smb_sess = smbsrv_session_new(req->smb_conn, NULL);
        if (!smb_sess) {
                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;
+       status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               return auth_nt_status_squash(status);
+       }
 
        /* To correctly process any AndX packet (like a tree connect)
         * we need to fill in the session on the request here */
@@ -260,7 +269,6 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup
        smb_sess = smbsrv_session_find_sesssetup(req->smb_conn, vuid);
        if (smb_sess) {
                gensec_ctx = smb_sess->gensec_ctx;
-               status = gensec_update(gensec_ctx, req, sess->spnego.in.secblob, &sess->spnego.out.secblob);
        } else {
                status = gensec_server_start(req, &gensec_ctx,
                                             req->smb_conn->connection->event.ctx);
@@ -281,9 +289,13 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup
                        return status;
                }
 
-               status = gensec_update(gensec_ctx, req, sess->spnego.in.secblob, &sess->spnego.out.secblob);
+               smb_sess = smbsrv_session_new(req->smb_conn, gensec_ctx);
+               if (!smb_sess) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
        }
 
+       status = gensec_update(gensec_ctx, req, sess->spnego.in.secblob, &sess->spnego.out.secblob);
        if (NT_STATUS_IS_OK(status)) {
                DATA_BLOB session_key;
                
@@ -314,22 +326,14 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup
                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;
-               talloc_steal(smb_sess, gensec_ctx);
-       } else {
-               smb_sess->session_info = talloc_reference(smb_sess, session_info);
-       }
-
        if (NT_STATUS_IS_OK(status)) {
                /* Ensure this is marked as a 'real' vuid, not one
                 * simply valid for the session setup leg */
-               smb_sess->finished_sesssetup = True;
+               status = smbsrv_session_sesssetup_finished(smb_sess, session_info);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return auth_nt_status_squash(status);
+               }
+               req->session = smb_sess;
        }
        sess->spnego.out.vuid = smb_sess->vuid;
 
index 46a10c74bb2a446fa506d11b6c6e53073d9cd710..f879845134e2ce07d9648dc501adc1d0ea487c9d 100644 (file)
@@ -38,21 +38,24 @@ struct smbsrv_session {
 
        struct smbsrv_connection *smb_conn;
 
-       /* the vuid is used to specify the security context for this
-          request. Note that this may not be the same vuid as we
-          received on the wire (for example, for share mode or guest
-          access) */
-       uint16_t vuid;
+       /* 
+        * an index passed over the wire:
+        * - 16 bit for smb
+        * - 64 bit for smb2
+        */
+       uint64_t vuid;
 
        struct gensec_security *gensec_ctx;
 
        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;
-
-       struct timeval connect_time;
+       /* some statictics for the management tools */
+       struct {
+               /* the time when the session setup started */
+               struct timeval connect_time;
+               /* the time when the session setup was finished */
+               struct timeval auth_time;
+       } statistics;
 };
 
 /* we need a forward declaration of the ntvfs_ops strucutre to prevent
@@ -242,13 +245,14 @@ struct smbsrv_connection {
 
        /* context associated with currently valid session setups */
        struct {
-               int num_validated_vuids;
-
                /* an id tree used to allocate vuids */
                /* this holds info on session vuids that are already
                 * validated for this VC */
                struct idr_context *idtree_vuid;
 
+               /* this is the limit of vuid values for this connection */
+               uint64_t idtree_limit;
+
                /* also kept as a link list so it can be enumerated by
                   the management code */
                struct smbsrv_session *list;