1 /*
2    Unix SMB/CIFS implementation.
3    RAW_SFILEINFO_* calls
4    Copyright (C) James Myers 2003
5    Copyright (C) Andrew Tridgell 2003
6 
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 2 of the License, or
10    (at your option) any later version.
11 
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.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 
22 #include "includes.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "librpc/gen_ndr/ndr_security.h"
25 
26 
27 /*
28   Handle setfileinfo/setpathinfo passthu constructions
29 */
smb_raw_setfileinfo_passthru(TALLOC_CTX * mem_ctx,enum smb_setfileinfo_level level,union smb_setfileinfo * parms,DATA_BLOB * blob)30 BOOL smb_raw_setfileinfo_passthru(TALLOC_CTX *mem_ctx,
31 				  enum smb_setfileinfo_level level,
32 				  union smb_setfileinfo *parms,
33 				  DATA_BLOB *blob)
34 {
35 	uint_t len;
36 
37 #define NEED_BLOB(n) do { \
38 	  *blob = data_blob_talloc(mem_ctx, NULL, n); \
39 	  if (blob->data == NULL) return False; \
40         } while (0)
41 
42 	switch (level) {
43 	case RAW_SFILEINFO_BASIC_INFORMATION:
44 		NEED_BLOB(40);
45 		smbcli_push_nttime(blob->data,  0, parms->basic_info.in.create_time);
46 		smbcli_push_nttime(blob->data,  8, parms->basic_info.in.access_time);
47 		smbcli_push_nttime(blob->data, 16, parms->basic_info.in.write_time);
48 		smbcli_push_nttime(blob->data, 24, parms->basic_info.in.change_time);
49 		SIVAL(blob->data,           32, parms->basic_info.in.attrib);
50 		SIVAL(blob->data,           36, 0); /* padding */
51 		return True;
52 
53 	case RAW_SFILEINFO_DISPOSITION_INFORMATION:
54 		NEED_BLOB(4);
55 		SIVAL(blob->data, 0, parms->disposition_info.in.delete_on_close);
56 		return True;
57 
58 	case RAW_SFILEINFO_ALLOCATION_INFORMATION:
59 		NEED_BLOB(8);
60 		SBVAL(blob->data, 0, parms->allocation_info.in.alloc_size);
61 		return True;
62 
63 	case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
64 		NEED_BLOB(8);
65 		SBVAL(blob->data, 0, parms->end_of_file_info.in.size);
66 		return True;
67 
68 	case RAW_SFILEINFO_RENAME_INFORMATION:
69 		NEED_BLOB(12);
70 		SIVAL(blob->data, 0, parms->rename_information.in.overwrite);
71 		SIVAL(blob->data, 4, parms->rename_information.in.root_fid);
72 		len = smbcli_blob_append_string(NULL, mem_ctx, blob,
73 						parms->rename_information.in.new_name,
74 						STR_UNICODE|STR_TERMINATE);
75 		SIVAL(blob->data, 8, len - 2);
76 		return True;
77 
78 	case RAW_SFILEINFO_POSITION_INFORMATION:
79 		NEED_BLOB(8);
80 		SBVAL(blob->data, 0, parms->position_information.in.position);
81 		return True;
82 
83 	case RAW_SFILEINFO_MODE_INFORMATION:
84 		NEED_BLOB(4);
85 		SIVAL(blob->data, 0, parms->mode_information.in.mode);
86 		return True;
87 
88 	case RAW_FILEINFO_SEC_DESC: {
89 		NTSTATUS status;
90 
91 		status = ndr_push_struct_blob(blob, mem_ctx,
92 					      parms->set_secdesc.in.sd,
93 					      (ndr_push_flags_fn_t)ndr_push_security_descriptor);
94 		if (!NT_STATUS_IS_OK(status)) return False;
95 
96 		return True;
97 	}
98 
99 		/* Unhandled levels */
100 	case RAW_SFILEINFO_1023:
101 	case RAW_SFILEINFO_1025:
102 	case RAW_SFILEINFO_1029:
103 	case RAW_SFILEINFO_1032:
104 	case RAW_SFILEINFO_1039:
105 	case RAW_SFILEINFO_1040:
106 		break;
107 
108 	default:
109 		DEBUG(0,("Unhandled setfileinfo passthru level %d\n", level));
110 		return False;
111 	}
112 
113 	return False;
114 }
115 
116 /*
117   Handle setfileinfo/setpathinfo trans2 backend.
118 */
smb_raw_setinfo_backend(struct smbcli_tree * tree,TALLOC_CTX * mem_ctx,union smb_setfileinfo * parms,DATA_BLOB * blob)119 static BOOL smb_raw_setinfo_backend(struct smbcli_tree *tree,
120 				    TALLOC_CTX *mem_ctx,
121 				    union smb_setfileinfo *parms,
122 				    DATA_BLOB *blob)
123 {
124 	switch (parms->generic.level) {
125 	case RAW_SFILEINFO_GENERIC:
126 	case RAW_SFILEINFO_SETATTR:
127 	case RAW_SFILEINFO_SETATTRE:
128 	case RAW_SFILEINFO_SEC_DESC:
129 		/* not handled here */
130 		return False;
131 
132 	case RAW_SFILEINFO_STANDARD:
133 		NEED_BLOB(12);
134 		raw_push_dos_date2(tree->session->transport,
135 				  blob->data, 0, parms->standard.in.create_time);
136 		raw_push_dos_date2(tree->session->transport,
137 				  blob->data, 4, parms->standard.in.access_time);
138 		raw_push_dos_date2(tree->session->transport,
139 				  blob->data, 8, parms->standard.in.write_time);
140 		return True;
141 
142 	case RAW_SFILEINFO_EA_SET:
143 		NEED_BLOB(ea_list_size(parms->ea_set.in.num_eas, parms->ea_set.in.eas));
144 		ea_put_list(blob->data, parms->ea_set.in.num_eas, parms->ea_set.in.eas);
145 		return True;
146 
147 	case RAW_SFILEINFO_BASIC_INFO:
148 	case RAW_SFILEINFO_BASIC_INFORMATION:
149 		return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_BASIC_INFORMATION,
150 						    parms, blob);
151 
152 	case RAW_SFILEINFO_UNIX_BASIC:
153 		NEED_BLOB(100);
154 		SBVAL(blob->data, 0, parms->unix_basic.in.end_of_file);
155 		SBVAL(blob->data, 8, parms->unix_basic.in.num_bytes);
156 		smbcli_push_nttime(blob->data, 16, parms->unix_basic.in.status_change_time);
157 		smbcli_push_nttime(blob->data, 24, parms->unix_basic.in.access_time);
158 		smbcli_push_nttime(blob->data, 32, parms->unix_basic.in.change_time);
159 		SBVAL(blob->data, 40, parms->unix_basic.in.uid);
160 		SBVAL(blob->data, 48, parms->unix_basic.in.gid);
161 		SIVAL(blob->data, 56, parms->unix_basic.in.file_type);
162 		SBVAL(blob->data, 60, parms->unix_basic.in.dev_major);
163 		SBVAL(blob->data, 68, parms->unix_basic.in.dev_minor);
164 		SBVAL(blob->data, 76, parms->unix_basic.in.unique_id);
165 		SBVAL(blob->data, 84, parms->unix_basic.in.permissions);
166 		SBVAL(blob->data, 92, parms->unix_basic.in.nlink);
167 		return True;
168 
169 	case RAW_SFILEINFO_DISPOSITION_INFO:
170 	case RAW_SFILEINFO_DISPOSITION_INFORMATION:
171 		return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_DISPOSITION_INFORMATION,
172 						    parms, blob);
173 
174 	case RAW_SFILEINFO_ALLOCATION_INFO:
175 	case RAW_SFILEINFO_ALLOCATION_INFORMATION:
176 		return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_ALLOCATION_INFORMATION,
177 						    parms, blob);
178 
179 	case RAW_SFILEINFO_END_OF_FILE_INFO:
180 	case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
181 		return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_END_OF_FILE_INFORMATION,
182 						    parms, blob);
183 
184 	case RAW_SFILEINFO_RENAME_INFORMATION:
185 		return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_RENAME_INFORMATION,
186 						    parms, blob);
187 
188 	case RAW_SFILEINFO_POSITION_INFORMATION:
189 		return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_POSITION_INFORMATION,
190 						    parms, blob);
191 
192 	case RAW_SFILEINFO_MODE_INFORMATION:
193 		return smb_raw_setfileinfo_passthru(mem_ctx, RAW_SFILEINFO_MODE_INFORMATION,
194 						    parms, blob);
195 
196 		/* Unhandled passthru levels */
197 	case RAW_SFILEINFO_1023:
198 	case RAW_SFILEINFO_1025:
199 	case RAW_SFILEINFO_1029:
200 	case RAW_SFILEINFO_1032:
201 	case RAW_SFILEINFO_1039:
202 	case RAW_SFILEINFO_1040:
203 		return smb_raw_setfileinfo_passthru(mem_ctx, parms->generic.level,
204 						    parms, blob);
205 
206 		/* Unhandled levels */
207 
208 	case RAW_SFILEINFO_UNIX_LINK:
209 	case RAW_SFILEINFO_UNIX_HLINK:
210 		break;
211 	}
212 
213 	return False;
214 }
215 
216 /****************************************************************************
217  Very raw set file info - takes data blob (async send)
218 ****************************************************************************/
smb_raw_setfileinfo_blob_send(struct smbcli_tree * tree,TALLOC_CTX * mem_ctx,uint16_t fnum,uint16_t info_level,DATA_BLOB * blob)219 static struct smbcli_request *smb_raw_setfileinfo_blob_send(struct smbcli_tree *tree,
220 							 TALLOC_CTX *mem_ctx,
221 							 uint16_t fnum,
222 							 uint16_t info_level,
223 							 DATA_BLOB *blob)
224 {
225 	struct smb_trans2 tp;
226 	uint16_t setup = TRANSACT2_SETFILEINFO;
227 
228 	tp.in.max_setup = 0;
229 	tp.in.flags = 0;
230 	tp.in.timeout = 0;
231 	tp.in.setup_count = 1;
232 	tp.in.max_param = 2;
233 	tp.in.max_data = 0;
234 	tp.in.setup = &setup;
235 
236 	tp.in.params = data_blob_talloc(mem_ctx, NULL, 6);
237 	if (!tp.in.params.data) {
238 		return NULL;
239 	}
240 	SSVAL(tp.in.params.data, 0, fnum);
241 	SSVAL(tp.in.params.data, 2, info_level);
242 	SSVAL(tp.in.params.data, 4, 0); /* reserved */
243 
244 	tp.in.data = *blob;
245 
246 	return smb_raw_trans2_send(tree, &tp);
247 }
248 
249 /****************************************************************************
250  Very raw set path info - takes data blob
251 ****************************************************************************/
smb_raw_setpathinfo_blob_send(struct smbcli_tree * tree,TALLOC_CTX * mem_ctx,const char * fname,uint16_t info_level,DATA_BLOB * blob)252 static struct smbcli_request *smb_raw_setpathinfo_blob_send(struct smbcli_tree *tree,
253 							    TALLOC_CTX *mem_ctx,
254 							    const char *fname,
255 							    uint16_t info_level,
256 							    DATA_BLOB *blob)
257 {
258 	struct smb_trans2 tp;
259 	uint16_t setup = TRANSACT2_SETPATHINFO;
260 
261 	tp.in.max_setup = 0;
262 	tp.in.flags = 0;
263 	tp.in.timeout = 0;
264 	tp.in.setup_count = 1;
265 	tp.in.max_param = 2;
266 	tp.in.max_data = 0;
267 	tp.in.setup = &setup;
268 
269 	tp.in.params = data_blob_talloc(mem_ctx, NULL, 6);
270 	if (!tp.in.params.data) {
271 		return NULL;
272 	}
273 	SSVAL(tp.in.params.data, 0, info_level);
274 	SIVAL(tp.in.params.data, 2, 0);
275 	smbcli_blob_append_string(tree->session, mem_ctx,
276 				  &tp.in.params,
277 				  fname, STR_TERMINATE);
278 
279 	tp.in.data = *blob;
280 
281 	return smb_raw_trans2_send(tree, &tp);
282 }
283 
284 /****************************************************************************
285  Handle setattr (async send)
286 ****************************************************************************/
smb_raw_setattr_send(struct smbcli_tree * tree,union smb_setfileinfo * parms)287 static struct smbcli_request *smb_raw_setattr_send(struct smbcli_tree *tree,
288 						union smb_setfileinfo *parms)
289 {
290 	struct smbcli_request *req;
291 
292 	req = smbcli_request_setup(tree, SMBsetatr, 8, 0);
293 	if (!req) return NULL;
294 
295 	SSVAL(req->out.vwv,         VWV(0), parms->setattr.in.attrib);
296 	raw_push_dos_date3(tree->session->transport,
297 			  req->out.vwv, VWV(1), parms->setattr.in.write_time);
298 	memset(req->out.vwv + VWV(3), 0, 10); /* reserved */
299 	smbcli_req_append_ascii4(req, parms->setattr.in.file.path, STR_TERMINATE);
300 	smbcli_req_append_ascii4(req, "", STR_TERMINATE);
301 
302 	if (!smbcli_request_send(req)) {
303 		smbcli_request_destroy(req);
304 		return NULL;
305 	}
306 
307 	return req;
308 }
309 
310 /****************************************************************************
311  Handle setattrE. (async send)
312 ****************************************************************************/
smb_raw_setattrE_send(struct smbcli_tree * tree,union smb_setfileinfo * parms)313 static struct smbcli_request *smb_raw_setattrE_send(struct smbcli_tree *tree,
314 						 union smb_setfileinfo *parms)
315 {
316 	struct smbcli_request *req;
317 
318 	req = smbcli_request_setup(tree, SMBsetattrE, 7, 0);
319 	if (!req) return NULL;
320 
321 	SSVAL(req->out.vwv,         VWV(0), parms->setattre.in.file.fnum);
322 	raw_push_dos_date2(tree->session->transport,
323 			  req->out.vwv, VWV(1), parms->setattre.in.create_time);
324 	raw_push_dos_date2(tree->session->transport,
325 			  req->out.vwv, VWV(3), parms->setattre.in.access_time);
326 	raw_push_dos_date2(tree->session->transport,
327 			  req->out.vwv, VWV(5), parms->setattre.in.write_time);
328 
329 	if (!smbcli_request_send(req)) {
330 		smbcli_request_destroy(req);
331 		return NULL;
332 	}
333 
334 	return req;
335 }
336 
337 /****************************************************************************
338  Set file info (async send)
339 ****************************************************************************/
smb_raw_setfileinfo_send(struct smbcli_tree * tree,union smb_setfileinfo * parms)340 struct smbcli_request *smb_raw_setfileinfo_send(struct smbcli_tree *tree,
341 					     union smb_setfileinfo *parms)
342 {
343 	DATA_BLOB blob;
344 	TALLOC_CTX *mem_ctx;
345 	struct smbcli_request *req;
346 
347 	if (parms->generic.level == RAW_SFILEINFO_SETATTRE) {
348 		return smb_raw_setattrE_send(tree, parms);
349 	}
350 	if (parms->generic.level == RAW_SFILEINFO_SEC_DESC) {
351 		return smb_raw_set_secdesc_send(tree, parms);
352 	}
353 	if (parms->generic.level >= RAW_SFILEINFO_GENERIC) {
354 		return NULL;
355 	}
356 
357 	mem_ctx = talloc_init("setpathinfo");
358 	if (!mem_ctx) return NULL;
359 
360 	if (!smb_raw_setinfo_backend(tree, mem_ctx, parms, &blob)) {
361 		talloc_free(mem_ctx);
362 		return NULL;
363 	}
364 
365 	/* send request and process the output */
366 	req = smb_raw_setfileinfo_blob_send(tree,
367 					    mem_ctx,
368 					    parms->generic.in.file.fnum,
369 					    parms->generic.level,
370 					    &blob);
371 
372 	talloc_free(mem_ctx);
373 	return req;
374 }
375 
376 /****************************************************************************
377  Set file info (async send)
378 ****************************************************************************/
smb_raw_setfileinfo(struct smbcli_tree * tree,union smb_setfileinfo * parms)379 NTSTATUS smb_raw_setfileinfo(struct smbcli_tree *tree,
380 			     union smb_setfileinfo *parms)
381 {
382 	struct smbcli_request *req = smb_raw_setfileinfo_send(tree, parms);
383 	return smbcli_request_simple_recv(req);
384 }
385 
386 
387 /****************************************************************************
388  Set path info (async send)
389 ****************************************************************************/
smb_raw_setpathinfo_send(struct smbcli_tree * tree,union smb_setfileinfo * parms)390 struct smbcli_request *smb_raw_setpathinfo_send(struct smbcli_tree *tree,
391 					     union smb_setfileinfo *parms)
392 {
393 	DATA_BLOB blob;
394 	TALLOC_CTX *mem_ctx;
395 	struct smbcli_request *req;
396 
397 	if (parms->generic.level == RAW_SFILEINFO_SETATTR) {
398 		return smb_raw_setattr_send(tree, parms);
399 	}
400 	if (parms->generic.level >= RAW_SFILEINFO_GENERIC) {
401 		return NULL;
402 	}
403 
404 	mem_ctx = talloc_init("setpathinfo");
405 	if (!mem_ctx) return NULL;
406 
407 	if (!smb_raw_setinfo_backend(tree, mem_ctx, parms, &blob)) {
408 		talloc_free(mem_ctx);
409 		return NULL;
410 	}
411 
412 	/* send request and process the output */
413 	req = smb_raw_setpathinfo_blob_send(tree,
414 					    mem_ctx,
415 					    parms->generic.in.file.path,
416 					    parms->generic.level,
417 					    &blob);
418 
419 	talloc_free(mem_ctx);
420 	return req;
421 }
422 
423 /****************************************************************************
424  Set path info (sync interface)
425 ****************************************************************************/
smb_raw_setpathinfo(struct smbcli_tree * tree,union smb_setfileinfo * parms)426 NTSTATUS smb_raw_setpathinfo(struct smbcli_tree *tree,
427 			     union smb_setfileinfo *parms)
428 {
429 	struct smbcli_request *req = smb_raw_setpathinfo_send(tree, parms);
430 	return smbcli_request_simple_recv(req);
431 }
432