2 Unix SMB/CIFS implementation.
4 SMB2 Create Context Blob handling
6 Copyright (C) Andrew Tridgell 2005
7 Copyright (C) Stefan Metzmacher 2008-2009
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "../libcli/smb/smb_common.h"
26 static size_t smb2_create_blob_padding(uint32_t offset
, size_t n
)
28 if ((offset
& (n
-1)) == 0) return 0;
29 return n
- (offset
& (n
-1));
33 parse a set of SMB2 create blobs
35 NTSTATUS
smb2_create_blob_parse(TALLOC_CTX
*mem_ctx
, const DATA_BLOB buffer
,
36 struct smb2_create_blobs
*blobs
)
38 const uint8_t *data
= buffer
.data
;
39 uint32_t remaining
= buffer
.length
;
41 while (remaining
> 0) {
43 uint32_t name_offset
, name_length
;
51 return NT_STATUS_INVALID_PARAMETER
;
54 name_offset
= SVAL(data
, 4);
55 name_length
= SVAL(data
, 6);
57 reserved
= SVAL(data
, 8);
59 data_offset
= SVAL(data
, 10);
60 data_length
= IVAL(data
, 12);
62 if ((next
& 0x7) != 0 ||
65 name_offset
> remaining
||
66 name_length
!= 4 || /* windows enforces this */
67 name_offset
+ name_length
> remaining
||
68 (data_offset
&& (data_offset
< name_offset
+ name_length
)) ||
69 (data_offset
&& (data_offset
> remaining
)) ||
70 (data_offset
&& data_length
&&
71 (data_offset
+ (uint64_t)data_length
> remaining
))) {
72 return NT_STATUS_INVALID_PARAMETER
;
75 tag
= talloc_strndup(mem_ctx
, (const char *)data
+ name_offset
, name_length
);
77 return NT_STATUS_NO_MEMORY
;
80 b
= data_blob_const(data
+data_offset
, data_length
);
81 status
= smb2_create_blob_add(mem_ctx
, blobs
, tag
, b
);
82 if (!NT_STATUS_IS_OK(status
)) {
94 return NT_STATUS_INVALID_PARAMETER
;
103 add a blob to a smb2_create attribute blob
105 static NTSTATUS
smb2_create_blob_push_one(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buffer
,
106 const struct smb2_create_blob
*blob
,
109 uint32_t ofs
= buffer
->length
;
110 size_t tag_length
= strlen(blob
->tag
);
111 uint8_t pad
= smb2_create_blob_padding(blob
->data
.length
+tag_length
, 4);
113 if (!data_blob_realloc(mem_ctx
, buffer
,
114 buffer
->length
+ 0x14 + tag_length
+ blob
->data
.length
+ pad
))
115 return NT_STATUS_NO_MEMORY
;
118 SIVAL(buffer
->data
, ofs
+0x00, 0);
120 SIVAL(buffer
->data
, ofs
+0x00, 0x14 + tag_length
+ blob
->data
.length
+ pad
);
122 SSVAL(buffer
->data
, ofs
+0x04, 0x10); /* offset of tag */
123 SIVAL(buffer
->data
, ofs
+0x06, tag_length
); /* tag length */
124 SSVAL(buffer
->data
, ofs
+0x0A, 0x14 + tag_length
); /* offset of data */
125 SIVAL(buffer
->data
, ofs
+0x0C, blob
->data
.length
);
126 memcpy(buffer
->data
+ofs
+0x10, blob
->tag
, tag_length
);
127 SIVAL(buffer
->data
, ofs
+0x10+tag_length
, 0); /* pad? */
128 memcpy(buffer
->data
+ofs
+0x14+tag_length
, blob
->data
.data
, blob
->data
.length
);
129 memset(buffer
->data
+ofs
+0x14+tag_length
+blob
->data
.length
, 0, pad
);
136 create a buffer of a set of create blobs
138 NTSTATUS
smb2_create_blob_push(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buffer
,
139 const struct smb2_create_blobs blobs
)
144 *buffer
= data_blob(NULL
, 0);
145 for (i
=0; i
< blobs
.num_blobs
; i
++) {
147 const struct smb2_create_blob
*c
;
149 if ((i
+ 1) == blobs
.num_blobs
) {
154 status
= smb2_create_blob_push_one(mem_ctx
, buffer
, c
, last
);
155 if (!NT_STATUS_IS_OK(status
)) {
163 NTSTATUS
smb2_create_blob_add(TALLOC_CTX
*mem_ctx
, struct smb2_create_blobs
*b
,
164 const char *tag
, DATA_BLOB data
)
166 struct smb2_create_blob
*array
;
168 array
= talloc_realloc(mem_ctx
, b
->blobs
,
169 struct smb2_create_blob
,
171 NT_STATUS_HAVE_NO_MEMORY(array
);
174 b
->blobs
[b
->num_blobs
].tag
= talloc_strdup(b
->blobs
, tag
);
175 NT_STATUS_HAVE_NO_MEMORY(b
->blobs
[b
->num_blobs
].tag
);
178 b
->blobs
[b
->num_blobs
].data
= data_blob_talloc(b
->blobs
,
181 NT_STATUS_HAVE_NO_MEMORY(b
->blobs
[b
->num_blobs
].data
.data
);
183 b
->blobs
[b
->num_blobs
].data
= data_blob(NULL
, 0);
192 * return the first blob with the given tag
194 struct smb2_create_blob
*smb2_create_blob_find(const struct smb2_create_blobs
*b
,
199 for (i
=0; i
< b
->num_blobs
; i
++) {
200 if (strcmp(b
->blobs
[i
].tag
, tag
) == 0) {