1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB client generic functions
5
6 Copyright (C) Andrew Tridgell 1994-1998
7
8 Copyright (C) 2011-2021
9 Free Software Foundation, Inc.
10
11 This file is part of the Midnight Commander.
12
13 The Midnight Commander is free software: you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation, either version 3 of the License,
16 or (at your option) any later version.
17
18 The Midnight Commander is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 */
26
27 #define NO_SYSLOG
28
29 #include "includes.h"
30 #include "trans2.h"
31
32
33 extern int DEBUGLEVEL;
34 extern pstring user_socket_options;
35
36 /*
37 * Change the port number used to call on
38 */
39 int
cli_set_port(struct cli_state * cli,int port)40 cli_set_port (struct cli_state *cli, int port)
41 {
42 if (port > 0)
43 cli->port = port;
44
45 return cli->port;
46 }
47
48 /****************************************************************************
49 recv an smb
50 ****************************************************************************/
51 static BOOL
cli_receive_smb(struct cli_state * cli)52 cli_receive_smb (struct cli_state *cli)
53 {
54 return client_receive_smb (cli->fd, cli->inbuf, cli->timeout);
55 }
56
57 /****************************************************************************
58 send an smb to a fd and re-establish if necessary
59 ****************************************************************************/
60 static BOOL
cli_send_smb(struct cli_state * cli)61 cli_send_smb (struct cli_state *cli)
62 {
63 size_t len;
64 size_t nwritten = 0;
65 ssize_t ret;
66 BOOL reestablished = False;
67
68 len = smb_len (cli->outbuf) + 4;
69
70 while (nwritten < len)
71 {
72 ret = write_socket (cli->fd, cli->outbuf + nwritten, len - nwritten);
73 if (ret <= 0 && errno == EPIPE && !reestablished)
74 {
75 if (cli_reestablish_connection (cli))
76 {
77 reestablished = True;
78 nwritten = 0;
79 continue;
80 }
81 }
82 if (ret <= 0)
83 {
84 DEBUG (0, ("Error writing %d bytes to client. %d. Exiting\n", (int) len, (int) ret));
85 close_sockets ();
86 exit (1);
87 }
88 nwritten += ret;
89 }
90
91 return True;
92 }
93
94 /*****************************************************
95 RAP error codes - a small start but will be extended.
96 *******************************************************/
97
98 struct
99 {
100 int err;
101 const char *message;
102 } const rap_errmap[] = {
103 {5, "User has insufficient privilege"},
104 {86, "The specified password is invalid"},
105 {2226, "Operation only permitted on a Primary Domain Controller"},
106 {2242, "The password of this user has expired."},
107 {2243, "The password of this user cannot change."},
108 {2244, "This password cannot be used now (password history conflict)."},
109 {2245, "The password is shorter than required."},
110 {2246, "The password of this user is too recent to change."},
111 {0, NULL}
112 };
113
114 /****************************************************************************
115 return a description of an SMB error
116 ****************************************************************************/
117 static char *
cli_smb_errstr(struct cli_state * cli)118 cli_smb_errstr (struct cli_state *cli)
119 {
120 return smb_errstr (cli->inbuf);
121 }
122
123 /******************************************************
124 Return an error message - either an SMB error or a RAP
125 error.
126 *******************************************************/
127
128 char *
cli_errstr(struct cli_state * cli)129 cli_errstr (struct cli_state *cli)
130 {
131 static fstring error_message;
132 uint8 errclass;
133 uint32 errnum;
134 uint32 nt_rpc_error;
135 int i;
136
137 /*
138 * Errors are of three kinds - smb errors,
139 * dealt with by cli_smb_errstr, NT errors,
140 * whose code is in cli.nt_error, and rap
141 * errors, whose error code is in cli.rap_error.
142 */
143
144 cli_error (cli, &errclass, &errnum, &nt_rpc_error);
145
146 if (errclass != 0)
147 {
148 return cli_smb_errstr (cli);
149 }
150
151 /*
152 * Was it an NT error ?
153 */
154
155 if (nt_rpc_error)
156 {
157 const char *nt_msg = get_nt_error_msg (nt_rpc_error);
158
159 if (nt_msg == NULL)
160 {
161 slprintf (error_message, sizeof (fstring) - 1, "NT code %d", nt_rpc_error);
162 }
163 else
164 {
165 fstrcpy (error_message, nt_msg);
166 }
167
168 return error_message;
169 }
170
171 /*
172 * Must have been a rap error.
173 */
174
175 slprintf (error_message, sizeof (error_message) - 1, "code %d", cli->rap_error);
176
177 for (i = 0; rap_errmap[i].message != NULL; i++)
178 {
179 if (rap_errmap[i].err == cli->rap_error)
180 {
181 fstrcpy (error_message, rap_errmap[i].message);
182 break;
183 }
184 }
185
186 return error_message;
187 }
188
189 /****************************************************************************
190 setup basics in a outgoing packet
191 ****************************************************************************/
192 static void
cli_setup_packet(struct cli_state * cli)193 cli_setup_packet (struct cli_state *cli)
194 {
195 cli->rap_error = 0;
196 cli->nt_error = 0;
197 SSVAL (cli->outbuf, smb_pid, cli->pid);
198 SSVAL (cli->outbuf, smb_uid, cli->vuid);
199 SSVAL (cli->outbuf, smb_mid, cli->mid);
200 if (cli->protocol > PROTOCOL_CORE)
201 {
202 SCVAL (cli->outbuf, smb_flg, 0x8);
203 SSVAL (cli->outbuf, smb_flg2, 0x1);
204 }
205 }
206
207 #if 0
208 /*****************************************************************************
209 Convert a character pointer in a cli_call_api() response to a form we can use.
210 This function contains code to prevent core dumps if the server returns
211 invalid data.
212 *****************************************************************************/
213 static char *
214 fix_char_ptr (unsigned int datap, unsigned int converter, char *rdata, int rdrcnt)
215 {
216 if (datap == 0)
217 { /* turn NULL pointers into zero length strings */
218 return "";
219 }
220 else
221 {
222 unsigned int offset = datap - converter;
223
224 if (offset >= rdrcnt)
225 {
226 DEBUG (1, ("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
227 datap, converter, rdrcnt));
228 return "<ERROR>";
229 }
230 else
231 {
232 return &rdata[offset];
233 }
234 }
235 }
236 #endif /* 0 */
237 /****************************************************************************
238 send a SMB trans or trans2 request
239 ****************************************************************************/
240 static BOOL
cli_send_trans(struct cli_state * cli,int trans,const char * name,int pipe_name_len,int fid,int flags,uint16 * setup,int lsetup,int msetup,char * param,int lparam,int mparam,char * data,int ldata,int mdata)241 cli_send_trans (struct cli_state *cli, int trans,
242 const char *name, int pipe_name_len,
243 int fid, int flags,
244 uint16 * setup, int lsetup, int msetup,
245 char *param, int lparam, int mparam, char *data, int ldata, int mdata)
246 {
247 int i;
248 int this_ldata, this_lparam;
249 int tot_data = 0, tot_param = 0;
250 char *outdata, *outparam;
251 char *p;
252
253 this_lparam = MIN (lparam, cli->max_xmit - (500 + lsetup * 2)); /* hack */
254 this_ldata = MIN (ldata, cli->max_xmit - (500 + lsetup * 2 + this_lparam));
255
256 memset (cli->outbuf, '\0', smb_size);
257 set_message (cli->outbuf, 14 + lsetup, 0, True);
258 CVAL (cli->outbuf, smb_com) = trans;
259 SSVAL (cli->outbuf, smb_tid, cli->cnum);
260 cli_setup_packet (cli);
261
262 outparam = smb_buf (cli->outbuf) + (trans == SMBtrans ? pipe_name_len + 1 : 3);
263 outdata = outparam + this_lparam;
264
265 /* primary request */
266 SSVAL (cli->outbuf, smb_tpscnt, lparam); /* tpscnt */
267 SSVAL (cli->outbuf, smb_tdscnt, ldata); /* tdscnt */
268 SSVAL (cli->outbuf, smb_mprcnt, mparam); /* mprcnt */
269 SSVAL (cli->outbuf, smb_mdrcnt, mdata); /* mdrcnt */
270 SCVAL (cli->outbuf, smb_msrcnt, msetup); /* msrcnt */
271 SSVAL (cli->outbuf, smb_flags, flags); /* flags */
272 SIVAL (cli->outbuf, smb_timeout, 0); /* timeout */
273 SSVAL (cli->outbuf, smb_pscnt, this_lparam); /* pscnt */
274 SSVAL (cli->outbuf, smb_psoff, smb_offset (outparam, cli->outbuf)); /* psoff */
275 SSVAL (cli->outbuf, smb_dscnt, this_ldata); /* dscnt */
276 SSVAL (cli->outbuf, smb_dsoff, smb_offset (outdata, cli->outbuf)); /* dsoff */
277 SCVAL (cli->outbuf, smb_suwcnt, lsetup); /* suwcnt */
278 for (i = 0; i < lsetup; i++) /* setup[] */
279 SSVAL (cli->outbuf, smb_setup + i * 2, setup[i]);
280 p = smb_buf (cli->outbuf);
281 if (trans == SMBtrans)
282 {
283 memcpy (p, name, pipe_name_len + 1); /* name[] */
284 }
285 else
286 {
287 *p++ = 0; /* put in a null smb_name */
288 *p++ = 'D';
289 *p++ = ' '; /* observed in OS/2 */
290 }
291 if (this_lparam) /* param[] */
292 memcpy (outparam, param, this_lparam);
293 if (this_ldata) /* data[] */
294 memcpy (outdata, data, this_ldata);
295 set_message (cli->outbuf, 14 + lsetup, /* wcnt, bcc */
296 PTR_DIFF (outdata + this_ldata, smb_buf (cli->outbuf)), False);
297
298 show_msg (cli->outbuf);
299 cli_send_smb (cli);
300
301 if (this_ldata < ldata || this_lparam < lparam)
302 {
303 /* receive interim response */
304 if (!cli_receive_smb (cli) || CVAL (cli->inbuf, smb_rcls) != 0)
305 {
306 return (False);
307 }
308
309 tot_data = this_ldata;
310 tot_param = this_lparam;
311
312 while (tot_data < ldata || tot_param < lparam)
313 {
314 this_lparam = MIN (lparam - tot_param, cli->max_xmit - 500); /* hack */
315 this_ldata = MIN (ldata - tot_data, cli->max_xmit - (500 + this_lparam));
316
317 set_message (cli->outbuf, trans == SMBtrans ? 8 : 9, 0, True);
318 CVAL (cli->outbuf, smb_com) = trans == SMBtrans ? SMBtranss : SMBtranss2;
319
320 outparam = smb_buf (cli->outbuf);
321 outdata = outparam + this_lparam;
322
323 /* secondary request */
324 SSVAL (cli->outbuf, smb_tpscnt, lparam); /* tpscnt */
325 SSVAL (cli->outbuf, smb_tdscnt, ldata); /* tdscnt */
326 SSVAL (cli->outbuf, smb_spscnt, this_lparam); /* pscnt */
327 SSVAL (cli->outbuf, smb_spsoff, smb_offset (outparam, cli->outbuf)); /* psoff */
328 SSVAL (cli->outbuf, smb_spsdisp, tot_param); /* psdisp */
329 SSVAL (cli->outbuf, smb_sdscnt, this_ldata); /* dscnt */
330 SSVAL (cli->outbuf, smb_sdsoff, smb_offset (outdata, cli->outbuf)); /* dsoff */
331 SSVAL (cli->outbuf, smb_sdsdisp, tot_data); /* dsdisp */
332 if (trans == SMBtrans2)
333 SSVALS (cli->outbuf, smb_sfid, fid); /* fid */
334 if (this_lparam) /* param[] */
335 memcpy (outparam, param, this_lparam);
336 if (this_ldata) /* data[] */
337 memcpy (outdata, data, this_ldata);
338 set_message (cli->outbuf, trans == SMBtrans ? 8 : 9, /* wcnt, bcc */
339 PTR_DIFF (outdata + this_ldata, smb_buf (cli->outbuf)), False);
340
341 show_msg (cli->outbuf);
342 cli_send_smb (cli);
343
344 tot_data += this_ldata;
345 tot_param += this_lparam;
346 }
347 }
348
349 return (True);
350 }
351
352
353 /****************************************************************************
354 receive a SMB trans or trans2 response allocating the necessary memory
355 ****************************************************************************/
356 static BOOL
cli_receive_trans(struct cli_state * cli,int trans,char ** param,int * param_len,char ** data,int * data_len)357 cli_receive_trans (struct cli_state *cli, int trans,
358 char **param, int *param_len, char **data, int *data_len)
359 {
360 int total_data = 0;
361 int total_param = 0;
362 int this_data, this_param;
363 uint8 eclass;
364 uint32 ecode;
365
366 *data_len = *param_len = 0;
367
368 if (!cli_receive_smb (cli))
369 return False;
370
371 show_msg (cli->inbuf);
372
373 /* sanity check */
374 if (CVAL (cli->inbuf, smb_com) != trans)
375 {
376 DEBUG (0, ("Expected %s response, got command 0x%02x\n",
377 trans == SMBtrans ? "SMBtrans" : "SMBtrans2", CVAL (cli->inbuf, smb_com)));
378 return (False);
379 }
380
381 /*
382 * An NT RPC pipe call can return ERRDOS, ERRmoredata
383 * to a trans call. This is not an error and should not
384 * be treated as such.
385 */
386
387 if (cli_error (cli, &eclass, &ecode, NULL))
388 {
389 if (cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata))
390 return (False);
391 }
392
393 /* parse out the lengths */
394 total_data = SVAL (cli->inbuf, smb_tdrcnt);
395 total_param = SVAL (cli->inbuf, smb_tprcnt);
396
397 /* allocate it */
398 *data = Realloc (*data, total_data);
399 *param = Realloc (*param, total_param);
400
401 while (1)
402 {
403 this_data = SVAL (cli->inbuf, smb_drcnt);
404 this_param = SVAL (cli->inbuf, smb_prcnt);
405
406 if (this_data + *data_len > total_data || this_param + *param_len > total_param)
407 {
408 DEBUG (1, ("Data overflow in cli_receive_trans\n"));
409 return False;
410 }
411
412 if (this_data)
413 memcpy (*data + SVAL (cli->inbuf, smb_drdisp),
414 smb_base (cli->inbuf) + SVAL (cli->inbuf, smb_droff), this_data);
415 if (this_param)
416 memcpy (*param + SVAL (cli->inbuf, smb_prdisp),
417 smb_base (cli->inbuf) + SVAL (cli->inbuf, smb_proff), this_param);
418 *data_len += this_data;
419 *param_len += this_param;
420
421 /* parse out the total lengths again - they can shrink! */
422 total_data = SVAL (cli->inbuf, smb_tdrcnt);
423 total_param = SVAL (cli->inbuf, smb_tprcnt);
424
425 if (total_data <= *data_len && total_param <= *param_len)
426 break;
427
428 if (!cli_receive_smb (cli))
429 return False;
430
431 show_msg (cli->inbuf);
432
433 /* sanity check */
434 if (CVAL (cli->inbuf, smb_com) != trans)
435 {
436 DEBUG (0, ("Expected %s response, got command 0x%02x\n",
437 trans == SMBtrans ? "SMBtrans" : "SMBtrans2", CVAL (cli->inbuf, smb_com)));
438 return (False);
439 }
440 if (cli_error (cli, &eclass, &ecode, NULL))
441 {
442 if (cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata))
443 return (False);
444 }
445 }
446
447 return (True);
448 }
449
450 #if 0
451 /****************************************************************************
452 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
453 ****************************************************************************/
454 BOOL
455 cli_api_pipe (struct cli_state * cli, char *pipe_name, int pipe_name_len,
456 uint16 * setup, uint32 setup_count, uint32 max_setup_count,
457 char *params, uint32 param_count, uint32 max_param_count,
458 char *data, uint32 data_count, uint32 max_data_count,
459 char **rparam, uint32 * rparam_count, char **rdata, uint32 * rdata_count)
460 {
461 if (pipe_name_len == 0)
462 pipe_name_len = strlen (pipe_name);
463
464 cli_send_trans (cli, SMBtrans, pipe_name, pipe_name_len, 0, 0, /* fid, flags */
465 setup, setup_count, max_setup_count,
466 params, param_count, max_param_count, data, data_count, max_data_count);
467
468 return (cli_receive_trans (cli, SMBtrans,
469 rparam, (int *) rparam_count, rdata, (int *) rdata_count));
470 }
471 #endif /*0 */
472
473 /****************************************************************************
474 call a remote api
475 ****************************************************************************/
476 BOOL
cli_api(struct cli_state * cli,char * param,int prcnt,int mprcnt,char * data,int drcnt,int mdrcnt,char ** rparam,int * rprcnt,char ** rdata,int * rdrcnt)477 cli_api (struct cli_state *cli,
478 char *param, int prcnt, int mprcnt,
479 char *data, int drcnt, int mdrcnt, char **rparam, int *rprcnt, char **rdata, int *rdrcnt)
480 {
481 cli_send_trans (cli, SMBtrans, PIPE_LANMAN, strlen (PIPE_LANMAN), /* Name, length */
482 0, 0, /* fid, flags */
483 NULL, 0, 0, /* Setup, length, max */
484 param, prcnt, mprcnt, /* Params, length, max */
485 data, drcnt, mdrcnt /* Data, length, max */
486 );
487
488 return (cli_receive_trans (cli, SMBtrans, rparam, rprcnt, rdata, rdrcnt));
489 }
490
491 #if 0
492 /****************************************************************************
493 perform a NetWkstaUserLogon
494 ****************************************************************************/
495 BOOL
496 cli_NetWkstaUserLogon (struct cli_state * cli, char *user, char *workstation)
497 {
498 char *rparam = NULL;
499 char *rdata = NULL;
500 char *p;
501 int rdrcnt, rprcnt;
502 pstring param;
503
504 memset (param, 0, sizeof (param));
505
506 /* send a SMBtrans command with api NetWkstaUserLogon */
507 p = param;
508 SSVAL (p, 0, 132); /* api number */
509 p += 2;
510 pstrcpy (p, "OOWb54WrLh");
511 p = skip_string (p, 1);
512 pstrcpy (p, "WB21BWDWWDDDDDDDzzzD");
513 p = skip_string (p, 1);
514 SSVAL (p, 0, 1);
515 p += 2;
516 pstrcpy (p, user);
517 strupper (p);
518 p += 21;
519 p++;
520 p += 15;
521 p++;
522 pstrcpy (p, workstation);
523 strupper (p);
524 p += 16;
525 SSVAL (p, 0, CLI_BUFFER_SIZE);
526 p += 2;
527 SSVAL (p, 0, CLI_BUFFER_SIZE);
528 p += 2;
529
530 if (cli_api (cli, param, PTR_DIFF (p, param), 1024, /* param, length, max */
531 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
532 &rparam, &rprcnt, /* return params, return size */
533 &rdata, &rdrcnt /* return data, return size */
534 ))
535 {
536 cli->rap_error = SVAL (rparam, 0);
537 p = rdata;
538
539 if (cli->rap_error == 0)
540 {
541 DEBUG (4, ("NetWkstaUserLogon success\n"));
542 cli->privileges = SVAL (p, 24);
543 fstrcpy (cli->eff_name, p + 2);
544 }
545 else
546 {
547 DEBUG (1, ("NetwkstaUserLogon gave error %d\n", cli->rap_error));
548 }
549 }
550
551 if (rparam)
552 free (rparam);
553 if (rdata)
554 free (rdata);
555 return (cli->rap_error == 0);
556 }
557 #endif /*0 */
558
559 /****************************************************************************
560 call a NetShareEnum - try and browse available connections on a host
561 ****************************************************************************/
562 int
cli_RNetShareEnum(struct cli_state * cli,void (* fn)(const char *,uint32,const char *,void *),void * state)563 cli_RNetShareEnum (struct cli_state *cli, void (*fn) (const char *, uint32, const char *, void *),
564 void *state)
565 {
566 char *rparam = NULL;
567 char *rdata = NULL;
568 char *p;
569 int rdrcnt, rprcnt;
570 pstring param;
571 int count = -1;
572
573 /* now send a SMBtrans command with api RNetShareEnum */
574 p = param;
575 SSVAL (p, 0, 0); /* api number */
576 p += 2;
577 pstrcpy (p, "WrLeh");
578 p = skip_string (p, 1);
579 pstrcpy (p, "B13BWz");
580 p = skip_string (p, 1);
581 SSVAL (p, 0, 1);
582 /*
583 * Win2k needs a *smaller* buffer than 0xFFFF here -
584 * it returns "out of server memory" with 0xFFFF !!! JRA.
585 */
586 SSVAL (p, 2, 0xFFE0);
587 p += 4;
588
589 if (cli_api (cli, param, PTR_DIFF (p, param), 1024, /* Param, length, maxlen */
590 NULL, 0, 0xFFE0, /* data, length, maxlen - Win2k needs a small buffer here too ! */
591 &rparam, &rprcnt, /* return params, length */
592 &rdata, &rdrcnt)) /* return data, length */
593 {
594 int res = SVAL (rparam, 0);
595 int converter = SVAL (rparam, 2);
596 int i;
597
598 if (res == 0 || res == ERRmoredata)
599 {
600 count = SVAL (rparam, 4);
601 p = rdata;
602
603 for (i = 0; i < count; i++, p += 20)
604 {
605 char *sname = p;
606 int type = SVAL (p, 14);
607 int comment_offset = IVAL (p, 16) & 0xFFFF;
608 const char *cmnt = comment_offset ? (rdata + comment_offset - converter) : "";
609 fn (sname, type, cmnt, state);
610 }
611 }
612 else
613 {
614 DEBUG (4, ("NetShareEnum res=%d\n", res));
615 }
616 }
617 else
618 {
619 DEBUG (4, ("NetShareEnum failed\n"));
620 }
621
622 if (rparam)
623 free (rparam);
624 if (rdata)
625 free (rdata);
626
627 return count;
628 }
629
630
631 /****************************************************************************
632 call a NetServerEnum for the specified workgroup and servertype mask.
633 This function then calls the specified callback function for each name returned.
634
635 The callback function takes 3 arguments: the machine name, the server type and
636 the comment.
637 ****************************************************************************/
638 BOOL
cli_NetServerEnum(struct cli_state * cli,char * workgroup,uint32 stype,void (* fn)(const char *,uint32,const char *,void *),void * state)639 cli_NetServerEnum (struct cli_state * cli, char *workgroup, uint32 stype,
640 void (*fn) (const char *, uint32, const char *, void *), void *state)
641 {
642 char *rparam = NULL;
643 char *rdata = NULL;
644 int rdrcnt, rprcnt;
645 char *p;
646 pstring param;
647 int uLevel = 1;
648 int count = -1;
649
650 /* send a SMBtrans command with api NetServerEnum */
651 p = param;
652 SSVAL (p, 0, 0x68); /* api number */
653 p += 2;
654 pstrcpy (p, "WrLehDz");
655 p = skip_string (p, 1);
656
657 pstrcpy (p, "B16BBDz");
658
659 p = skip_string (p, 1);
660 SSVAL (p, 0, uLevel);
661 SSVAL (p, 2, CLI_BUFFER_SIZE);
662 p += 4;
663 SIVAL (p, 0, stype);
664 p += 4;
665
666 pstrcpy (p, workgroup);
667 p = skip_string (p, 1);
668
669 if (cli_api (cli, param, PTR_DIFF (p, param), 8, /* params, length, max */
670 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
671 &rparam, &rprcnt, /* return params, return size */
672 &rdata, &rdrcnt /* return data, return size */
673 ))
674 {
675 int res = SVAL (rparam, 0);
676 int converter = SVAL (rparam, 2);
677 int i;
678
679 if (res == 0 || res == ERRmoredata)
680 {
681 count = SVAL (rparam, 4);
682 p = rdata;
683
684 for (i = 0; i < count; i++, p += 26)
685 {
686 char *sname = p;
687 int comment_offset = (IVAL (p, 22) & 0xFFFF) - converter;
688 const char *cmnt = comment_offset ? (rdata + comment_offset) : "";
689 if (comment_offset < 0 || comment_offset > rdrcnt)
690 continue;
691
692 stype = IVAL (p, 18) & ~SV_TYPE_LOCAL_LIST_ONLY;
693
694 fn (sname, stype, cmnt, state);
695 }
696 }
697 }
698
699 if (rparam)
700 free (rparam);
701 if (rdata)
702 free (rdata);
703
704 return (count > 0);
705 }
706
707
708
709
710 static struct
711 {
712 int prot;
713 const char *name;
714 }
715 const prots[] = {
716 {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
717 {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},
718 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"},
719 {PROTOCOL_LANMAN1, "LANMAN1.0"},
720 {PROTOCOL_LANMAN2, "LM1.2X002"},
721 {PROTOCOL_LANMAN2, "Samba"},
722 {PROTOCOL_NT1, "NT LANMAN 1.0"},
723 {PROTOCOL_NT1, "NT LM 0.12"},
724 {-1, NULL}
725 };
726
727
728 /****************************************************************************
729 send a session setup
730 ****************************************************************************/
731 BOOL
cli_session_setup(struct cli_state * cli,char * user,char * pass,int passlen,char * ntpass,int ntpasslen,char * workgroup)732 cli_session_setup (struct cli_state *cli,
733 char *user,
734 char *pass, int passlen, char *ntpass, int ntpasslen, char *workgroup)
735 {
736 char *p;
737 fstring pword, ntpword;
738
739 if (cli->protocol < PROTOCOL_LANMAN1)
740 return True;
741
742 if ((size_t) passlen > sizeof (pword) - 1 || (size_t) ntpasslen > sizeof (ntpword) - 1)
743 {
744 return False;
745 }
746
747 if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0'))
748 {
749 /* Null session connect. */
750 pword[0] = '\0';
751 ntpword[0] = '\0';
752 }
753 else
754 {
755 if ((cli->sec_mode & 2) && passlen != 24)
756 {
757 passlen = 24;
758 ntpasslen = 24;
759 SMBencrypt ((uchar *) pass, (uchar *) cli->cryptkey, (uchar *) pword);
760 SMBNTencrypt ((uchar *) ntpass, (uchar *) cli->cryptkey, (uchar *) ntpword);
761 }
762 else
763 {
764 fstrcpy (pword, pass);
765 fstrcpy (ntpword, "");
766 ntpasslen = 0;
767 }
768 }
769
770 /* if in share level security then don't send a password now */
771 if (!(cli->sec_mode & 1))
772 {
773 fstrcpy (pword, "");
774 passlen = 1;
775 fstrcpy (ntpword, "");
776 ntpasslen = 1;
777 }
778
779 /* send a session setup command */
780 memset (cli->outbuf, '\0', smb_size);
781
782 if (cli->protocol < PROTOCOL_NT1)
783 {
784 set_message (cli->outbuf, 10, 1 + strlen (user) + passlen, True);
785 CVAL (cli->outbuf, smb_com) = SMBsesssetupX;
786 cli_setup_packet (cli);
787
788 CVAL (cli->outbuf, smb_vwv0) = 0xFF;
789 SSVAL (cli->outbuf, smb_vwv2, cli->max_xmit);
790 SSVAL (cli->outbuf, smb_vwv3, 2);
791 SSVAL (cli->outbuf, smb_vwv4, 1);
792 SIVAL (cli->outbuf, smb_vwv5, cli->sesskey);
793 SSVAL (cli->outbuf, smb_vwv7, passlen);
794 p = smb_buf (cli->outbuf);
795 memcpy (p, pword, passlen);
796 p += passlen;
797 pstrcpy (p, user);
798 strupper (p);
799 unix_to_dos (p, True);
800 }
801 else
802 {
803 set_message (cli->outbuf, 13, 0, True);
804 CVAL (cli->outbuf, smb_com) = SMBsesssetupX;
805 cli_setup_packet (cli);
806
807 CVAL (cli->outbuf, smb_vwv0) = 0xFF;
808 SSVAL (cli->outbuf, smb_vwv2, CLI_BUFFER_SIZE);
809 SSVAL (cli->outbuf, smb_vwv3, 2);
810 SSVAL (cli->outbuf, smb_vwv4, cli->pid);
811 SIVAL (cli->outbuf, smb_vwv5, cli->sesskey);
812 SSVAL (cli->outbuf, smb_vwv7, passlen);
813 SSVAL (cli->outbuf, smb_vwv8, ntpasslen);
814 SSVAL (cli->outbuf, smb_vwv11, 0);
815 p = smb_buf (cli->outbuf);
816 memcpy (p, pword, passlen);
817 p += SVAL (cli->outbuf, smb_vwv7);
818 memcpy (p, ntpword, ntpasslen);
819 p += SVAL (cli->outbuf, smb_vwv8);
820 pstrcpy (p, user);
821 strupper (p);
822 unix_to_dos (p, True);
823 p = skip_string (p, 1);
824 pstrcpy (p, workgroup);
825 strupper (p);
826 p = skip_string (p, 1);
827 pstrcpy (p, "Unix");
828 p = skip_string (p, 1);
829 pstrcpy (p, "Samba");
830 p = skip_string (p, 1);
831 set_message (cli->outbuf, 13, PTR_DIFF (p, smb_buf (cli->outbuf)), False);
832 }
833
834 cli_send_smb (cli);
835 if (!cli_receive_smb (cli))
836 return False;
837
838 show_msg (cli->inbuf);
839
840 if (CVAL (cli->inbuf, smb_rcls) != 0)
841 {
842 return False;
843 }
844
845 /* use the returned vuid from now on */
846 cli->vuid = SVAL (cli->inbuf, smb_uid);
847
848 if (cli->protocol >= PROTOCOL_NT1)
849 {
850 /*
851 * Save off some of the connected server
852 * info.
853 */
854 char *server_domain, *server_os, *server_type;
855 server_os = smb_buf (cli->inbuf);
856 server_type = skip_string (server_os, 1);
857 server_domain = skip_string (server_type, 1);
858 fstrcpy (cli->server_os, server_os);
859 fstrcpy (cli->server_type, server_type);
860 fstrcpy (cli->server_domain, server_domain);
861 }
862
863 fstrcpy (cli->user_name, user);
864
865 return True;
866 }
867
868 /****************************************************************************
869 Send a uloggoff.
870 *****************************************************************************/
871 #if 0
872 BOOL
873 cli_ulogoff (struct cli_state * cli)
874 {
875 memset (cli->outbuf, '\0', smb_size);
876 set_message (cli->outbuf, 2, 0, True);
877 CVAL (cli->outbuf, smb_com) = SMBulogoffX;
878 cli_setup_packet (cli);
879 SSVAL (cli->outbuf, smb_vwv0, 0xFF);
880 SSVAL (cli->outbuf, smb_vwv2, 0); /* no additional info */
881
882 cli_send_smb (cli);
883 if (!cli_receive_smb (cli))
884 return False;
885
886 return CVAL (cli->inbuf, smb_rcls) == 0;
887 }
888 #endif /*0 */
889
890 /****************************************************************************
891 send a tconX
892 ****************************************************************************/
893 BOOL
cli_send_tconX(struct cli_state * cli,const char * share,const char * dev,const char * pass,int passlen)894 cli_send_tconX (struct cli_state * cli,
895 const char *share, const char *dev, const char *pass, int passlen)
896 {
897 fstring fullshare, pword;
898 char *p;
899 memset (cli->outbuf, '\0', smb_size);
900 memset (cli->inbuf, '\0', smb_size);
901
902 fstrcpy (cli->share, share);
903
904 /* in user level security don't send a password now */
905 if (cli->sec_mode & 1)
906 {
907 passlen = 1;
908 pass = "";
909 }
910
911 if ((cli->sec_mode & 2) && *pass && passlen != 24)
912 {
913 passlen = 24;
914 SMBencrypt ((uchar *) pass, (uchar *) cli->cryptkey, (uchar *) pword);
915 }
916 else
917 {
918 memcpy (pword, pass, passlen);
919 }
920
921 slprintf (fullshare, sizeof (fullshare) - 1, "\\\\%s\\%s", cli->desthost, share);
922 unix_to_dos (fullshare, True);
923 strupper (fullshare);
924
925 set_message (cli->outbuf, 4, 2 + strlen (fullshare) + passlen + strlen (dev), True);
926 CVAL (cli->outbuf, smb_com) = SMBtconX;
927 cli_setup_packet (cli);
928
929 SSVAL (cli->outbuf, smb_vwv0, 0xFF);
930 SSVAL (cli->outbuf, smb_vwv3, passlen);
931
932 p = smb_buf (cli->outbuf);
933 memcpy (p, pword, passlen);
934 p += passlen;
935 fstrcpy (p, fullshare);
936 p = skip_string (p, 1);
937 pstrcpy (p, dev);
938
939 SCVAL (cli->inbuf, smb_rcls, 1);
940
941 cli_send_smb (cli);
942 if (!cli_receive_smb (cli))
943 return False;
944
945 if (CVAL (cli->inbuf, smb_rcls) != 0)
946 {
947 return False;
948 }
949
950 fstrcpy (cli->dev, "A:");
951
952 if (cli->protocol >= PROTOCOL_NT1)
953 {
954 fstrcpy (cli->dev, smb_buf (cli->inbuf));
955 }
956
957 if (strcasecmp (share, "IPC$") == 0)
958 {
959 fstrcpy (cli->dev, "IPC");
960 }
961
962 /* only grab the device if we have a recent protocol level */
963 if (cli->protocol >= PROTOCOL_NT1 && smb_buflen (cli->inbuf) == 3)
964 {
965 /* almost certainly win95 - enable bug fixes */
966 cli->win95 = True;
967 }
968
969 cli->cnum = SVAL (cli->inbuf, smb_tid);
970 return True;
971 }
972
973 #if 0
974 /****************************************************************************
975 send a tree disconnect
976 ****************************************************************************/
977 BOOL
978 cli_tdis (struct cli_state * cli)
979 {
980 memset (cli->outbuf, '\0', smb_size);
981 set_message (cli->outbuf, 0, 0, True);
982 CVAL (cli->outbuf, smb_com) = SMBtdis;
983 SSVAL (cli->outbuf, smb_tid, cli->cnum);
984 cli_setup_packet (cli);
985
986 cli_send_smb (cli);
987 if (!cli_receive_smb (cli))
988 return False;
989
990 return CVAL (cli->inbuf, smb_rcls) == 0;
991 }
992 #endif /*0 */
993
994 /****************************************************************************
995 rename a file
996 ****************************************************************************/
997 BOOL
cli_rename(struct cli_state * cli,char * fname_src,char * fname_dst)998 cli_rename (struct cli_state * cli, char *fname_src, char *fname_dst)
999 {
1000 char *p;
1001
1002 memset (cli->outbuf, '\0', smb_size);
1003 memset (cli->inbuf, '\0', smb_size);
1004
1005 set_message (cli->outbuf, 1, 4 + strlen (fname_src) + strlen (fname_dst), True);
1006
1007 CVAL (cli->outbuf, smb_com) = SMBmv;
1008 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1009 cli_setup_packet (cli);
1010
1011 SSVAL (cli->outbuf, smb_vwv0, aSYSTEM | aHIDDEN);
1012
1013 p = smb_buf (cli->outbuf);
1014 *p++ = 4;
1015 pstrcpy (p, fname_src);
1016 p = skip_string (p, 1);
1017 *p++ = 4;
1018 pstrcpy (p, fname_dst);
1019
1020 cli_send_smb (cli);
1021 if (!cli_receive_smb (cli))
1022 {
1023 return False;
1024 }
1025
1026 if (CVAL (cli->inbuf, smb_rcls) != 0)
1027 {
1028 return False;
1029 }
1030
1031 return True;
1032 }
1033
1034 /****************************************************************************
1035 delete a file
1036 ****************************************************************************/
1037 BOOL
cli_unlink(struct cli_state * cli,char * fname)1038 cli_unlink (struct cli_state * cli, char *fname)
1039 {
1040 char *p;
1041
1042 memset (cli->outbuf, '\0', smb_size);
1043 memset (cli->inbuf, '\0', smb_size);
1044
1045 set_message (cli->outbuf, 1, 2 + strlen (fname), True);
1046
1047 CVAL (cli->outbuf, smb_com) = SMBunlink;
1048 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1049 cli_setup_packet (cli);
1050
1051 SSVAL (cli->outbuf, smb_vwv0, aSYSTEM | aHIDDEN);
1052
1053 p = smb_buf (cli->outbuf);
1054 *p++ = 4;
1055 pstrcpy (p, fname);
1056
1057 cli_send_smb (cli);
1058 if (!cli_receive_smb (cli))
1059 {
1060 return False;
1061 }
1062
1063 if (CVAL (cli->inbuf, smb_rcls) != 0)
1064 {
1065 return False;
1066 }
1067
1068 return True;
1069 }
1070
1071 /****************************************************************************
1072 create a directory
1073 ****************************************************************************/
1074 BOOL
cli_mkdir(struct cli_state * cli,char * dname)1075 cli_mkdir (struct cli_state * cli, char *dname)
1076 {
1077 char *p;
1078
1079 memset (cli->outbuf, '\0', smb_size);
1080 memset (cli->inbuf, '\0', smb_size);
1081
1082 set_message (cli->outbuf, 0, 2 + strlen (dname), True);
1083
1084 CVAL (cli->outbuf, smb_com) = SMBmkdir;
1085 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1086 cli_setup_packet (cli);
1087
1088 p = smb_buf (cli->outbuf);
1089 *p++ = 4;
1090 pstrcpy (p, dname);
1091
1092 cli_send_smb (cli);
1093 if (!cli_receive_smb (cli))
1094 {
1095 return False;
1096 }
1097
1098 if (CVAL (cli->inbuf, smb_rcls) != 0)
1099 {
1100 return False;
1101 }
1102
1103 return True;
1104 }
1105
1106 /****************************************************************************
1107 remove a directory
1108 ****************************************************************************/
1109 BOOL
cli_rmdir(struct cli_state * cli,char * dname)1110 cli_rmdir (struct cli_state * cli, char *dname)
1111 {
1112 char *p;
1113
1114 memset (cli->outbuf, '\0', smb_size);
1115 memset (cli->inbuf, '\0', smb_size);
1116
1117 set_message (cli->outbuf, 0, 2 + strlen (dname), True);
1118
1119 CVAL (cli->outbuf, smb_com) = SMBrmdir;
1120 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1121 cli_setup_packet (cli);
1122
1123 p = smb_buf (cli->outbuf);
1124 *p++ = 4;
1125 pstrcpy (p, dname);
1126
1127 cli_send_smb (cli);
1128 if (!cli_receive_smb (cli))
1129 {
1130 return False;
1131 }
1132
1133 if (CVAL (cli->inbuf, smb_rcls) != 0)
1134 {
1135 return False;
1136 }
1137
1138 return True;
1139 }
1140
1141 #if 0
1142 /****************************************************************************
1143 open a file
1144 ****************************************************************************/
1145 int
1146 cli_nt_create (struct cli_state *cli, char *fname)
1147 {
1148 char *p;
1149
1150 memset (cli->outbuf, '\0', smb_size);
1151 memset (cli->inbuf, '\0', smb_size);
1152
1153 set_message (cli->outbuf, 24, 1 + strlen (fname), True);
1154
1155 CVAL (cli->outbuf, smb_com) = SMBntcreateX;
1156 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1157 cli_setup_packet (cli);
1158
1159 SSVAL (cli->outbuf, smb_vwv0, 0xFF);
1160 SIVAL (cli->outbuf, smb_ntcreate_Flags, 0x06);
1161 SIVAL (cli->outbuf, smb_ntcreate_RootDirectoryFid, 0x0);
1162 SIVAL (cli->outbuf, smb_ntcreate_DesiredAccess, 0x2019f);
1163 SIVAL (cli->outbuf, smb_ntcreate_FileAttributes, 0x0);
1164 SIVAL (cli->outbuf, smb_ntcreate_ShareAccess, 0x03);
1165 SIVAL (cli->outbuf, smb_ntcreate_CreateDisposition, 0x01);
1166 SIVAL (cli->outbuf, smb_ntcreate_CreateOptions, 0x0);
1167 SIVAL (cli->outbuf, smb_ntcreate_ImpersonationLevel, 0x02);
1168 SSVAL (cli->outbuf, smb_ntcreate_NameLength, strlen (fname));
1169
1170 p = smb_buf (cli->outbuf);
1171 pstrcpy (p, fname);
1172 p = skip_string (p, 1);
1173
1174 cli_send_smb (cli);
1175 if (!cli_receive_smb (cli))
1176 {
1177 return -1;
1178 }
1179
1180 if (CVAL (cli->inbuf, smb_rcls) != 0)
1181 {
1182 return -1;
1183 }
1184
1185 return SVAL (cli->inbuf, smb_vwv2 + 1);
1186 }
1187 #endif /*0 */
1188
1189 /****************************************************************************
1190 open a file
1191 ****************************************************************************/
1192 int
cli_open(struct cli_state * cli,char * fname,int flags,int share_mode)1193 cli_open (struct cli_state *cli, char *fname, int flags, int share_mode)
1194 {
1195 char *p;
1196 unsigned openfn = 0;
1197 unsigned accessmode = 0;
1198
1199 /* you must open for RW not just write - otherwise getattrE doesn't
1200 work! */
1201 if ((flags & O_ACCMODE) == O_WRONLY && strncmp (cli->dev, "LPT", 3))
1202 {
1203 flags = (flags & ~O_ACCMODE) | O_RDWR;
1204 }
1205
1206 if (flags & O_CREAT)
1207 openfn |= (1 << 4);
1208 if (!(flags & O_EXCL))
1209 {
1210 if (flags & O_TRUNC)
1211 openfn |= (1 << 1);
1212 else
1213 openfn |= (1 << 0);
1214 }
1215
1216 accessmode = (share_mode << 4);
1217
1218 if ((flags & O_ACCMODE) == O_RDWR)
1219 {
1220 accessmode |= 2;
1221 }
1222 else if ((flags & O_ACCMODE) == O_WRONLY)
1223 {
1224 accessmode |= 1;
1225 }
1226
1227 #if defined(O_SYNC)
1228 if ((flags & O_SYNC) == O_SYNC)
1229 {
1230 accessmode |= (1 << 14);
1231 }
1232 #endif /* O_SYNC */
1233
1234 memset (cli->outbuf, '\0', smb_size);
1235 memset (cli->inbuf, '\0', smb_size);
1236
1237 set_message (cli->outbuf, 15, 1 + strlen (fname), True);
1238
1239 CVAL (cli->outbuf, smb_com) = SMBopenX;
1240 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1241 cli_setup_packet (cli);
1242
1243 SSVAL (cli->outbuf, smb_vwv0, 0xFF);
1244 SSVAL (cli->outbuf, smb_vwv2, 0); /* no additional info */
1245 SSVAL (cli->outbuf, smb_vwv3, accessmode);
1246 SSVAL (cli->outbuf, smb_vwv4, aSYSTEM | aHIDDEN);
1247 SSVAL (cli->outbuf, smb_vwv5, 0);
1248 SSVAL (cli->outbuf, smb_vwv8, openfn);
1249
1250 p = smb_buf (cli->outbuf);
1251 pstrcpy (p, fname);
1252 p = skip_string (p, 1);
1253
1254 cli_send_smb (cli);
1255 if (!cli_receive_smb (cli))
1256 {
1257 return -1;
1258 }
1259
1260 if (CVAL (cli->inbuf, smb_rcls) != 0)
1261 {
1262 return -1;
1263 }
1264
1265 return SVAL (cli->inbuf, smb_vwv2);
1266 }
1267
1268
1269
1270
1271 /****************************************************************************
1272 close a file
1273 ****************************************************************************/
1274 BOOL
cli_close(struct cli_state * cli,int fnum)1275 cli_close (struct cli_state * cli, int fnum)
1276 {
1277 memset (cli->outbuf, '\0', smb_size);
1278 memset (cli->inbuf, '\0', smb_size);
1279
1280 set_message (cli->outbuf, 3, 0, True);
1281
1282 CVAL (cli->outbuf, smb_com) = SMBclose;
1283 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1284 cli_setup_packet (cli);
1285
1286 SSVAL (cli->outbuf, smb_vwv0, fnum);
1287 SIVALS (cli->outbuf, smb_vwv1, -1);
1288
1289 cli_send_smb (cli);
1290 if (!cli_receive_smb (cli))
1291 {
1292 return False;
1293 }
1294
1295 if (CVAL (cli->inbuf, smb_rcls) != 0)
1296 {
1297 return False;
1298 }
1299
1300 return True;
1301 }
1302
1303 #if 0
1304 /****************************************************************************
1305 lock a file
1306 ****************************************************************************/
1307 BOOL
1308 cli_lock (struct cli_state * cli, int fnum, uint32 offset, uint32 len, int timeout)
1309 {
1310 char *p;
1311 int saved_timeout = cli->timeout;
1312
1313 memset (cli->outbuf, '\0', smb_size);
1314 memset (cli->inbuf, '\0', smb_size);
1315
1316 set_message (cli->outbuf, 8, 10, True);
1317
1318 CVAL (cli->outbuf, smb_com) = SMBlockingX;
1319 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1320 cli_setup_packet (cli);
1321
1322 CVAL (cli->outbuf, smb_vwv0) = 0xFF;
1323 SSVAL (cli->outbuf, smb_vwv2, fnum);
1324 CVAL (cli->outbuf, smb_vwv3) = 0;
1325 SIVALS (cli->outbuf, smb_vwv4, timeout);
1326 SSVAL (cli->outbuf, smb_vwv6, 0);
1327 SSVAL (cli->outbuf, smb_vwv7, 1);
1328
1329 p = smb_buf (cli->outbuf);
1330 SSVAL (p, 0, cli->pid);
1331 SIVAL (p, 2, offset);
1332 SIVAL (p, 6, len);
1333 cli_send_smb (cli);
1334
1335 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout;
1336
1337 if (!cli_receive_smb (cli))
1338 {
1339 cli->timeout = saved_timeout;
1340 return False;
1341 }
1342
1343 cli->timeout = saved_timeout;
1344
1345 if (CVAL (cli->inbuf, smb_rcls) != 0)
1346 {
1347 return False;
1348 }
1349
1350 return True;
1351 }
1352
1353 /****************************************************************************
1354 unlock a file
1355 ****************************************************************************/
1356 BOOL
1357 cli_unlock (struct cli_state * cli, int fnum, uint32 offset, uint32 len, int timeout)
1358 {
1359 char *p;
1360
1361 memset (cli->outbuf, '\0', smb_size);
1362 memset (cli->inbuf, '\0', smb_size);
1363
1364 set_message (cli->outbuf, 8, 10, True);
1365
1366 CVAL (cli->outbuf, smb_com) = SMBlockingX;
1367 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1368 cli_setup_packet (cli);
1369
1370 CVAL (cli->outbuf, smb_vwv0) = 0xFF;
1371 SSVAL (cli->outbuf, smb_vwv2, fnum);
1372 CVAL (cli->outbuf, smb_vwv3) = 0;
1373 SIVALS (cli->outbuf, smb_vwv4, timeout);
1374 SSVAL (cli->outbuf, smb_vwv6, 1);
1375 SSVAL (cli->outbuf, smb_vwv7, 0);
1376
1377 p = smb_buf (cli->outbuf);
1378 SSVAL (p, 0, cli->pid);
1379 SIVAL (p, 2, offset);
1380 SIVAL (p, 6, len);
1381
1382 cli_send_smb (cli);
1383 if (!cli_receive_smb (cli))
1384 {
1385 return False;
1386 }
1387
1388 if (CVAL (cli->inbuf, smb_rcls) != 0)
1389 {
1390 return False;
1391 }
1392
1393 return True;
1394 }
1395 #endif /*0 */
1396
1397
1398 /****************************************************************************
1399 issue a single SMBread and don't wait for a reply
1400 ****************************************************************************/
1401 static void
cli_issue_read(struct cli_state * cli,int fnum,off_t offset,size_t size,int i)1402 cli_issue_read (struct cli_state *cli, int fnum, off_t offset, size_t size, int i)
1403 {
1404 memset (cli->outbuf, '\0', smb_size);
1405 memset (cli->inbuf, '\0', smb_size);
1406
1407 set_message (cli->outbuf, 10, 0, True);
1408
1409 CVAL (cli->outbuf, smb_com) = SMBreadX;
1410 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1411 cli_setup_packet (cli);
1412
1413 CVAL (cli->outbuf, smb_vwv0) = 0xFF;
1414 SSVAL (cli->outbuf, smb_vwv2, fnum);
1415 SIVAL (cli->outbuf, smb_vwv3, offset);
1416 SSVAL (cli->outbuf, smb_vwv5, size);
1417 SSVAL (cli->outbuf, smb_vwv6, size);
1418 SSVAL (cli->outbuf, smb_mid, cli->mid + i);
1419
1420 cli_send_smb (cli);
1421 }
1422
1423 /****************************************************************************
1424 read from a file
1425 ****************************************************************************/
1426 size_t
cli_read(struct cli_state * cli,int fnum,char * buf,off_t offset,size_t size)1427 cli_read (struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
1428 {
1429 char *p;
1430 int total = -1;
1431 int issued = 0;
1432 int received = 0;
1433 int mpx = MAX (cli->max_mux - 1, 1);
1434 int block = (cli->max_xmit - (smb_size + 32)) & ~1023;
1435 int mid;
1436 int blocks = (size + (block - 1)) / block;
1437
1438 if (size == 0)
1439 return 0;
1440
1441 while (received < blocks)
1442 {
1443 int size2;
1444
1445 while (issued - received < mpx && issued < blocks)
1446 {
1447 int size1 = MIN (block, (int) size - issued * block);
1448 cli_issue_read (cli, fnum, offset + issued * block, size1, issued);
1449 issued++;
1450 }
1451
1452 if (!cli_receive_smb (cli))
1453 {
1454 return total;
1455 }
1456
1457 received++;
1458 mid = SVAL (cli->inbuf, smb_mid) - cli->mid;
1459 size2 = SVAL (cli->inbuf, smb_vwv5);
1460
1461 if (CVAL (cli->inbuf, smb_rcls) != 0)
1462 {
1463 blocks = MIN (blocks, mid - 1);
1464 continue;
1465 }
1466
1467 if (size2 <= 0)
1468 {
1469 blocks = MIN (blocks, mid - 1);
1470 /* this distinguishes EOF from an error */
1471 total = MAX (total, 0);
1472 continue;
1473 }
1474
1475 if (size2 > block)
1476 {
1477 DEBUG (0, ("server returned more than we wanted!\n"));
1478 exit (1);
1479 }
1480 if (mid >= issued)
1481 {
1482 DEBUG (0, ("invalid mid from server!\n"));
1483 exit (1);
1484 }
1485 p = smb_base (cli->inbuf) + SVAL (cli->inbuf, smb_vwv6);
1486
1487 memcpy (buf + mid * block, p, size2);
1488
1489 total = MAX (total, mid * block + size2);
1490 }
1491
1492 while (received < issued)
1493 {
1494 cli_receive_smb (cli);
1495 received++;
1496 }
1497
1498 return total;
1499 }
1500
1501
1502 /****************************************************************************
1503 issue a single SMBwrite and don't wait for a reply
1504 ****************************************************************************/
1505 static void
cli_issue_write(struct cli_state * cli,int fnum,off_t offset,uint16 mode,const char * buf,size_t size,int i)1506 cli_issue_write (struct cli_state *cli, int fnum, off_t offset, uint16 mode, const char *buf,
1507 size_t size, int i)
1508 {
1509 char *p;
1510
1511 memset (cli->outbuf, '\0', smb_size);
1512 memset (cli->inbuf, '\0', smb_size);
1513
1514 set_message (cli->outbuf, 12, size, True);
1515
1516 CVAL (cli->outbuf, smb_com) = SMBwriteX;
1517 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1518 cli_setup_packet (cli);
1519
1520 CVAL (cli->outbuf, smb_vwv0) = 0xFF;
1521 SSVAL (cli->outbuf, smb_vwv2, fnum);
1522
1523 SIVAL (cli->outbuf, smb_vwv3, offset);
1524 SIVAL (cli->outbuf, smb_vwv5, IS_BITS_SET_ALL (mode, 0x0008) ? 0xFFFFFFFF : 0);
1525 SSVAL (cli->outbuf, smb_vwv7, mode);
1526
1527 SSVAL (cli->outbuf, smb_vwv8, IS_BITS_SET_ALL (mode, 0x0008) ? size : 0);
1528 SSVAL (cli->outbuf, smb_vwv10, size);
1529 SSVAL (cli->outbuf, smb_vwv11, smb_buf (cli->outbuf) - smb_base (cli->outbuf));
1530
1531 p = smb_base (cli->outbuf) + SVAL (cli->outbuf, smb_vwv11);
1532 memcpy (p, buf, size);
1533
1534 SSVAL (cli->outbuf, smb_mid, cli->mid + i);
1535
1536 show_msg (cli->outbuf);
1537 cli_send_smb (cli);
1538 }
1539
1540 /****************************************************************************
1541 write to a file
1542 write_mode: 0x0001 disallow write cacheing
1543 0x0002 return bytes remaining
1544 0x0004 use raw named pipe protocol
1545 0x0008 start of message mode named pipe protocol
1546 ****************************************************************************/
1547 ssize_t
cli_write(struct cli_state * cli,int fnum,uint16 write_mode,const char * buf,off_t offset,size_t size)1548 cli_write (struct cli_state *cli,
1549 int fnum, uint16 write_mode, const char *buf, off_t offset, size_t size)
1550 {
1551 int bwritten = 0;
1552 int issued = 0;
1553 int received = 0;
1554 int mpx = MAX (cli->max_mux - 1, 1);
1555 int block = (cli->max_xmit - (smb_size + 32)) & ~1023;
1556 int blocks = (size + (block - 1)) / block;
1557
1558 while (received < blocks)
1559 {
1560
1561 while ((issued - received < mpx) && (issued < blocks))
1562 {
1563 int bsent = issued * block;
1564 int size1 = MIN (block, (int) size - bsent);
1565
1566 cli_issue_write (cli, fnum, offset + bsent, write_mode, buf + bsent, size1, issued);
1567 issued++;
1568 }
1569
1570 if (!cli_receive_smb (cli))
1571 {
1572 return bwritten;
1573 }
1574
1575 received++;
1576
1577 if (CVAL (cli->inbuf, smb_rcls) != 0)
1578 {
1579 break;
1580 }
1581
1582 bwritten += SVAL (cli->inbuf, smb_vwv2);
1583 }
1584
1585 while (received < issued && cli_receive_smb (cli))
1586 {
1587 received++;
1588 }
1589
1590 return bwritten;
1591 }
1592
1593 #if 0
1594 /****************************************************************************
1595 write to a file using a SMBwrite and not bypassing 0 byte writes
1596 ****************************************************************************/
1597 ssize_t
1598 cli_smbwrite (struct cli_state * cli, int fnum, const char *buf, off_t offset, size_t size)
1599 {
1600 char *p;
1601
1602 memset (cli->outbuf, '\0', smb_size);
1603 memset (cli->inbuf, '\0', smb_size);
1604
1605 set_message (cli->outbuf, 5, 3 + size, True);
1606
1607 CVAL (cli->outbuf, smb_com) = SMBwrite;
1608 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1609 cli_setup_packet (cli);
1610
1611 SSVAL (cli->outbuf, smb_vwv0, fnum);
1612 SSVAL (cli->outbuf, smb_vwv1, size);
1613 SIVAL (cli->outbuf, smb_vwv2, offset);
1614 SSVAL (cli->outbuf, smb_vwv4, 0);
1615
1616 p = smb_buf (cli->outbuf);
1617 *p++ = 1;
1618 SSVAL (p, 0, size);
1619 memcpy (p + 2, buf, size);
1620
1621 cli_send_smb (cli);
1622 if (!cli_receive_smb (cli))
1623 {
1624 return False;
1625 }
1626
1627 if (CVAL (cli->inbuf, smb_rcls) != 0)
1628 {
1629 return -1;
1630 }
1631
1632 return SVAL (cli->inbuf, smb_vwv0);
1633 }
1634 #endif /*0 */
1635
1636 /****************************************************************************
1637 do a SMBgetattrE call
1638 ****************************************************************************/
1639 BOOL
cli_getattrE(struct cli_state * cli,int fd,uint16 * attr,size_t * size,time_t * c_time,time_t * a_time,time_t * m_time)1640 cli_getattrE (struct cli_state * cli, int fd,
1641 uint16 * attr, size_t * size, time_t * c_time, time_t * a_time, time_t * m_time)
1642 {
1643 memset (cli->outbuf, '\0', smb_size);
1644 memset (cli->inbuf, '\0', smb_size);
1645
1646 set_message (cli->outbuf, 2, 0, True);
1647
1648 CVAL (cli->outbuf, smb_com) = SMBgetattrE;
1649 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1650 cli_setup_packet (cli);
1651
1652 SSVAL (cli->outbuf, smb_vwv0, fd);
1653
1654 cli_send_smb (cli);
1655 if (!cli_receive_smb (cli))
1656 {
1657 return False;
1658 }
1659
1660 if (CVAL (cli->inbuf, smb_rcls) != 0)
1661 {
1662 return False;
1663 }
1664
1665 if (size)
1666 {
1667 *size = IVAL (cli->inbuf, smb_vwv6);
1668 }
1669
1670 if (attr)
1671 {
1672 *attr = SVAL (cli->inbuf, smb_vwv10);
1673 }
1674
1675 if (c_time)
1676 {
1677 *c_time = make_unix_date3 (cli->inbuf + smb_vwv0);
1678 }
1679
1680 if (a_time)
1681 {
1682 *a_time = make_unix_date3 (cli->inbuf + smb_vwv2);
1683 }
1684
1685 if (m_time)
1686 {
1687 *m_time = make_unix_date3 (cli->inbuf + smb_vwv4);
1688 }
1689
1690 return True;
1691 }
1692
1693 #if 0
1694 /****************************************************************************
1695 do a SMBgetatr call
1696 ****************************************************************************/
1697 BOOL
1698 cli_getatr (struct cli_state * cli, char *fname, uint16 * attr, size_t * size, time_t * t)
1699 {
1700 char *p;
1701
1702 memset (cli->outbuf, '\0', smb_size);
1703 memset (cli->inbuf, '\0', smb_size);
1704
1705 set_message (cli->outbuf, 0, strlen (fname) + 2, True);
1706
1707 CVAL (cli->outbuf, smb_com) = SMBgetatr;
1708 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1709 cli_setup_packet (cli);
1710
1711 p = smb_buf (cli->outbuf);
1712 *p = 4;
1713 pstrcpy (p + 1, fname);
1714
1715 cli_send_smb (cli);
1716 if (!cli_receive_smb (cli))
1717 {
1718 return False;
1719 }
1720
1721 if (CVAL (cli->inbuf, smb_rcls) != 0)
1722 {
1723 return False;
1724 }
1725
1726 if (size)
1727 {
1728 *size = IVAL (cli->inbuf, smb_vwv3);
1729 }
1730
1731 if (t)
1732 {
1733 *t = make_unix_date3 (cli->inbuf + smb_vwv1);
1734 }
1735
1736 if (attr)
1737 {
1738 *attr = SVAL (cli->inbuf, smb_vwv0);
1739 }
1740
1741
1742 return True;
1743 }
1744 #endif /* 0 */
1745
1746 /****************************************************************************
1747 do a SMBsetatr call
1748 ****************************************************************************/
1749 BOOL
cli_setatr(struct cli_state * cli,char * fname,uint16 attr,time_t t)1750 cli_setatr (struct cli_state * cli, char *fname, uint16 attr, time_t t)
1751 {
1752 char *p;
1753
1754 memset (cli->outbuf, '\0', smb_size);
1755 memset (cli->inbuf, '\0', smb_size);
1756
1757 set_message (cli->outbuf, 8, strlen (fname) + 4, True);
1758
1759 CVAL (cli->outbuf, smb_com) = SMBsetatr;
1760 SSVAL (cli->outbuf, smb_tid, cli->cnum);
1761 cli_setup_packet (cli);
1762
1763 SSVAL (cli->outbuf, smb_vwv0, attr);
1764 put_dos_date3 (cli->outbuf, smb_vwv1, t);
1765
1766 p = smb_buf (cli->outbuf);
1767 *p = 4;
1768 pstrcpy (p + 1, fname);
1769 p = skip_string (p, 1);
1770 *p = 4;
1771
1772 cli_send_smb (cli);
1773 if (!cli_receive_smb (cli))
1774 {
1775 return False;
1776 }
1777
1778 if (CVAL (cli->inbuf, smb_rcls) != 0)
1779 {
1780 return False;
1781 }
1782
1783 return True;
1784 }
1785
1786 #if 0
1787 /****************************************************************************
1788 send a qpathinfo call
1789 ****************************************************************************/
1790 BOOL
1791 cli_qpathinfo (struct cli_state * cli, const char *fname,
1792 time_t * c_time, time_t * a_time, time_t * m_time, size_t * size, uint16 * mode)
1793 {
1794 int data_len = 0;
1795 int param_len = 0;
1796 uint16 setup = TRANSACT2_QPATHINFO;
1797 pstring param;
1798 char *rparam = NULL, *rdata = NULL;
1799 int count = 8;
1800 BOOL ret;
1801 time_t (*date_fn) (void *);
1802
1803 param_len = strlen (fname) + 7;
1804
1805 memset (param, 0, param_len);
1806 SSVAL (param, 0, SMB_INFO_STANDARD);
1807 pstrcpy (¶m[6], fname);
1808
1809 do
1810 {
1811 ret = (cli_send_trans (cli, SMBtrans2, NULL, 0, /* Name, length */
1812 -1, 0, /* fid, flags */
1813 &setup, 1, 0, /* setup, length, max */
1814 param, param_len, 10, /* param, length, max */
1815 NULL, data_len, cli->max_xmit /* data, length, max */
1816 ) && cli_receive_trans (cli, SMBtrans2, &rparam, ¶m_len, &rdata, &data_len));
1817 if (!ret)
1818 {
1819 /* we need to work around a Win95 bug - sometimes
1820 it gives ERRSRV/ERRerror temprarily */
1821 uint8 eclass;
1822 uint32 ecode;
1823 cli_error (cli, &eclass, &ecode, NULL);
1824 if (eclass != ERRSRV || ecode != ERRerror)
1825 break;
1826 msleep (100);
1827 }
1828 }
1829 while (count-- && ret == False);
1830
1831 if (!ret || !rdata || data_len < 22)
1832 {
1833 return False;
1834 }
1835
1836 if (cli->win95)
1837 {
1838 date_fn = make_unix_date;
1839 }
1840 else
1841 {
1842 date_fn = make_unix_date2;
1843 }
1844
1845 if (c_time)
1846 {
1847 *c_time = date_fn (rdata + 0);
1848 }
1849 if (a_time)
1850 {
1851 *a_time = date_fn (rdata + 4);
1852 }
1853 if (m_time)
1854 {
1855 *m_time = date_fn (rdata + 8);
1856 }
1857 if (size)
1858 {
1859 *size = IVAL (rdata, 12);
1860 }
1861 if (mode)
1862 {
1863 *mode = SVAL (rdata, l1_attrFile);
1864 }
1865
1866 if (rdata)
1867 free (rdata);
1868 if (rparam)
1869 free (rparam);
1870 return True;
1871 }
1872
1873 /****************************************************************************
1874 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1875 ****************************************************************************/
1876 BOOL
1877 cli_qpathinfo2 (struct cli_state * cli, const char *fname,
1878 time_t * c_time, time_t * a_time, time_t * m_time,
1879 time_t * w_time, size_t * size, uint16 * mode, SMB_INO_T * ino)
1880 {
1881 int data_len = 0;
1882 int param_len = 0;
1883 uint16 setup = TRANSACT2_QPATHINFO;
1884 pstring param;
1885 char *rparam = NULL, *rdata = NULL;
1886
1887 param_len = strlen (fname) + 7;
1888
1889 memset (param, 0, param_len);
1890 SSVAL (param, 0, SMB_QUERY_FILE_ALL_INFO);
1891 pstrcpy (¶m[6], fname);
1892
1893 if (!cli_send_trans (cli, SMBtrans2, NULL, 0, /* name, length */
1894 -1, 0, /* fid, flags */
1895 &setup, 1, 0, /* setup, length, max */
1896 param, param_len, 10, /* param, length, max */
1897 NULL, data_len, cli->max_xmit /* data, length, max */
1898 ))
1899 {
1900 return False;
1901 }
1902
1903 if (!cli_receive_trans (cli, SMBtrans2, &rparam, ¶m_len, &rdata, &data_len))
1904 {
1905 return False;
1906 }
1907
1908 if (!rdata || data_len < 22)
1909 {
1910 return False;
1911 }
1912
1913 if (c_time)
1914 {
1915 *c_time = interpret_long_date (rdata + 0) - cli->serverzone;
1916 }
1917 if (a_time)
1918 {
1919 *a_time = interpret_long_date (rdata + 8) - cli->serverzone;
1920 }
1921 if (m_time)
1922 {
1923 *m_time = interpret_long_date (rdata + 16) - cli->serverzone;
1924 }
1925 if (w_time)
1926 {
1927 *w_time = interpret_long_date (rdata + 24) - cli->serverzone;
1928 }
1929 if (mode)
1930 {
1931 *mode = SVAL (rdata, 32);
1932 }
1933 if (size)
1934 {
1935 *size = IVAL (rdata, 48);
1936 }
1937 if (ino)
1938 {
1939 *ino = IVAL (rdata, 64);
1940 }
1941
1942 if (rdata)
1943 free (rdata);
1944 if (rparam)
1945 free (rparam);
1946 return True;
1947 }
1948 #endif /* 0 */
1949
1950 /****************************************************************************
1951 send a qfileinfo call
1952 ****************************************************************************/
1953 BOOL
cli_qfileinfo(struct cli_state * cli,int fnum,uint16 * mode,size_t * size,time_t * c_time,time_t * a_time,time_t * m_time,time_t * w_time,SMB_INO_T * ino)1954 cli_qfileinfo (struct cli_state * cli, int fnum,
1955 uint16 * mode, size_t * size,
1956 time_t * c_time, time_t * a_time, time_t * m_time, time_t * w_time, SMB_INO_T * ino)
1957 {
1958 int data_len = 0;
1959 int param_len = 0;
1960 uint16 setup = TRANSACT2_QFILEINFO;
1961 pstring param;
1962 char *rparam = NULL, *rdata = NULL;
1963
1964 /* if its a win95 server then fail this - win95 totally screws it
1965 up */
1966 if (cli->win95)
1967 return False;
1968
1969 param_len = 4;
1970
1971 memset (param, 0, param_len);
1972 SSVAL (param, 0, fnum);
1973 SSVAL (param, 2, SMB_QUERY_FILE_ALL_INFO);
1974
1975 if (!cli_send_trans (cli, SMBtrans2, NULL, 0, /* name, length */
1976 -1, 0, /* fid, flags */
1977 &setup, 1, 0, /* setup, length, max */
1978 param, param_len, 2, /* param, length, max */
1979 NULL, data_len, cli->max_xmit /* data, length, max */
1980 ))
1981 {
1982 return False;
1983 }
1984
1985 if (!cli_receive_trans (cli, SMBtrans2, &rparam, ¶m_len, &rdata, &data_len))
1986 {
1987 return False;
1988 }
1989
1990 if (!rdata || data_len < 68)
1991 {
1992 return False;
1993 }
1994
1995 if (c_time)
1996 {
1997 *c_time = interpret_long_date (rdata + 0) - cli->serverzone;
1998 }
1999 if (a_time)
2000 {
2001 *a_time = interpret_long_date (rdata + 8) - cli->serverzone;
2002 }
2003 if (m_time)
2004 {
2005 *m_time = interpret_long_date (rdata + 16) - cli->serverzone;
2006 }
2007 if (w_time)
2008 {
2009 *w_time = interpret_long_date (rdata + 24) - cli->serverzone;
2010 }
2011 if (mode)
2012 {
2013 *mode = SVAL (rdata, 32);
2014 }
2015 if (size)
2016 {
2017 *size = IVAL (rdata, 48);
2018 }
2019 if (ino)
2020 {
2021 *ino = IVAL (rdata, 64);
2022 }
2023
2024 if (rdata)
2025 free (rdata);
2026 if (rparam)
2027 free (rparam);
2028 return True;
2029 }
2030
2031
2032 /****************************************************************************
2033 interpret a long filename structure - this is mostly guesses at the moment
2034 The length of the structure is returned
2035 The structure of a long filename depends on the info level. 260 is used
2036 by NT and 2 is used by OS/2
2037 ****************************************************************************/
2038 static int
interpret_long_filename(int level,char * p,file_info * finfo)2039 interpret_long_filename (int level, char *p, file_info * finfo)
2040 {
2041 extern file_info const def_finfo;
2042
2043 if (finfo)
2044 memcpy (finfo, &def_finfo, sizeof (*finfo));
2045
2046 switch (level)
2047 {
2048 case 1: /* OS/2 understands this */
2049 if (finfo)
2050 {
2051 /* these dates are converted to GMT by make_unix_date */
2052 finfo->ctime = make_unix_date2 (p + 4);
2053 finfo->atime = make_unix_date2 (p + 8);
2054 finfo->mtime = make_unix_date2 (p + 12);
2055 finfo->size = IVAL (p, 16);
2056 finfo->mode = CVAL (p, 24);
2057 pstrcpy (finfo->name, p + 27);
2058 }
2059 return (28 + CVAL (p, 26));
2060
2061 case 2: /* this is what OS/2 uses mostly */
2062 if (finfo)
2063 {
2064 /* these dates are converted to GMT by make_unix_date */
2065 finfo->ctime = make_unix_date2 (p + 4);
2066 finfo->atime = make_unix_date2 (p + 8);
2067 finfo->mtime = make_unix_date2 (p + 12);
2068 finfo->size = IVAL (p, 16);
2069 finfo->mode = CVAL (p, 24);
2070 pstrcpy (finfo->name, p + 31);
2071 }
2072 return (32 + CVAL (p, 30));
2073
2074 /* levels 3 and 4 are untested */
2075 case 3:
2076 if (finfo)
2077 {
2078 /* these dates are probably like the other ones */
2079 finfo->ctime = make_unix_date2 (p + 8);
2080 finfo->atime = make_unix_date2 (p + 12);
2081 finfo->mtime = make_unix_date2 (p + 16);
2082 finfo->size = IVAL (p, 20);
2083 finfo->mode = CVAL (p, 28);
2084 pstrcpy (finfo->name, p + 33);
2085 }
2086 return (SVAL (p, 4) + 4);
2087
2088 case 4:
2089 if (finfo)
2090 {
2091 /* these dates are probably like the other ones */
2092 finfo->ctime = make_unix_date2 (p + 8);
2093 finfo->atime = make_unix_date2 (p + 12);
2094 finfo->mtime = make_unix_date2 (p + 16);
2095 finfo->size = IVAL (p, 20);
2096 finfo->mode = CVAL (p, 28);
2097 pstrcpy (finfo->name, p + 37);
2098 }
2099 return (SVAL (p, 4) + 4);
2100
2101 case 260: /* NT uses this, but also accepts 2 */
2102 if (finfo)
2103 {
2104 int ret = SVAL (p, 0);
2105 int namelen;
2106 p += 4; /* next entry offset */
2107 p += 4; /* fileindex */
2108
2109 /* these dates appear to arrive in a
2110 weird way. It seems to be localtime
2111 plus the serverzone given in the
2112 initial connect. This is GMT when
2113 DST is not in effect and one hour
2114 from GMT otherwise. Can this really
2115 be right??
2116
2117 I suppose this could be called
2118 kludge-GMT. Is is the GMT you get
2119 by using the current DST setting on
2120 a different localtime. It will be
2121 cheap to calculate, I suppose, as
2122 no DST tables will be needed */
2123
2124 finfo->ctime = interpret_long_date (p);
2125 p += 8;
2126 finfo->atime = interpret_long_date (p);
2127 p += 8;
2128 finfo->mtime = interpret_long_date (p);
2129 p += 8;
2130 p += 8;
2131 finfo->size = IVAL (p, 0);
2132 p += 8;
2133 p += 8; /* alloc size */
2134 finfo->mode = CVAL (p, 0);
2135 p += 4;
2136 namelen = IVAL (p, 0);
2137 p += 4;
2138 p += 4; /* EA size */
2139 p += 2; /* short name len? */
2140 p += 24; /* short name? */
2141 StrnCpy (finfo->name, p, namelen);
2142 return (ret);
2143 }
2144 return (SVAL (p, 0));
2145 }
2146
2147 DEBUG (1, ("Unknown long filename format %d\n", level));
2148 return (SVAL (p, 0));
2149 }
2150
2151
2152 /****************************************************************************
2153 do a directory listing, calling fn on each file found
2154 ****************************************************************************/
2155 int
cli_list(struct cli_state * cli,const char * Mask,uint16 attribute,void (* fn)(file_info *,const char *,void *),void * state)2156 cli_list (struct cli_state *cli, const char *Mask, uint16 attribute,
2157 void (*fn) (file_info *, const char *, void *), void *state)
2158 {
2159 int max_matches = 512;
2160 /* NT uses 260, OS/2 uses 2. Both accept 1. */
2161 int info_level = cli->protocol < PROTOCOL_NT1 ? 1 : 260;
2162 char *p, *p2;
2163 pstring mask;
2164 file_info finfo;
2165 int i;
2166 char *dirlist = NULL;
2167 int dirlist_len = 0;
2168 int total_received = -1;
2169 BOOL First = True;
2170 int ff_resume_key = 0;
2171 int ff_searchcount = 0;
2172 int ff_eos = 0;
2173 int ff_lastname = 0;
2174 int ff_dir_handle = 0;
2175 int loop_count = 0;
2176 char *rparam = NULL, *rdata = NULL;
2177 int param_len, data_len;
2178
2179 uint16 setup;
2180 pstring param;
2181
2182 pstrcpy (mask, Mask);
2183
2184 while (ff_eos == 0)
2185 {
2186 loop_count++;
2187 if (loop_count > 200)
2188 {
2189 DEBUG (0, ("Error: Looping in FIND_NEXT??\n"));
2190 break;
2191 }
2192
2193 param_len = 12 + strlen (mask) + 1;
2194
2195 if (First)
2196 {
2197 setup = TRANSACT2_FINDFIRST;
2198 SSVAL (param, 0, attribute); /* attribute */
2199 SSVAL (param, 2, max_matches); /* max count */
2200 SSVAL (param, 4, 8 + 4 + 2); /* resume required + close on end + continue */
2201 SSVAL (param, 6, info_level);
2202 SIVAL (param, 8, 0);
2203 pstrcpy (param + 12, mask);
2204 }
2205 else
2206 {
2207 setup = TRANSACT2_FINDNEXT;
2208 SSVAL (param, 0, ff_dir_handle);
2209 SSVAL (param, 2, max_matches); /* max count */
2210 SSVAL (param, 4, info_level);
2211 SIVAL (param, 6, ff_resume_key); /* ff_resume_key */
2212 SSVAL (param, 10, 8 + 4 + 2); /* resume required + close on end + continue */
2213 pstrcpy (param + 12, mask);
2214
2215 DEBUG (5, ("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
2216 ff_dir_handle, ff_resume_key, ff_lastname, mask));
2217 }
2218
2219 if (!cli_send_trans (cli, SMBtrans2, NULL, 0, /* Name, length */
2220 -1, 0, /* fid, flags */
2221 &setup, 1, 0, /* setup, length, max */
2222 param, param_len, 10, /* param, length, max */
2223 NULL, 0, cli->max_xmit /* data, length, max */
2224 ))
2225 {
2226 break;
2227 }
2228
2229 if (!cli_receive_trans (cli, SMBtrans2, &rparam, ¶m_len, &rdata, &data_len))
2230 {
2231 /* we need to work around a Win95 bug - sometimes
2232 it gives ERRSRV/ERRerror temprarily */
2233 uint8 eclass;
2234 uint32 ecode;
2235 cli_error (cli, &eclass, &ecode, NULL);
2236 if (eclass != ERRSRV || ecode != ERRerror)
2237 break;
2238 msleep (100);
2239 continue;
2240 }
2241
2242 if (total_received == -1)
2243 total_received = 0;
2244
2245 /* parse out some important return info */
2246 p = rparam;
2247 if (First)
2248 {
2249 ff_dir_handle = SVAL (p, 0);
2250 ff_searchcount = SVAL (p, 2);
2251 ff_eos = SVAL (p, 4);
2252 ff_lastname = SVAL (p, 8);
2253 }
2254 else
2255 {
2256 ff_searchcount = SVAL (p, 0);
2257 ff_eos = SVAL (p, 2);
2258 ff_lastname = SVAL (p, 6);
2259 }
2260
2261 if (ff_searchcount == 0)
2262 break;
2263
2264 /* point to the data bytes */
2265 p = rdata;
2266
2267 /* we might need the lastname for continuations */
2268 if (ff_lastname > 0)
2269 {
2270 switch (info_level)
2271 {
2272 case 260:
2273 ff_resume_key = 0;
2274 StrnCpy (mask, p + ff_lastname, data_len - ff_lastname);
2275 break;
2276 case 1:
2277 pstrcpy (mask, p + ff_lastname + 1);
2278 ff_resume_key = 0;
2279 break;
2280 }
2281 }
2282 else
2283 {
2284 pstrcpy (mask, "");
2285 }
2286
2287 /* and add them to the dirlist pool */
2288 dirlist = Realloc (dirlist, dirlist_len + data_len);
2289
2290 if (!dirlist)
2291 {
2292 DEBUG (0, ("Failed to expand dirlist\n"));
2293 break;
2294 }
2295
2296 /* put in a length for the last entry, to ensure we can chain entries
2297 into the next packet */
2298 for (p2 = p, i = 0; i < (ff_searchcount - 1); i++)
2299 p2 += interpret_long_filename (info_level, p2, NULL);
2300 SSVAL (p2, 0, data_len - PTR_DIFF (p2, p));
2301
2302 /* grab the data for later use */
2303 memcpy (dirlist + dirlist_len, p, data_len);
2304 dirlist_len += data_len;
2305
2306 total_received += ff_searchcount;
2307
2308 if (rdata)
2309 free (rdata);
2310 rdata = NULL;
2311 if (rparam)
2312 free (rparam);
2313 rparam = NULL;
2314
2315 DEBUG (3, ("received %d entries (eos=%d resume=%d)\n",
2316 ff_searchcount, ff_eos, ff_resume_key));
2317
2318 First = False;
2319 }
2320
2321 for (p = dirlist, i = 0; i < total_received; i++)
2322 {
2323 p += interpret_long_filename (info_level, p, &finfo);
2324 fn (&finfo, Mask, state);
2325 }
2326
2327 /* free up the dirlist buffer */
2328 if (dirlist)
2329 free (dirlist);
2330 return (total_received);
2331 }
2332
2333
2334 /****************************************************************************
2335 send a negprot command
2336 ****************************************************************************/
2337 BOOL
cli_negprot(struct cli_state * cli)2338 cli_negprot (struct cli_state * cli)
2339 {
2340 char *p;
2341 int numprots;
2342 int plength;
2343
2344 memset (cli->outbuf, '\0', smb_size);
2345
2346 /* setup the protocol strings */
2347 for (plength = 0, numprots = 0;
2348 prots[numprots].name && prots[numprots].prot <= cli->protocol; numprots++)
2349 plength += strlen (prots[numprots].name) + 2;
2350
2351 set_message (cli->outbuf, 0, plength, True);
2352
2353 p = smb_buf (cli->outbuf);
2354 for (numprots = 0; prots[numprots].name && prots[numprots].prot <= cli->protocol; numprots++)
2355 {
2356 *p++ = 2;
2357 pstrcpy (p, prots[numprots].name);
2358 p += strlen (p) + 1;
2359 }
2360
2361 CVAL (cli->outbuf, smb_com) = SMBnegprot;
2362 cli_setup_packet (cli);
2363
2364 CVAL (smb_buf (cli->outbuf), 0) = 2;
2365
2366 cli_send_smb (cli);
2367 if (!cli_receive_smb (cli))
2368 return False;
2369
2370 show_msg (cli->inbuf);
2371
2372 if (CVAL (cli->inbuf, smb_rcls) != 0 || ((int) SVAL (cli->inbuf, smb_vwv0) >= numprots))
2373 {
2374 return (False);
2375 }
2376
2377 cli->protocol = prots[SVAL (cli->inbuf, smb_vwv0)].prot;
2378
2379
2380 if (cli->protocol >= PROTOCOL_NT1)
2381 {
2382 /* NT protocol */
2383 cli->sec_mode = CVAL (cli->inbuf, smb_vwv1);
2384 cli->max_mux = SVAL (cli->inbuf, smb_vwv1 + 1);
2385 cli->max_xmit = IVAL (cli->inbuf, smb_vwv3 + 1);
2386 cli->sesskey = IVAL (cli->inbuf, smb_vwv7 + 1);
2387 cli->serverzone = SVALS (cli->inbuf, smb_vwv15 + 1) * 60;
2388 /* this time arrives in real GMT */
2389 cli->servertime = interpret_long_date (cli->inbuf + smb_vwv11 + 1);
2390 memcpy (cli->cryptkey, smb_buf (cli->inbuf), 8);
2391 cli->capabilities = IVAL (cli->inbuf, smb_vwv9 + 1);
2392 if (cli->capabilities & 1)
2393 {
2394 cli->readbraw_supported = True;
2395 cli->writebraw_supported = True;
2396 }
2397 }
2398 else if (cli->protocol >= PROTOCOL_LANMAN1)
2399 {
2400 cli->sec_mode = SVAL (cli->inbuf, smb_vwv1);
2401 cli->max_xmit = SVAL (cli->inbuf, smb_vwv2);
2402 cli->sesskey = IVAL (cli->inbuf, smb_vwv6);
2403 cli->serverzone = SVALS (cli->inbuf, smb_vwv10) * 60;
2404 /* this time is converted to GMT by make_unix_date */
2405 cli->servertime = make_unix_date (cli->inbuf + smb_vwv8);
2406 cli->readbraw_supported = ((SVAL (cli->inbuf, smb_vwv5) & 0x1) != 0);
2407 cli->writebraw_supported = ((SVAL (cli->inbuf, smb_vwv5) & 0x2) != 0);
2408 memcpy (cli->cryptkey, smb_buf (cli->inbuf), 8);
2409 }
2410 else
2411 {
2412 /* the old core protocol */
2413 cli->sec_mode = 0;
2414 cli->serverzone = TimeDiff (time (NULL));
2415 }
2416
2417 cli->max_xmit = MIN (cli->max_xmit, CLI_BUFFER_SIZE);
2418
2419 return True;
2420 }
2421
2422
2423 /****************************************************************************
2424 send a session request. see rfc1002.txt 4.3 and 4.3.2
2425 ****************************************************************************/
2426 BOOL
cli_session_request(struct cli_state * cli,struct nmb_name * calling,struct nmb_name * called)2427 cli_session_request (struct cli_state * cli, struct nmb_name * calling, struct nmb_name * called)
2428 {
2429 char *p;
2430 int len = 4;
2431 /* send a session request (RFC 1002) */
2432
2433 memcpy (&(cli->calling), calling, sizeof (*calling));
2434 memcpy (&(cli->called), called, sizeof (*called));
2435
2436 /* put in the destination name */
2437 p = cli->outbuf + len;
2438 name_mangle (cli->called.name, p, cli->called.name_type);
2439 len += name_len (p);
2440
2441 /* and my name */
2442 p = cli->outbuf + len;
2443 name_mangle (cli->calling.name, p, cli->calling.name_type);
2444 len += name_len (p);
2445
2446 /* setup the packet length */
2447 _smb_setlen (cli->outbuf, len);
2448 CVAL (cli->outbuf, 0) = 0x81;
2449
2450 #ifdef WITH_SSL
2451 retry:
2452 #endif /* WITH_SSL */
2453
2454 cli_send_smb (cli);
2455 DEBUG (5, ("Sent session request\n"));
2456
2457 if (!cli_receive_smb (cli))
2458 return False;
2459
2460 if (CVAL (cli->inbuf, 0) == 0x84)
2461 {
2462 /* C. Hoch 9/14/95 Start */
2463 /* For information, here is the response structure.
2464 * We do the byte-twiddling to for portability.
2465 struct RetargetResponse{
2466 unsigned char type;
2467 unsigned char flags;
2468 int16 length;
2469 int32 ip_addr;
2470 int16 port;
2471 };
2472 */
2473 int port = (CVAL (cli->inbuf, 8) << 8) + CVAL (cli->inbuf, 9);
2474 /* SESSION RETARGET */
2475 putip ((char *) &cli->dest_ip, cli->inbuf + 4);
2476
2477 close_sockets ();
2478 cli->fd = open_socket_out (SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
2479 if (cli->fd == -1)
2480 return False;
2481
2482 DEBUG (3, ("Retargeted\n"));
2483
2484 set_socket_options (cli->fd, user_socket_options);
2485
2486 /* Try again */
2487 return cli_session_request (cli, calling, called);
2488 } /* C. Hoch 9/14/95 End */
2489
2490 #ifdef WITH_SSL
2491 if (CVAL (cli->inbuf, 0) == 0x83 && CVAL (cli->inbuf, 4) == 0x8e)
2492 { /* use ssl */
2493 if (!sslutil_fd_is_ssl (cli->fd))
2494 {
2495 if (sslutil_connect (cli->fd) == 0)
2496 goto retry;
2497 }
2498 }
2499 #endif /* WITH_SSL */
2500
2501 if (CVAL (cli->inbuf, 0) != 0x82)
2502 {
2503 /* This is the wrong place to put the error... JRA. */
2504 cli->rap_error = CVAL (cli->inbuf, 0);
2505 return False;
2506 }
2507 return (True);
2508 }
2509
2510
2511 /****************************************************************************
2512 open the client sockets
2513 ****************************************************************************/
2514 BOOL
cli_connect(struct cli_state * cli,const char * host,struct in_addr * ip)2515 cli_connect (struct cli_state * cli, const char *host, struct in_addr * ip)
2516 {
2517 extern struct in_addr ipzero;
2518
2519 fstrcpy (cli->desthost, host);
2520
2521 if (!ip || ip_equal (*ip, ipzero))
2522 {
2523 if (!resolve_name (cli->desthost, &cli->dest_ip, 0x20))
2524 {
2525 return False;
2526 }
2527 if (ip)
2528 *ip = cli->dest_ip;
2529 }
2530 else
2531 {
2532 cli->dest_ip = *ip;
2533 }
2534
2535 if (cli->port == 0)
2536 cli->port = 139; /* Set to default */
2537
2538 cli->fd = open_socket_out (SOCK_STREAM, &cli->dest_ip, cli->port, cli->timeout);
2539 if (cli->fd == -1)
2540 return False;
2541
2542 return True;
2543 }
2544
2545
2546 /****************************************************************************
2547 initialise a client structure
2548 ****************************************************************************/
2549 struct cli_state *
cli_initialise(struct cli_state * cli)2550 cli_initialise (struct cli_state *cli)
2551 {
2552 if (!cli)
2553 {
2554 cli = (struct cli_state *) malloc (sizeof (*cli));
2555 if (!cli)
2556 return NULL;
2557 ZERO_STRUCTP (cli);
2558 }
2559
2560 if (cli->initialised)
2561 {
2562 cli_shutdown (cli);
2563 }
2564
2565 ZERO_STRUCTP (cli);
2566
2567 cli->port = 0;
2568 cli->fd = -1;
2569 cli->cnum = -1;
2570 cli->pid = (uint16) getpid ();
2571 cli->mid = 1;
2572 cli->vuid = UID_FIELD_INVALID;
2573 cli->protocol = PROTOCOL_NT1;
2574 cli->timeout = 20000; /* Timeout is in milliseconds. */
2575 cli->bufsize = CLI_BUFFER_SIZE + 4;
2576 cli->max_xmit = cli->bufsize;
2577 cli->outbuf = (char *) malloc (cli->bufsize);
2578 cli->inbuf = (char *) malloc (cli->bufsize);
2579 if (!cli->outbuf || !cli->inbuf)
2580 {
2581 return False;
2582 }
2583
2584 cli->initialised = 1;
2585
2586 return cli;
2587 }
2588
2589 /****************************************************************************
2590 shutdown a client structure
2591 ****************************************************************************/
2592 void
cli_shutdown(struct cli_state * cli)2593 cli_shutdown (struct cli_state *cli)
2594 {
2595 if (cli->outbuf)
2596 {
2597 free (cli->outbuf);
2598 }
2599 if (cli->inbuf)
2600 {
2601 free (cli->inbuf);
2602 }
2603 #ifdef WITH_SSL
2604 if (cli->fd != -1)
2605 sslutil_disconnect (cli->fd);
2606 #endif /* WITH_SSL */
2607 if (cli->fd != -1)
2608 close (cli->fd);
2609 memset (cli, 0, sizeof (*cli));
2610 }
2611
2612
2613 /****************************************************************************
2614 return error codes for the last packet
2615 returns 0 if there was no error and the best approx of a unix errno
2616 otherwise
2617
2618 for 32 bit "warnings", a return code of 0 is expected.
2619
2620 ****************************************************************************/
2621 int
cli_error(struct cli_state * cli,uint8 * eclass,uint32 * num,uint32 * nt_rpc_error)2622 cli_error (struct cli_state *cli, uint8 * eclass, uint32 * num, uint32 * nt_rpc_error)
2623 {
2624 int flgs2 = SVAL (cli->inbuf, smb_flg2);
2625 char rcls;
2626 int code;
2627
2628 if (eclass)
2629 *eclass = 0;
2630 if (num)
2631 *num = 0;
2632 if (nt_rpc_error)
2633 *nt_rpc_error = cli->nt_error;
2634
2635 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES)
2636 {
2637 /* 32 bit error codes detected */
2638 uint32 nt_err = IVAL (cli->inbuf, smb_rcls);
2639 if (num)
2640 *num = nt_err;
2641 DEBUG (10, ("cli_error: 32 bit codes: code=%08x\n", nt_err));
2642 if (!IS_BITS_SET_ALL (nt_err, 0xc0000000))
2643 return 0;
2644
2645 switch (nt_err & 0xFFFFFF)
2646 {
2647 case NT_STATUS_ACCESS_VIOLATION:
2648 return EACCES;
2649 case NT_STATUS_NO_SUCH_FILE:
2650 return ENOENT;
2651 case NT_STATUS_NO_SUCH_DEVICE:
2652 return ENODEV;
2653 case NT_STATUS_INVALID_HANDLE:
2654 return EBADF;
2655 case NT_STATUS_NO_MEMORY:
2656 return ENOMEM;
2657 case NT_STATUS_ACCESS_DENIED:
2658 return EACCES;
2659 case NT_STATUS_OBJECT_NAME_NOT_FOUND:
2660 return ENOENT;
2661 case NT_STATUS_SHARING_VIOLATION:
2662 return EBUSY;
2663 case NT_STATUS_OBJECT_PATH_INVALID:
2664 return ENOTDIR;
2665 case NT_STATUS_OBJECT_NAME_COLLISION:
2666 return EEXIST;
2667 }
2668
2669 /* for all other cases - a default code */
2670 return EINVAL;
2671 }
2672
2673 rcls = CVAL (cli->inbuf, smb_rcls);
2674 code = SVAL (cli->inbuf, smb_err);
2675 if (rcls == 0)
2676 return 0;
2677
2678 if (eclass)
2679 *eclass = rcls;
2680 if (num)
2681 *num = code;
2682
2683 if (rcls == ERRDOS)
2684 {
2685 switch (code)
2686 {
2687 case ERRbadfile:
2688 return ENOENT;
2689 case ERRbadpath:
2690 return ENOTDIR;
2691 case ERRnoaccess:
2692 return EACCES;
2693 case ERRfilexists:
2694 return EEXIST;
2695 case ERRrename:
2696 return EEXIST;
2697 case ERRbadshare:
2698 return EBUSY;
2699 case ERRlock:
2700 return EBUSY;
2701 }
2702 }
2703 if (rcls == ERRSRV)
2704 {
2705 switch (code)
2706 {
2707 case ERRbadpw:
2708 return EPERM;
2709 case ERRaccess:
2710 return EACCES;
2711 case ERRnoresource:
2712 return ENOMEM;
2713 case ERRinvdevice:
2714 return ENODEV;
2715 case ERRinvnetname:
2716 return ENODEV;
2717 }
2718 }
2719 /* for other cases */
2720 return EINVAL;
2721 }
2722
2723 #if 0
2724 /****************************************************************************
2725 set socket options on a open connection
2726 ****************************************************************************/
2727 void
2728 cli_sockopt (struct cli_state *cli, char *options)
2729 {
2730 set_socket_options (cli->fd, options);
2731 }
2732
2733 /****************************************************************************
2734 set the PID to use for smb messages. Return the old pid.
2735 ****************************************************************************/
2736 uint16
2737 cli_setpid (struct cli_state *cli, uint16 pid)
2738 {
2739 uint16 ret = cli->pid;
2740 cli->pid = pid;
2741 return ret;
2742 }
2743 #endif /* 0 */
2744
2745 /****************************************************************************
2746 re-establishes a connection
2747 ****************************************************************************/
2748 BOOL
cli_reestablish_connection(struct cli_state * cli)2749 cli_reestablish_connection (struct cli_state * cli)
2750 {
2751 struct nmb_name calling;
2752 struct nmb_name called;
2753 fstring dest_host;
2754 fstring share;
2755 fstring dev;
2756 BOOL do_tcon = False;
2757 int oldfd = cli->fd;
2758
2759 if (!cli->initialised || cli->fd == -1)
2760 {
2761 DEBUG (3, ("cli_reestablish_connection: not connected\n"));
2762 return False;
2763 }
2764
2765 /* copy the parameters necessary to re-establish the connection */
2766
2767 if (cli->cnum != 0)
2768 {
2769 fstrcpy (share, cli->share);
2770 fstrcpy (dev, cli->dev);
2771 do_tcon = True;
2772 }
2773
2774 memcpy (&called, &(cli->called), sizeof (called));
2775 memcpy (&calling, &(cli->calling), sizeof (calling));
2776 fstrcpy (dest_host, cli->full_dest_host_name);
2777
2778 DEBUG (5, ("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2779 nmb_namestr (&calling), nmb_namestr (&called),
2780 inet_ntoa (cli->dest_ip), cli->user_name, cli->domain));
2781
2782 cli->fd = -1;
2783
2784 if (cli_establish_connection (cli,
2785 dest_host, &cli->dest_ip,
2786 &calling, &called, share, dev, False, do_tcon))
2787 {
2788 if (cli->fd != oldfd)
2789 {
2790 if (dup2 (cli->fd, oldfd) == oldfd)
2791 {
2792 close (cli->fd);
2793 }
2794 }
2795 return True;
2796 }
2797 return False;
2798 }
2799
2800 /****************************************************************************
2801 establishes a connection right up to doing tconX, reading in a password.
2802 ****************************************************************************/
2803 BOOL
cli_establish_connection(struct cli_state * cli,char * dest_host,struct in_addr * dest_ip,struct nmb_name * calling,struct nmb_name * called,char * service,char * service_type,BOOL do_shutdown,BOOL do_tcon)2804 cli_establish_connection (struct cli_state * cli,
2805 char *dest_host, struct in_addr * dest_ip,
2806 struct nmb_name * calling, struct nmb_name * called,
2807 char *service, char *service_type, BOOL do_shutdown, BOOL do_tcon)
2808 {
2809 DEBUG (5, ("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
2810 nmb_namestr (calling), nmb_namestr (called), inet_ntoa (*dest_ip),
2811 cli->user_name, cli->domain));
2812
2813 /* establish connection */
2814
2815 if ((!cli->initialised))
2816 {
2817 return False;
2818 }
2819
2820 if (cli->fd == -1)
2821 {
2822 if (!cli_connect (cli, dest_host, dest_ip))
2823 {
2824 DEBUG (1, ("cli_establish_connection: failed to connect to %s (%s)\n",
2825 nmb_namestr (calling), inet_ntoa (*dest_ip)));
2826 return False;
2827 }
2828 }
2829
2830 if (!cli_session_request (cli, calling, called))
2831 {
2832 DEBUG (1, ("failed session request\n"));
2833 if (do_shutdown)
2834 cli_shutdown (cli);
2835 return False;
2836 }
2837
2838 if (!cli_negprot (cli))
2839 {
2840 DEBUG (1, ("failed negprot\n"));
2841 if (do_shutdown)
2842 cli_shutdown (cli);
2843 return False;
2844 }
2845
2846 if (cli->pwd.cleartext || cli->pwd.null_pwd)
2847 {
2848 fstring passwd;
2849 int pass_len;
2850
2851 if (cli->pwd.null_pwd)
2852 {
2853 /* attempt null session */
2854 passwd[0] = 0;
2855 pass_len = 1;
2856 }
2857 else
2858 {
2859 /* attempt clear-text session */
2860 pwd_get_cleartext (&(cli->pwd), passwd);
2861 pass_len = strlen (passwd);
2862 }
2863
2864 /* attempt clear-text session */
2865 if (!cli_session_setup (cli, cli->user_name, passwd, pass_len, NULL, 0, cli->domain))
2866 {
2867 DEBUG (1, ("failed session setup\n"));
2868 if (do_shutdown)
2869 {
2870 cli_shutdown (cli);
2871 }
2872 return False;
2873 }
2874 if (do_tcon)
2875 {
2876 if (!cli_send_tconX (cli, service, service_type, (char *) passwd, strlen (passwd)))
2877 {
2878 DEBUG (1, ("failed tcon_X\n"));
2879 if (do_shutdown)
2880 {
2881 cli_shutdown (cli);
2882 }
2883 return False;
2884 }
2885 }
2886 }
2887 else
2888 {
2889 /* attempt encrypted session */
2890 unsigned char nt_sess_pwd[24];
2891 unsigned char lm_sess_pwd[24];
2892
2893 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
2894 pwd_make_lm_nt_owf (&(cli->pwd), cli->cryptkey);
2895 pwd_get_lm_nt_owf (&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
2896
2897 /* attempt encrypted session */
2898 if (!cli_session_setup (cli, cli->user_name,
2899 (char *) lm_sess_pwd, sizeof (lm_sess_pwd),
2900 (char *) nt_sess_pwd, sizeof (nt_sess_pwd), cli->domain))
2901 {
2902 DEBUG (1, ("failed session setup\n"));
2903 if (do_shutdown)
2904 cli_shutdown (cli);
2905 return False;
2906 }
2907
2908 if (do_tcon)
2909 {
2910 if (!cli_send_tconX (cli, service, service_type,
2911 (char *) nt_sess_pwd, sizeof (nt_sess_pwd)))
2912 {
2913 DEBUG (1, ("failed tcon_X\n"));
2914 if (do_shutdown)
2915 cli_shutdown (cli);
2916 return False;
2917 }
2918 }
2919 }
2920
2921 if (do_shutdown)
2922 cli_shutdown (cli);
2923
2924 return True;
2925 }
2926
2927
2928 /****************************************************************************
2929 check for existence of a dir
2930 ****************************************************************************/
2931 BOOL
cli_chkpath(struct cli_state * cli,char * path)2932 cli_chkpath (struct cli_state * cli, char *path)
2933 {
2934 pstring path2;
2935 char *p;
2936
2937 safe_strcpy (path2, path, sizeof (pstring) - 1);
2938 trim_string (path2, NULL, "\\");
2939 if (!*path2)
2940 *path2 = '\\';
2941
2942 memset (cli->outbuf, '\0', smb_size);
2943 set_message (cli->outbuf, 0, 4 + strlen (path2), True);
2944 SCVAL (cli->outbuf, smb_com, SMBchkpth);
2945 SSVAL (cli->outbuf, smb_tid, cli->cnum);
2946 cli_setup_packet (cli);
2947 p = smb_buf (cli->outbuf);
2948 *p++ = 4;
2949 safe_strcpy (p, path2, strlen (path2));
2950
2951 cli_send_smb (cli);
2952 if (!cli_receive_smb (cli))
2953 {
2954 return False;
2955 }
2956
2957 if (cli_error (cli, NULL, NULL, NULL))
2958 return False;
2959
2960 return True;
2961 }
2962
2963 #if 0
2964 /****************************************************************************
2965 start a message sequence
2966 ****************************************************************************/
2967 BOOL
2968 cli_message_start (struct cli_state * cli, char *host, char *username, int *grp)
2969 {
2970 char *p;
2971
2972 /* send a SMBsendstrt command */
2973 memset (cli->outbuf, '\0', smb_size);
2974 set_message (cli->outbuf, 0, 0, True);
2975 CVAL (cli->outbuf, smb_com) = SMBsendstrt;
2976 SSVAL (cli->outbuf, smb_tid, cli->cnum);
2977 cli_setup_packet (cli);
2978
2979 p = smb_buf (cli->outbuf);
2980 *p++ = 4;
2981 pstrcpy (p, username);
2982 p = skip_string (p, 1);
2983 *p++ = 4;
2984 pstrcpy (p, host);
2985 p = skip_string (p, 1);
2986
2987 set_message (cli->outbuf, 0, PTR_DIFF (p, smb_buf (cli->outbuf)), False);
2988
2989 cli_send_smb (cli);
2990
2991 if (!cli_receive_smb (cli))
2992 {
2993 return False;
2994 }
2995
2996 if (cli_error (cli, NULL, NULL, NULL))
2997 return False;
2998
2999 *grp = SVAL (cli->inbuf, smb_vwv0);
3000
3001 return True;
3002 }
3003
3004
3005 /****************************************************************************
3006 send a message
3007 ****************************************************************************/
3008 BOOL
3009 cli_message_text (struct cli_state * cli, char *msg, int len, int grp)
3010 {
3011 char *p;
3012
3013 memset (cli->outbuf, '\0', smb_size);
3014 set_message (cli->outbuf, 1, len + 3, True);
3015 CVAL (cli->outbuf, smb_com) = SMBsendtxt;
3016 SSVAL (cli->outbuf, smb_tid, cli->cnum);
3017 cli_setup_packet (cli);
3018
3019 SSVAL (cli->outbuf, smb_vwv0, grp);
3020
3021 p = smb_buf (cli->outbuf);
3022 *p = 1;
3023 SSVAL (p, 1, len);
3024 memcpy (p + 3, msg, len);
3025 cli_send_smb (cli);
3026
3027 if (!cli_receive_smb (cli))
3028 {
3029 return False;
3030 }
3031
3032 if (cli_error (cli, NULL, NULL, NULL))
3033 return False;
3034
3035 return True;
3036 }
3037
3038 /****************************************************************************
3039 end a message
3040 ****************************************************************************/
3041 BOOL
3042 cli_message_end (struct cli_state * cli, int grp)
3043 {
3044 memset (cli->outbuf, '\0', smb_size);
3045 set_message (cli->outbuf, 1, 0, True);
3046 CVAL (cli->outbuf, smb_com) = SMBsendend;
3047 SSVAL (cli->outbuf, smb_tid, cli->cnum);
3048
3049 SSVAL (cli->outbuf, smb_vwv0, grp);
3050
3051 cli_setup_packet (cli);
3052
3053 cli_send_smb (cli);
3054
3055 if (!cli_receive_smb (cli))
3056 {
3057 return False;
3058 }
3059
3060 if (cli_error (cli, NULL, NULL, NULL))
3061 return False;
3062
3063 return True;
3064 }
3065 #endif /*0 */
3066
3067 #if 0 /* May be useful one day */
3068 /****************************************************************************
3069 query disk space
3070 ****************************************************************************/
3071 BOOL
3072 cli_dskattr (struct cli_state * cli, int *bsize, int *total, int *avail)
3073 {
3074 memset (cli->outbuf, '\0', smb_size);
3075 set_message (cli->outbuf, 0, 0, True);
3076 CVAL (cli->outbuf, smb_com) = SMBdskattr;
3077 SSVAL (cli->outbuf, smb_tid, cli->cnum);
3078 cli_setup_packet (cli);
3079
3080 cli_send_smb (cli);
3081 if (!cli_receive_smb (cli))
3082 {
3083 return False;
3084 }
3085
3086 *bsize = SVAL (cli->inbuf, smb_vwv1) * SVAL (cli->inbuf, smb_vwv2);
3087 *total = SVAL (cli->inbuf, smb_vwv0);
3088 *avail = SVAL (cli->inbuf, smb_vwv3);
3089
3090 return True;
3091 }
3092 #endif /* 0 */
3093