ensure we don't change the incoming blobs in a SMB2 create
[kai/samba.git] / source4 / libcli / smb2 / create.c
index 4a97f8aafb87f75250c569246e505b61e0f2b29e..bff0a1587d683fc07c80b1eeafcb25110388b583 100644 (file)
@@ -59,6 +59,7 @@ NTSTATUS smb2_create_blob_parse(TALLOC_CTX *mem_ctx, const DATA_BLOB buffer,
                    next > remaining ||
                    name_offset < 16 ||
                    name_offset > remaining ||
+                   name_length != 4 || /* windows enforces this */
                    name_offset + name_length > remaining ||
                    data_offset < name_offset + name_length ||
                    data_offset > remaining ||
@@ -125,6 +126,35 @@ static NTSTATUS smb2_create_blob_push_one(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer
        return NT_STATUS_OK;
 }
 
+
+/*
+  create a buffer of a set of create blobs
+*/
+NTSTATUS smb2_create_blob_push(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer,
+                              const struct smb2_create_blobs blobs)
+{
+       int i;
+       NTSTATUS status;
+
+       *buffer = data_blob(NULL, 0);
+       for (i=0; i < blobs.num_blobs; i++) {
+               bool last = false;
+               const struct smb2_create_blob *c;
+
+               if ((i + 1) == blobs.num_blobs) {
+                       last = true;
+               }
+
+               c = &blobs.blobs[i];
+               status = smb2_create_blob_push_one(mem_ctx, buffer, c, last);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+       }
+       return NT_STATUS_OK;
+}
+
+
 NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, struct smb2_create_blobs *b,
                              const char *tag, DATA_BLOB data)
 {
@@ -160,9 +190,11 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
 {
        struct smb2_request *req;
        NTSTATUS status;
-       DATA_BLOB blob = data_blob(NULL, 0);
-       uint32_t i;
-       struct smb2_create_blobs blobs = io->in.blobs;
+       DATA_BLOB blob;
+       struct smb2_create_blobs blobs;
+       int i;
+
+       ZERO_STRUCT(blobs);
 
        req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, true, 0);
        if (req == NULL) return NULL;
@@ -281,29 +313,31 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
        }
 
        /* and any custom blobs */
-       for (i=0; i < blobs.num_blobs; i++) {
-               bool last = false;
-               const struct smb2_create_blob *c;
-
-               if ((i + 1) == blobs.num_blobs) {
-                       last = true;
-               }
-
-               c = &blobs.blobs[i];
-               status = smb2_create_blob_push_one(req, &blob,
-                                                  c, last);
+       for (i=0;i<io->in.blobs.num_blobs;i++) {
+               status = smb2_create_blob_add(req, &blobs,
+                                             io->in.blobs.blobs[i].tag, 
+                                             io->in.blobs.blobs[i].data);
                if (!NT_STATUS_IS_OK(status)) {
                        talloc_free(req);
                        return NULL;
                }
        }
 
+
+       status = smb2_create_blob_push(req, &blob, blobs);
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(req);
+               return NULL;
+       }
+
        status = smb2_push_o32s32_blob(&req->out, 0x30, blob);
        if (!NT_STATUS_IS_OK(status)) {
                talloc_free(req);
                return NULL;
        }
 
+       data_blob_free(&blob);
+
        smb2_transport_send(req);
 
        return req;