auth/credentials: don't ignore "client use kerberos" and --use-kerberos for machine...
[Samba.git] / source4 / libcli / smb2 / util.c
blobf86a149c646a041f46bf6baf139559b86a10cadb
1 /*
2 Unix SMB/CIFS implementation.
4 SMB2 client utility functions
6 Copyright (C) Andrew Tridgell 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "libcli/smb2/smb2.h"
26 #include "libcli/smb2/smb2_calls.h"
27 #include "libcli/smb_composite/smb_composite.h"
28 #include "librpc/gen_ndr/ndr_security.h"
31 simple close wrapper with SMB2
33 NTSTATUS smb2_util_close(struct smb2_tree *tree, struct smb2_handle h)
35 struct smb2_close c;
37 ZERO_STRUCT(c);
38 c.in.file.handle = h;
40 return smb2_close(tree, &c);
44 unlink a file with SMB2
46 NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname)
48 union smb_unlink io;
50 ZERO_STRUCT(io);
51 io.unlink.in.pattern = fname;
53 return smb2_composite_unlink(tree, &io);
58 rmdir with SMB2
60 NTSTATUS smb2_util_rmdir(struct smb2_tree *tree, const char *dname)
62 struct smb_rmdir io;
64 ZERO_STRUCT(io);
65 io.in.path = dname;
67 return smb2_composite_rmdir(tree, &io);
72 mkdir with SMB2
74 NTSTATUS smb2_util_mkdir(struct smb2_tree *tree, const char *dname)
76 union smb_mkdir io;
78 ZERO_STRUCT(io);
79 io.mkdir.level = RAW_MKDIR_MKDIR;
80 io.mkdir.in.path = dname;
82 return smb2_composite_mkdir(tree, &io);
87 set file attribute with SMB2
89 NTSTATUS smb2_util_setatr(struct smb2_tree *tree, const char *name, uint32_t attrib)
91 struct smb2_create cr = {0};
92 struct smb2_handle h1 = {{0}};
93 union smb_setfileinfo setinfo;
94 NTSTATUS status;
96 cr = (struct smb2_create) {
97 .in.desired_access = SEC_FILE_WRITE_ATTRIBUTE,
98 .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
99 .in.create_disposition = FILE_OPEN,
100 .in.fname = name,
102 status = smb2_create(tree, tree, &cr);
103 if (!NT_STATUS_IS_OK(status)) {
104 return status;
106 h1 = cr.out.file.handle;
108 setinfo = (union smb_setfileinfo) {
109 .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION,
110 .basic_info.in.file.handle = h1,
111 .basic_info.in.attrib = attrib,
114 status = smb2_setinfo_file(tree, &setinfo);
115 if (!NT_STATUS_IS_OK(status)) {
116 smb2_util_close(tree, h1);
117 return status;
120 smb2_util_close(tree, h1);
121 return NT_STATUS_OK;
126 get file attribute with SMB2
128 NTSTATUS smb2_util_getatr(struct smb2_tree *tree, const char *fname,
129 uint16_t *attr, size_t *size, time_t *t)
131 union smb_fileinfo parms;
132 NTSTATUS status;
133 struct smb2_create create_io = {0};
135 create_io.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
136 create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
137 create_io.in.create_disposition = FILE_OPEN;
138 create_io.in.fname = fname;
139 status = smb2_create(tree, tree, &create_io);
140 if (!NT_STATUS_IS_OK(status)) {
141 return status;
144 ZERO_STRUCT(parms);
145 parms.all_info2.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
146 parms.all_info2.in.file.handle = create_io.out.file.handle;
147 status = smb2_getinfo_file(tree, tree, &parms);
148 if (!NT_STATUS_IS_OK(status)) {
149 return status;
152 status = smb2_util_close(tree, create_io.out.file.handle);
153 if (!NT_STATUS_IS_OK(status)) {
154 return status;
157 if (size) {
158 *size = parms.all_info2.out.size;
161 if (t) {
162 *t = parms.all_info2.out.write_time;
165 if (attr) {
166 *attr = parms.all_info2.out.attrib;
169 return status;
174 recursively descend a tree deleting all files
175 returns the number of files deleted, or -1 on error
177 int smb2_deltree(struct smb2_tree *tree, const char *dname)
179 NTSTATUS status;
180 uint32_t total_deleted = 0;
181 unsigned int count, i;
182 union smb_search_data *list;
183 TALLOC_CTX *tmp_ctx = talloc_new(tree);
184 struct smb2_find f;
185 struct smb2_create create_parm;
186 bool did_delete;
188 /* it might be a file */
189 status = smb2_util_unlink(tree, dname);
190 if (NT_STATUS_IS_OK(status)) {
191 talloc_free(tmp_ctx);
192 return 1;
194 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
195 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
196 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_FILE)) {
197 talloc_free(tmp_ctx);
198 return 0;
201 if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
202 /* it could be read-only */
203 smb2_util_setatr(tree, dname, FILE_ATTRIBUTE_NORMAL);
204 status = smb2_util_unlink(tree, dname);
206 if (NT_STATUS_IS_OK(status)) {
207 talloc_free(tmp_ctx);
208 return 1;
211 ZERO_STRUCT(create_parm);
212 create_parm.in.desired_access = SEC_FILE_READ_DATA;
213 create_parm.in.share_access =
214 NTCREATEX_SHARE_ACCESS_READ|
215 NTCREATEX_SHARE_ACCESS_WRITE;
216 create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
217 create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
218 create_parm.in.fname = dname;
220 status = smb2_create(tree, tmp_ctx, &create_parm);
221 if (NT_STATUS_IS_ERR(status)) {
222 DEBUG(2,("Failed to open %s - %s\n", dname, nt_errstr(status)));
223 talloc_free(tmp_ctx);
224 return -1;
228 do {
229 did_delete = false;
231 ZERO_STRUCT(f);
232 f.in.file.handle = create_parm.out.file.handle;
233 f.in.max_response_size = 0x10000;
234 f.in.level = SMB2_FIND_NAME_INFO;
235 f.in.pattern = "*";
237 status = smb2_find_level(tree, tmp_ctx, &f, &count, &list);
238 if (NT_STATUS_IS_ERR(status)) {
239 DEBUG(2,("Failed to list %s - %s\n",
240 dname, nt_errstr(status)));
241 smb2_util_close(tree, create_parm.out.file.handle);
242 talloc_free(tmp_ctx);
243 return -1;
246 for (i=0;i<count;i++) {
247 char *name;
248 if (strcmp(".", list[i].name_info.name.s) == 0 ||
249 strcmp("..", list[i].name_info.name.s) == 0) {
250 continue;
252 name = talloc_asprintf(tmp_ctx, "%s\\%s", dname, list[i].name_info.name.s);
253 status = smb2_util_unlink(tree, name);
254 if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
255 /* it could be read-only */
256 smb2_util_setatr(tree, name, FILE_ATTRIBUTE_NORMAL);
257 status = smb2_util_unlink(tree, name);
260 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
261 int ret;
262 ret = smb2_deltree(tree, name);
263 if (ret > 0) total_deleted += ret;
265 talloc_free(name);
266 if (NT_STATUS_IS_OK(status)) {
267 total_deleted++;
268 did_delete = true;
271 } while (did_delete);
273 smb2_util_close(tree, create_parm.out.file.handle);
275 status = smb2_util_rmdir(tree, dname);
276 if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
277 /* it could be read-only */
278 smb2_util_setatr(tree, dname, FILE_ATTRIBUTE_NORMAL);
279 status = smb2_util_rmdir(tree, dname);
282 if (NT_STATUS_IS_ERR(status)) {
283 DEBUG(2,("Failed to delete %s - %s\n",
284 dname, nt_errstr(status)));
285 talloc_free(tmp_ctx);
286 return -1;
289 talloc_free(tmp_ctx);
291 return total_deleted;
295 check if two SMB2 file handles are the same
297 bool smb2_util_handle_equal(const struct smb2_handle h1,
298 const struct smb2_handle h2)
300 return (h1.data[0] == h2.data[0]) && (h1.data[1] == h2.data[1]);
303 bool smb2_util_handle_empty(const struct smb2_handle h)
305 struct smb2_handle empty;
307 ZERO_STRUCT(empty);
309 return smb2_util_handle_equal(h, empty);
312 /****************************************************************************
313 send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call
314 ****************************************************************************/
315 NTSTATUS smb2_qpathinfo_alt_name(TALLOC_CTX *ctx, struct smb2_tree *tree,
316 const char *fname, const char **alt_name)
318 union smb_fileinfo parms;
319 TALLOC_CTX *mem_ctx;
320 NTSTATUS status;
321 struct smb2_create create_io = {0};
323 mem_ctx = talloc_new(ctx);
324 if (!mem_ctx) {
325 return NT_STATUS_NO_MEMORY;
328 create_io.in.desired_access = SEC_FILE_READ_ATTRIBUTE;
329 create_io.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
330 create_io.in.create_disposition = FILE_OPEN;
331 create_io.in.fname = fname;
332 status = smb2_create(tree, mem_ctx, &create_io);
333 if (!NT_STATUS_IS_OK(status)) {
334 talloc_free(mem_ctx);
335 return status;
338 parms.alt_name_info.level = RAW_FILEINFO_SMB2_ALT_NAME_INFORMATION;
339 parms.alt_name_info.in.file.handle = create_io.out.file.handle;
341 status = smb2_getinfo_file(tree, mem_ctx, &parms);
342 if (!NT_STATUS_IS_OK(status)) {
343 talloc_free(mem_ctx);
344 return status;
347 status = smb2_util_close(tree, create_io.out.file.handle);
348 if (!NT_STATUS_IS_OK(status)) {
349 talloc_free(mem_ctx);
350 return status;
353 if (!parms.alt_name_info.out.fname.s) {
354 *alt_name = talloc_strdup(ctx, "");
355 } else {
356 *alt_name = talloc_strdup(ctx,
357 parms.alt_name_info.out.fname.s);
360 talloc_free(mem_ctx);
362 return NT_STATUS_OK;