r17930: Merge noinclude branch:
[kai/samba.git] / source4 / smb_server / smb_server.h
index 02070f2b130eaba99bf8a2b65f64fe27438d23e7..e0913db030755567ebdc8a15c311bd80ae22d1ec 100644 (file)
@@ -3,7 +3,7 @@
    
    Copyright (C) Andrew Tridgell              2003
    Copyright (C) James J Myers                       2003 <myersjj@samba.org>
-   Copyright (C) Stefan Metzmacher            2004
+   Copyright (C) Stefan Metzmacher            2004-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
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include "request.h"
-#include "smbd/process_model.h"
+#include "libcli/raw/request.h"
+#include "libcli/raw/interfaces.h"
+#include "lib/events/events.h"
+#include "lib/socket/socket.h"
+#include "lib/util/dlinklist.h"
 
 /*
   this header declares the core context structures associated with smb
   sockets, tree connects, requests etc
 
   the idea is that we will eventually get rid of all our global
-  variables and instead store our stang from structures hanging off
+  variables and instead store our state from structures hanging off
   these basic elements
 */
 
+struct smbsrv_tcons_context {
+       /* an id tree used to allocate tids */
+       struct idr_context *idtree_tid;
+
+       /* this is the limit of vuid values for this connection */
+       uint32_t idtree_limit;
+
+       /* list of open tree connects */
+       struct smbsrv_tcon *list;
+};
+
+struct smbsrv_sessions_context {
+       /* 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;
+};
+
+struct smbsrv_handles_context {
+       /* an id tree used to allocate file handles */
+       struct idr_context *idtree_hid;
+
+       /* this is the limit of handle values for this context */
+       uint64_t idtree_limit;
+
+       /* also kept as a link list so it can be enumerated by
+          the management code */
+       struct smbsrv_handle *list;
+};
+
 /* the current user context for a request */
 struct smbsrv_session {
        struct smbsrv_session *prev, *next;
 
        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;
+       /*
+        * in SMB2 tcons belong to just one session
+        * and not to the whole connection
+        */
+       struct smbsrv_tcons_context smb2_tcons;
+
+       /*
+        * the open file handles for this session,
+        * used for SMBexit, SMBulogoff and SMB2 SessionLogoff
+        */
+       struct smbsrv_handle_session_item *handles;
+
+       /* 
+        * 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;
+
+       /* some statistics 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;
+               /* the time when the last request comes in */
+               struct timeval last_request_time;
+       } statistics;
 };
 
 /* we need a forward declaration of the ntvfs_ops strucutre to prevent
@@ -59,24 +122,95 @@ struct smbsrv_tcon {
        /* the server context that this was created on */
        struct smbsrv_connection *smb_conn;
 
-       uint16_t tid; /* an index passed over the wire (the TID) */
+       /* the open file handles on this tcon */
+       struct smbsrv_handles_context handles;
+
+       /* 
+        * an index passed over the wire:
+        * - 16 bit for smb
+        * - 32 bit for smb2
+        */
+       uint32_t tid; /* an index passed over the wire (the TID) */
 
-       int service;
-       BOOL read_only;
-       BOOL admin_user;
+       /* the share name */
+       const char *share_name;
 
        /* the NTVFS context - see source/ntvfs/ for details */
-       struct ntvfs_context *ntvfs_ctx;
+       struct ntvfs_context *ntvfs;
+
+       /* some stuff to support share level security */
+       struct {
+               /* in share level security we need to fake up a session */
+               struct smbsrv_session *session;
+       } sec_share;
 
-       /* the reported filesystem type */
-       char *fs_type;
+       /* some stuff to support share level security */
+       struct {
+               /* in SMB2 a tcon always belongs to one session */
+               struct smbsrv_session *session;
+       } smb2;
 
-       /* the reported device type */
-       char *dev_type;
+       /* some statistics for the management tools */
+       struct {
+               /* the time when the tree connect started */
+               struct timeval connect_time;
+               /* the time when the last request comes in */
+               struct timeval last_request_time;
+       } statistics;
+};
+
+struct smbsrv_handle {
+       struct smbsrv_handle *next, *prev;
+
+       /* the tcon the handle belongs to */
+       struct smbsrv_tcon *tcon;
+
+       /* the session the handle was opened on */
+       struct smbsrv_session *session;
+
+       /* the smbpid used on the open, used for SMBexit */
+       uint16_t smbpid;
+
+       /*
+        * this is for adding the handle into a linked list
+        * on the smbsrv_session, we can't use *next,*prev
+        * for this because they're used for the linked list on the 
+        * smbsrv_tcon
+        */
+       struct smbsrv_handle_session_item {
+               struct smbsrv_handle_session_item *prev, *next;
+               struct smbsrv_handle *handle;
+       } session_item;
+
+       /*
+        * the value passed over the wire
+        * - 16 bit for smb
+        * - 64 bit for smb2
+        *   Note: for SMB2 handles are 128 bit
+        *         we'll fill the 2nd 64 bit with:
+        *         - 32 bit TID
+        *         - 32 bit 0xFFFFFFFF
+        */
+       uint64_t hid;
+
+       /*
+        * the ntvfs handle passed to the ntvfs backend
+        */
+       struct ntvfs_handle *ntvfs;
+
+       /* some statistics for the management tools */
+       struct {
+               /* the time when the tree connect started */
+               struct timeval open_time;
+               /* the time when the last request comes in */
+               struct timeval last_use_time;
+       } statistics;
 };
 
 /* a set of flags to control handling of request structures */
-#define REQ_CONTROL_LARGE     (1<<1) /* allow replies larger than max_xmit */
+#define SMBSRV_REQ_CONTROL_LARGE     (1<<1) /* allow replies larger than max_xmit */
+
+#define SMBSRV_REQ_DEFAULT_STR_FLAGS(req) (((req)->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII)
 
 /* the context for a single SMB request. This is passed to any request-context 
    functions */
@@ -93,18 +227,23 @@ struct smbsrv_request {
        /* the session context is derived from the vuid */
        struct smbsrv_session *session;
 
-       /* a set of flags to control usage of the request. See REQ_CONTROL_* */
-       unsigned control_flags;
-
-       /* the smb pid is needed for locking contexts */
-       uint16_t smbpid;
-
-       /* the flags from the SMB request, in raw form (host byte order) */
-       uint16_t flags, flags2;
+       /* a set of flags to control usage of the request. See SMBSRV_REQ_CONTROL_* */
+       uint32_t control_flags;
 
        /* the system time when the request arrived */
        struct timeval request_time;
 
+       /* a pointer to the per request union smb_* io structure */
+       void *io_ptr;
+
+       /* the ntvfs_request */
+       struct ntvfs_request *ntvfs;
+
+       /* Now the SMB specific stuff */
+
+       /* the flags from the SMB request, in raw form (host byte order) */
+       uint16_t flags2;
+
        /* this can contain a fnum from an earlier part of a chained
         * message (such as an SMBOpenX), or -1 */
        int chained_fnum;
@@ -115,34 +254,11 @@ struct smbsrv_request {
        /* the sequence number for signing */
        uint64_t seq_num;
 
-       /* ntvfs per request async states */
-       struct ntvfs_async_state *async_states;
-
        struct request_buffer in;
        struct request_buffer out;
 };
 
-/* this contains variables that should be used in % substitutions for
- * smb.conf parameters */
-struct substitute_context {
-       char *remote_arch;
-
-       /* our local netbios name, as give to us by the client */
-       char *local_machine;
-
-       /* the remote netbios name, as give to us by the client */
-       char *remote_machine;
-
-       /* the select remote protocol */
-       char *remote_proto;     
-
-       /* the name of the client as should be displayed in
-        * smbstatus. Can be an IP or a netbios name */
-       char *client_name; 
-
-       /* the username for %U */
-       char *user_name;
-};
+enum security_types {SEC_SHARE,SEC_USER};
 
 /* smb server context structure. This should contain all the state
  * information associated with a SMB server connection 
@@ -173,24 +289,20 @@ struct smbsrv_connection {
                 */
                unsigned max_recv; /* init to BUFFER_SIZE */
        
-               /* a guess at the remote architecture. Try not to rely on this - in almost
-                  all cases using these values is the wrong thing to do */
-               enum remote_arch_types ra_type;
-       
                /* the negotiatiated protocol */
                enum protocol_types protocol;
        
                /* authentication context for multi-part negprot */
                struct auth_context *auth_context;
        
-               /* state of NTLMSSP auth */
-               struct auth_ntlmssp_state *ntlmssp_state;
+               /* reference to the kerberos keytab, or machine trust account */
+               struct cli_credentials *server_credentials;
        
                /* did we tell the client we support encrypted passwords? */
                BOOL encrypted_passwords;
        
-               /* did we send an extended security negprot reply? */
-               BOOL spnego_negotiated;
+               /* Did we choose SPNEGO, or perhaps raw NTLMSSP, or even no extended security at all? */
+               const char *oid;
        
                /* client capabilities */
                uint32_t client_caps;
@@ -203,43 +315,41 @@ struct smbsrv_connection {
                struct nbt_name *calling_name;
        } negotiate;
 
-       /* the context associated with open tree connects on a smb socket */
-       struct {
-               /* list of open tree connects */
-               struct smbsrv_tcon *tcons;
-
-               /* an id tree used to allocate tids */
-               struct idr_context *idtree_tid;
-       } tree;
+       /* the context associated with open tree connects on a smb socket, not for SMB2 */
+       struct smbsrv_tcons_context smb_tcons;
 
        /* context associated with currently valid session setups */
+       struct smbsrv_sessions_context sessions;
+
+       /*
+        * the server_context holds a linked list of pending requests,
+        * this is used for finding the request structures on ntcancel requests
+        * For SMB only
+        */
+       struct smbsrv_request *requests;
+
+       /*
+        * the server_context holds a linked list of pending requests,
+        * and an idtree for finding the request structures on SMB2 Cancel
+        * For SMB2 only
+        */
        struct {
-               /* this holds info on session vuids that are already validated for this VC */
-               struct smbsrv_session *session_list;
-               uint16_t next_vuid; /* initialise to VUID_OFFSET */
-               int num_validated_vuids;
-       } sessions;
-
-       /* the server_context holds a linked list of pending requests,
-        * this is used for blocking locks and requests blocked due to oplock
-        * break requests */
-       struct _smbsrv_pending_request {
-               struct _smbsrv_pending_request *next, *prev;
-       
-               /* the request itself - needs to be freed */
-               struct smbsrv_request *request;
-       } *requests;
+               /* an id tree used to allocate ids */
+               struct idr_context *idtree_req;
+
+               /* this is the limit of pending requests values for this connection */
+               uint32_t idtree_limit;
+
+               /* list of open tree connects */
+               struct smb2srv_request *list;
+       } requests2;
 
        struct smb_signing_context signing;
-       
+
        struct stream_connection *connection;
 
        /* this holds a partially received request */
-       struct smbsrv_request *partial_req;
-
-       /* this holds list of replies that are waiting to be sent
-          to the client */
-       struct smbsrv_request *pending_send;
+       struct packet_context *packet;
 
        /* a list of partially received transaction requests */
        struct smbsrv_trans_partial {
@@ -248,4 +358,127 @@ struct smbsrv_connection {
                struct smb_trans2 *trans;
                uint8_t command;
        } *trans_partial;
+
+       /* configuration parameters */
+       struct {
+               enum security_types security;
+               BOOL nt_status_support;
+       } config;
+
+       /* some statictics for the management tools */
+       struct {
+               /* the time when the client connects */
+               struct timeval connect_time;
+               /* the time when the last request comes in */
+               struct timeval last_request_time;
+       } statistics;
+
+       struct share_context *share_context;
 };
+
+#include "smb_server/smb_server_proto.h"
+#include "smb_server/smb/smb_proto.h"
+
+/* useful way of catching wct errors with file and line number */
+#define SMBSRV_CHECK_WCT(req, wcount) do { \
+       if ((req)->in.wct != (wcount)) { \
+               DEBUG(1,("Unexpected WCT %d at %s(%d) - expected %d\n", \
+                        (req)->in.wct, __FILE__, __LINE__, wcount)); \
+               smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror)); \
+               return; \
+       } \
+} while (0)
+       
+/* useful wrapper for talloc with NO_MEMORY reply */
+#define SMBSRV_TALLOC_IO_PTR(ptr, type) do { \
+       ptr = talloc(req, type); \
+       if (!ptr) { \
+               smbsrv_send_error(req, NT_STATUS_NO_MEMORY); \
+               return; \
+       } \
+       req->io_ptr = ptr; \
+} while (0)
+
+#define SMBSRV_SETUP_NTVFS_REQUEST(send_fn, state) do { \
+       req->ntvfs = ntvfs_request_create(req->tcon->ntvfs, req, \
+                                         req->session->session_info,\
+                                         SVAL(req->in.hdr,HDR_PID), \
+                                         req->request_time, \
+                                         req, send_fn, state); \
+       if (!req->ntvfs) { \
+               smbsrv_send_error(req, NT_STATUS_NO_MEMORY); \
+               return; \
+       } \
+       (void)talloc_steal(req->tcon->ntvfs, req); \
+       req->ntvfs->frontend_data.private_data = req; \
+} while (0)
+
+#define SMBSRV_CHECK_FILE_HANDLE(handle) do { \
+       if (!handle) { \
+               smbsrv_send_error(req, NT_STATUS_INVALID_HANDLE); \
+               return; \
+       } \
+} while (0)
+
+#define SMBSRV_CHECK_FILE_HANDLE_ERROR(handle, _status) do { \
+       if (!handle) { \
+               smbsrv_send_error(req, _status); \
+               return; \
+       } \
+} while (0)
+
+#define SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(handle) do { \
+       if (!handle) { \
+               return NT_STATUS_INVALID_HANDLE; \
+       } \
+} while (0)
+
+#define SMBSRV_CHECK(cmd) do {\
+       NTSTATUS _status; \
+       _status = cmd; \
+       if (!NT_STATUS_IS_OK(_status)) { \
+               smbsrv_send_error(req,  _status); \
+               return; \
+       } \
+} while (0)
+
+/* 
+   check if the backend wants to handle the request asynchronously.
+   if it wants it handled synchronously then call the send function
+   immediately
+*/
+#define SMBSRV_CALL_NTVFS_BACKEND(cmd) do { \
+       req->ntvfs->async_states->status = cmd; \
+       if (req->ntvfs->async_states->state & NTVFS_ASYNC_STATE_ASYNC) { \
+               DLIST_ADD_END(req->smb_conn->requests, req, struct smbsrv_request *); \
+       } else { \
+               req->ntvfs->async_states->send_fn(req->ntvfs); \
+       } \
+} while (0)
+
+/* check req->ntvfs->async_states->status and if not OK then send an error reply */
+#define SMBSRV_CHECK_ASYNC_STATUS_ERR_SIMPLE do { \
+       req = talloc_get_type(ntvfs->async_states->private_data, struct smbsrv_request); \
+       if (NT_STATUS_IS_ERR(ntvfs->async_states->status)) { \
+               smbsrv_send_error(req, ntvfs->async_states->status); \
+               return; \
+       } \
+} while (0)
+#define SMBSRV_CHECK_ASYNC_STATUS_ERR(ptr, type) do { \
+       SMBSRV_CHECK_ASYNC_STATUS_ERR_SIMPLE; \
+       ptr = talloc_get_type(req->io_ptr, type); \
+} while (0)
+#define SMBSRV_CHECK_ASYNC_STATUS_SIMPLE do { \
+       req = talloc_get_type(ntvfs->async_states->private_data, struct smbsrv_request); \
+       if (!NT_STATUS_IS_OK(ntvfs->async_states->status)) { \
+               smbsrv_send_error(req, ntvfs->async_states->status); \
+               return; \
+       } \
+} while (0)
+#define SMBSRV_CHECK_ASYNC_STATUS(ptr, type) do { \
+       SMBSRV_CHECK_ASYNC_STATUS_SIMPLE; \
+       ptr = talloc_get_type(req->io_ptr, type); \
+} while (0)
+
+/* zero out some reserved fields in a reply */
+#define SMBSRV_VWV_RESERVED(start, count) memset(req->out.vwv + VWV(start), 0, (count)*2)