s3:smbd: check the incoming session id for SMB2 requests
authorStefan Metzmacher <metze@samba.org>
Wed, 20 May 2009 18:51:10 +0000 (20:51 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 20 May 2009 18:53:39 +0000 (20:53 +0200)
metze

source3/smbd/globals.h
source3/smbd/smb2_server.c
source3/smbd/smb2_sesssetup.c

index 5a7ad7d9e32918a19bd388a904747f909d23ce98..345f74880203a5819418041121c70d57d70a34c3 100644 (file)
@@ -201,6 +201,7 @@ extern int num_children;
 
 struct tstream_context;
 struct smbd_smb2_request;
+struct smbd_smb2_session;
 
 DATA_BLOB negprot_spnego(void);
 
@@ -220,6 +221,8 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
 NTSTATUS smbd_smb2_request_done(struct smbd_smb2_request *req,
                                DATA_BLOB body, DATA_BLOB *dyn);
 
+NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req);
+
 NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req);
 NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *req);
 NTSTATUS smbd_smb2_request_process_keepalive(struct smbd_smb2_request *req);
@@ -229,6 +232,9 @@ struct smbd_smb2_request {
 
        struct smbd_server_connection *conn;
 
+       /* the session the request operates on, maybe NULL */
+       struct smbd_smb2_session *session;
+
        int current_idx;
 
        struct {
index 6d8961eebb1ddab70911fe5ab46fc5885dae4495..36f4c10b17d6aec56043d301fed1a7e26d84b5a8 100644 (file)
@@ -288,6 +288,7 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
        const uint8_t *inhdr;
        int i = req->current_idx;
        uint16_t opcode;
+       NTSTATUS status;
 
        inhdr = (const uint8_t *)req->in.vector[i].iov_base;
 
@@ -303,35 +304,73 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
                return smbd_smb2_request_process_sesssetup(req);
 
        case SMB2_OP_LOGOFF:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
-               return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
        case SMB2_OP_TCON:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
-               return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
        case SMB2_OP_TDIS:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_CREATE:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_CLOSE:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_FLUSH:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_READ:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_WRITE:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_LOCK:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_IOCTL:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_CANCEL:
@@ -341,18 +380,38 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
                return smbd_smb2_request_process_keepalive(req);
 
        case SMB2_OP_FIND:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_NOTIFY:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_GETINFO:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_SETINFO:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
 
        case SMB2_OP_BREAK:
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
                return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
        }
 
index 6c4da393e17849bc19d29ab1749874e9b9b8795f..d322223ad5fa3215ed740126d11ee2e13cae0ca2 100644 (file)
@@ -180,6 +180,11 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req,
        } else if (NT_STATUS_IS_OK(status)) {
                /* TODO: setup session key for signing */
                session->status = NT_STATUS_OK;
+               /*
+                * we attach the session to the request
+                * so that the response can be signed
+                */
+               req->session = session;
        } else {
                return status;
        }
@@ -188,3 +193,29 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req,
        return status;
 }
 
+NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
+{
+       const uint8_t *inhdr;
+       int i = req->current_idx;
+       uint64_t in_session_id;
+       void *p;
+       struct smbd_smb2_session *session;
+
+       inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
+
+       in_session_id = SVAL(inhdr, SMB2_HDR_SESSION_ID);
+
+       /* lookup an existing session */
+       p = idr_find(req->conn->smb2.sessions.idtree, in_session_id);
+       if (p == NULL) {
+               return NT_STATUS_USER_SESSION_DELETED;
+       }
+       session = talloc_get_type_abort(p, struct smbd_smb2_session);
+
+       if (!NT_STATUS_IS_OK(session->status)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       req->session = session;
+       return NT_STATUS_OK;
+}