Change uint_t to unsigned int in source4
[garming/samba-autobuild/.git] / source4 / smb_server / smb / trans2.c
index a8fe9f165d29dc2a6c1306f1f84f4a53c87af379..36dc3175e8d25c56b7fd40c1dbf1836a6d8d4c4c 100644 (file)
@@ -5,7 +5,7 @@
 
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 /*
    This file handles the parsing of transact2 requests
 */
 
 #include "includes.h"
-#include "dlinklist.h"
 #include "smb_server/smb_server.h"
-#include "librpc/gen_ndr/ndr_misc.h"
 #include "ntvfs/ntvfs.h"
 #include "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
 
 #define TRANS2_CHECK_ASYNC_STATUS_SIMPLE do { \
        if (!NT_STATUS_IS_OK(req->ntvfs->async_states->status)) { \
@@ -64,7 +62,7 @@ struct trans_op {
 /* setup a trans2 reply, given the data and params sizes */
 static NTSTATUS trans2_setup_reply(struct smb_trans2 *trans,
                                   uint16_t param_size, uint16_t data_size,
-                                  uint16_t setup_count)
+                                  uint8_t setup_count)
 {
        trans->out.setup_count = setup_count;
        if (setup_count > 0) {
@@ -249,7 +247,7 @@ static NTSTATUS trans2_open(struct smbsrv_request *req, struct trans_op *op)
        io->t2open.in.num_eas      = 0;
        io->t2open.in.eas          = NULL;
 
-       smbsrv_blob_pull_string(req, &trans->in.params, 28, &io->t2open.in.fname, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 28, &io->t2open.in.fname, 0);
        if (io->t2open.in.fname == NULL) {
                return NT_STATUS_FOOBAR;
        }
@@ -297,7 +295,7 @@ static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct trans_op *op)
        NT_STATUS_HAVE_NO_MEMORY(io);
 
        io->t2mkdir.level = RAW_MKDIR_T2MKDIR;
-       smbsrv_blob_pull_string(req, &trans->in.params, 4, &io->t2mkdir.in.path, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 4, &io->t2mkdir.in.path, 0);
        if (io->t2mkdir.in.path == NULL) {
                return NT_STATUS_FOOBAR;
        }
@@ -462,7 +460,7 @@ static NTSTATUS trans2_qpathinfo(struct smbsrv_request *req, struct trans_op *op
 
        level = SVAL(trans->in.params.data, 0);
 
-       smbsrv_blob_pull_string(req, &trans->in.params, 6, &st->generic.in.file.path, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 6, &st->generic.in.file.path, 0);
        if (st->generic.in.file.path == NULL) {
                return NT_STATUS_FOOBAR;
        }
@@ -588,18 +586,30 @@ static NTSTATUS trans2_parse_sfileinfo(struct smbsrv_request *req,
        case RAW_SFILEINFO_UNIX_BASIC:
        case RAW_SFILEINFO_UNIX_LINK:
        case RAW_SFILEINFO_UNIX_HLINK:
-       case RAW_SFILEINFO_1023:
+       case RAW_SFILEINFO_PIPE_INFORMATION:
+       case RAW_SFILEINFO_VALID_DATA_INFORMATION:
+       case RAW_SFILEINFO_SHORT_NAME_INFORMATION:
        case RAW_SFILEINFO_1025:
+       case RAW_SFILEINFO_1027:
        case RAW_SFILEINFO_1029:
+       case RAW_SFILEINFO_1030:
+       case RAW_SFILEINFO_1031:
        case RAW_SFILEINFO_1032:
-       case RAW_SFILEINFO_1039:
-       case RAW_SFILEINFO_1040:
+       case RAW_SFILEINFO_1036:
+       case RAW_SFILEINFO_1041:
+       case RAW_SFILEINFO_1042:
+       case RAW_SFILEINFO_1043:
+       case RAW_SFILEINFO_1044:
+               return NT_STATUS_INVALID_LEVEL;
+
+       default:
+               /* we need a default here to cope with invalid values on the wire */
                return NT_STATUS_INVALID_LEVEL;
        }
 
        return smbsrv_pull_passthru_sfileinfo(st, passthru_level, st,
                                              blob, SMBSRV_REQ_DEFAULT_STR_FLAGS(req),
-                                             req);
+                                             &req->in.bufinfo);
 }
 
 /*
@@ -658,7 +668,7 @@ static NTSTATUS trans2_setpathinfo(struct smbsrv_request *req, struct trans_op *
 
        level = SVAL(trans->in.params.data, 0);
 
-       smbsrv_blob_pull_string(req, &trans->in.params, 6, &st->generic.in.file.path, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 6, &st->generic.in.file.path, 0);
        if (st->generic.in.file.path == NULL) {
                return NT_STATUS_FOOBAR;
        }
@@ -682,7 +692,7 @@ static NTSTATUS trans2_setpathinfo(struct smbsrv_request *req, struct trans_op *
 struct find_state {
        struct trans_op *op;
        void *search;
-       enum smb_search_level level;
+       enum smb_search_data_level data_level;
        uint16_t last_entry_offset;
        uint16_t flags;
 };
@@ -691,24 +701,21 @@ struct find_state {
   fill a single entry in a trans2 find reply 
 */
 static NTSTATUS find_fill_info(struct find_state *state,
-                              union smb_search_data *file)
+                              const union smb_search_data *file)
 {
        struct smbsrv_request *req = state->op->req;
        struct smb_trans2 *trans = state->op->trans;
        uint8_t *data;
-       uint_t ofs = trans->out.data.length;
+       unsigned int ofs = trans->out.data.length;
        uint32_t ea_size;
 
-       switch (state->level) {
-       case RAW_SEARCH_SEARCH:
-       case RAW_SEARCH_FFIRST:
-       case RAW_SEARCH_FUNIQUE:
-       case RAW_SEARCH_GENERIC:
-       case RAW_SEARCH_SMB2:
+       switch (state->data_level) {
+       case RAW_SEARCH_DATA_GENERIC:
+       case RAW_SEARCH_DATA_SEARCH:
                /* handled elsewhere */
                return NT_STATUS_INVALID_LEVEL;
 
-       case RAW_SEARCH_STANDARD:
+       case RAW_SEARCH_DATA_STANDARD:
                if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
                        TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 27));
                        SIVAL(trans->out.data.data, ofs, file->standard.resume_key);
@@ -728,7 +735,7 @@ static NTSTATUS find_fill_info(struct find_state *state,
                                                       STR_LEN8BIT | STR_TERMINATE | STR_LEN_NOTERM));
                break;
 
-       case RAW_SEARCH_EA_SIZE:
+       case RAW_SEARCH_DATA_EA_SIZE:
                if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
                        TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 31));
                        SIVAL(trans->out.data.data, ofs, file->ea_size.resume_key);
@@ -750,7 +757,7 @@ static NTSTATUS find_fill_info(struct find_state *state,
                TRANS2_CHECK(smbsrv_blob_fill_data(trans, &trans->out.data, trans->out.data.length + 1));
                break;
 
-       case RAW_SEARCH_EA_LIST:
+       case RAW_SEARCH_DATA_EA_LIST:
                ea_size = ea_list_size(file->ea_list.eas.num_eas, file->ea_list.eas.eas);
                if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
                        TRANS2_CHECK(smbsrv_blob_grow_data(trans, &trans->out.data, ofs + 27 + ea_size));
@@ -773,25 +780,29 @@ static NTSTATUS find_fill_info(struct find_state *state,
                TRANS2_CHECK(smbsrv_blob_fill_data(trans, &trans->out.data, trans->out.data.length + 1));
                break;
 
-       case RAW_SEARCH_DIRECTORY_INFO:
-       case RAW_SEARCH_FULL_DIRECTORY_INFO:
-       case RAW_SEARCH_NAME_INFO:
-       case RAW_SEARCH_BOTH_DIRECTORY_INFO:
-       case RAW_SEARCH_ID_FULL_DIRECTORY_INFO:
-       case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO:
-               return smbsrv_push_passthru_search(trans, &trans->out.data, state->level, file,
+       case RAW_SEARCH_DATA_DIRECTORY_INFO:
+       case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
+       case RAW_SEARCH_DATA_NAME_INFO:
+       case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
+       case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
+       case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
+               return smbsrv_push_passthru_search(trans, &trans->out.data, state->data_level, file,
                                                   SMBSRV_REQ_DEFAULT_STR_FLAGS(req));
+
+       case RAW_SEARCH_DATA_UNIX_INFO:
+       case RAW_SEARCH_DATA_UNIX_INFO2:
+               return NT_STATUS_INVALID_LEVEL;
        }
 
        return NT_STATUS_OK;
 }
 
 /* callback function for trans2 findfirst/findnext */
-static BOOL find_callback(void *private, union smb_search_data *file)
+static bool find_callback(void *private_data, const union smb_search_data *file)
 {
-       struct find_state *state = talloc_get_type(private, struct find_state);
+       struct find_state *state = talloc_get_type(private_data, struct find_state);
        struct smb_trans2 *trans = state->op->trans;
-       uint_t old_length;
+       unsigned int old_length;
 
        old_length = trans->out.data.length;
 
@@ -799,11 +810,11 @@ static BOOL find_callback(void *private, union smb_search_data *file)
            trans->out.data.length > trans->in.max_data) {
                /* restore the old length and tell the backend to stop */
                smbsrv_blob_grow_data(trans, &trans->out.data, old_length);
-               return False;
+               return false;
        }
 
        state->last_entry_offset = old_length;  
-       return True;
+       return true;
 }
 
 /*
@@ -856,17 +867,18 @@ static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct trans_op *op
        level                             = SVAL(trans->in.params.data, 6);
        search->t2ffirst.in.storage_type  = IVAL(trans->in.params.data, 8);
 
-       smbsrv_blob_pull_string(req, &trans->in.params, 12, &search->t2ffirst.in.pattern, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 12, &search->t2ffirst.in.pattern, 0);
        if (search->t2ffirst.in.pattern == NULL) {
                return NT_STATUS_FOOBAR;
        }
 
-       search->t2ffirst.level = (enum smb_search_level)level;
-       if (search->t2ffirst.level >= RAW_SEARCH_GENERIC) {
+       search->t2ffirst.level = RAW_SEARCH_TRANS2;
+       search->t2ffirst.data_level = (enum smb_search_data_level)level;
+       if (search->t2ffirst.data_level >= RAW_SEARCH_DATA_GENERIC) {
                return NT_STATUS_INVALID_LEVEL;
        }
 
-       if (search->t2ffirst.level == RAW_SEARCH_EA_LIST) {
+       if (search->t2ffirst.data_level == RAW_SEARCH_DATA_EA_LIST) {
                TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req,
                                               &search->t2ffirst.in.num_names, 
                                               &search->t2ffirst.in.ea_names));
@@ -878,7 +890,7 @@ static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct trans_op *op
        NT_STATUS_HAVE_NO_MEMORY(state);
        state->op               = op;
        state->search           = search;
-       state->level            = search->t2ffirst.level;
+       state->data_level       = search->t2ffirst.data_level;
        state->last_entry_offset= 0;
        state->flags            = search->t2ffirst.in.flags;
 
@@ -941,17 +953,18 @@ static NTSTATUS trans2_findnext(struct smbsrv_request *req, struct trans_op *op)
        search->t2fnext.in.resume_key    = IVAL(trans->in.params.data, 6);
        search->t2fnext.in.flags         = SVAL(trans->in.params.data, 10);
 
-       smbsrv_blob_pull_string(req, &trans->in.params, 12, &search->t2fnext.in.last_name, 0);
+       smbsrv_blob_pull_string(&req->in.bufinfo, &trans->in.params, 12, &search->t2fnext.in.last_name, 0);
        if (search->t2fnext.in.last_name == NULL) {
                return NT_STATUS_FOOBAR;
        }
 
-       search->t2fnext.level = (enum smb_search_level)level;
-       if (search->t2fnext.level >= RAW_SEARCH_GENERIC) {
+       search->t2fnext.level = RAW_SEARCH_TRANS2;
+       search->t2fnext.data_level = (enum smb_search_data_level)level;
+       if (search->t2fnext.data_level >= RAW_SEARCH_DATA_GENERIC) {
                return NT_STATUS_INVALID_LEVEL;
        }
 
-       if (search->t2fnext.level == RAW_SEARCH_EA_LIST) {
+       if (search->t2fnext.data_level == RAW_SEARCH_DATA_EA_LIST) {
                TRANS2_CHECK(ea_pull_name_list(&trans->in.data, req,
                                               &search->t2fnext.in.num_names, 
                                               &search->t2fnext.in.ea_names));
@@ -962,7 +975,7 @@ static NTSTATUS trans2_findnext(struct smbsrv_request *req, struct trans_op *op)
        NT_STATUS_HAVE_NO_MEMORY(state);
        state->op               = op;
        state->search           = search;
-       state->level            = search->t2fnext.level;
+       state->data_level       = search->t2fnext.data_level;
        state->last_entry_offset= 0;
        state->flags            = search->t2fnext.in.flags;
 
@@ -1021,6 +1034,12 @@ static NTSTATUS trans2_backend(struct smbsrv_request *req, struct trans_op *op)
        return NT_STATUS_FOOBAR;
 }
 
+int smbsrv_trans_partial_destructor(struct smbsrv_trans_partial *tp)
+{
+       DLIST_REMOVE(tp->req->smb_conn->trans_partial, tp);
+       return 0;
+}
+
 
 /*
   send a continue request
@@ -1028,6 +1047,7 @@ static NTSTATUS trans2_backend(struct smbsrv_request *req, struct trans_op *op)
 static void reply_trans_continue(struct smbsrv_request *req, uint8_t command,
                                 struct smb_trans2 *trans)
 {
+       struct smbsrv_request *req2;
        struct smbsrv_trans_partial *tp;
        int count;
 
@@ -1040,15 +1060,18 @@ static void reply_trans_continue(struct smbsrv_request *req, uint8_t command,
 
        tp = talloc(req, struct smbsrv_trans_partial);
 
-       tp->req = talloc_reference(tp, req);
-       tp->trans = trans;
+       tp->req = req;
+       tp->u.trans = trans;
        tp->command = command;
 
        DLIST_ADD(req->smb_conn->trans_partial, tp);
+       talloc_set_destructor(tp, smbsrv_trans_partial_destructor);
+
+       req2 = smbsrv_setup_secondary_request(req);
 
        /* send a 'please continue' reply */
-       smbsrv_setup_reply(req, 0, 0);
-       smbsrv_send_reply(req);
+       smbsrv_setup_reply(req2, 0, 0);
+       smbsrv_send_reply(req2);
 }
 
 
@@ -1093,7 +1116,7 @@ static void reply_trans_send(struct ntvfs_request *ntvfs)
           the negotiated buffer size */
        do {
                uint16_t this_data, this_param, max_bytes;
-               uint_t align1 = 1, align2 = (params_left ? 2 : 0);
+               unsigned int align1 = 1, align2 = (params_left ? 2 : 0);
                struct smbsrv_request *this_req;
 
                max_bytes = req_max_data(req) - (align1 + align2);
@@ -1132,7 +1155,8 @@ static void reply_trans_send(struct ntvfs_request *ntvfs)
                      PTR_DIFF(this_req->out.data + this_param, this_req->out.hdr));
                SSVAL(this_req->out.vwv, VWV(8), PTR_DIFF(data, trans->out.data.data));
 
-               SSVAL(this_req->out.vwv, VWV(9), trans->out.setup_count);
+               SCVAL(this_req->out.vwv, VWV(9), trans->out.setup_count);
+               SCVAL(this_req->out.vwv, VWV(9)+1, 0); /* reserved */
                for (i=0;i<trans->out.setup_count;i++) {
                        SSVAL(this_req->out.vwv, VWV(10+i), trans->out.setup[i]);
                }
@@ -1235,11 +1259,11 @@ static void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
        }
 
        if (command == SMBtrans) {
-               req_pull_string(req, &trans->in.trans_name, req->in.data, -1, STR_TERMINATE);
+               req_pull_string(&req->in.bufinfo, &trans->in.trans_name, req->in.data, -1, STR_TERMINATE);
        }
 
-       if (!req_pull_blob(req, req->in.hdr + param_ofs, param_count, &trans->in.params) ||
-           !req_pull_blob(req, req->in.hdr + data_ofs, data_count, &trans->in.data)) {
+       if (!req_pull_blob(&req->in.bufinfo, req->in.hdr + param_ofs, param_count, &trans->in.params) ||
+           !req_pull_blob(&req->in.bufinfo, req->in.hdr + data_ofs, data_count, &trans->in.data)) {
                smbsrv_send_error(req, NT_STATUS_FOOBAR);
                return;
        }
@@ -1266,9 +1290,20 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
        uint16_t param_disp, data_disp;
        uint16_t param_total, data_total;
        DATA_BLOB params, data;
+       uint8_t wct;
+
+       if (command == SMBtrans2) {
+               wct = 9;
+       } else {
+               wct = 8;
+       }
 
        /* parse request */
-       if (req->in.wct < 8) {
+       if (req->in.wct != wct) {
+               /*
+                * TODO: add some error code tests
+                *       w2k3 returns NT_STATUS_DOS(ERRSRV, ERRerror) here
+                */
                smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
                return;
        }
@@ -1286,7 +1321,7 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
                return;
        }
 
-       trans = tp->trans;
+       trans = tp->u.trans;
 
        param_total           = SVAL(req->in.vwv, VWV(0));
        data_total            = SVAL(req->in.vwv, VWV(1));
@@ -1297,8 +1332,8 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
        data_ofs              = SVAL(req->in.vwv, VWV(6));
        data_disp             = SVAL(req->in.vwv, VWV(7));
 
-       if (!req_pull_blob(req, req->in.hdr + param_ofs, param_count, &params) ||
-           !req_pull_blob(req, req->in.hdr + data_ofs, data_count, &data)) {
+       if (!req_pull_blob(&req->in.bufinfo, req->in.hdr + param_ofs, param_count, &params) ||
+           !req_pull_blob(&req->in.bufinfo, req->in.hdr + data_ofs, data_count, &data)) {
                smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
                return;
        }
@@ -1319,7 +1354,8 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
                                                         uint8_t, 
                                                         param_disp + param_count);
                if (trans->in.params.data == NULL) {
-                       goto failed;
+                       smbsrv_send_error(tp->req, NT_STATUS_NO_MEMORY);
+                       return;
                }
                trans->in.params.length = param_disp + param_count;
        }
@@ -1330,7 +1366,8 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
                                                       uint8_t, 
                                                       data_disp + data_count);
                if (trans->in.data.data == NULL) {
-                       goto failed;
+                       smbsrv_send_error(tp->req, NT_STATUS_NO_MEMORY);
+                       return;
                }
                trans->in.data.length = data_disp + data_count;
        }
@@ -1348,16 +1385,11 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
        if (trans->in.params.length == param_total &&
            trans->in.data.length == data_total) {
                /* its now complete */
-               DLIST_REMOVE(tp->req->smb_conn->trans_partial, tp);
-               reply_trans_complete(tp->req, command, trans);
+               req = tp->req;
+               talloc_free(tp);
+               reply_trans_complete(req, command, trans);
        }
        return;
-
-failed:        
-       smbsrv_send_error(tp->req, NT_STATUS_NO_MEMORY);
-       DLIST_REMOVE(req->smb_conn->trans_partial, tp);
-       talloc_free(req);
-       talloc_free(tp);
 }