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/>.
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
,
30 size_t *pconverted_size
)
32 TALLOC_CTX
*frame
= talloc_stackframe();
35 size_t converted_size
;
38 * This check prevents us from
39 * (re)alloc buf on a NULL TALLOC_CTX.
46 buflen
= talloc_get_size(buf
);
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);
63 if (!convert_string_talloc(frame
, CH_UNIX
,
64 ucs2
? CH_UTF16LE
: CH_DOS
,
65 str
, str_len
, &converted
,
71 buf
= talloc_realloc(NULL
, buf
, uint8_t,
72 buflen
+ converted_size
);
78 memcpy(buf
+ buflen
, converted
, converted_size
);
80 TALLOC_FREE(converted
);
82 if (pconverted_size
) {
83 *pconverted_size
= converted_size
;
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
{
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
,
136 struct smbXcli_tcon
*tcon
,
137 struct smbXcli_session
*session
,
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
;
153 size_t converted_len
;
155 req
= tevent_req_create(mem_ctx
, &state
, struct smb1cli_ntcreatex_state
);
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,
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
,
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
);
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
;
213 static const struct smb1cli_req_expected_response expected
[] = {
215 .status
= NT_STATUS_OK
,
220 * This is the broken version see from
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
,
231 .status
= NT_STATUS_OK
,
236 status
= smb1cli_req_recv(subreq
, state
,
241 NULL
, /* pvwv_offset */
242 NULL
, /* num_bytes */
244 NULL
, /* pbytes_offset */
246 expected
, ARRAY_SIZE(expected
));
248 if (tevent_req_nterror(req
, status
)) {
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
);
271 if (tevent_req_is_nterror(req
, &status
)) {
272 tevent_req_received(req
);
276 *pfnum
= state
->fnum
;
277 tevent_req_received(req
);
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
,
310 struct smbXcli_tcon
*tcon
,
311 struct smbXcli_session
*session
,
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
,
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
;
340 ev
= samba_tevent_context_init(frame
);
342 status
= NT_STATUS_NO_MEMORY
;
346 req
= smb1cli_ntcreatex_send(frame
, ev
, conn
,
349 fname
, CreatFlags
, RootDirectoryFid
,
350 DesiredAccess
, AllocationSize
,
351 FileAttributes
, ShareAccess
,
352 CreateDisposition
, CreateOptions
,
353 ImpersonationLevel
, SecurityFlags
);
355 status
= NT_STATUS_NO_MEMORY
;
359 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
363 status
= smb1cli_ntcreatex_recv(req
, pfnum
);