source: trunk/samba-3.0.25pre1/source/libsmb/clirap.c@ 5

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

Initial code import

File size: 26.0 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 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
24
25/****************************************************************************
26Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
27****************************************************************************/
28BOOL 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)
34{
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);
41
42 return (cli_receive_trans(cli, SMBtrans,
43 rparam, (unsigned int *)rparam_count,
44 rdata, (unsigned int *)rdata_count));
45}
46
47/****************************************************************************
48call a remote api
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/****************************************************************************
71perform a NetWkstaUserLogon
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(p,1);
89 pstrcpy_base(p,"WB21BWDWWDDDDDDDzzzD",param);
90 p = skip_string(p,1);
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/****************************************************************************
132call a NetShareEnum - try and browse available connections on a host
133****************************************************************************/
134int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
135{
136 char *rparam = NULL;
137 char *rdata = NULL;
138 char *p;
139 unsigned int rdrcnt,rprcnt;
140 pstring param;
141 int count = -1;
142
143 /* now send a SMBtrans command with api RNetShareEnum */
144 p = param;
145 SSVAL(p,0,0); /* api number */
146 p += 2;
147 pstrcpy_base(p,"WrLeh",param);
148 p = skip_string(p,1);
149 pstrcpy_base(p,"B13BWz",param);
150 p = skip_string(p,1);
151 SSVAL(p,0,1);
152 /*
153 * Win2k needs a *smaller* buffer than 0xFFFF here -
154 * it returns "out of server memory" with 0xFFFF !!! JRA.
155 */
156 SSVAL(p,2,0xFFE0);
157 p += 4;
158
159 if (cli_api(cli,
160 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
161 NULL, 0, 0xFFE0, /* data, length, maxlen - Win2k needs a small buffer here too ! */
162 &rparam, &rprcnt, /* return params, length */
163 &rdata, &rdrcnt)) /* return data, length */
164 {
165 int res = rparam? SVAL(rparam,0) : -1;
166
167 if (res == 0 || res == ERRmoredata) {
168 int converter=SVAL(rparam,2);
169 int i;
170
171 count=SVAL(rparam,4);
172 p = rdata;
173
174 for (i=0;i<count;i++,p+=20) {
175 char *sname = p;
176 int type = SVAL(p,14);
177 int comment_offset = IVAL(p,16) & 0xFFFF;
178 const char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
179 pstring s1, s2;
180
181 pull_ascii_pstring(s1, sname);
182 pull_ascii_pstring(s2, cmnt);
183
184 fn(s1, type, s2, state);
185 }
186 } else {
187 DEBUG(4,("NetShareEnum res=%d\n", res));
188 }
189 } else {
190 DEBUG(4,("NetShareEnum failed\n"));
191 }
192
193 SAFE_FREE(rparam);
194 SAFE_FREE(rdata);
195
196 return count;
197}
198
199
200/****************************************************************************
201call a NetServerEnum for the specified workgroup and servertype mask. This
202function then calls the specified callback function for each name returned.
203
204The callback function takes 4 arguments: the machine name, the server type,
205the comment and a state pointer.
206****************************************************************************/
207BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
208 void (*fn)(const char *, uint32, const char *, void *),
209 void *state)
210{
211 char *rparam = NULL;
212 char *rdata = NULL;
213 unsigned int rdrcnt,rprcnt;
214 char *p;
215 pstring param;
216 int uLevel = 1;
217 int count = -1;
218
219 errno = 0; /* reset */
220
221 /* send a SMBtrans command with api NetServerEnum */
222 p = param;
223 SSVAL(p,0,0x68); /* api number */
224 p += 2;
225 pstrcpy_base(p,"WrLehDz", param);
226 p = skip_string(p,1);
227
228 pstrcpy_base(p,"B16BBDz", param);
229
230 p = skip_string(p,1);
231 SSVAL(p,0,uLevel);
232 SSVAL(p,2,CLI_BUFFER_SIZE);
233 p += 4;
234 SIVAL(p,0,stype);
235 p += 4;
236
237 p += push_ascii(p, workgroup, sizeof(pstring)-PTR_DIFF(p,param)-1, STR_TERMINATE|STR_UPPER);
238
239 if (cli_api(cli,
240 param, PTR_DIFF(p,param), 8, /* params, length, max */
241 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
242 &rparam, &rprcnt, /* return params, return size */
243 &rdata, &rdrcnt /* return data, return size */
244 )) {
245 int res = rparam? SVAL(rparam,0) : -1;
246
247 if (res == 0 || res == ERRmoredata ||
248 (res != -1 && cli_errno(cli) == 0)) {
249 int i;
250 int converter=SVAL(rparam,2);
251
252 count=SVAL(rparam,4);
253 p = rdata;
254
255 for (i = 0;i < count;i++, p += 26) {
256 char *sname = p;
257 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
258 const char *cmnt = comment_offset?(rdata+comment_offset):"";
259 pstring s1, s2;
260
261 if (comment_offset < 0 || comment_offset > (int)rdrcnt) continue;
262
263 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
264
265 pull_ascii_pstring(s1, sname);
266 pull_ascii_pstring(s2, cmnt);
267 fn(s1, stype, s2, state);
268 }
269 }
270 }
271
272 SAFE_FREE(rparam);
273 SAFE_FREE(rdata);
274
275 if (count < 0) {
276 errno = cli_errno(cli);
277 } else {
278 if (!count) {
279 /* this is a very special case, when the domain master for the
280 work group isn't part of the work group itself, there is something
281 wild going on */
282 errno = ENOENT;
283 }
284 }
285
286 return(count > 0);
287}
288
289
290
291/****************************************************************************
292Send a SamOEMChangePassword command
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(p,1);
317 pstrcpy_base(p, "B516B16", param);
318 p = skip_string(p,1);
319 pstrcpy_base(p,user, param);
320 p = skip_string(p,1);
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, (char *)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 SAFE_FREE(rparam);
373 SAFE_FREE(rdata);
374
375 return (cli->rap_error == 0);
376}
377
378
379/****************************************************************************
380send a qpathinfo call
381****************************************************************************/
382BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
383 time_t *change_time,
384 time_t *access_time,
385 time_t *write_time,
386 SMB_OFF_T *size, uint16 *mode)
387{
388 unsigned int data_len = 0;
389 unsigned int param_len = 0;
390 unsigned int rparam_len, rdata_len;
391 uint16 setup = TRANSACT2_QPATHINFO;
392 pstring param;
393 char *rparam=NULL, *rdata=NULL;
394 int count=8;
395 BOOL ret;
396 time_t (*date_fn)(struct cli_state *, void *);
397 char *p;
398
399 p = param;
400 memset(p, 0, 6);
401 SSVAL(p, 0, SMB_INFO_STANDARD);
402 p += 6;
403 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
404
405 param_len = PTR_DIFF(p, param);
406
407 do {
408 ret = (cli_send_trans(cli, SMBtrans2,
409 NULL, /* Name */
410 -1, 0, /* fid, flags */
411 &setup, 1, 0, /* setup, length, max */
412 param, param_len, 10, /* param, length, max */
413 NULL, data_len, cli->max_xmit /* data, length, max */
414 ) &&
415 cli_receive_trans(cli, SMBtrans2,
416 &rparam, &rparam_len,
417 &rdata, &rdata_len));
418 if (!cli_is_dos_error(cli)) break;
419 if (!ret) {
420 /* we need to work around a Win95 bug - sometimes
421 it gives ERRSRV/ERRerror temprarily */
422 uint8 eclass;
423 uint32 ecode;
424 cli_dos_error(cli, &eclass, &ecode);
425 if (eclass != ERRSRV || ecode != ERRerror) break;
426 smb_msleep(100);
427 }
428 } while (count-- && ret==False);
429
430 if (!ret || !rdata || rdata_len < 22) {
431 return False;
432 }
433
434 if (cli->win95) {
435 date_fn = cli_make_unix_date;
436 } else {
437 date_fn = cli_make_unix_date2;
438 }
439
440 if (change_time) {
441 *change_time = date_fn(cli, rdata+0);
442 }
443 if (access_time) {
444 *access_time = date_fn(cli, rdata+4);
445 }
446 if (write_time) {
447 *write_time = date_fn(cli, rdata+8);
448 }
449 if (size) {
450 *size = IVAL(rdata, 12);
451 }
452 if (mode) {
453 *mode = SVAL(rdata,l1_attrFile);
454 }
455
456 SAFE_FREE(rdata);
457 SAFE_FREE(rparam);
458 return True;
459}
460
461
462/****************************************************************************
463send a setpathinfo call
464****************************************************************************/
465BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
466 time_t create_time,
467 time_t access_time,
468 time_t write_time,
469 time_t change_time,
470 uint16 mode)
471{
472 unsigned int data_len = 0;
473 unsigned int param_len = 0;
474 unsigned int rparam_len, rdata_len;
475 uint16 setup = TRANSACT2_SETPATHINFO;
476 pstring param;
477 pstring data;
478 char *rparam=NULL, *rdata=NULL;
479 int count=8;
480 BOOL ret;
481 char *p;
482
483 memset(param, 0, sizeof(param));
484 memset(data, 0, sizeof(data));
485
486 p = param;
487
488 /* Add the information level */
489 SSVAL(p, 0, SMB_FILE_BASIC_INFORMATION);
490
491 /* Skip reserved */
492 p += 6;
493
494 /* Add the file name */
495 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
496
497 param_len = PTR_DIFF(p, param);
498
499 p = data;
500
501 /*
502 * Add the create, last access, modification, and status change times
503 */
504
505 put_long_date(p, create_time);
506 p += 8;
507
508 put_long_date(p, access_time);
509 p += 8;
510
511 put_long_date(p, write_time);
512 p += 8;
513
514 put_long_date(p, change_time);
515 p += 8;
516
517 /* Add attributes */
518 SIVAL(p, 0, mode);
519 p += 4;
520
521 /* Add padding */
522 SIVAL(p, 0, 0);
523 p += 4;
524
525 data_len = PTR_DIFF(p, data);
526
527 do {
528 ret = (cli_send_trans(cli, SMBtrans2,
529 NULL, /* Name */
530 -1, 0, /* fid, flags */
531 &setup, 1, 0, /* setup, length, max */
532 param, param_len, 10, /* param, length, max */
533 data, data_len, cli->max_xmit /* data, length, max */
534 ) &&
535 cli_receive_trans(cli, SMBtrans2,
536 &rparam, &rparam_len,
537 &rdata, &rdata_len));
538 if (!cli_is_dos_error(cli)) break;
539 if (!ret) {
540 /* we need to work around a Win95 bug - sometimes
541 it gives ERRSRV/ERRerror temprarily */
542 uint8 eclass;
543 uint32 ecode;
544 cli_dos_error(cli, &eclass, &ecode);
545 if (eclass != ERRSRV || ecode != ERRerror) break;
546 smb_msleep(100);
547 }
548 } while (count-- && ret==False);
549
550 if (!ret) {
551 return False;
552 }
553
554 SAFE_FREE(rdata);
555 SAFE_FREE(rparam);
556 return True;
557}
558
559
560/****************************************************************************
561send 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/****************************************************************************
636send a qfileinfo QUERY_FILE_NAME_INFO call
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/****************************************************************************
679send a qfileinfo call
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/****************************************************************************
754send a qpathinfo BASIC_INFO call
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 /* send full paths to dfs root shares */
769
770 if ( cli->dfsroot )
771 pstr_sprintf(path, "\\%s\\%s\\%s", cli->desthost, cli->share, name );
772 else
773 pstrcpy( path, name );
774
775 /* cleanup */
776
777 len = strlen( path );
778 if ( path[len] == '\\' )
779 path[len] = '\0';
780
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);
787
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;
796 }
797
798 if (!cli_receive_trans(cli, SMBtrans2,
799 &rparam, &param_len,
800 &rdata, &data_len)) {
801 return False;
802 }
803
804 if (data_len < 36) {
805 SAFE_FREE(rdata);
806 SAFE_FREE(rparam);
807 return False;
808 }
809
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. */
813
814 *attributes = IVAL( rdata, 32 );
815
816 SAFE_FREE(rparam);
817 SAFE_FREE(rdata);
818
819 return True;
820}
821
822/****************************************************************************
823send a qfileinfo call
824****************************************************************************/
825
826BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
827{
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;
833
834 *poutdata = NULL;
835 *poutlen = 0;
836
837 /* if its a win95 server then fail this - win95 totally screws it
838 up */
839 if (cli->win95)
840 return False;
841
842 param_len = 4;
843
844 memset(param, 0, param_len);
845 SSVAL(param, 0, fnum);
846 SSVAL(param, 2, level);
847
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;
856 }
857
858 if (!cli_receive_trans(cli, SMBtrans2,
859 &rparam, &param_len,
860 &rdata, &data_len)) {
861 return False;
862 }
863
864 *poutdata = (char *)memdup(rdata, data_len);
865 if (!*poutdata) {
866 SAFE_FREE(rdata);
867 SAFE_FREE(rparam);
868 return False;
869 }
870
871 *poutlen = data_len;
872
873 SAFE_FREE(rdata);
874 SAFE_FREE(rparam);
875 return True;
876}
877
878
879
880/****************************************************************************
881send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call
882****************************************************************************/
883NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
884{
885 unsigned int data_len = 0;
886 unsigned int param_len = 0;
887 uint16 setup = TRANSACT2_QPATHINFO;
888 pstring param;
889 char *rparam=NULL, *rdata=NULL;
890 int count=8;
891 char *p;
892 BOOL ret;
893 unsigned int len;
894
895 p = param;
896 memset(p, 0, 6);
897 SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
898 p += 6;
899 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
900
901 param_len = PTR_DIFF(p, param);
902
903 do {
904 ret = (cli_send_trans(cli, SMBtrans2,
905 NULL, /* Name */
906 -1, 0, /* fid, flags */
907 &setup, 1, 0, /* setup, length, max */
908 param, param_len, 10, /* param, length, max */
909 NULL, data_len, cli->max_xmit /* data, length, max */
910 ) &&
911 cli_receive_trans(cli, SMBtrans2,
912 &rparam, &param_len,
913 &rdata, &data_len));
914 if (!ret && cli_is_dos_error(cli)) {
915 /* we need to work around a Win95 bug - sometimes
916 it gives ERRSRV/ERRerror temprarily */
917 uint8 eclass;
918 uint32 ecode;
919 cli_dos_error(cli, &eclass, &ecode);
920 if (eclass != ERRSRV || ecode != ERRerror) break;
921 smb_msleep(100);
922 }
923 } while (count-- && ret==False);
924
925 if (!ret || !rdata || data_len < 4) {
926 return NT_STATUS_UNSUCCESSFUL;
927 }
928
929 len = IVAL(rdata, 0);
930
931 if (len > data_len - 4) {
932 return NT_STATUS_INVALID_NETWORK_RESPONSE;
933 }
934
935 clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
936
937 SAFE_FREE(rdata);
938 SAFE_FREE(rparam);
939
940 return NT_STATUS_OK;
941}
Note: See TracBrowser for help on using the repository browser.