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
;
44 uint32_t reserved
, data_offset
;
51 return NT_STATUS_INVALID_PARAMETER
;
54 name_offset
= SVAL(data
, 4);
55 name_length
= SVAL(data
, 6);
56 reserved
= SVAL(data
, 8);
57 data_offset
= SVAL(data
, 10);
58 data_length
= IVAL(data
, 12);
60 if ((next
& 0x7) != 0 ||
63 name_offset
> remaining
||
64 name_length
!= 4 || /* windows enforces this */
65 name_offset
+ name_length
> remaining
||
66 (data_offset
&& (data_offset
< name_offset
+ name_length
)) ||
67 (data_offset
&& (data_offset
> remaining
)) ||
68 (data_offset
&& data_length
&&
69 (data_offset
+ (uint64_t)data_length
> remaining
))) {
70 return NT_STATUS_INVALID_PARAMETER
;
73 tag
= talloc_strndup(mem_ctx
, (const char *)data
+ name_offset
, name_length
);
75 return NT_STATUS_NO_MEMORY
;
78 b
= data_blob_const(data
+data_offset
, data_length
);
79 status
= smb2_create_blob_add(mem_ctx
, blobs
, tag
, b
);
80 if (!NT_STATUS_IS_OK(status
)) {
92 return NT_STATUS_INVALID_PARAMETER
;
101 add a blob to a smb2_create attribute blob
103 static NTSTATUS
smb2_create_blob_push_one(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buffer
,
104 const struct smb2_create_blob
*blob
,
107 uint32_t ofs
= buffer
->length
;
108 size_t tag_length
= strlen(blob
->tag
);
109 uint8_t pad
= smb2_create_blob_padding(blob
->data
.length
+tag_length
, 4);
111 if (!data_blob_realloc(mem_ctx
, buffer
,
112 buffer
->length
+ 0x14 + tag_length
+ blob
->data
.length
+ pad
))
113 return NT_STATUS_NO_MEMORY
;
116 SIVAL(buffer
->data
, ofs
+0x00, 0);
118 SIVAL(buffer
->data
, ofs
+0x00, 0x14 + tag_length
+ blob
->data
.length
+ pad
);
120 SSVAL(buffer
->data
, ofs
+0x04, 0x10); /* offset of tag */
121 SIVAL(buffer
->data
, ofs
+0x06, tag_length
); /* tag length */
122 SSVAL(buffer
->data
, ofs
+0x0A, 0x14 + tag_length
); /* offset of data */
123 SIVAL(buffer
->data
, ofs
+0x0C, blob
->data
.length
);
124 memcpy(buffer
->data
+ofs
+0x10, blob
->tag
, tag_length
);
125 SIVAL(buffer
->data
, ofs
+0x10+tag_length
, 0); /* pad? */
126 memcpy(buffer
->data
+ofs
+0x14+tag_length
, blob
->data
.data
, blob
->data
.length
);
127 memset(buffer
->data
+ofs
+0x14+tag_length
+blob
->data
.length
, 0, pad
);
134 create a buffer of a set of create blobs
136 NTSTATUS
smb2_create_blob_push(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buffer
,
137 const struct smb2_create_blobs blobs
)
142 *buffer
= data_blob(NULL
, 0);
143 for (i
=0; i
< blobs
.num_blobs
; i
++) {
145 const struct smb2_create_blob
*c
;
147 if ((i
+ 1) == blobs
.num_blobs
) {
152 status
= smb2_create_blob_push_one(mem_ctx
, buffer
, c
, last
);
153 if (!NT_STATUS_IS_OK(status
)) {
161 NTSTATUS
smb2_create_blob_add(TALLOC_CTX
*mem_ctx
, struct smb2_create_blobs
*b
,
162 const char *tag
, DATA_BLOB data
)
164 struct smb2_create_blob
*array
;
166 array
= talloc_realloc(mem_ctx
, b
->blobs
,
167 struct smb2_create_blob
,
169 NT_STATUS_HAVE_NO_MEMORY(array
);
172 b
->blobs
[b
->num_blobs
].tag
= talloc_strdup(b
->blobs
, tag
);
173 NT_STATUS_HAVE_NO_MEMORY(b
->blobs
[b
->num_blobs
].tag
);
176 b
->blobs
[b
->num_blobs
].data
= data_blob_talloc(b
->blobs
,
179 NT_STATUS_HAVE_NO_MEMORY(b
->blobs
[b
->num_blobs
].data
.data
);
181 b
->blobs
[b
->num_blobs
].data
= data_blob(NULL
, 0);
190 * return the first blob with the given tag
192 struct smb2_create_blob
*smb2_create_blob_find(const struct smb2_create_blobs
*b
,
197 for (i
=0; i
< b
->num_blobs
; i
++) {
198 if (strcmp(b
->blobs
[i
].tag
, tag
) == 0) {