Updated with sepcifics of how we determine sendfile.
[Samba.git] / source / libsmb / clirap.c
blobcada138082a4452eecf25b93307e0ef65b106e28
1 /*
2 Unix SMB/CIFS implementation.
3 client RAP calls
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Gerald (Jerry) Carter 2004
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.
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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 /****************************************************************************
25 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
26 ****************************************************************************/
28 BOOL cli_api_pipe(struct cli_state *cli, const char *pipe_name,
29 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
30 char *params, uint32 param_count, uint32 max_param_count,
31 char *data, uint32 data_count, uint32 max_data_count,
32 char **rparam, uint32 *rparam_count,
33 char **rdata, uint32 *rdata_count)
35 cli_send_trans(cli, SMBtrans,
36 pipe_name,
37 0,0, /* fid, flags */
38 setup, setup_count, max_setup_count,
39 params, param_count, max_param_count,
40 data, data_count, max_data_count);
42 return (cli_receive_trans(cli, SMBtrans,
43 rparam, (unsigned int *)rparam_count,
44 rdata, (unsigned int *)rdata_count));
47 /****************************************************************************
48 Call a remote api
49 ****************************************************************************/
51 BOOL cli_api(struct cli_state *cli,
52 char *param, int prcnt, int mprcnt,
53 char *data, int drcnt, int mdrcnt,
54 char **rparam, unsigned int *rprcnt,
55 char **rdata, unsigned int *rdrcnt)
57 cli_send_trans(cli,SMBtrans,
58 PIPE_LANMAN, /* Name */
59 0,0, /* fid, flags */
60 NULL,0,0, /* Setup, length, max */
61 param, prcnt, mprcnt, /* Params, length, max */
62 data, drcnt, mdrcnt /* Data, length, max */
65 return (cli_receive_trans(cli,SMBtrans,
66 rparam, rprcnt,
67 rdata, rdrcnt));
70 /****************************************************************************
71 Perform a NetWkstaUserLogon.
72 ****************************************************************************/
74 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
76 char *rparam = NULL;
77 char *rdata = NULL;
78 char *p;
79 unsigned int rdrcnt,rprcnt;
80 pstring param;
82 memset(param, 0, sizeof(param));
84 /* send a SMBtrans command with api NetWkstaUserLogon */
85 p = param;
86 SSVAL(p,0,132); /* api number */
87 p += 2;
88 pstrcpy_base(p,"OOWb54WrLh",param);
89 p = skip_string(param,sizeof(param),p);
90 pstrcpy_base(p,"WB21BWDWWDDDDDDDzzzD",param);
91 p = skip_string(param,sizeof(param),p);
92 SSVAL(p,0,1);
93 p += 2;
94 pstrcpy_base(p,user,param);
95 strupper_m(p);
96 p += 21;
97 p++;
98 p += 15;
99 p++;
100 pstrcpy_base(p, workstation, param);
101 strupper_m(p);
102 p += 16;
103 SSVAL(p, 0, CLI_BUFFER_SIZE);
104 p += 2;
105 SSVAL(p, 0, CLI_BUFFER_SIZE);
106 p += 2;
108 if (cli_api(cli,
109 param, PTR_DIFF(p,param),1024, /* param, length, max */
110 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
111 &rparam, &rprcnt, /* return params, return size */
112 &rdata, &rdrcnt /* return data, return size */
113 )) {
114 cli->rap_error = rparam? SVAL(rparam,0) : -1;
115 p = rdata;
117 if (cli->rap_error == 0) {
118 DEBUG(4,("NetWkstaUserLogon success\n"));
119 cli->privileges = SVAL(p, 24);
120 /* The cli->eff_name field used to be set here
121 but it wasn't used anywhere else. */
122 } else {
123 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
127 SAFE_FREE(rparam);
128 SAFE_FREE(rdata);
129 return (cli->rap_error == 0);
132 /****************************************************************************
133 Call a NetShareEnum - try and browse available connections on a host.
134 ****************************************************************************/
136 int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
138 char *rparam = NULL;
139 char *rdata = NULL;
140 char *p;
141 unsigned int rdrcnt,rprcnt;
142 pstring param;
143 int count = -1;
145 /* now send a SMBtrans command with api RNetShareEnum */
146 p = param;
147 SSVAL(p,0,0); /* api number */
148 p += 2;
149 pstrcpy_base(p,"WrLeh",param);
150 p = skip_string(param,sizeof(param),p);
151 pstrcpy_base(p,"B13BWz",param);
152 p = skip_string(param,sizeof(param),p);
153 SSVAL(p,0,1);
155 * Win2k needs a *smaller* buffer than 0xFFFF here -
156 * it returns "out of server memory" with 0xFFFF !!! JRA.
158 SSVAL(p,2,0xFFE0);
159 p += 4;
161 if (cli_api(cli,
162 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
163 NULL, 0, 0xFFE0, /* data, length, maxlen - Win2k needs a small buffer here too ! */
164 &rparam, &rprcnt, /* return params, length */
165 &rdata, &rdrcnt)) /* return data, length */
167 int res = rparam? SVAL(rparam,0) : -1;
169 if (res == 0 || res == ERRmoredata) {
170 int converter=SVAL(rparam,2);
171 int i;
173 count=SVAL(rparam,4);
174 p = rdata;
176 for (i=0;i<count;i++,p+=20) {
177 char *sname = p;
178 int type = SVAL(p,14);
179 int comment_offset = IVAL(p,16) & 0xFFFF;
180 const char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
181 pstring s1, s2;
183 pull_ascii_pstring(s1, sname);
184 pull_ascii_pstring(s2, cmnt);
186 fn(s1, type, s2, state);
188 } else {
189 DEBUG(4,("NetShareEnum res=%d\n", res));
191 } else {
192 DEBUG(4,("NetShareEnum failed\n"));
195 SAFE_FREE(rparam);
196 SAFE_FREE(rdata);
198 return count;
201 /****************************************************************************
202 Call a NetServerEnum for the specified workgroup and servertype mask. This
203 function then calls the specified callback function for each name returned.
205 The callback function takes 4 arguments: the machine name, the server type,
206 the comment and a state pointer.
207 ****************************************************************************/
209 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
210 void (*fn)(const char *, uint32, const char *, void *),
211 void *state)
213 char *rparam = NULL;
214 char *rdata = NULL;
215 unsigned int rdrcnt,rprcnt;
216 char *p;
217 pstring param;
218 int uLevel = 1;
219 int count = -1;
220 size_t len;
222 errno = 0; /* reset */
224 /* send a SMBtrans command with api NetServerEnum */
225 p = param;
226 SSVAL(p,0,0x68); /* api number */
227 p += 2;
228 pstrcpy_base(p,"WrLehDz", param);
229 p = skip_string(param,sizeof(param),p);
231 pstrcpy_base(p,"B16BBDz", param);
233 p = skip_string(param,sizeof(param),p);
234 SSVAL(p,0,uLevel);
235 SSVAL(p,2,CLI_BUFFER_SIZE);
236 p += 4;
237 SIVAL(p,0,stype);
238 p += 4;
240 len = push_ascii(p, workgroup, sizeof(pstring)-PTR_DIFF(p,param)-1, STR_TERMINATE|STR_UPPER);
241 if (len == (size_t)-1) {
242 return false;
244 p += len;
246 if (cli_api(cli,
247 param, PTR_DIFF(p,param), 8, /* params, length, max */
248 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
249 &rparam, &rprcnt, /* return params, return size */
250 &rdata, &rdrcnt /* return data, return size */
251 )) {
252 int res = rparam? SVAL(rparam,0) : -1;
254 if (res == 0 || res == ERRmoredata ||
255 (res != -1 && cli_errno(cli) == 0)) {
256 int i;
257 int converter=SVAL(rparam,2);
259 count=SVAL(rparam,4);
260 p = rdata;
262 for (i = 0;i < count;i++, p += 26) {
263 char *sname = p;
264 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
265 const char *cmnt = comment_offset?(rdata+comment_offset):"";
266 pstring s1, s2;
268 if (comment_offset < 0 || comment_offset > (int)rdrcnt) continue;
270 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
272 pull_ascii_pstring(s1, sname);
273 pull_ascii_pstring(s2, cmnt);
274 fn(s1, stype, s2, state);
279 SAFE_FREE(rparam);
280 SAFE_FREE(rdata);
282 if (count < 0) {
283 errno = cli_errno(cli);
284 } else {
285 if (!count) {
286 /* this is a very special case, when the domain master for the
287 work group isn't part of the work group itself, there is something
288 wild going on */
289 errno = ENOENT;
293 return(count > 0);
296 /****************************************************************************
297 Send a SamOEMChangePassword command.
298 ****************************************************************************/
300 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
301 const char *old_password)
303 pstring param;
304 unsigned char data[532];
305 char *p = param;
306 unsigned char old_pw_hash[16];
307 unsigned char new_pw_hash[16];
308 unsigned int data_len;
309 unsigned int param_len = 0;
310 char *rparam = NULL;
311 char *rdata = NULL;
312 unsigned int rprcnt, rdrcnt;
314 if (strlen(user) >= sizeof(fstring)-1) {
315 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
316 return False;
319 SSVAL(p,0,214); /* SamOEMChangePassword command. */
320 p += 2;
321 pstrcpy_base(p, "zsT", param);
322 p = skip_string(param,sizeof(param),p);
323 pstrcpy_base(p, "B516B16", param);
324 p = skip_string(param,sizeof(param),p);
325 pstrcpy_base(p,user, param);
326 p = skip_string(param,sizeof(param),p);
327 SSVAL(p,0,532);
328 p += 2;
330 param_len = PTR_DIFF(p,param);
333 * Get the Lanman hash of the old password, we
334 * use this as the key to make_oem_passwd_hash().
336 E_deshash(old_password, old_pw_hash);
338 encode_pw_buffer(data, new_password, STR_ASCII);
340 #ifdef DEBUG_PASSWORD
341 DEBUG(100,("make_oem_passwd_hash\n"));
342 dump_data(100, (char *)data, 516);
343 #endif
344 SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
347 * Now place the old password hash in the data.
349 E_deshash(new_password, new_pw_hash);
351 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
353 data_len = 532;
355 if (cli_send_trans(cli,SMBtrans,
356 PIPE_LANMAN, /* name */
357 0,0, /* fid, flags */
358 NULL,0,0, /* setup, length, max */
359 param,param_len,2, /* param, length, max */
360 (char *)data,data_len,0 /* data, length, max */
361 ) == False) {
362 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
363 user ));
364 return False;
367 if (!cli_receive_trans(cli,SMBtrans,
368 &rparam, &rprcnt,
369 &rdata, &rdrcnt)) {
370 DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
371 user ));
372 return False;
375 if (rparam) {
376 cli->rap_error = SVAL(rparam,0);
379 SAFE_FREE(rparam);
380 SAFE_FREE(rdata);
382 return (cli->rap_error == 0);
385 /****************************************************************************
386 Send a qpathinfo call.
387 ****************************************************************************/
389 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
390 time_t *change_time,
391 time_t *access_time,
392 time_t *write_time,
393 SMB_OFF_T *size, uint16 *mode)
395 unsigned int data_len = 0;
396 unsigned int param_len = 0;
397 unsigned int rparam_len, rdata_len;
398 uint16 setup = TRANSACT2_QPATHINFO;
399 pstring param;
400 char *rparam=NULL, *rdata=NULL;
401 int count=8;
402 BOOL ret;
403 time_t (*date_fn)(struct cli_state *, void *);
404 char *p;
406 p = param;
407 memset(p, 0, 6);
408 SSVAL(p, 0, SMB_INFO_STANDARD);
409 p += 6;
410 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
412 param_len = PTR_DIFF(p, param);
414 do {
415 ret = (cli_send_trans(cli, SMBtrans2,
416 NULL, /* Name */
417 -1, 0, /* fid, flags */
418 &setup, 1, 0, /* setup, length, max */
419 param, param_len, 10, /* param, length, max */
420 NULL, data_len, cli->max_xmit /* data, length, max */
421 ) &&
422 cli_receive_trans(cli, SMBtrans2,
423 &rparam, &rparam_len,
424 &rdata, &rdata_len));
425 if (!cli_is_dos_error(cli)) break;
426 if (!ret) {
427 /* we need to work around a Win95 bug - sometimes
428 it gives ERRSRV/ERRerror temprarily */
429 uint8 eclass;
430 uint32 ecode;
431 cli_dos_error(cli, &eclass, &ecode);
432 if (eclass != ERRSRV || ecode != ERRerror) break;
433 smb_msleep(100);
435 } while (count-- && ret==False);
437 if (!ret || !rdata || rdata_len < 22) {
438 return False;
441 if (cli->win95) {
442 date_fn = cli_make_unix_date;
443 } else {
444 date_fn = cli_make_unix_date2;
447 if (change_time) {
448 *change_time = date_fn(cli, rdata+0);
450 if (access_time) {
451 *access_time = date_fn(cli, rdata+4);
453 if (write_time) {
454 *write_time = date_fn(cli, rdata+8);
456 if (size) {
457 *size = IVAL(rdata, 12);
459 if (mode) {
460 *mode = SVAL(rdata,l1_attrFile);
463 SAFE_FREE(rdata);
464 SAFE_FREE(rparam);
465 return True;
468 /****************************************************************************
469 Send a setpathinfo call.
470 ****************************************************************************/
472 BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
473 time_t create_time,
474 time_t access_time,
475 time_t write_time,
476 time_t change_time,
477 uint16 mode)
479 unsigned int data_len = 0;
480 unsigned int param_len = 0;
481 unsigned int rparam_len, rdata_len;
482 uint16 setup = TRANSACT2_SETPATHINFO;
483 pstring param;
484 pstring data;
485 char *rparam=NULL, *rdata=NULL;
486 int count=8;
487 BOOL ret;
488 char *p;
490 memset(param, 0, sizeof(param));
491 memset(data, 0, sizeof(data));
493 p = param;
495 /* Add the information level */
496 SSVAL(p, 0, SMB_FILE_BASIC_INFORMATION);
498 /* Skip reserved */
499 p += 6;
501 /* Add the file name */
502 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
504 param_len = PTR_DIFF(p, param);
506 p = data;
509 * Add the create, last access, modification, and status change times
512 put_long_date(p, create_time);
513 p += 8;
515 put_long_date(p, access_time);
516 p += 8;
518 put_long_date(p, write_time);
519 p += 8;
521 put_long_date(p, change_time);
522 p += 8;
524 /* Add attributes */
525 SIVAL(p, 0, mode);
526 p += 4;
528 /* Add padding */
529 SIVAL(p, 0, 0);
530 p += 4;
532 data_len = PTR_DIFF(p, data);
534 do {
535 ret = (cli_send_trans(cli, SMBtrans2,
536 NULL, /* Name */
537 -1, 0, /* fid, flags */
538 &setup, 1, 0, /* setup, length, max */
539 param, param_len, 10, /* param, length, max */
540 data, data_len, cli->max_xmit /* data, length, max */
541 ) &&
542 cli_receive_trans(cli, SMBtrans2,
543 &rparam, &rparam_len,
544 &rdata, &rdata_len));
545 if (!cli_is_dos_error(cli)) break;
546 if (!ret) {
547 /* we need to work around a Win95 bug - sometimes
548 it gives ERRSRV/ERRerror temprarily */
549 uint8 eclass;
550 uint32 ecode;
551 cli_dos_error(cli, &eclass, &ecode);
552 if (eclass != ERRSRV || ecode != ERRerror) break;
553 smb_msleep(100);
555 } while (count-- && ret==False);
557 if (!ret) {
558 return False;
561 SAFE_FREE(rdata);
562 SAFE_FREE(rparam);
563 return True;
566 /****************************************************************************
567 Send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level.
568 ****************************************************************************/
570 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
571 struct timespec *create_time,
572 struct timespec *access_time,
573 struct timespec *write_time,
574 struct timespec *change_time,
575 SMB_OFF_T *size, uint16 *mode,
576 SMB_INO_T *ino)
578 unsigned int data_len = 0;
579 unsigned int param_len = 0;
580 uint16 setup = TRANSACT2_QPATHINFO;
581 pstring param;
582 char *rparam=NULL, *rdata=NULL;
583 char *p;
585 p = param;
586 memset(p, 0, 6);
587 SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
588 p += 6;
589 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
591 param_len = PTR_DIFF(p, param);
593 if (!cli_send_trans(cli, SMBtrans2,
594 NULL, /* name */
595 -1, 0, /* fid, flags */
596 &setup, 1, 0, /* setup, length, max */
597 param, param_len, 10, /* param, length, max */
598 NULL, data_len, cli->max_xmit /* data, length, max */
599 )) {
600 return False;
603 if (!cli_receive_trans(cli, SMBtrans2,
604 &rparam, &param_len,
605 &rdata, &data_len)) {
606 return False;
609 if (!rdata || data_len < 22) {
610 return False;
613 if (create_time) {
614 *create_time = interpret_long_date(rdata+0);
616 if (access_time) {
617 *access_time = interpret_long_date(rdata+8);
619 if (write_time) {
620 *write_time = interpret_long_date(rdata+16);
622 if (change_time) {
623 *change_time = interpret_long_date(rdata+24);
625 if (mode) {
626 *mode = SVAL(rdata, 32);
628 if (size) {
629 *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
631 if (ino) {
632 *ino = IVAL(rdata, 64);
635 SAFE_FREE(rdata);
636 SAFE_FREE(rparam);
637 return True;
640 /****************************************************************************
641 Send a qfileinfo QUERY_FILE_NAME_INFO call.
642 ****************************************************************************/
644 BOOL cli_qfilename(struct cli_state *cli, int fnum,
645 pstring name)
647 unsigned int data_len = 0;
648 unsigned int param_len = 0;
649 uint16 setup = TRANSACT2_QFILEINFO;
650 pstring param;
651 char *rparam=NULL, *rdata=NULL;
653 param_len = 4;
654 memset(param, 0, param_len);
655 SSVAL(param, 0, fnum);
656 SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
658 if (!cli_send_trans(cli, SMBtrans2,
659 NULL, /* name */
660 -1, 0, /* fid, flags */
661 &setup, 1, 0, /* setup, length, max */
662 param, param_len, 2, /* param, length, max */
663 NULL, data_len, cli->max_xmit /* data, length, max */
664 )) {
665 return False;
668 if (!cli_receive_trans(cli, SMBtrans2,
669 &rparam, &param_len,
670 &rdata, &data_len)) {
671 return False;
674 if (!rdata || data_len < 4) {
675 return False;
678 clistr_pull(cli, name, rdata+4, sizeof(pstring), IVAL(rdata, 0), STR_UNICODE);
680 return True;
683 /****************************************************************************
684 Send a qfileinfo call.
685 ****************************************************************************/
687 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
688 uint16 *mode, SMB_OFF_T *size,
689 struct timespec *create_time,
690 struct timespec *access_time,
691 struct timespec *write_time,
692 struct timespec *change_time,
693 SMB_INO_T *ino)
695 unsigned int data_len = 0;
696 unsigned int param_len = 0;
697 uint16 setup = TRANSACT2_QFILEINFO;
698 pstring param;
699 char *rparam=NULL, *rdata=NULL;
701 /* if its a win95 server then fail this - win95 totally screws it
702 up */
703 if (cli->win95) return False;
705 param_len = 4;
707 memset(param, 0, param_len);
708 SSVAL(param, 0, fnum);
709 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
711 if (!cli_send_trans(cli, SMBtrans2,
712 NULL, /* name */
713 -1, 0, /* fid, flags */
714 &setup, 1, 0, /* setup, length, max */
715 param, param_len, 2, /* param, length, max */
716 NULL, data_len, cli->max_xmit /* data, length, max */
717 )) {
718 return False;
721 if (!cli_receive_trans(cli, SMBtrans2,
722 &rparam, &param_len,
723 &rdata, &data_len)) {
724 return False;
727 if (!rdata || data_len < 68) {
728 return False;
731 if (create_time) {
732 *create_time = interpret_long_date(rdata+0);
734 if (access_time) {
735 *access_time = interpret_long_date(rdata+8);
737 if (write_time) {
738 *write_time = interpret_long_date(rdata+16);
740 if (change_time) {
741 *change_time = interpret_long_date(rdata+24);
743 if (mode) {
744 *mode = SVAL(rdata, 32);
746 if (size) {
747 *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
749 if (ino) {
750 *ino = IVAL(rdata, 64);
753 SAFE_FREE(rdata);
754 SAFE_FREE(rparam);
755 return True;
758 /****************************************************************************
759 Send a qpathinfo BASIC_INFO call.
760 ****************************************************************************/
762 BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name,
763 SMB_STRUCT_STAT *sbuf, uint32 *attributes )
765 unsigned int param_len = 0;
766 unsigned int data_len = 0;
767 uint16 setup = TRANSACT2_QPATHINFO;
768 char param[sizeof(pstring)+6];
769 char *rparam=NULL, *rdata=NULL;
770 char *p;
771 pstring path;
772 int len;
774 pstrcpy( path, name );
775 /* cleanup */
777 len = strlen( path );
778 if ( path[len-1] == '\\' || path[len-1] == '/')
779 path[len-1] = '\0';
781 p = param;
782 memset(p, 0, 6);
783 SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO);
784 p += 6;
785 p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
786 param_len = PTR_DIFF(p, param);
788 if (!cli_send_trans(cli, SMBtrans2,
789 NULL, /* name */
790 -1, 0, /* fid, flags */
791 &setup, 1, 0, /* setup, length, max */
792 param, param_len, 2, /* param, length, max */
793 NULL, 0, cli->max_xmit /* data, length, max */
794 )) {
795 return False;
798 if (!cli_receive_trans(cli, SMBtrans2,
799 &rparam, &param_len,
800 &rdata, &data_len)) {
801 return False;
804 if (data_len < 36) {
805 SAFE_FREE(rdata);
806 SAFE_FREE(rparam);
807 return False;
810 set_atimespec(sbuf, interpret_long_date( rdata+8 )); /* Access time. */
811 set_mtimespec(sbuf, interpret_long_date( rdata+16 )); /* Write time. */
812 set_ctimespec(sbuf, interpret_long_date( rdata+24 )); /* Change time. */
814 *attributes = IVAL( rdata, 32 );
816 SAFE_FREE(rparam);
817 SAFE_FREE(rdata);
819 return True;
822 /****************************************************************************
823 Send a qfileinfo call.
824 ****************************************************************************/
826 BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
828 unsigned int data_len = 0;
829 unsigned int param_len = 0;
830 uint16 setup = TRANSACT2_QFILEINFO;
831 pstring param;
832 char *rparam=NULL, *rdata=NULL;
834 *poutdata = NULL;
835 *poutlen = 0;
837 /* if its a win95 server then fail this - win95 totally screws it
838 up */
839 if (cli->win95)
840 return False;
842 param_len = 4;
844 memset(param, 0, param_len);
845 SSVAL(param, 0, fnum);
846 SSVAL(param, 2, level);
848 if (!cli_send_trans(cli, SMBtrans2,
849 NULL, /* name */
850 -1, 0, /* fid, flags */
851 &setup, 1, 0, /* setup, length, max */
852 param, param_len, 2, /* param, length, max */
853 NULL, data_len, cli->max_xmit /* data, length, max */
854 )) {
855 return False;
858 if (!cli_receive_trans(cli, SMBtrans2,
859 &rparam, &param_len,
860 &rdata, &data_len)) {
861 return False;
864 *poutdata = (char *)memdup(rdata, data_len);
865 if (!*poutdata) {
866 SAFE_FREE(rdata);
867 SAFE_FREE(rparam);
868 return False;
871 *poutlen = data_len;
873 SAFE_FREE(rdata);
874 SAFE_FREE(rparam);
875 return True;
878 /****************************************************************************
879 Send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call.
880 ****************************************************************************/
882 NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
884 unsigned int data_len = 0;
885 unsigned int param_len = 0;
886 uint16 setup = TRANSACT2_QPATHINFO;
887 pstring param;
888 char *rparam=NULL, *rdata=NULL;
889 int count=8;
890 char *p;
891 BOOL ret;
892 unsigned int len;
894 p = param;
895 memset(p, 0, 6);
896 SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
897 p += 6;
898 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
900 param_len = PTR_DIFF(p, param);
902 do {
903 ret = (cli_send_trans(cli, SMBtrans2,
904 NULL, /* Name */
905 -1, 0, /* fid, flags */
906 &setup, 1, 0, /* setup, length, max */
907 param, param_len, 10, /* param, length, max */
908 NULL, data_len, cli->max_xmit /* data, length, max */
909 ) &&
910 cli_receive_trans(cli, SMBtrans2,
911 &rparam, &param_len,
912 &rdata, &data_len));
913 if (!ret && cli_is_dos_error(cli)) {
914 /* we need to work around a Win95 bug - sometimes
915 it gives ERRSRV/ERRerror temprarily */
916 uint8 eclass;
917 uint32 ecode;
918 cli_dos_error(cli, &eclass, &ecode);
919 if (eclass != ERRSRV || ecode != ERRerror) break;
920 smb_msleep(100);
922 } while (count-- && ret==False);
924 if (!ret || !rdata || data_len < 4) {
925 return NT_STATUS_UNSUCCESSFUL;
928 len = IVAL(rdata, 0);
930 if (len > data_len - 4) {
931 return NT_STATUS_INVALID_NETWORK_RESPONSE;
934 clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
936 SAFE_FREE(rdata);
937 SAFE_FREE(rparam);
939 return NT_STATUS_OK;