source: trunk/samba/source/libsmb/clirap.c@ 77

Last change on this file since 77 was 77, checked in by Paul Smedley, 18 years ago

Update trunk to 3.2.0pre1

File size: 26.8 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 client RAP calls
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Gerald (Jerry) Carter 2004
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 3 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, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "includes.h"
22
23/****************************************************************************
24 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
25****************************************************************************/
26
27BOOL cli_api_pipe(struct cli_state *cli, const char *pipe_name,
28 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
29 char *params, uint32 param_count, uint32 max_param_count,
30 char *data, uint32 data_count, uint32 max_data_count,
31 char **rparam, uint32 *rparam_count,
32 char **rdata, uint32 *rdata_count)
33{
34 cli_send_trans(cli, SMBtrans,
35 pipe_name,
36 0,0, /* fid, flags */
37 setup, setup_count, max_setup_count,
38 params, param_count, max_param_count,
39 data, data_count, max_data_count);
40
41 return (cli_receive_trans(cli, SMBtrans,
42 rparam, (unsigned int *)rparam_count,
43 rdata, (unsigned int *)rdata_count));
44}
45
46/****************************************************************************
47 Call a remote api
48****************************************************************************/
49
50BOOL cli_api(struct cli_state *cli,
51 char *param, int prcnt, int mprcnt,
52 char *data, int drcnt, int mdrcnt,
53 char **rparam, unsigned int *rprcnt,
54 char **rdata, unsigned int *rdrcnt)
55{
56 cli_send_trans(cli,SMBtrans,
57 PIPE_LANMAN, /* Name */
58 0,0, /* fid, flags */
59 NULL,0,0, /* Setup, length, max */
60 param, prcnt, mprcnt, /* Params, length, max */
61 data, drcnt, mdrcnt /* Data, length, max */
62 );
63
64 return (cli_receive_trans(cli,SMBtrans,
65 rparam, rprcnt,
66 rdata, rdrcnt));
67}
68
69/****************************************************************************
70 Perform a NetWkstaUserLogon.
71****************************************************************************/
72
73BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
74{
75 char *rparam = NULL;
76 char *rdata = NULL;
77 char *p;
78 unsigned int rdrcnt,rprcnt;
79 pstring param;
80
81 memset(param, 0, sizeof(param));
82
83 /* send a SMBtrans command with api NetWkstaUserLogon */
84 p = param;
85 SSVAL(p,0,132); /* api number */
86 p += 2;
87 pstrcpy_base(p,"OOWb54WrLh",param);
88 p = skip_string(param,sizeof(param),p);
89 pstrcpy_base(p,"WB21BWDWWDDDDDDDzzzD",param);
90 p = skip_string(param,sizeof(param),p);
91 SSVAL(p,0,1);
92 p += 2;
93 pstrcpy_base(p,user,param);
94 strupper_m(p);
95 p += 21;
96 p++;
97 p += 15;
98 p++;
99 pstrcpy_base(p, workstation, param);
100 strupper_m(p);
101 p += 16;
102 SSVAL(p, 0, CLI_BUFFER_SIZE);
103 p += 2;
104 SSVAL(p, 0, CLI_BUFFER_SIZE);
105 p += 2;
106
107 if (cli_api(cli,
108 param, PTR_DIFF(p,param),1024, /* param, length, max */
109 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
110 &rparam, &rprcnt, /* return params, return size */
111 &rdata, &rdrcnt /* return data, return size */
112 )) {
113 cli->rap_error = rparam? SVAL(rparam,0) : -1;
114 p = rdata;
115
116 if (cli->rap_error == 0) {
117 DEBUG(4,("NetWkstaUserLogon success\n"));
118 cli->privileges = SVAL(p, 24);
119 /* The cli->eff_name field used to be set here
120 but it wasn't used anywhere else. */
121 } else {
122 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
123 }
124 }
125
126 SAFE_FREE(rparam);
127 SAFE_FREE(rdata);
128 return (cli->rap_error == 0);
129}
130
131/****************************************************************************
132 Call a NetShareEnum - try and browse available connections on a host.
133****************************************************************************/
134
135int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
136{
137 char *rparam = NULL;
138 char *rdata = NULL;
139 char *p;
140 unsigned int rdrcnt,rprcnt;
141 pstring param;
142 int count = -1;
143
144 /* now send a SMBtrans command with api RNetShareEnum */
145 p = param;
146 SSVAL(p,0,0); /* api number */
147 p += 2;
148 pstrcpy_base(p,"WrLeh",param);
149 p = skip_string(param,sizeof(param),p);
150 pstrcpy_base(p,"B13BWz",param);
151 p = skip_string(param,sizeof(param),p);
152 SSVAL(p,0,1);
153 /*
154 * Win2k needs a *smaller* buffer than 0xFFFF here -
155 * it returns "out of server memory" with 0xFFFF !!! JRA.
156 */
157 SSVAL(p,2,0xFFE0);
158 p += 4;
159
160 if (cli_api(cli,
161 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
162 NULL, 0, 0xFFE0, /* data, length, maxlen - Win2k needs a small buffer here too ! */
163 &rparam, &rprcnt, /* return params, length */
164 &rdata, &rdrcnt)) /* return data, length */
165 {
166 int res = rparam? SVAL(rparam,0) : -1;
167
168 if (res == 0 || res == ERRmoredata) {
169 int converter=SVAL(rparam,2);
170 int i;
171
172 count=SVAL(rparam,4);
173 p = rdata;
174
175 for (i=0;i<count;i++,p+=20) {
176 char *sname = p;
177 int type = SVAL(p,14);
178 int comment_offset = IVAL(p,16) & 0xFFFF;
179 const char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
180 pstring s1, s2;
181
182 pull_ascii_pstring(s1, sname);
183 pull_ascii_pstring(s2, cmnt);
184
185 fn(s1, type, s2, state);
186 }
187 } else {
188 DEBUG(4,("NetShareEnum res=%d\n", res));
189 }
190 } else {
191 DEBUG(4,("NetShareEnum failed\n"));
192 }
193
194 SAFE_FREE(rparam);
195 SAFE_FREE(rdata);
196
197 return count;
198}
199
200/****************************************************************************
201 Call a NetServerEnum for the specified workgroup and servertype mask. This
202 function then calls the specified callback function for each name returned.
203
204 The callback function takes 4 arguments: the machine name, the server type,
205 the comment and a state pointer.
206****************************************************************************/
207
208BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
209 void (*fn)(const char *, uint32, const char *, void *),
210 void *state)
211{
212 char *rparam = NULL;
213 char *rdata = NULL;
214 unsigned int rdrcnt,rprcnt;
215 char *p;
216 pstring param;
217 int uLevel = 1;
218 int count = -1;
219
220 errno = 0; /* reset */
221
222 /* send a SMBtrans command with api NetServerEnum */
223 p = param;
224 SSVAL(p,0,0x68); /* api number */
225 p += 2;
226 pstrcpy_base(p,"WrLehDz", param);
227 p = skip_string(param,sizeof(param),p);
228
229 pstrcpy_base(p,"B16BBDz", param);
230
231 p = skip_string(param,sizeof(param),p);
232 SSVAL(p,0,uLevel);
233 SSVAL(p,2,CLI_BUFFER_SIZE);
234 p += 4;
235 SIVAL(p,0,stype);
236 p += 4;
237
238 p += push_ascii(p, workgroup, sizeof(pstring)-PTR_DIFF(p,param)-1, STR_TERMINATE|STR_UPPER);
239
240 if (cli_api(cli,
241 param, PTR_DIFF(p,param), 8, /* params, length, max */
242 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
243 &rparam, &rprcnt, /* return params, return size */
244 &rdata, &rdrcnt /* return data, return size */
245 )) {
246 int res = rparam? SVAL(rparam,0) : -1;
247
248 if (res == 0 || res == ERRmoredata ||
249 (res != -1 && cli_errno(cli) == 0)) {
250 int i;
251 int converter=SVAL(rparam,2);
252
253 count=SVAL(rparam,4);
254 p = rdata;
255
256 for (i = 0;i < count;i++, p += 26) {
257 char *sname = p;
258 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
259 const char *cmnt = comment_offset?(rdata+comment_offset):"";
260 pstring s1, s2;
261
262 if (comment_offset < 0 || comment_offset > (int)rdrcnt) continue;
263
264 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
265
266 pull_ascii_pstring(s1, sname);
267 pull_ascii_pstring(s2, cmnt);
268 fn(s1, stype, s2, state);
269 }
270 }
271 }
272
273 SAFE_FREE(rparam);
274 SAFE_FREE(rdata);
275
276 if (count < 0) {
277 errno = cli_errno(cli);
278 } else {
279 if (!count) {
280 /* this is a very special case, when the domain master for the
281 work group isn't part of the work group itself, there is something
282 wild going on */
283 errno = ENOENT;
284 }
285 }
286
287 return(count > 0);
288}
289
290/****************************************************************************
291 Send a SamOEMChangePassword command.
292****************************************************************************/
293
294BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
295 const char *old_password)
296{
297 pstring param;
298 unsigned char data[532];
299 char *p = param;
300 unsigned char old_pw_hash[16];
301 unsigned char new_pw_hash[16];
302 unsigned int data_len;
303 unsigned int param_len = 0;
304 char *rparam = NULL;
305 char *rdata = NULL;
306 unsigned int rprcnt, rdrcnt;
307
308 if (strlen(user) >= sizeof(fstring)-1) {
309 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
310 return False;
311 }
312
313 SSVAL(p,0,214); /* SamOEMChangePassword command. */
314 p += 2;
315 pstrcpy_base(p, "zsT", param);
316 p = skip_string(param,sizeof(param),p);
317 pstrcpy_base(p, "B516B16", param);
318 p = skip_string(param,sizeof(param),p);
319 pstrcpy_base(p,user, param);
320 p = skip_string(param,sizeof(param),p);
321 SSVAL(p,0,532);
322 p += 2;
323
324 param_len = PTR_DIFF(p,param);
325
326 /*
327 * Get the Lanman hash of the old password, we
328 * use this as the key to make_oem_passwd_hash().
329 */
330 E_deshash(old_password, old_pw_hash);
331
332 encode_pw_buffer(data, new_password, STR_ASCII);
333
334#ifdef DEBUG_PASSWORD
335 DEBUG(100,("make_oem_passwd_hash\n"));
336 dump_data(100, data, 516);
337#endif
338 SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
339
340 /*
341 * Now place the old password hash in the data.
342 */
343 E_deshash(new_password, new_pw_hash);
344
345 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
346
347 data_len = 532;
348
349 if (cli_send_trans(cli,SMBtrans,
350 PIPE_LANMAN, /* name */
351 0,0, /* fid, flags */
352 NULL,0,0, /* setup, length, max */
353 param,param_len,2, /* param, length, max */
354 (char *)data,data_len,0 /* data, length, max */
355 ) == False) {
356 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
357 user ));
358 return False;
359 }
360
361 if (!cli_receive_trans(cli,SMBtrans,
362 &rparam, &rprcnt,
363 &rdata, &rdrcnt)) {
364 DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
365 user ));
366 return False;
367 }
368
369 if (rparam) {
370 cli->rap_error = SVAL(rparam,0);
371 }
372
373 SAFE_FREE(rparam);
374 SAFE_FREE(rdata);
375
376 return (cli->rap_error == 0);
377}
378
379/****************************************************************************
380 Send a qpathinfo call.
381****************************************************************************/
382
383BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
384 time_t *change_time,
385 time_t *access_time,
386 time_t *write_time,
387 SMB_OFF_T *size, uint16 *mode)
388{
389 unsigned int data_len = 0;
390 unsigned int param_len = 0;
391 unsigned int rparam_len, rdata_len;
392 uint16 setup = TRANSACT2_QPATHINFO;
393 pstring param;
394 char *rparam=NULL, *rdata=NULL;
395 int count=8;
396 BOOL ret;
397 time_t (*date_fn)(struct cli_state *, void *);
398 char *p;
399
400 p = param;
401 memset(p, 0, 6);
402 SSVAL(p, 0, SMB_INFO_STANDARD);
403 p += 6;
404 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
405
406 param_len = PTR_DIFF(p, param);
407
408 do {
409 ret = (cli_send_trans(cli, SMBtrans2,
410 NULL, /* Name */
411 -1, 0, /* fid, flags */
412 &setup, 1, 0, /* setup, length, max */
413 param, param_len, 10, /* param, length, max */
414 NULL, data_len, cli->max_xmit /* data, length, max */
415 ) &&
416 cli_receive_trans(cli, SMBtrans2,
417 &rparam, &rparam_len,
418 &rdata, &rdata_len));
419 if (!cli_is_dos_error(cli)) break;
420 if (!ret) {
421 /* we need to work around a Win95 bug - sometimes
422 it gives ERRSRV/ERRerror temprarily */
423 uint8 eclass;
424 uint32 ecode;
425 cli_dos_error(cli, &eclass, &ecode);
426 if (eclass != ERRSRV || ecode != ERRerror) break;
427 smb_msleep(100);
428 }
429 } while (count-- && ret==False);
430
431 if (!ret || !rdata || rdata_len < 22) {
432 return False;
433 }
434
435 if (cli->win95) {
436 date_fn = cli_make_unix_date;
437 } else {
438 date_fn = cli_make_unix_date2;
439 }
440
441 if (change_time) {
442 *change_time = date_fn(cli, rdata+0);
443 }
444 if (access_time) {
445 *access_time = date_fn(cli, rdata+4);
446 }
447 if (write_time) {
448 *write_time = date_fn(cli, rdata+8);
449 }
450 if (size) {
451 *size = IVAL(rdata, 12);
452 }
453 if (mode) {
454 *mode = SVAL(rdata,l1_attrFile);
455 }
456
457 SAFE_FREE(rdata);
458 SAFE_FREE(rparam);
459 return True;
460}
461
462/****************************************************************************
463 Send a setpathinfo call.
464****************************************************************************/
465
466BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
467 time_t create_time,
468 time_t access_time,
469 time_t write_time,
470 time_t change_time,
471 uint16 mode)
472{
473 unsigned int data_len = 0;
474 unsigned int param_len = 0;
475 unsigned int rparam_len, rdata_len;
476 uint16 setup = TRANSACT2_SETPATHINFO;
477 pstring param;
478 pstring data;
479 char *rparam=NULL, *rdata=NULL;
480 int count=8;
481 BOOL ret;
482 char *p;
483
484 memset(param, 0, sizeof(param));
485 memset(data, 0, sizeof(data));
486
487 p = param;
488
489 /* Add the information level */
490 SSVAL(p, 0, SMB_FILE_BASIC_INFORMATION);
491
492 /* Skip reserved */
493 p += 6;
494
495 /* Add the file name */
496 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
497
498 param_len = PTR_DIFF(p, param);
499
500 p = data;
501
502 /*
503 * Add the create, last access, modification, and status change times
504 */
505
506 put_long_date(p, create_time);
507 p += 8;
508
509 put_long_date(p, access_time);
510 p += 8;
511
512 put_long_date(p, write_time);
513 p += 8;
514
515 put_long_date(p, change_time);
516 p += 8;
517
518 /* Add attributes */
519 SIVAL(p, 0, mode);
520 p += 4;
521
522 /* Add padding */
523 SIVAL(p, 0, 0);
524 p += 4;
525
526 data_len = PTR_DIFF(p, data);
527
528 do {
529 ret = (cli_send_trans(cli, SMBtrans2,
530 NULL, /* Name */
531 -1, 0, /* fid, flags */
532 &setup, 1, 0, /* setup, length, max */
533 param, param_len, 10, /* param, length, max */
534 data, data_len, cli->max_xmit /* data, length, max */
535 ) &&
536 cli_receive_trans(cli, SMBtrans2,
537 &rparam, &rparam_len,
538 &rdata, &rdata_len));
539 if (!cli_is_dos_error(cli)) break;
540 if (!ret) {
541 /* we need to work around a Win95 bug - sometimes
542 it gives ERRSRV/ERRerror temprarily */
543 uint8 eclass;
544 uint32 ecode;
545 cli_dos_error(cli, &eclass, &ecode);
546 if (eclass != ERRSRV || ecode != ERRerror) break;
547 smb_msleep(100);
548 }
549 } while (count-- && ret==False);
550
551 if (!ret) {
552 return False;
553 }
554
555 SAFE_FREE(rdata);
556 SAFE_FREE(rparam);
557 return True;
558}
559
560/****************************************************************************
561 Send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level.
562****************************************************************************/
563
564BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
565 struct timespec *create_time,
566 struct timespec *access_time,
567 struct timespec *write_time,
568 struct timespec *change_time,
569 SMB_OFF_T *size, uint16 *mode,
570 SMB_INO_T *ino)
571{
572 unsigned int data_len = 0;
573 unsigned int param_len = 0;
574 uint16 setup = TRANSACT2_QPATHINFO;
575 pstring param;
576 char *rparam=NULL, *rdata=NULL;
577 char *p;
578
579 p = param;
580 memset(p, 0, 6);
581 SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
582 p += 6;
583 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
584
585 param_len = PTR_DIFF(p, param);
586
587 if (!cli_send_trans(cli, SMBtrans2,
588 NULL, /* name */
589 -1, 0, /* fid, flags */
590 &setup, 1, 0, /* setup, length, max */
591 param, param_len, 10, /* param, length, max */
592 NULL, data_len, cli->max_xmit /* data, length, max */
593 )) {
594 return False;
595 }
596
597 if (!cli_receive_trans(cli, SMBtrans2,
598 &rparam, &param_len,
599 &rdata, &data_len)) {
600 return False;
601 }
602
603 if (!rdata || data_len < 22) {
604 return False;
605 }
606
607 if (create_time) {
608 *create_time = interpret_long_date(rdata+0);
609 }
610 if (access_time) {
611 *access_time = interpret_long_date(rdata+8);
612 }
613 if (write_time) {
614 *write_time = interpret_long_date(rdata+16);
615 }
616 if (change_time) {
617 *change_time = interpret_long_date(rdata+24);
618 }
619 if (mode) {
620 *mode = SVAL(rdata, 32);
621 }
622 if (size) {
623 *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
624 }
625 if (ino) {
626 *ino = IVAL(rdata, 64);
627 }
628
629 SAFE_FREE(rdata);
630 SAFE_FREE(rparam);
631 return True;
632}
633
634/****************************************************************************
635 Send a qfileinfo QUERY_FILE_NAME_INFO call.
636****************************************************************************/
637
638BOOL cli_qfilename(struct cli_state *cli, int fnum,
639 pstring name)
640{
641 unsigned int data_len = 0;
642 unsigned int param_len = 0;
643 uint16 setup = TRANSACT2_QFILEINFO;
644 pstring param;
645 char *rparam=NULL, *rdata=NULL;
646
647 param_len = 4;
648 memset(param, 0, param_len);
649 SSVAL(param, 0, fnum);
650 SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
651
652 if (!cli_send_trans(cli, SMBtrans2,
653 NULL, /* name */
654 -1, 0, /* fid, flags */
655 &setup, 1, 0, /* setup, length, max */
656 param, param_len, 2, /* param, length, max */
657 NULL, data_len, cli->max_xmit /* data, length, max */
658 )) {
659 return False;
660 }
661
662 if (!cli_receive_trans(cli, SMBtrans2,
663 &rparam, &param_len,
664 &rdata, &data_len)) {
665 return False;
666 }
667
668 if (!rdata || data_len < 4) {
669 return False;
670 }
671
672 clistr_pull(cli, name, rdata+4, sizeof(pstring), IVAL(rdata, 0), STR_UNICODE);
673
674 return True;
675}
676
677/****************************************************************************
678 Send a qfileinfo call.
679****************************************************************************/
680
681BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
682 uint16 *mode, SMB_OFF_T *size,
683 struct timespec *create_time,
684 struct timespec *access_time,
685 struct timespec *write_time,
686 struct timespec *change_time,
687 SMB_INO_T *ino)
688{
689 unsigned int data_len = 0;
690 unsigned int param_len = 0;
691 uint16 setup = TRANSACT2_QFILEINFO;
692 pstring param;
693 char *rparam=NULL, *rdata=NULL;
694
695 /* if its a win95 server then fail this - win95 totally screws it
696 up */
697 if (cli->win95) return False;
698
699 param_len = 4;
700
701 memset(param, 0, param_len);
702 SSVAL(param, 0, fnum);
703 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
704
705 if (!cli_send_trans(cli, SMBtrans2,
706 NULL, /* name */
707 -1, 0, /* fid, flags */
708 &setup, 1, 0, /* setup, length, max */
709 param, param_len, 2, /* param, length, max */
710 NULL, data_len, cli->max_xmit /* data, length, max */
711 )) {
712 return False;
713 }
714
715 if (!cli_receive_trans(cli, SMBtrans2,
716 &rparam, &param_len,
717 &rdata, &data_len)) {
718 return False;
719 }
720
721 if (!rdata || data_len < 68) {
722 return False;
723 }
724
725 if (create_time) {
726 *create_time = interpret_long_date(rdata+0);
727 }
728 if (access_time) {
729 *access_time = interpret_long_date(rdata+8);
730 }
731 if (write_time) {
732 *write_time = interpret_long_date(rdata+16);
733 }
734 if (change_time) {
735 *change_time = interpret_long_date(rdata+24);
736 }
737 if (mode) {
738 *mode = SVAL(rdata, 32);
739 }
740 if (size) {
741 *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
742 }
743 if (ino) {
744 *ino = IVAL(rdata, 64);
745 }
746
747 SAFE_FREE(rdata);
748 SAFE_FREE(rparam);
749 return True;
750}
751
752/****************************************************************************
753 Send a qpathinfo BASIC_INFO call.
754****************************************************************************/
755
756BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name,
757 SMB_STRUCT_STAT *sbuf, uint32 *attributes )
758{
759 unsigned int param_len = 0;
760 unsigned int data_len = 0;
761 uint16 setup = TRANSACT2_QPATHINFO;
762 char param[sizeof(pstring)+6];
763 char *rparam=NULL, *rdata=NULL;
764 char *p;
765 pstring path;
766 int len;
767
768 pstrcpy( path, name );
769 /* cleanup */
770
771 len = strlen( path );
772 if ( path[len-1] == '\\' || path[len-1] == '/')
773 path[len-1] = '\0';
774
775 p = param;
776 memset(p, 0, 6);
777 SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO);
778 p += 6;
779 p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
780 param_len = PTR_DIFF(p, param);
781
782 if (!cli_send_trans(cli, SMBtrans2,
783 NULL, /* name */
784 -1, 0, /* fid, flags */
785 &setup, 1, 0, /* setup, length, max */
786 param, param_len, 2, /* param, length, max */
787 NULL, 0, cli->max_xmit /* data, length, max */
788 )) {
789 return False;
790 }
791
792 if (!cli_receive_trans(cli, SMBtrans2,
793 &rparam, &param_len,
794 &rdata, &data_len)) {
795 return False;
796 }
797
798 if (data_len < 36) {
799 SAFE_FREE(rdata);
800 SAFE_FREE(rparam);
801 return False;
802 }
803
804 set_atimespec(sbuf, interpret_long_date( rdata+8 )); /* Access time. */
805 set_mtimespec(sbuf, interpret_long_date( rdata+16 )); /* Write time. */
806 set_ctimespec(sbuf, interpret_long_date( rdata+24 )); /* Change time. */
807
808 *attributes = IVAL( rdata, 32 );
809
810 SAFE_FREE(rparam);
811 SAFE_FREE(rdata);
812
813 return True;
814}
815
816/****************************************************************************
817 Send a qfileinfo call.
818****************************************************************************/
819
820BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
821{
822 unsigned int data_len = 0;
823 unsigned int param_len = 0;
824 uint16 setup = TRANSACT2_QFILEINFO;
825 pstring param;
826 char *rparam=NULL, *rdata=NULL;
827
828 *poutdata = NULL;
829 *poutlen = 0;
830
831 /* if its a win95 server then fail this - win95 totally screws it
832 up */
833 if (cli->win95)
834 return False;
835
836 param_len = 4;
837
838 memset(param, 0, param_len);
839 SSVAL(param, 0, fnum);
840 SSVAL(param, 2, level);
841
842 if (!cli_send_trans(cli, SMBtrans2,
843 NULL, /* name */
844 -1, 0, /* fid, flags */
845 &setup, 1, 0, /* setup, length, max */
846 param, param_len, 2, /* param, length, max */
847 NULL, data_len, cli->max_xmit /* data, length, max */
848 )) {
849 return False;
850 }
851
852 if (!cli_receive_trans(cli, SMBtrans2,
853 &rparam, &param_len,
854 &rdata, &data_len)) {
855 return False;
856 }
857
858 *poutdata = (char *)memdup(rdata, data_len);
859 if (!*poutdata) {
860 SAFE_FREE(rdata);
861 SAFE_FREE(rparam);
862 return False;
863 }
864
865 *poutlen = data_len;
866
867 SAFE_FREE(rdata);
868 SAFE_FREE(rparam);
869 return True;
870}
871
872/****************************************************************************
873 Send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call.
874****************************************************************************/
875
876NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
877{
878 unsigned int data_len = 0;
879 unsigned int param_len = 0;
880 uint16 setup = TRANSACT2_QPATHINFO;
881 pstring param;
882 char *rparam=NULL, *rdata=NULL;
883 int count=8;
884 char *p;
885 BOOL ret;
886 unsigned int len;
887
888 p = param;
889 memset(p, 0, 6);
890 SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
891 p += 6;
892 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
893
894 param_len = PTR_DIFF(p, param);
895
896 do {
897 ret = (cli_send_trans(cli, SMBtrans2,
898 NULL, /* Name */
899 -1, 0, /* fid, flags */
900 &setup, 1, 0, /* setup, length, max */
901 param, param_len, 10, /* param, length, max */
902 NULL, data_len, cli->max_xmit /* data, length, max */
903 ) &&
904 cli_receive_trans(cli, SMBtrans2,
905 &rparam, &param_len,
906 &rdata, &data_len));
907 if (!ret && cli_is_dos_error(cli)) {
908 /* we need to work around a Win95 bug - sometimes
909 it gives ERRSRV/ERRerror temprarily */
910 uint8 eclass;
911 uint32 ecode;
912 cli_dos_error(cli, &eclass, &ecode);
913 if (eclass != ERRSRV || ecode != ERRerror) break;
914 smb_msleep(100);
915 }
916 } while (count-- && ret==False);
917
918 if (!ret || !rdata || data_len < 4) {
919 return NT_STATUS_UNSUCCESSFUL;
920 }
921
922 len = IVAL(rdata, 0);
923
924 if (len > data_len - 4) {
925 return NT_STATUS_INVALID_NETWORK_RESPONSE;
926 }
927
928 clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
929
930 SAFE_FREE(rdata);
931 SAFE_FREE(rparam);
932
933 return NT_STATUS_OK;
934}
Note: See TracBrowser for help on using the repository browser.