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 ||
66 name_offset
+ name_length
> remaining
||
67 (data_offset
& 0x7) != 0 ||
68 (data_offset
&& (data_offset
< name_offset
+ name_length
)) ||
69 (data_offset
> remaining
) ||
70 (data_offset
+ (uint64_t)data_length
> remaining
)) {
71 return NT_STATUS_INVALID_PARAMETER
;
74 tag
= talloc_strndup(mem_ctx
, (const char *)data
+ name_offset
, name_length
);
76 return NT_STATUS_NO_MEMORY
;
79 b
= data_blob_const(data
+data_offset
, data_length
);
80 status
= smb2_create_blob_add(mem_ctx
, blobs
, tag
, b
);
81 if (!NT_STATUS_IS_OK(status
)) {
93 return NT_STATUS_INVALID_PARAMETER
;
102 add a blob to a smb2_create attribute blob
104 static NTSTATUS
smb2_create_blob_push_one(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buffer
,
105 const struct smb2_create_blob
*blob
,
108 uint32_t ofs
= buffer
->length
;
109 size_t tag_length
= strlen(blob
->tag
);
110 size_t blob_offset
= 0;
112 size_t next_offset
= 0;
116 blob_offset
= 0x10 + tag_length
;
117 blob_pad
= smb2_create_blob_padding(blob_offset
, 8);
118 next_offset
= blob_offset
+ blob_pad
+ blob
->data
.length
;
120 next_pad
= smb2_create_blob_padding(next_offset
, 8);
123 ok
= data_blob_realloc(mem_ctx
, buffer
,
124 buffer
->length
+ next_offset
+ next_pad
);
126 return NT_STATUS_NO_MEMORY
;
130 SIVAL(buffer
->data
, ofs
+0x00, 0);
132 SIVAL(buffer
->data
, ofs
+0x00, next_offset
+ next_pad
);
134 SSVAL(buffer
->data
, ofs
+0x04, 0x10); /* offset of tag */
135 SIVAL(buffer
->data
, ofs
+0x06, tag_length
); /* tag length */
136 SSVAL(buffer
->data
, ofs
+0x0A, blob_offset
+ blob_pad
); /* offset of data */
137 SIVAL(buffer
->data
, ofs
+0x0C, blob
->data
.length
);
138 memcpy(buffer
->data
+ofs
+0x10, blob
->tag
, tag_length
);
140 memset(buffer
->data
+ofs
+blob_offset
, 0, blob_pad
);
141 blob_offset
+= blob_pad
;
143 memcpy(buffer
->data
+ofs
+blob_offset
, blob
->data
.data
, blob
->data
.length
);
145 memset(buffer
->data
+ofs
+next_offset
, 0, next_pad
);
146 next_offset
+= next_pad
;
154 create a buffer of a set of create blobs
156 NTSTATUS
smb2_create_blob_push(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buffer
,
157 const struct smb2_create_blobs blobs
)
162 *buffer
= data_blob(NULL
, 0);
163 for (i
=0; i
< blobs
.num_blobs
; i
++) {
165 const struct smb2_create_blob
*c
;
167 if ((i
+ 1) == blobs
.num_blobs
) {
172 status
= smb2_create_blob_push_one(mem_ctx
, buffer
, c
, last
);
173 if (!NT_STATUS_IS_OK(status
)) {
181 NTSTATUS
smb2_create_blob_add(TALLOC_CTX
*mem_ctx
, struct smb2_create_blobs
*b
,
182 const char *tag
, DATA_BLOB data
)
184 struct smb2_create_blob
*array
;
186 array
= talloc_realloc(mem_ctx
, b
->blobs
,
187 struct smb2_create_blob
,
189 NT_STATUS_HAVE_NO_MEMORY(array
);
192 b
->blobs
[b
->num_blobs
].tag
= talloc_strdup(b
->blobs
, tag
);
193 NT_STATUS_HAVE_NO_MEMORY(b
->blobs
[b
->num_blobs
].tag
);
196 b
->blobs
[b
->num_blobs
].data
= data_blob_talloc(b
->blobs
,
199 NT_STATUS_HAVE_NO_MEMORY(b
->blobs
[b
->num_blobs
].data
.data
);
201 b
->blobs
[b
->num_blobs
].data
= data_blob_null
;
210 * return the first blob with the given tag
212 struct smb2_create_blob
*smb2_create_blob_find(const struct smb2_create_blobs
*b
,
217 for (i
=0; i
< b
->num_blobs
; i
++) {
218 if (strcmp(b
->blobs
[i
].tag
, tag
) == 0) {