source: branches/samba-3.0/source/libsmb/clirap.c@ 216

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

Update source to 3.0.27a

File size: 27.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 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
26****************************************************************************/
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/****************************************************************************
48 Call a remote api
49****************************************************************************/
50
51BOOL 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)
56{
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 */
63 );
64
65 return (cli_receive_trans(cli,SMBtrans,
66 rparam, rprcnt,
67 rdata, rdrcnt));
68}
69
70/****************************************************************************
71 Perform a NetWkstaUserLogon.
72****************************************************************************/
73
74BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
75{
76 char *rparam = NULL;
77 char *rdata = NULL;
78 char *p;
79 unsigned int rdrcnt,rprcnt;
80 pstring param;
81
82 memset(param, 0, sizeof(param));
83
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;
107
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;
116
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));
124 }
125 }
126
127 SAFE_FREE(rparam);
128 SAFE_FREE(rdata);
129 return (cli->rap_error == 0);
130}
131
132/****************************************************************************
133 Call a NetShareEnum - try and browse available connections on a host.
134****************************************************************************/
135
136int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
137{
138 char *rparam = NULL;
139 char *rdata = NULL;
140 char *p;
141 unsigned int rdrcnt,rprcnt;
142 pstring param;
143 int count = -1;
144
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);
154 /*
155 * Win2k needs a *smaller* buffer than 0xFFFF here -
156 * it returns "out of server memory" with 0xFFFF !!! JRA.
157 */
158 SSVAL(p,2,0xFFE0);
159 p += 4;
160
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 */
166 {
167 int res = rparam? SVAL(rparam,0) : -1;
168
169 if (res == 0 || res == ERRmoredata) {
170 int converter=SVAL(rparam,2);
171 int i;
172
173 count=SVAL(rparam,4);
174 p = rdata;
175
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;
182
183 pull_ascii_pstring(s1, sname);
184 pull_ascii_pstring(s2, cmnt);
185
186 fn(s1, type, s2, state);
187 }
188 } else {
189 DEBUG(4,("NetShareEnum res=%d\n", res));
190 }
191 } else {
192 DEBUG(4,("NetShareEnum failed\n"));
193 }
194
195 SAFE_FREE(rparam);
196 SAFE_FREE(rdata);
197
198 return count;
199}
200
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.
204
205 The callback function takes 4 arguments: the machine name, the server type,
206 the comment and a state pointer.
207****************************************************************************/
208
209BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
210 void (*fn)(const char *, uint32, const char *, void *),
211 void *state)
212{
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;
221
222 errno = 0; /* reset */
223
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);
230
231 pstrcpy_base(p,"B16BBDz", param);
232
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;
239
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;
243 }
244 p += len;
245
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;
253
254 if (res == 0 || res == ERRmoredata ||
255 (res != -1 && cli_errno(cli) == 0)) {
256 int i;
257 int converter=SVAL(rparam,2);
258
259 count=SVAL(rparam,4);
260 p = rdata;
261
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;
267
268 if (comment_offset < 0 || comment_offset > (int)rdrcnt) continue;
269
270 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
271
272 pull_ascii_pstring(s1, sname);
273 pull_ascii_pstring(s2, cmnt);
274 fn(s1, stype, s2, state);
275 }
276 }
277 }
278
279 SAFE_FREE(rparam);
280 SAFE_FREE(rdata);
281
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;
290 }
291 }
292
293 return(count > 0);
294}
295
296/****************************************************************************
297 Send a SamOEMChangePassword command.
298****************************************************************************/
299
300BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
301 const char *old_password)
302{
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;
313
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;
317 }
318
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;
329
330 param_len = PTR_DIFF(p,param);
331
332 /*
333 * Get the Lanman hash of the old password, we
334 * use this as the key to make_oem_passwd_hash().
335 */
336 E_deshash(old_password, old_pw_hash);
337
338 encode_pw_buffer(data, new_password, STR_ASCII);
339
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);
345
346 /*
347 * Now place the old password hash in the data.
348 */
349 E_deshash(new_password, new_pw_hash);
350
351 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
352
353 data_len = 532;
354
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;
365 }
366
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;
373 }
374
375 if (rparam) {
376 cli->rap_error = SVAL(rparam,0);
377 }
378
379 SAFE_FREE(rparam);
380 SAFE_FREE(rdata);
381
382 return (cli->rap_error == 0);
383}
384
385/****************************************************************************
386 Send a qpathinfo call.
387****************************************************************************/
388
389BOOL 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)
394{
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;
405
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);
411
412 param_len = PTR_DIFF(p, param);
413
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);
434 }
435 } while (count-- && ret==False);
436
437 if (!ret || !rdata || rdata_len < 22) {
438 return False;
439 }
440
441 if (cli->win95) {
442 date_fn = cli_make_unix_date;
443 } else {
444 date_fn = cli_make_unix_date2;
445 }
446
447 if (change_time) {
448 *change_time = date_fn(cli, rdata+0);
449 }
450 if (access_time) {
451 *access_time = date_fn(cli, rdata+4);
452 }
453 if (write_time) {
454 *write_time = date_fn(cli, rdata+8);
455 }
456 if (size) {
457 *size = IVAL(rdata, 12);
458 }
459 if (mode) {
460 *mode = SVAL(rdata,l1_attrFile);
461 }
462
463 SAFE_FREE(rdata);
464 SAFE_FREE(rparam);
465 return True;
466}
467
468/****************************************************************************
469 Send a setpathinfo call.
470****************************************************************************/
471
472BOOL 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)
478{
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;
489
490 memset(param, 0, sizeof(param));
491 memset(data, 0, sizeof(data));
492
493 p = param;
494
495 /* Add the information level */
496 SSVAL(p, 0, SMB_FILE_BASIC_INFORMATION);
497
498 /* Skip reserved */
499 p += 6;
500
501 /* Add the file name */
502 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
503
504 param_len = PTR_DIFF(p, param);
505
506 p = data;
507
508 /*
509 * Add the create, last access, modification, and status change times
510 */
511
512 put_long_date(p, create_time);
513 p += 8;
514
515 put_long_date(p, access_time);
516 p += 8;
517
518 put_long_date(p, write_time);
519 p += 8;
520
521 put_long_date(p, change_time);
522 p += 8;
523
524 /* Add attributes */
525 SIVAL(p, 0, mode);
526 p += 4;
527
528 /* Add padding */
529 SIVAL(p, 0, 0);
530 p += 4;
531
532 data_len = PTR_DIFF(p, data);
533
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);
554 }
555 } while (count-- && ret==False);
556
557 if (!ret) {
558 return False;
559 }
560
561 SAFE_FREE(rdata);
562 SAFE_FREE(rparam);
563 return True;
564}
565
566/****************************************************************************
567 Send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level.
568****************************************************************************/
569
570BOOL 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)
577{
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;
584
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);
590
591 param_len = PTR_DIFF(p, param);
592
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;
601 }
602
603 if (!cli_receive_trans(cli, SMBtrans2,
604 &rparam, &param_len,
605 &rdata, &data_len)) {
606 return False;
607 }
608
609 if (!rdata || data_len < 22) {
610 return False;
611 }
612
613 if (create_time) {
614 *create_time = interpret_long_date(rdata+0);
615 }
616 if (access_time) {
617 *access_time = interpret_long_date(rdata+8);
618 }
619 if (write_time) {
620 *write_time = interpret_long_date(rdata+16);
621 }
622 if (change_time) {
623 *change_time = interpret_long_date(rdata+24);
624 }
625 if (mode) {
626 *mode = SVAL(rdata, 32);
627 }
628 if (size) {
629 *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
630 }
631 if (ino) {
632 *ino = IVAL(rdata, 64);
633 }
634
635 SAFE_FREE(rdata);
636 SAFE_FREE(rparam);
637 return True;
638}
639
640/****************************************************************************
641 Send a qfileinfo QUERY_FILE_NAME_INFO call.
642****************************************************************************/
643
644BOOL cli_qfilename(struct cli_state *cli, int fnum,
645 pstring name)
646{
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;
652
653 param_len = 4;
654 memset(param, 0, param_len);
655 SSVAL(param, 0, fnum);
656 SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
657
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;
666 }
667
668 if (!cli_receive_trans(cli, SMBtrans2,
669 &rparam, &param_len,
670 &rdata, &data_len)) {
671 return False;
672 }
673
674 if (!rdata || data_len < 4) {
675 return False;
676 }
677
678 clistr_pull(cli, name, rdata+4, sizeof(pstring), IVAL(rdata, 0), STR_UNICODE);
679
680 return True;
681}
682
683/****************************************************************************
684 Send a qfileinfo call.
685****************************************************************************/
686
687BOOL 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)
694{
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;
700
701 /* if its a win95 server then fail this - win95 totally screws it
702 up */
703 if (cli->win95) return False;
704
705 param_len = 4;
706
707 memset(param, 0, param_len);
708 SSVAL(param, 0, fnum);
709 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
710
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;
719 }
720
721 if (!cli_receive_trans(cli, SMBtrans2,
722 &rparam, &param_len,
723 &rdata, &data_len)) {
724 return False;
725 }
726
727 if (!rdata || data_len < 68) {
728 return False;
729 }
730
731 if (create_time) {
732 *create_time = interpret_long_date(rdata+0);
733 }
734 if (access_time) {
735 *access_time = interpret_long_date(rdata+8);
736 }
737 if (write_time) {
738 *write_time = interpret_long_date(rdata+16);
739 }
740 if (change_time) {
741 *change_time = interpret_long_date(rdata+24);
742 }
743 if (mode) {
744 *mode = SVAL(rdata, 32);
745 }
746 if (size) {
747 *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
748 }
749 if (ino) {
750 *ino = IVAL(rdata, 64);
751 }
752
753 SAFE_FREE(rdata);
754 SAFE_FREE(rparam);
755 return True;
756}
757
758/****************************************************************************
759 Send a qpathinfo BASIC_INFO call.
760****************************************************************************/
761
762BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name,
763 SMB_STRUCT_STAT *sbuf, uint32 *attributes )
764{
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;
773
774 pstrcpy( path, name );
775 /* cleanup */
776
777 len = strlen( path );
778 if ( path[len-1] == '\\' || path[len-1] == '/')
779 path[len-1] = '\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/****************************************************************************
823 Send 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 Send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call.
880****************************************************************************/
881
882NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
883{
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;
893
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);
899
900 param_len = PTR_DIFF(p, param);
901
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);
921 }
922 } while (count-- && ret==False);
923
924 if (!ret || !rdata || data_len < 4) {
925 return NT_STATUS_UNSUCCESSFUL;
926 }
927
928 len = IVAL(rdata, 0);
929
930 if (len > data_len - 4) {
931 return NT_STATUS_INVALID_NETWORK_RESPONSE;
932 }
933
934 clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
935
936 SAFE_FREE(rdata);
937 SAFE_FREE(rparam);
938
939 return NT_STATUS_OK;
940}
Note: See TracBrowser for help on using the repository browser.