selftest: Move MIT Kerberos knownfails to separate files in their own directory
[Samba.git] / libcli / smb / smb2cli_create.c
blobe740365412e986bac9e42976abdff4e39448c77b
1 /*
2 Unix SMB/CIFS implementation.
3 smb2 lib
4 Copyright (C) Volker Lendecke 2011
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "system/network.h"
22 #include "lib/util/tevent_ntstatus.h"
23 #include "smb_common.h"
24 #include "smbXcli_base.h"
25 #include "smb2_create_blob.h"
26 #include "reparse.h"
28 struct smb2cli_create_state {
29 enum protocol_types protocol; /* for symlink error response parser */
30 uint8_t *name_utf16;
31 size_t name_utf16_len;
32 uint8_t fixed[56];
34 uint64_t fid_persistent;
35 uint64_t fid_volatile;
36 struct smb_create_returns cr;
37 struct smb2_create_blobs blobs;
38 struct symlink_reparse_struct *symlink;
39 struct tevent_req *subreq;
42 static void smb2cli_create_done(struct tevent_req *subreq);
43 static bool smb2cli_create_cancel(struct tevent_req *req);
45 struct tevent_req *smb2cli_create_send(
46 TALLOC_CTX *mem_ctx,
47 struct tevent_context *ev,
48 struct smbXcli_conn *conn,
49 uint32_t timeout_msec,
50 struct smbXcli_session *session,
51 struct smbXcli_tcon *tcon,
52 const char *filename,
53 uint8_t oplock_level, /* SMB2_OPLOCK_LEVEL_* */
54 uint32_t impersonation_level, /* SMB2_IMPERSONATION_* */
55 uint32_t desired_access,
56 uint32_t file_attributes,
57 uint32_t share_access,
58 uint32_t create_disposition,
59 uint32_t create_options,
60 struct smb2_create_blobs *blobs)
62 struct tevent_req *req, *subreq;
63 struct smb2cli_create_state *state;
64 uint8_t *fixed;
65 DATA_BLOB blob;
66 NTSTATUS status;
67 size_t blobs_offset;
68 uint8_t *dyn;
69 size_t dyn_len;
70 size_t max_dyn_len;
71 uint32_t additional_flags = 0;
72 uint32_t clear_flags = 0;
73 bool ok;
75 req = tevent_req_create(mem_ctx, &state,
76 struct smb2cli_create_state);
77 if (req == NULL) {
78 return NULL;
80 state->protocol = smbXcli_conn_protocol(conn);
82 ok = convert_string_talloc(
83 state,
84 CH_UNIX,
85 CH_UTF16,
86 filename,
87 strlen(filename),
88 &state->name_utf16,
89 &state->name_utf16_len);
90 if (!ok) {
91 tevent_req_oom(req);
92 return tevent_req_post(req, ev);
95 if (strlen(filename) == 0) {
96 TALLOC_FREE(state->name_utf16);
97 state->name_utf16_len = 0;
100 fixed = state->fixed;
102 SSVAL(fixed, 0, 57);
103 SCVAL(fixed, 3, oplock_level);
104 SIVAL(fixed, 4, impersonation_level);
105 SIVAL(fixed, 24, desired_access);
106 SIVAL(fixed, 28, file_attributes);
107 SIVAL(fixed, 32, share_access);
108 SIVAL(fixed, 36, create_disposition);
109 SIVAL(fixed, 40, create_options);
111 SSVAL(fixed, 44, SMB2_HDR_BODY + 56);
112 SSVAL(fixed, 46, state->name_utf16_len);
114 blob = data_blob_null;
116 if (blobs != NULL) {
117 status = smb2_create_blob_push(state, &blob, *blobs);
118 if (tevent_req_nterror(req, status)) {
119 return tevent_req_post(req, ev);
123 blobs_offset = state->name_utf16_len;
124 blobs_offset = ((blobs_offset + 3) & ~3);
126 if (blob.length > 0) {
127 blobs_offset = ((blobs_offset + 7) & ~7);
128 SIVAL(fixed, 48, blobs_offset + SMB2_HDR_BODY + 56);
129 SIVAL(fixed, 52, blob.length);
132 dyn_len = MAX(1, blobs_offset + blob.length);
133 dyn = talloc_zero_array(state, uint8_t, dyn_len);
134 if (tevent_req_nomem(dyn, req)) {
135 return tevent_req_post(req, ev);
138 if (state->name_utf16 != NULL) {
139 memcpy(dyn, state->name_utf16, state->name_utf16_len);
142 if (blob.data != NULL) {
143 memcpy(dyn + blobs_offset,
144 blob.data, blob.length);
145 data_blob_free(&blob);
148 if (smbXcli_conn_dfs_supported(conn) &&
149 smbXcli_tcon_is_dfs_share(tcon))
151 additional_flags |= SMB2_HDR_FLAG_DFS;
155 * We use max_dyn_len = 0
156 * as we don't explicitly ask for any output length.
158 * But it's still possible for the server to return
159 * large create blobs.
161 max_dyn_len = 0;
163 subreq = smb2cli_req_send(state, ev, conn, SMB2_OP_CREATE,
164 additional_flags, clear_flags,
165 timeout_msec,
166 tcon,
167 session,
168 state->fixed, sizeof(state->fixed),
169 dyn, dyn_len,
170 max_dyn_len);
171 if (tevent_req_nomem(subreq, req)) {
172 return tevent_req_post(req, ev);
174 tevent_req_set_callback(subreq, smb2cli_create_done, req);
176 state->subreq = subreq;
177 tevent_req_set_cancel_fn(req, smb2cli_create_cancel);
179 return req;
182 static bool smb2cli_create_cancel(struct tevent_req *req)
184 struct smb2cli_create_state *state = tevent_req_data(req,
185 struct smb2cli_create_state);
186 return tevent_req_cancel(state->subreq);
190 * [MS-SMB2] 2.2.2.2.1 Symbolic Link Error Response
193 static NTSTATUS smb2cli_parse_symlink_error_response(
194 TALLOC_CTX *mem_ctx,
195 const uint8_t *buf,
196 size_t buflen,
197 struct symlink_reparse_struct **psymlink)
199 struct symlink_reparse_struct *symlink = NULL;
200 struct reparse_data_buffer reparse_buf = {
201 .tag = 0,
203 uint32_t symlink_length, error_tag;
204 NTSTATUS status;
206 if (buflen < 8) {
207 DBG_DEBUG("buffer too short: %zu bytes\n", buflen);
208 return NT_STATUS_INVALID_NETWORK_RESPONSE;
211 symlink_length = IVAL(buf, 0);
212 if (symlink_length != (buflen-4)) {
213 DBG_DEBUG("symlink_length=%"PRIu32", (buflen-4)=%zu\n",
214 symlink_length, buflen-4);
215 return NT_STATUS_INVALID_NETWORK_RESPONSE;
218 error_tag = IVAL(buf, 4);
219 if (error_tag != SYMLINK_ERROR_TAG) {
220 DBG_DEBUG("error_tag=%"PRIu32", expected 0x%x\n",
221 error_tag,
222 SYMLINK_ERROR_TAG);
223 return NT_STATUS_INVALID_NETWORK_RESPONSE;
226 symlink = talloc(mem_ctx, struct symlink_reparse_struct);
227 if (symlink == NULL) {
228 return NT_STATUS_NO_MEMORY;
231 status = reparse_data_buffer_parse(symlink,
232 &reparse_buf,
233 buf + 8,
234 buflen - 8);
235 if (!NT_STATUS_IS_OK(status)) {
236 DBG_DEBUG("reparse_data_buffer_parse() failed: %s\n",
237 nt_errstr(status));
238 TALLOC_FREE(symlink);
239 return status;
242 if (reparse_buf.tag != IO_REPARSE_TAG_SYMLINK) {
243 DBG_DEBUG("Got tag 0x%" PRIx32 ", "
244 "expected IO_REPARSE_TAG_SYMLINK\n",
245 reparse_buf.tag);
246 TALLOC_FREE(symlink);
247 return NT_STATUS_INVALID_NETWORK_RESPONSE;
250 *symlink = reparse_buf.parsed.lnk;
251 *psymlink = symlink;
252 return NT_STATUS_OK;
256 * [MS-SMB2] 2.2.2 ErrorData
258 * This is in theory a broad API, but as right now we only have a
259 * single [MS-SMB2] 2.2.2.2.1 symlink error response we can return
260 * just this.
262 static NTSTATUS smb2cli_create_error_data_parse(
263 enum protocol_types protocol,
264 uint8_t error_context_count,
265 uint32_t byte_count,
266 const uint8_t *buf,
267 size_t buflen,
268 TALLOC_CTX *mem_ctx,
269 struct symlink_reparse_struct **_symlink)
271 struct symlink_reparse_struct *symlink = NULL;
272 uint32_t error_data_length, error_id;
273 NTSTATUS status;
275 if (protocol != PROTOCOL_SMB3_11) {
276 if (error_context_count != 0) {
277 DBG_DEBUG("Got error_context_count=%"PRIu8"\n",
278 error_context_count);
279 return NT_STATUS_INVALID_NETWORK_RESPONSE;
282 status = smb2cli_parse_symlink_error_response(
283 mem_ctx, buf, buflen, &symlink);
284 if (!NT_STATUS_IS_OK(status)) {
285 return status;
287 *_symlink = symlink;
288 return NT_STATUS_OK;
292 * The STOPPED_ON_SYMLINK that I've seen coming from W2k16 has
293 * just a single array element in the [MS-SMB2] 2.2.2
294 * ErrorData array. We'll need to adapt this if there actually
295 * comes an array of multiple ErrorData elements.
298 if (error_context_count != 1) {
299 DBG_DEBUG("Got error_context_count=%"PRIu8"\n",
300 error_context_count);
301 return NT_STATUS_INVALID_NETWORK_RESPONSE;
304 if (byte_count != buflen) {
305 DBG_DEBUG("bytecount=%"PRIu32", "
306 "buflen=%zu\n",
307 byte_count,
308 buflen);
309 return NT_STATUS_INVALID_NETWORK_RESPONSE;
312 if (buflen < 8) {
313 DBG_DEBUG("buflen=%zu\n", buflen);
314 return NT_STATUS_INVALID_NETWORK_RESPONSE;
317 error_data_length = IVAL(buf, 0);
318 if (error_data_length != (buflen - 8)) {
319 DBG_DEBUG("error_data_length=%"PRIu32", expected %zu\n",
320 error_data_length,
321 buflen - 8);
322 return NT_STATUS_INVALID_NETWORK_RESPONSE;
325 error_id = IVAL(buf, 4);
326 if (error_id != 0) {
327 DBG_DEBUG("error_id=%"PRIu32", expected 0\n", error_id);
328 return NT_STATUS_INVALID_NETWORK_RESPONSE;
331 status = smb2cli_parse_symlink_error_response(
332 mem_ctx, buf + 8, buflen - 8, &symlink);
333 if (!NT_STATUS_IS_OK(status)) {
334 DBG_DEBUG("smb2cli_parse_symlink_error_response failed: %s\n",
335 nt_errstr(status));
336 return status;
339 *_symlink = symlink;
340 return NT_STATUS_OK;
343 static NTSTATUS smb2cli_create_unparsed_unix_len(
344 size_t unparsed_utf16_len,
345 uint8_t *name_utf16,
346 size_t name_utf16_len,
347 size_t *_unparsed_unix_len)
349 uint8_t *unparsed_utf16 = NULL;
350 uint8_t *unparsed_unix = NULL;
351 size_t unparsed_unix_len = 0;
352 bool ok;
354 if (unparsed_utf16_len > name_utf16_len) {
355 DBG_DEBUG("unparsed_utf16_len=%zu, name_utf16_len=%zu\n",
356 unparsed_utf16_len,
357 name_utf16_len);
358 return NT_STATUS_INVALID_NETWORK_RESPONSE;
361 if (unparsed_utf16_len == 0) {
362 *_unparsed_unix_len = 0;
363 return NT_STATUS_OK;
366 unparsed_utf16 = name_utf16 + name_utf16_len - unparsed_utf16_len;
368 ok = convert_string_talloc(
369 talloc_tos(),
370 CH_UTF16,
371 CH_UNIX,
372 unparsed_utf16,
373 unparsed_utf16_len,
374 &unparsed_unix,
375 &unparsed_unix_len);
376 if (!ok) {
377 NTSTATUS status = map_nt_error_from_unix_common(errno);
378 DBG_DEBUG("convert_string_talloc failed: %s\n",
379 strerror(errno));
380 return status;
382 *_unparsed_unix_len = unparsed_unix_len;
383 return NT_STATUS_OK;
386 static void smb2cli_create_done(struct tevent_req *subreq)
388 struct tevent_req *req =
389 tevent_req_callback_data(subreq,
390 struct tevent_req);
391 struct smb2cli_create_state *state =
392 tevent_req_data(req,
393 struct smb2cli_create_state);
394 NTSTATUS status;
395 struct iovec *iov;
396 uint8_t *body;
397 uint32_t offset, length;
398 static const struct smb2cli_req_expected_response expected[] = {
400 .status = NT_STATUS_OK,
401 .body_size = 0x59
404 .status = NT_STATUS_STOPPED_ON_SYMLINK,
405 .body_size = 0x9,
409 status = smb2cli_req_recv(subreq, state, &iov,
410 expected, ARRAY_SIZE(expected));
411 TALLOC_FREE(subreq);
413 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
414 uint16_t error_context_count = CVAL(iov[1].iov_base, 2);
415 uint32_t byte_count = IVAL(iov[1].iov_base, 4);
416 size_t unparsed_unix_len = 0;
418 NTSTATUS symlink_status;
420 symlink_status = smb2cli_create_error_data_parse(
421 state->protocol,
422 error_context_count,
423 byte_count,
424 iov[2].iov_base,
425 iov[2].iov_len,
426 state,
427 &state->symlink);
428 if (tevent_req_nterror(req, symlink_status)) {
429 return;
433 * Our callers want to know the unparsed length in
434 * unix encoding.
436 symlink_status = smb2cli_create_unparsed_unix_len(
437 state->symlink->unparsed_path_length,
438 state->name_utf16,
439 state->name_utf16_len,
440 &unparsed_unix_len);
441 if (tevent_req_nterror(req, symlink_status)) {
442 return;
444 state->symlink->unparsed_path_length = unparsed_unix_len;
447 if (tevent_req_nterror(req, status)) {
448 return;
451 body = (uint8_t *)iov[1].iov_base;
453 state->cr.oplock_level = CVAL(body, 2);
454 state->cr.flags = CVAL(body, 3);
455 state->cr.create_action = IVAL(body, 4);
456 state->cr.creation_time = BVAL(body, 8);
457 state->cr.last_access_time = BVAL(body, 16);
458 state->cr.last_write_time = BVAL(body, 24);
459 state->cr.change_time = BVAL(body, 32);
460 state->cr.allocation_size = BVAL(body, 40);
461 state->cr.end_of_file = BVAL(body, 48);
462 state->cr.file_attributes = IVAL(body, 56);
463 state->fid_persistent = BVAL(body, 64);
464 state->fid_volatile = BVAL(body, 72);
466 offset = IVAL(body, 80);
467 length = IVAL(body, 84);
469 if ((offset != 0) && (length != 0)) {
470 if ((offset != SMB2_HDR_BODY + 88) ||
471 (length > iov[2].iov_len)) {
472 tevent_req_nterror(
473 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
474 return;
476 status = smb2_create_blob_parse(
477 state, data_blob_const(iov[2].iov_base, length),
478 &state->blobs);
479 if (tevent_req_nterror(req, status)) {
480 return;
483 tevent_req_done(req);
486 NTSTATUS smb2cli_create_recv(struct tevent_req *req,
487 uint64_t *fid_persistent,
488 uint64_t *fid_volatile,
489 struct smb_create_returns *cr,
490 TALLOC_CTX *mem_ctx,
491 struct smb2_create_blobs *blobs,
492 struct symlink_reparse_struct **psymlink)
494 struct smb2cli_create_state *state =
495 tevent_req_data(req,
496 struct smb2cli_create_state);
497 NTSTATUS status;
499 if (tevent_req_is_nterror(req, &status)) {
500 if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK) &&
501 (psymlink != NULL)) {
502 *psymlink = talloc_move(mem_ctx, &state->symlink);
504 tevent_req_received(req);
505 return status;
507 *fid_persistent = state->fid_persistent;
508 *fid_volatile = state->fid_volatile;
509 if (cr) {
510 *cr = state->cr;
512 if (blobs) {
513 blobs->num_blobs = state->blobs.num_blobs;
514 blobs->blobs = talloc_move(mem_ctx, &state->blobs.blobs);
516 tevent_req_received(req);
517 return NT_STATUS_OK;
520 NTSTATUS smb2cli_create(struct smbXcli_conn *conn,
521 uint32_t timeout_msec,
522 struct smbXcli_session *session,
523 struct smbXcli_tcon *tcon,
524 const char *filename,
525 uint8_t oplock_level, /* SMB2_OPLOCK_LEVEL_* */
526 uint32_t impersonation_level, /* SMB2_IMPERSONATION_* */
527 uint32_t desired_access,
528 uint32_t file_attributes,
529 uint32_t share_access,
530 uint32_t create_disposition,
531 uint32_t create_options,
532 struct smb2_create_blobs *blobs,
533 uint64_t *fid_persistent,
534 uint64_t *fid_volatile,
535 struct smb_create_returns *cr,
536 TALLOC_CTX *mem_ctx,
537 struct smb2_create_blobs *ret_blobs,
538 struct symlink_reparse_struct **psymlink)
540 TALLOC_CTX *frame = talloc_stackframe();
541 struct tevent_context *ev;
542 struct tevent_req *req;
543 NTSTATUS status = NT_STATUS_NO_MEMORY;
545 if (smbXcli_conn_has_async_calls(conn)) {
547 * Can't use sync call while an async call is in flight
549 status = NT_STATUS_INVALID_PARAMETER;
550 goto fail;
552 ev = samba_tevent_context_init(frame);
553 if (ev == NULL) {
554 goto fail;
556 req = smb2cli_create_send(frame, ev, conn, timeout_msec,
557 session, tcon,
558 filename, oplock_level,
559 impersonation_level, desired_access,
560 file_attributes, share_access,
561 create_disposition, create_options,
562 blobs);
563 if (req == NULL) {
564 goto fail;
566 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
567 goto fail;
569 status = smb2cli_create_recv(
570 req,
571 fid_persistent,
572 fid_volatile,
574 mem_ctx,
575 ret_blobs,
576 psymlink);
577 fail:
578 TALLOC_FREE(frame);
579 return status;