s3:rpc_client: add cli_rpc_pipe_open_schannel_with_creds() helper function
[Samba.git] / libcli / smb / smb1cli_create.c
blob1963aedf694ea3a2cfb3fdb28588bd79819c2d74
1 /*
2 Unix SMB/CIFS implementation.
4 Copyright (C) Gregor Beck 2013
5 Copyright (C) Stefan Metzmacher 2013
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/network.h"
23 #include "lib/util/tevent_ntstatus.h"
24 #include "smb_common.h"
25 #include "smbXcli_base.h"
27 static uint8_t *internal_bytes_push_str(uint8_t *buf, bool ucs2,
28 const char *str, size_t str_len,
29 bool align_odd,
30 size_t *pconverted_size)
32 TALLOC_CTX *frame = talloc_stackframe();
33 size_t buflen;
34 char *converted;
35 size_t converted_size;
38 * This check prevents us from
39 * (re)alloc buf on a NULL TALLOC_CTX.
41 if (buf == NULL) {
42 TALLOC_FREE(frame);
43 return NULL;
46 buflen = talloc_get_size(buf);
48 if (ucs2 &&
49 ((align_odd && (buflen % 2 == 0)) ||
50 (!align_odd && (buflen % 2 == 1)))) {
52 * We're pushing into an SMB buffer, align odd
54 buf = talloc_realloc(NULL, buf, uint8_t, buflen + 1);
55 if (buf == NULL) {
56 TALLOC_FREE(frame);
57 return NULL;
59 buf[buflen] = '\0';
60 buflen += 1;
63 if (!convert_string_talloc(frame, CH_UNIX,
64 ucs2 ? CH_UTF16LE : CH_DOS,
65 str, str_len, &converted,
66 &converted_size)) {
67 TALLOC_FREE(frame);
68 return NULL;
71 buf = talloc_realloc(NULL, buf, uint8_t,
72 buflen + converted_size);
73 if (buf == NULL) {
74 TALLOC_FREE(frame);
75 return NULL;
78 memcpy(buf + buflen, converted, converted_size);
80 TALLOC_FREE(converted);
82 if (pconverted_size) {
83 *pconverted_size = converted_size;
86 TALLOC_FREE(frame);
87 return buf;
90 static uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2,
91 const char *str, size_t str_len,
92 size_t *pconverted_size)
94 return internal_bytes_push_str(buf, ucs2, str, str_len,
95 true, pconverted_size);
98 struct smb1cli_ntcreatex_state {
99 uint16_t vwv[24];
100 uint16_t fnum;
103 static void smb1cli_ntcreatex_done(struct tevent_req *subreq);
106 * Send an asynchronous SMB_COM_NT_CREATE_ANDX request.
107 * <a href="http://msdn.microsoft.com/en-us/library/ee442175.aspx">MS-CIFS 2.2.4.64.1</a>
108 * @see smb1cli_ntcreatex_recv(), smb1cli_ntcreatex()
110 * @param[in] mem_ctx The memory context for the result.
111 * @param[in] ev The event context to work on.
112 * @param[in] conn The smb connection.
113 * @param[in] timeout_msec If positiv a timeout for the request.
114 * @param[in] pid The process identifier
115 * @param[in] tcon The smb tree connect.
116 * @param[in] session The smb session.
117 * @param[in] fname The name of the file or directory to be opened or created.
118 * @param[in] CreatFlags
119 * @param[in] RootDirectoryFid The file id of an opened root directory fname is based on. 0 means root of the share.
120 * @param[in] DesiredAccess A field of flags that indicate standard, specific, and generic access rights to be requested.
121 * @param[in] AllocationSize Number of Bytes to allocate if the file is to be created or overwritten.
122 * @param[in] FileAttributes <a href="http://msdn.microsoft.com/en-us/library/ee878573.aspx">Extended file attributes</a>
123 * @param[in] ShareAccess A field that specifies how the file should be shared with other processes.
124 * @param[in] CreateDisposition A value that represents the action to take if the file already exists or if the file is a new file and does not already exist.
125 * @param[in] CreateOptions A field of flag options to use if creating a file or directory.
126 * @param[in] ImpersonationLevel
127 * @param[in] SecurityFlags
129 * @return a tevent_req or NULL
131 struct tevent_req *smb1cli_ntcreatex_send(TALLOC_CTX *mem_ctx,
132 struct tevent_context *ev,
133 struct smbXcli_conn *conn,
134 uint32_t timeout_msec,
135 uint32_t pid,
136 struct smbXcli_tcon *tcon,
137 struct smbXcli_session *session,
138 const char *fname,
139 uint32_t CreatFlags,
140 uint32_t RootDirectoryFid,
141 uint32_t DesiredAccess,
142 uint64_t AllocationSize,
143 uint32_t FileAttributes,
144 uint32_t ShareAccess,
145 uint32_t CreateDisposition,
146 uint32_t CreateOptions,
147 uint32_t ImpersonationLevel,
148 uint8_t SecurityFlags)
150 struct tevent_req *req, *subreq;
151 struct smb1cli_ntcreatex_state *state;
152 uint8_t *bytes;
153 size_t converted_len;
155 req = tevent_req_create(mem_ctx, &state, struct smb1cli_ntcreatex_state);
156 if (req == NULL) {
157 return NULL;
160 SCVAL(state->vwv+0, 0, 0xFF);
161 SCVAL(state->vwv+0, 1, 0);
162 SSVAL(state->vwv+1, 0, 0);
163 SCVAL(state->vwv+2, 0, 0);
164 SIVAL(state->vwv+3, 1, CreatFlags);
165 SIVAL(state->vwv+5, 1, RootDirectoryFid);
166 SIVAL(state->vwv+7, 1, DesiredAccess);
167 SBVAL(state->vwv+9, 1, AllocationSize);
168 SIVAL(state->vwv+13, 1, FileAttributes);
169 SIVAL(state->vwv+15, 1, ShareAccess);
170 SIVAL(state->vwv+17, 1, CreateDisposition);
171 SIVAL(state->vwv+19, 1, CreateOptions);
172 SIVAL(state->vwv+21, 1, ImpersonationLevel);
173 SCVAL(state->vwv+23, 1, SecurityFlags);
175 bytes = talloc_array(state, uint8_t, 0);
176 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(conn),
177 fname, strlen(fname)+1,
178 &converted_len);
180 /* sigh. this copes with broken netapp filer behaviour */
181 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(conn), "", 1, NULL);
183 if (tevent_req_nomem(bytes, req)) {
184 return tevent_req_post(req, ev);
187 SSVAL(state->vwv+2, 1, converted_len);
189 subreq = smb1cli_req_send(state, ev, conn, SMBntcreateX,
190 0, 0, /* *_flags */
191 0, 0, /* *_flags2 */
192 timeout_msec, pid, tcon, session,
193 ARRAY_SIZE(state->vwv), state->vwv,
194 talloc_get_size(bytes), bytes);
195 if (tevent_req_nomem(subreq, req)) {
196 return tevent_req_post(req, ev);
198 tevent_req_set_callback(subreq, smb1cli_ntcreatex_done, req);
200 return req;
203 static void smb1cli_ntcreatex_done(struct tevent_req *subreq)
205 struct tevent_req *req = tevent_req_callback_data(
206 subreq, struct tevent_req);
207 struct smb1cli_ntcreatex_state *state = tevent_req_data(
208 req, struct smb1cli_ntcreatex_state);
209 struct iovec *recv_iov = NULL;
210 uint8_t wct;
211 uint16_t *vwv;
212 NTSTATUS status;
213 static const struct smb1cli_req_expected_response expected[] = {
215 .status = NT_STATUS_OK,
216 .wct = 0x22
220 * This is the broken version see from
221 * [MS-SMB]:
222 * Windows-based SMB servers send 50 (0x32) words in the extended
223 * response although they set the WordCount field to 0x2A.
225 * And Samba does the same...
227 .status = NT_STATUS_OK,
228 .wct = 0x2a
231 .status = NT_STATUS_OK,
232 .wct = 0x32
236 status = smb1cli_req_recv(subreq, state,
237 &recv_iov,
238 NULL, /* phdr */
239 &wct,
240 &vwv,
241 NULL, /* pvwv_offset */
242 NULL, /* num_bytes */
243 NULL, /* bytes */
244 NULL, /* pbytes_offset */
245 NULL, /* inbuf */
246 expected, ARRAY_SIZE(expected));
247 TALLOC_FREE(subreq);
248 if (tevent_req_nterror(req, status)) {
249 return;
252 state->fnum = SVAL(vwv+2, 1);
253 tevent_req_done(req);
257 * Receive the response to an asynchronous SMB_COM_NT_CREATE_ANDX request.
258 * <a href="http://msdn.microsoft.com/en-us/library/ee441612.aspx">MS-CIFS 2.2.4.64.2</a>
260 * @param[in] req A tevent request created with smb1cli_ntcreatex_send()
261 * @param[out] pfnum The file id of the opened file or directory.
263 * @return NT_STATUS_OK on succsess
265 NTSTATUS smb1cli_ntcreatex_recv(struct tevent_req *req, uint16_t *pfnum)
267 struct smb1cli_ntcreatex_state *state = tevent_req_data(
268 req, struct smb1cli_ntcreatex_state);
269 NTSTATUS status;
271 if (tevent_req_is_nterror(req, &status)) {
272 tevent_req_received(req);
273 return status;
276 *pfnum = state->fnum;
277 tevent_req_received(req);
278 return NT_STATUS_OK;
283 * Send a synchronous SMB_COM_NT_CREATE_ANDX request.
284 * <a href="http://msdn.microsoft.com/en-us/library/ee442091.aspx">MS-CIFS 2.2.4.64</a>
285 * @see smb1cli_ntcreatex_send() smb1cli_ntcreatex_recv()
287 * @param[in] conn The smb connection.
288 * @param[in] timeout_msec If positiv a timeout for the request.
289 * @param[in] pid The process identifier
290 * @param[in] tcon The smb tree connect.
291 * @param[in] session The smb session.
292 * @param[in] fname The name of the file or directory to be opened or created.
293 * @param[in] CreatFlags
294 * @param[in] RootDirectoryFid The file id of an opened root directory fname is based on. 0 means root of the share.
295 * @param[in] DesiredAccess A field of flags that indicate standard, specific, and generic access rights to be requested.
296 * @param[in] AllocationSize Number of Bytes to allocate if the file is to be created or overwritten.
297 * @param[in] FileAttributes <a href="http://msdn.microsoft.com/en-us/library/ee878573.aspx">Extended file attributes</a>
298 * @param[in] ShareAccess A field that specifies how the file should be shared with other processes.
299 * @param[in] CreateDisposition A value that represents the action to take if the file already exists or if the file is a new file and does not already exist.
300 * @param[in] CreateOptions A field of flag options to use if creating a file or directory.
301 * @param[in] ImpersonationLevel
302 * @param[in] SecurityFlags
303 * @param[out] pfnum The file id representing the file or directory created or opened.
305 * @return NT_STATUS_OK on succsess
307 NTSTATUS smb1cli_ntcreatex(struct smbXcli_conn *conn,
308 uint32_t timeout_msec,
309 uint32_t pid,
310 struct smbXcli_tcon *tcon,
311 struct smbXcli_session *session,
312 const char *fname,
313 uint32_t CreatFlags,
314 uint32_t RootDirectoryFid,
315 uint32_t DesiredAccess,
316 uint64_t AllocationSize,
317 uint32_t FileAttributes,
318 uint32_t ShareAccess,
319 uint32_t CreateDisposition,
320 uint32_t CreateOptions,
321 uint32_t ImpersonationLevel,
322 uint8_t SecurityFlags,
323 uint16_t *pfnum)
325 TALLOC_CTX *frame = NULL;
326 struct tevent_context *ev;
327 struct tevent_req *req;
328 NTSTATUS status = NT_STATUS_OK;
330 frame = talloc_stackframe();
332 if (smbXcli_conn_has_async_calls(conn)) {
334 * Can't use sync call while an async call is in flight
336 status = NT_STATUS_INVALID_PARAMETER;
337 goto fail;
340 ev = samba_tevent_context_init(frame);
341 if (ev == NULL) {
342 status = NT_STATUS_NO_MEMORY;
343 goto fail;
346 req = smb1cli_ntcreatex_send(frame, ev, conn,
347 timeout_msec,
348 pid, tcon, session,
349 fname, CreatFlags, RootDirectoryFid,
350 DesiredAccess, AllocationSize,
351 FileAttributes, ShareAccess,
352 CreateDisposition, CreateOptions,
353 ImpersonationLevel, SecurityFlags);
354 if (req == NULL) {
355 status = NT_STATUS_NO_MEMORY;
356 goto fail;
359 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
360 goto fail;
363 status = smb1cli_ntcreatex_recv(req, pfnum);
364 fail:
365 TALLOC_FREE(frame);
366 return status;