s3:smbd: SMB2 session ids are 64bit...
[ira/wip.git] / source3 / smbd / smb2_server.c
index c4c5492e5fdfce509dc0bda86159e7a4285dda3e..c6160189fe2057bae6ed08e5a31f9641ac3dafe9 100644 (file)
@@ -55,6 +55,13 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *conn)
                return NT_STATUS_NO_MEMORY;
        }
 
+       conn->smb2.sessions.idtree = idr_init(conn);
+       if (conn->smb2.sessions.idtree == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       conn->smb2.sessions.limit = 0x00FFFFFF;
+       conn->smb2.sessions.list = NULL;
+
        ret = tstream_bsd_existing_socket(conn, smbd_server_fd(),
                                          &conn->smb2.stream);
        if (ret == -1) {
@@ -281,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;
 
@@ -293,38 +301,76 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
                return smbd_smb2_request_process_negprot(req);
 
        case SMB2_OP_SESSSETUP:
-               return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
+               return smbd_smb2_request_process_sesssetup(req);
 
        case SMB2_OP_LOGOFF:
-               return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED);
+               status = smbd_smb2_request_check_session(req);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return smbd_smb2_request_error(req, status);
+               }
+               return smbd_smb2_request_process_logoff(req);
 
-               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:
@@ -334,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);
        }
 
@@ -394,6 +460,48 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
        return NT_STATUS_OK;
 }
 
+static void smbd_smb2_request_dispatch_compound(struct tevent_req *subreq)
+{
+       struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
+                                       struct smbd_smb2_request);
+       struct smbd_server_connection *conn = req->conn;
+       NTSTATUS status;
+
+       tevent_wakeup_recv(subreq);
+       TALLOC_FREE(subreq);
+
+       DEBUG(10,("smbd_smb2_request_dispatch_compound: idx[%d] of %d vectors\n",
+                 req->current_idx, req->in.vector_count));
+
+       status = smbd_smb2_request_dispatch(req);
+       if (!NT_STATUS_IS_OK(status)) {
+               smbd_server_connection_terminate(conn, nt_errstr(status));
+               return;
+       }
+}
+
+static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
+{
+       struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
+                                       struct smbd_smb2_request);
+       struct smbd_server_connection *conn = req->conn;
+       int ret;
+       int sys_errno;
+       TALLOC_CTX *mem_pool;
+
+       ret = tstream_writev_queue_recv(subreq, &sys_errno);
+       TALLOC_FREE(subreq);
+       if (ret == -1) {
+               NTSTATUS status = map_nt_error_from_unix(sys_errno);
+               smbd_server_connection_terminate(conn, nt_errstr(status));
+               return;
+       }
+
+       mem_pool = req->mem_pool;
+       req = NULL;
+       talloc_free(mem_pool);
+}
+
 NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
                                    NTSTATUS status,
                                    DATA_BLOB *info)
@@ -463,7 +571,7 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
        /* the fallback dynamic buffer */
        outdyn = outhdr + SMB2_HDR_BODY + 8;
 
-       next_command_ofs = SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
+       next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
        SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
 
        req->out.vector[i+1].iov_base = (void *)body.data;
@@ -506,48 +614,6 @@ NTSTATUS smbd_smb2_request_done(struct smbd_smb2_request *req,
        return smbd_smb2_request_done_ex(req, NT_STATUS_OK, body, dyn);
 }
 
-static void smbd_smb2_request_dispatch_compound(struct tevent_req *subreq)
-{
-       struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
-                                       struct smbd_smb2_request);
-       struct smbd_server_connection *conn = req->conn;
-       NTSTATUS status;
-
-       tevent_wakeup_recv(subreq);
-       TALLOC_FREE(subreq);
-
-       DEBUG(10,("smbd_smb2_request_dispatch_compound: idx[%d] of %d vectors\n",
-                 req->current_idx, req->in.vector_count));
-
-       status = smbd_smb2_request_dispatch(req);
-       if (!NT_STATUS_IS_OK(status)) {
-               smbd_server_connection_terminate(conn, nt_errstr(status));
-               return;
-       }
-}
-
-static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
-{
-       struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
-                                       struct smbd_smb2_request);
-       struct smbd_server_connection *conn = req->conn;
-       int ret;
-       int sys_errno;
-       TALLOC_CTX *mem_pool;
-
-       ret = tstream_writev_queue_recv(subreq, &sys_errno);
-       TALLOC_FREE(subreq);
-       if (ret == -1) {
-               NTSTATUS status = map_nt_error_from_unix(sys_errno);
-               smbd_server_connection_terminate(conn, nt_errstr(status));
-               return;
-       }
-
-       mem_pool = req->mem_pool;
-       req = NULL;
-       talloc_free(mem_pool);
-}
-
 struct smbd_smb2_request_read_state {
        size_t missing;
        bool asked_for_header;