2 Unix SMB/Netbios implementation.
4 SMB client generic functions
5 Copyright (C) Andrew Tridgell 1994-1999
6 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 extern int DEBUGLEVEL;
32 * set the port that will be used for connections by the client
35 int cli_set_port(struct cli_state *cli, int port)
41 return cli->port; /* return it incase caller wants it */
45 /****************************************************************************
46 copy a string (unicode or otherwise) into an SMB buffer. skips a string
48 ****************************************************************************/
49 static char *cli_put_string(struct cli_state *cli, char *p, const char *str,
52 uint16 flgs2 = SVAL(cli->outbuf, smb_flg2);
53 if (IS_BITS_SET_ALL(flgs2, FLAGS2_UNICODE_STRINGS))
55 p = align2(p, cli->outbuf);
56 p = ascii_to_unibuf(p, str, 1024);
67 p = skip_string(p, 1);
76 /****************************************************************************
77 copy a string (unicode or otherwise) into an SMB buffer. skips a string
79 ****************************************************************************/
80 static const char *cli_get_string(struct cli_state *cli, char *p,
81 char *str, size_t str_len)
83 uint16 flgs2 = SVAL(cli->inbuf,smb_flg2);
84 if (IS_BITS_SET_ALL(flgs2, FLAGS2_UNICODE_STRINGS))
86 return unibuf_to_ascii(str, p, str_len);
90 safe_strcpy(str, p, str_len-1);
91 return skip_string(p, 1);
95 /****************************************************************************
97 ****************************************************************************/
98 static BOOL cli_receive_smb(struct cli_state *cli)
100 return client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
103 /****************************************************************************
104 send an smb to a fd and re-establish if necessary
105 ****************************************************************************/
106 static BOOL cli_send_smb(struct cli_state *cli, BOOL show)
111 BOOL reestablished=False;
113 len = smb_len(cli->outbuf) + 4;
117 uint8 msg_type = CVAL(cli->outbuf, 0);
120 show_msg(cli->outbuf);
124 dump_data(10, cli->outbuf, len);
128 while (nwritten < len) {
129 ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
130 if (ret <= 0 && errno == EPIPE && !reestablished)
132 DEBUG(5,("cli_send_smb: write error (%s) - reconnecting\n",
135 if (cli_reestablish_connection(cli)) {
136 reestablished = True;
142 DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",
152 /******************************************************
153 Return an error message - either an SMB error or a RAP
155 *******************************************************/
157 char *cli_errstr(struct cli_state *cli)
159 static fstring error_message;
160 cli_safe_errstr(cli, error_message, sizeof(error_message));
161 return error_message;
164 /****************************************************************************
165 return a description of an SMB error
166 ****************************************************************************/
167 void cli_safe_smb_errstr(struct cli_state *cli, char *msg, size_t len)
169 smb_safe_errstr(cli->inbuf, msg, len);
172 /*****************************************************
173 RAP error codes - a small start but will be extended.
174 *******************************************************/
182 {5, "User has insufficient privilege" },
183 {86, "The specified password is invalid" },
184 {2226, "Operation only permitted on a Primary Domain Controller" },
185 {2242, "The password of this user has expired." },
186 {2243, "The password of this user cannot change." },
187 {2244, "This password cannot be used now (password history conflict)." },
188 {2245, "The password is shorter than required." },
189 {2246, "The password of this user is too recent to change."},
193 /****************************************************************************
194 return a description of a RAP error
195 ****************************************************************************/
196 BOOL get_safe_rap_errstr(int rap_error, char *err_msg, size_t msglen)
200 slprintf(err_msg, msglen - 1, "RAP code %d", rap_error);
202 for (i = 0; rap_errmap[i].message != NULL; i++)
204 if (rap_errmap[i].err == rap_error)
206 safe_strcpy( err_msg, rap_errmap[i].message, msglen);
213 /****************************************************************************
214 return a description of an SMB error
215 ****************************************************************************/
216 void cli_safe_errstr(struct cli_state *cli, char *err_msg, size_t msglen)
222 * Errors are of three kinds - smb errors,
223 * dealt with by cli_smb_errstr, NT errors,
224 * whose code is in cli.nt_error, and rap
225 * errors, whose error code is in cli.rap_error.
228 cli_error(cli, &errclass, &errnum);
232 cli_safe_smb_errstr(cli, err_msg, msglen);
234 else if (cli->nt_error)
237 * Was it an NT error ?
240 (void)get_safe_nt_error_msg(cli->nt_error, err_msg, msglen);
245 * Must have been a rap error.
247 (void)get_safe_rap_errstr(cli->rap_error, err_msg, msglen);
250 /****************************************************************************
251 setup basics in a outgoing packet
252 ****************************************************************************/
253 static void cli_setup_packet(struct cli_state *cli)
256 flgs2 |= FLAGS2_LONG_PATH_COMPONENTS;
257 flgs2 |= FLAGS2_32_BIT_ERROR_CODES;
259 flgs2 |= FLAGS2_UNICODE_STRINGS;
261 flgs2 |= FLAGS2_EXT_SEC;
265 SSVAL(cli->outbuf,smb_pid,cli->pid);
266 SSVAL(cli->outbuf,smb_uid,cli->vuid);
267 SSVAL(cli->outbuf,smb_mid,cli->mid);
269 if (cli->protocol > PROTOCOL_CORE)
271 SCVAL(cli->outbuf,smb_flg,0x8);
272 SSVAL(cli->outbuf,smb_flg2,flgs2);
277 /*****************************************************************************
278 Convert a character pointer in a cli_call_api() response to a form we can use.
279 This function contains code to prevent core dumps if the server returns
281 *****************************************************************************/
282 static char *fix_char_ptr(unsigned int datap, unsigned int converter,
283 char *rdata, int rdrcnt)
285 if (datap == 0) { /* turn NULL pointers into zero length strings */
288 unsigned int offset = datap - converter;
290 if (offset >= rdrcnt) {
291 DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
292 datap, converter, rdrcnt));
295 return &rdata[offset];
300 /****************************************************************************
301 send a SMB trans or trans2 request
302 ****************************************************************************/
303 BOOL cli_send_trans(struct cli_state *cli, int trans,
304 char *name, int pipe_name_len,
306 uint16 *setup, int lsetup, int msetup,
307 char *param, int lparam, int mparam,
308 char *data, int ldata, int mdata)
311 int this_ldata,this_lparam;
312 int tot_data=0,tot_param=0;
313 char *outdata,*outparam;
316 this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
317 this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
319 bzero(cli->outbuf,smb_size);
320 set_message(cli->outbuf,14+lsetup,0,True);
321 CVAL(cli->outbuf,smb_com) = trans;
322 SSVAL(cli->outbuf,smb_tid, cli->cnum);
323 cli_setup_packet(cli);
325 outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len+1 : 3);
326 outdata = outparam+this_lparam;
328 /* primary request */
329 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
330 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
331 SSVAL(cli->outbuf,smb_mprcnt,mparam); /* mprcnt */
332 SSVAL(cli->outbuf,smb_mdrcnt,mdata); /* mdrcnt */
333 SCVAL(cli->outbuf,smb_msrcnt,msetup); /* msrcnt */
334 SSVAL(cli->outbuf,smb_flags,flags); /* flags */
335 SIVAL(cli->outbuf,smb_timeout,0); /* timeout */
336 SSVAL(cli->outbuf,smb_pscnt,this_lparam); /* pscnt */
337 SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
338 SSVAL(cli->outbuf,smb_dscnt,this_ldata); /* dscnt */
339 SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
340 SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */
341 for (i=0;i<lsetup;i++) /* setup[] */
342 SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
343 p = smb_buf(cli->outbuf);
344 if (trans==SMBtrans) {
345 memcpy(p,name, pipe_name_len + 1); /* name[] */
347 *p++ = 0; /* put in a null smb_name */
348 *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */
350 if (this_lparam) /* param[] */
351 memcpy(outparam,param,this_lparam);
352 if (this_ldata) /* data[] */
353 memcpy(outdata,data,this_ldata);
354 set_message(cli->outbuf,14+lsetup, /* wcnt, bcc */
355 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
357 cli_send_smb(cli, True);
359 if (this_ldata < ldata || this_lparam < lparam) {
360 /* receive interim response */
361 if (!cli_receive_smb(cli) ||
362 CVAL(cli->inbuf,smb_rcls) != 0) {
366 tot_data = this_ldata;
367 tot_param = this_lparam;
369 while (tot_data < ldata || tot_param < lparam) {
370 this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
371 this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
373 set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
374 CVAL(cli->outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
376 outparam = smb_buf(cli->outbuf);
377 outdata = outparam+this_lparam;
379 /* secondary request */
380 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
381 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
382 SSVAL(cli->outbuf,smb_spscnt,this_lparam); /* pscnt */
383 SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
384 SSVAL(cli->outbuf,smb_spsdisp,tot_param); /* psdisp */
385 SSVAL(cli->outbuf,smb_sdscnt,this_ldata); /* dscnt */
386 SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
387 SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */
388 if (trans==SMBtrans2)
389 SSVALS(cli->outbuf,smb_sfid,fid); /* fid */
390 if (this_lparam) /* param[] */
391 memcpy(outparam,param,this_lparam);
392 if (this_ldata) /* data[] */
393 memcpy(outdata,data,this_ldata);
394 set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
395 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
397 cli_send_smb(cli, True);
399 tot_data += this_ldata;
400 tot_param += this_lparam;
408 /****************************************************************************
409 receive a SMB trans or trans2 response allocating the necessary memory
410 ****************************************************************************/
411 static BOOL cli_receive_trans(struct cli_state *cli,int trans,
412 char **param, int *param_len,
413 char **data, int *data_len)
417 int this_data,this_param;
419 *data_len = *param_len = 0;
421 if (!cli_receive_smb(cli))
425 if (CVAL(cli->inbuf,smb_com) != trans) {
426 DEBUG(0,("Expected %s response, got command 0x%02x\n",
427 trans==SMBtrans?"SMBtrans":"SMBtrans2",
428 CVAL(cli->inbuf,smb_com)));
432 if (cli_error(cli, NULL, NULL))
437 /* parse out the lengths */
438 total_data = SVAL(cli->inbuf,smb_tdrcnt);
439 total_param = SVAL(cli->inbuf,smb_tprcnt);
442 *data = Realloc(*data,total_data);
443 *param = Realloc(*param,total_param);
446 this_data = SVAL(cli->inbuf,smb_drcnt);
447 this_param = SVAL(cli->inbuf,smb_prcnt);
449 if (this_data + *data_len > total_data ||
450 this_param + *param_len > total_param) {
451 DEBUG(1,("Data overflow in cli_receive_trans\n"));
456 memcpy(*data + SVAL(cli->inbuf,smb_drdisp),
457 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff),
460 memcpy(*param + SVAL(cli->inbuf,smb_prdisp),
461 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff),
463 *data_len += this_data;
464 *param_len += this_param;
466 /* parse out the total lengths again - they can shrink! */
467 total_data = SVAL(cli->inbuf,smb_tdrcnt);
468 total_param = SVAL(cli->inbuf,smb_tprcnt);
470 if (total_data <= *data_len && total_param <= *param_len)
473 if (!cli_receive_smb(cli))
477 if (CVAL(cli->inbuf,smb_com) != trans) {
478 DEBUG(0,("Expected %s response, got command 0x%02x\n",
479 trans==SMBtrans?"SMBtrans":"SMBtrans2",
480 CVAL(cli->inbuf,smb_com)));
484 if (cli_error(cli, NULL, NULL))
493 /****************************************************************************
494 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
495 ****************************************************************************/
496 BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name, int pipe_name_len,
497 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
498 char *params, uint32 param_count, uint32 max_param_count,
499 char *data, uint32 data_count, uint32 max_data_count,
500 char **rparam, uint32 *rparam_count,
501 char **rdata, uint32 *rdata_count)
503 if (pipe_name_len == 0)
504 pipe_name_len = strlen(pipe_name);
506 cli_send_trans(cli, SMBtrans,
507 pipe_name, pipe_name_len,
508 0,0, /* fid, flags */
509 setup, setup_count, max_setup_count,
510 params, param_count, max_param_count,
511 data, data_count, max_data_count);
513 return (cli_receive_trans(cli, SMBtrans,
514 rparam, (int *)rparam_count,
515 rdata, (int *)rdata_count));
518 /****************************************************************************
520 ****************************************************************************/
521 BOOL cli_api(struct cli_state *cli,
522 char *param, int prcnt, int mprcnt,
523 char *data, int drcnt, int mdrcnt,
524 char **rparam, int *rprcnt,
525 char **rdata, int *rdrcnt)
527 cli_send_trans(cli,SMBtrans,
528 PIPE_LANMAN,strlen(PIPE_LANMAN), /* Name, length */
529 0,0, /* fid, flags */
530 NULL,0,0, /* Setup, length, max */
531 param, prcnt, mprcnt, /* Params, length, max */
532 data, drcnt, mdrcnt /* Data, length, max */
535 return (cli_receive_trans(cli,SMBtrans,
541 /****************************************************************************
542 perform a NetWkstaUserLogon
543 ****************************************************************************/
544 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
552 memset(param, 0, sizeof(param));
554 /* send a SMBtrans command with api NetWkstaUserLogon */
556 SSVAL(p,0,132); /* api number */
558 pstrcpy(p,"OOWb54WrLh");
559 p = skip_string(p,1);
560 pstrcpy(p,"WB21BWDWWDDDDDDDzzzD");
561 p = skip_string(p,1);
570 pstrcpy(p, workstation);
573 SSVAL(p, 0, CLI_BUFFER_SIZE);
575 SSVAL(p, 0, CLI_BUFFER_SIZE);
579 param, PTR_DIFF(p,param),1024, /* param, length, max */
580 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
581 &rparam, &rprcnt, /* return params, return size */
582 &rdata, &rdrcnt /* return data, return size */
584 cli->rap_error = SVAL(rparam,0);
587 if (cli->rap_error == 0) {
588 DEBUG(4,("NetWkstaUserLogon success\n"));
589 cli->privilages = SVAL(p, 24);
590 fstrcpy(cli->eff_name,p+2);
592 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
600 return (cli->rap_error == 0);
603 /****************************************************************************
604 call a NetShareEnum - try and browse available connections on a host
605 ****************************************************************************/
606 BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *))
615 /* now send a SMBtrans command with api RNetShareEnum */
617 SSVAL(p,0,0); /* api number */
620 p = skip_string(p,1);
622 p = skip_string(p,1);
628 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
629 NULL, 0, 0xFFFF, /* data, length, maxlen */
630 &rparam, &rprcnt, /* return params, length */
631 &rdata, &rdrcnt)) /* return data, length */
633 int res = SVAL(rparam,0);
634 int converter=SVAL(rparam,2);
637 if (res == 0 || res == ERRmoredata) {
638 count=SVAL(rparam,4);
641 for (i=0;i<count;i++,p+=20) {
643 int type = SVAL(p,14);
644 int comment_offset = IVAL(p,16) & 0xFFFF;
645 char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
646 fn(sname, type, cmnt);
649 DEBUG(4,("NetShareEnum res=%d\n", res));
652 DEBUG(4,("NetShareEnum failed\n"));
664 /****************************************************************************
665 call a NetServerEnum for the specified workgroup and servertype mask.
666 This function then calls the specified callback function for each name returned.
668 The callback function takes 3 arguments: the machine name, the server type and
670 ****************************************************************************/
671 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
672 void (*fn)(const char *, uint32, const char *))
682 /* send a SMBtrans command with api NetServerEnum */
684 SSVAL(p,0,0x68); /* api number */
686 pstrcpy(p,"WrLehDz");
687 p = skip_string(p,1);
689 pstrcpy(p,"B16BBDz");
691 p = skip_string(p,1);
693 SSVAL(p,2,CLI_BUFFER_SIZE);
698 pstrcpy(p, workgroup);
699 p = skip_string(p,1);
702 param, PTR_DIFF(p,param), 8, /* params, length, max */
703 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
704 &rparam, &rprcnt, /* return params, return size */
705 &rdata, &rdrcnt /* return data, return size */
707 int res = SVAL(rparam,0);
708 int converter=SVAL(rparam,2);
711 if (res == 0 || res == ERRmoredata) {
712 count=SVAL(rparam,4);
715 for (i = 0;i < count;i++, p += 26) {
717 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
718 char *cmnt = comment_offset?(rdata+comment_offset):"";
719 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
721 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
723 fn(sname, stype, cmnt);
745 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
746 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
747 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
748 {PROTOCOL_LANMAN1,"LANMAN1.0"},
749 {PROTOCOL_LANMAN2,"LM1.2X002"},
750 {PROTOCOL_LANMAN2,"Samba"},
751 {PROTOCOL_NT1,"NT LANMAN 1.0"},
752 {PROTOCOL_NT1,"NT LM 0.12"},
759 /****************************************************************************
761 ****************************************************************************/
762 BOOL cli_session_setup_x(struct cli_state *cli,
764 char *pass, int passlen,
765 char *ntpass, int ntpasslen,
771 BOOL esec = cli->capabilities & CAP_EXTENDED_SECURITY;
773 DEBUG(100,("cli_session_setup. extended security: %s\n",
776 #ifdef DEBUG_PASSWORD
777 DEBUG(100,("cli_session_setup. pass, ntpass\n"));
778 dump_data(100, pass, passlen);
779 dump_data(100, ntpass, ntpasslen);
782 if (cli->protocol < PROTOCOL_LANMAN1)
787 /* send a session setup command */
788 bzero(cli->outbuf,smb_size);
790 if (cli->protocol < PROTOCOL_NT1)
792 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
793 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
794 cli_setup_packet(cli);
796 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
797 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
798 SSVAL(cli->outbuf,smb_vwv3,2);
799 SSVAL(cli->outbuf,smb_vwv4,1);
800 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
801 SSVAL(cli->outbuf,smb_vwv7,passlen);
802 p = smb_buf(cli->outbuf);
803 memcpy(p,pass,passlen);
810 set_message(cli->outbuf,12,0,True);
811 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
812 cli_setup_packet(cli);
814 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
815 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
816 SSVAL(cli->outbuf,smb_vwv3,2);
817 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
818 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
819 SSVAL(cli->outbuf,smb_vwv7,passlen);
820 SIVAL(cli->outbuf,smb_vwv10, CAP_EXTENDED_SECURITY|CAP_STATUS32|CAP_UNICODE);
821 p = smb_buf(cli->outbuf);
822 memcpy(p,pass,passlen);
825 p = cli_put_string(cli, p, "Unix", False);
826 p = cli_put_string(cli, p, "Samba", False);
827 p = cli_put_string(cli, p, "", False);
830 set_message(cli->outbuf,12,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
834 set_message(cli->outbuf,13,0,True);
835 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
836 cli_setup_packet(cli);
838 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
839 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
840 SSVAL(cli->outbuf,smb_vwv3,2);
841 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
842 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
843 SSVAL(cli->outbuf,smb_vwv7,passlen);
844 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
845 SSVAL(cli->outbuf,smb_vwv11,0);
846 p = smb_buf(cli->outbuf);
847 memcpy(p,pass,passlen);
848 p += SVAL(cli->outbuf,smb_vwv7);
849 memcpy(p,ntpass,ntpasslen);
850 p += SVAL(cli->outbuf,smb_vwv8);
852 p = cli_put_string(cli, p, user, False);
853 strupper(user_domain);
854 p = cli_put_string(cli, p, user_domain, False);
855 p = cli_put_string(cli, p, "Unix", True);
856 p = cli_put_string(cli, p, "Samba", False);
858 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
861 cli_send_smb(cli, True);
862 if (!cli_receive_smb(cli))
864 DEBUG(10,("cli_session_setup_x: receive smb failed\n"));
868 if (cli_error(cli, &eclass, &ecode))
870 uint16 flgs2 = SVAL(cli->inbuf,smb_flg2);
871 if (IS_BITS_CLR_ALL(flgs2, FLAGS2_32_BIT_ERROR_CODES))
873 if (ecode != ERRmoredata || !esec)
878 else if (ecode != 0xC0000016) /* STATUS_MORE_PROCESSING_REQD */
884 /* use the returned vuid from now on */
885 cli->vuid = SVAL(cli->inbuf,smb_uid);
887 if (cli->protocol >= PROTOCOL_NT1)
895 * Save off some of the connected server
902 server_os = smb_buf(cli->inbuf);
903 server_type = skip_string(server_os,1);
904 server_domain = skip_string(server_type,1);
906 fstrcpy(cli->server_os, server_os);
907 fstrcpy(cli->server_type, server_type);
908 fstrcpy(cli->server_domain, server_domain);
915 static BOOL cli_calc_session_pwds(struct cli_state *cli,
916 char *pword, char *ntpword,
917 char *pass, int *passlen,
918 char *ntpass, int *ntpasslen,
921 BOOL ntpass_ok = ntpass != NULL && ntpasslen != NULL;
923 if (pass == NULL || passlen == NULL)
925 DEBUG(0,("cli_calc_session_pwds: pass and passlen are NULL\n"));
928 if ((ntpass != NULL || ntpasslen != NULL) &&
929 (ntpass == NULL || ntpasslen == NULL))
931 DEBUG(0,("cli_calc_session_pwds: ntpasswd pointers invalid\n"));
935 #ifdef DEBUG_PASSWORD
936 DEBUG(100,("cli_calc_session_pwds. pass, ntpass\n"));
937 dump_data(100, pass, *passlen);
940 dump_data(100, ntpass, *ntpasslen);
943 if (!IS_BITS_SET_ALL(cli->sec_mode, 1))
945 /* if in share level security then don't send a password now */
955 else if ((*passlen == 0 || *passlen == 1) && (pass[0] == '\0'))
957 /* Null session connect. */
973 if (*passlen == 24 && *ntpasslen >= 24)
975 if (IS_BITS_SET_ALL(cli->sec_mode, 2))
977 /* encrypted password, implicit from 24-byte lengths */
978 memcpy(pword , pass , *passlen);
979 memcpy(ntpword, ntpass, *ntpasslen);
983 DEBUG(0,("cli_calc_session_pwds: encrypted passwords not supported by server\n"));
987 else if (*ntpasslen == 0 || !IS_BITS_SET_ALL(cli->sec_mode, 2))
989 /* plain-text password: server doesn't support encrypted. */
990 fstrcpy(pword, pass);
991 fstrcpy(ntpword, "");
994 else if (ntpasslen != NULL)
996 /* passlen != 0, ntpasslen != 0 && server supports encryption */
999 /* plain-text password requesting to be encrypted */
1000 uchar *srv_key = (uchar *)cli->cryptkey;
1004 SMBgenclientchals(cli->lm_cli_chal,
1006 &cli->nt_cli_chal_len,
1010 nt_owf_gen(pword, nt_owf);
1011 ntv2_owf_gen(nt_owf, cli->user_name, cli->domain, kr);
1014 memcpy(pword, cli->lm_cli_chal, 8);
1015 SMBOWFencrypt_ntv2(kr,
1017 cli->lm_cli_chal, 8,
1022 memcpy(ntpword, cli->lm_cli_chal, cli->nt_cli_chal_len);
1023 SMBOWFencrypt_ntv2(kr,
1025 cli->nt_cli_chal, cli->nt_cli_chal_len,
1026 &ntpword[cli->nt_cli_chal_len]);
1027 *ntpasslen = cli->nt_cli_chal_len + 16;
1031 /* plain-text password requesting to be encrypted */
1032 uchar *key = (uchar *)cli->cryptkey;
1033 SMBencrypt ((uchar *)pass , key,(uchar *)pword );
1034 SMBNTencrypt((uchar *)ntpass, key,(uchar *)ntpword);
1042 /****************************************************************************
1043 send a session setup
1044 ****************************************************************************/
1045 BOOL cli_session_setup(struct cli_state *cli,
1047 char *pass, int passlen,
1048 char *ntpass, int ntpasslen,
1051 fstring pword, ntpword;
1053 if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1)
1058 fstrcpy(cli->user_name, user);
1060 return cli_calc_session_pwds(cli, pword, ntpword,
1062 ntpass, &ntpasslen, cli->use_ntlmv2) &&
1063 cli_session_setup_x(cli, user, pass, passlen, ntpass, ntpasslen,
1067 /****************************************************************************
1069 *****************************************************************************/
1071 BOOL cli_ulogoff(struct cli_state *cli)
1073 bzero(cli->outbuf,smb_size);
1074 set_message(cli->outbuf,2,0,True);
1075 CVAL(cli->outbuf,smb_com) = SMBulogoffX;
1076 cli_setup_packet(cli);
1077 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1078 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1080 cli_send_smb(cli, True);
1081 if (!cli_receive_smb(cli))
1084 return CVAL(cli->inbuf,smb_rcls) == 0;
1087 /****************************************************************************
1089 ****************************************************************************/
1090 BOOL cli_send_tconX(struct cli_state *cli,
1091 char *share, char *dev, char *pass, int passlen)
1093 fstring fullshare, pword;
1095 bzero(cli->outbuf,smb_size);
1096 bzero(cli->inbuf,smb_size);
1098 fstrcpy(cli->share, share);
1100 /* in user level security don't send a password now */
1101 if (cli->sec_mode & 1) {
1106 if ((cli->sec_mode & 2) && *pass && passlen != 24) {
1108 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
1110 memcpy(pword, pass, passlen);
1113 slprintf(fullshare, sizeof(fullshare)-1,
1114 "\\\\%s\\%s", cli->desthost, share);
1115 strupper(fullshare);
1117 set_message(cli->outbuf,4, 0, True);
1118 CVAL(cli->outbuf,smb_com) = SMBtconX;
1119 cli_setup_packet(cli);
1121 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1122 SSVAL(cli->outbuf,smb_vwv3,passlen);
1124 p = smb_buf(cli->outbuf);
1125 memcpy(p,pword,passlen);
1127 p = cli_put_string(cli, p, fullshare, False);
1129 p = skip_string(p, 1);
1131 set_message(cli->outbuf,4,PTR_DIFF(p, smb_buf(cli->outbuf)),False);
1133 SCVAL(cli->inbuf,smb_rcls, 1);
1135 cli_send_smb(cli, True);
1136 if (!cli_receive_smb(cli))
1139 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1143 fstrcpy(cli->dev, "A:");
1145 if (cli->protocol >= PROTOCOL_NT1)
1147 cli_get_string(cli, smb_buf(cli->inbuf),
1148 cli->dev, sizeof(cli->dev));
1151 if (strcasecmp(share,"IPC$")==0) {
1152 fstrcpy(cli->dev, "IPC");
1155 /* only grab the device if we have a recent protocol level */
1156 if (cli->protocol >= PROTOCOL_NT1 && smb_buflen(cli->inbuf) == 3)
1158 /* almost certainly win95 - enable bug fixes */
1162 cli->cnum = SVAL(cli->inbuf,smb_tid);
1167 /****************************************************************************
1168 send a tree disconnect
1169 ****************************************************************************/
1170 BOOL cli_tdis(struct cli_state *cli)
1172 bzero(cli->outbuf,smb_size);
1173 set_message(cli->outbuf,0,0,True);
1174 CVAL(cli->outbuf,smb_com) = SMBtdis;
1175 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1176 cli_setup_packet(cli);
1178 cli_send_smb(cli, True);
1179 if (!cli_receive_smb(cli))
1182 return CVAL(cli->inbuf,smb_rcls) == 0;
1185 /****************************************************************************
1187 ****************************************************************************/
1188 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
1192 bzero(cli->outbuf,smb_size);
1193 bzero(cli->inbuf,smb_size);
1195 set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
1197 CVAL(cli->outbuf,smb_com) = SMBmv;
1198 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1199 cli_setup_packet(cli);
1201 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
1203 p = smb_buf(cli->outbuf);
1205 pstrcpy(p,fname_src);
1206 p = skip_string(p,1);
1208 pstrcpy(p,fname_dst);
1210 cli_send_smb(cli, True);
1211 if (!cli_receive_smb(cli)) {
1215 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1222 /****************************************************************************
1224 ****************************************************************************/
1225 BOOL cli_unlink(struct cli_state *cli, char *fname)
1229 bzero(cli->outbuf,smb_size);
1230 bzero(cli->inbuf,smb_size);
1232 set_message(cli->outbuf,1, 2 + strlen(fname),True);
1234 CVAL(cli->outbuf,smb_com) = SMBunlink;
1235 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1236 cli_setup_packet(cli);
1238 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
1240 p = smb_buf(cli->outbuf);
1244 cli_send_smb(cli, True);
1245 if (!cli_receive_smb(cli)) {
1249 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1256 /****************************************************************************
1258 ****************************************************************************/
1259 BOOL cli_mkdir(struct cli_state *cli, char *dname)
1263 bzero(cli->outbuf,smb_size);
1264 bzero(cli->inbuf,smb_size);
1266 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1268 CVAL(cli->outbuf,smb_com) = SMBmkdir;
1269 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1270 cli_setup_packet(cli);
1272 p = smb_buf(cli->outbuf);
1276 cli_send_smb(cli, True);
1277 if (!cli_receive_smb(cli)) {
1281 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1288 /****************************************************************************
1290 ****************************************************************************/
1291 BOOL cli_rmdir(struct cli_state *cli, char *dname)
1295 bzero(cli->outbuf,smb_size);
1296 bzero(cli->inbuf,smb_size);
1298 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1300 CVAL(cli->outbuf,smb_com) = SMBrmdir;
1301 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1302 cli_setup_packet(cli);
1304 p = smb_buf(cli->outbuf);
1308 cli_send_smb(cli, True);
1309 if (!cli_receive_smb(cli)) {
1313 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1322 /****************************************************************************
1324 ****************************************************************************/
1325 int cli_nt_create(struct cli_state *cli, char *fname)
1329 bzero(cli->outbuf,smb_size);
1330 bzero(cli->inbuf,smb_size);
1332 set_message(cli->outbuf,24,1 + strlen(fname),True);
1334 CVAL(cli->outbuf,smb_com) = SMBntcreateX;
1335 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1336 cli_setup_packet(cli);
1338 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1339 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0x06);
1340 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
1341 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, 0x2019f);
1342 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0);
1343 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03);
1344 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01);
1345 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0);
1346 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
1347 SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname));
1349 p = smb_buf(cli->outbuf);
1351 p = skip_string(p,1);
1353 cli_send_smb(cli, True);
1354 if (!cli_receive_smb(cli)) {
1358 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1362 return SVAL(cli->inbuf,smb_vwv2 + 1);
1366 /****************************************************************************
1368 ****************************************************************************/
1369 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
1373 unsigned accessmode=0;
1375 /* you must open for RW not just write - otherwise getattrE doesn't
1377 if ((flags & O_ACCMODE) == O_WRONLY && strncmp(cli->dev, "LPT", 3)) {
1378 flags = (flags & ~O_ACCMODE) | O_RDWR;
1381 if (flags & O_CREAT)
1383 if (!(flags & O_EXCL)) {
1384 if (flags & O_TRUNC)
1390 accessmode = (share_mode<<4);
1392 if ((flags & O_ACCMODE) == O_RDWR) {
1394 } else if ((flags & O_ACCMODE) == O_WRONLY) {
1399 if ((flags & O_SYNC) == O_SYNC) {
1400 accessmode |= (1<<14);
1404 bzero(cli->outbuf,smb_size);
1405 bzero(cli->inbuf,smb_size);
1407 set_message(cli->outbuf,15,1 + strlen(fname),True);
1409 CVAL(cli->outbuf,smb_com) = SMBopenX;
1410 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1411 cli_setup_packet(cli);
1413 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1414 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1415 SSVAL(cli->outbuf,smb_vwv3,accessmode);
1416 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1417 SSVAL(cli->outbuf,smb_vwv5,0);
1418 SSVAL(cli->outbuf,smb_vwv8,openfn);
1420 p = smb_buf(cli->outbuf);
1421 p = cli_put_string(cli, p, fname, False);
1423 set_message(cli->outbuf,15,PTR_DIFF(p, smb_buf(cli->outbuf)),False);
1425 cli_send_smb(cli, True);
1426 if (!cli_receive_smb(cli)) {
1430 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1434 return SVAL(cli->inbuf,smb_vwv2);
1440 /****************************************************************************
1442 ****************************************************************************/
1443 BOOL cli_close(struct cli_state *cli, int fnum)
1445 bzero(cli->outbuf,smb_size);
1446 bzero(cli->inbuf,smb_size);
1448 set_message(cli->outbuf,3,0,True);
1450 CVAL(cli->outbuf,smb_com) = SMBclose;
1451 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1452 cli_setup_packet(cli);
1454 SSVAL(cli->outbuf,smb_vwv0,fnum);
1455 SIVALS(cli->outbuf,smb_vwv1,-1);
1457 cli_send_smb(cli, True);
1458 if (!cli_receive_smb(cli)) {
1462 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1470 /****************************************************************************
1472 ****************************************************************************/
1473 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1476 int saved_timeout = cli->timeout;
1478 bzero(cli->outbuf,smb_size);
1479 bzero(cli->inbuf,smb_size);
1481 set_message(cli->outbuf,8,10,True);
1483 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1484 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1485 cli_setup_packet(cli);
1487 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1488 SSVAL(cli->outbuf,smb_vwv2,fnum);
1489 CVAL(cli->outbuf,smb_vwv3) = 0;
1490 SIVALS(cli->outbuf, smb_vwv4, timeout);
1491 SSVAL(cli->outbuf,smb_vwv6,0);
1492 SSVAL(cli->outbuf,smb_vwv7,1);
1494 p = smb_buf(cli->outbuf);
1495 SSVAL(p, 0, cli->pid);
1496 SIVAL(p, 2, offset);
1498 cli_send_smb(cli, True);
1500 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout;
1502 if (!cli_receive_smb(cli)) {
1503 cli->timeout = saved_timeout;
1507 cli->timeout = saved_timeout;
1509 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1516 /****************************************************************************
1518 ****************************************************************************/
1519 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1523 bzero(cli->outbuf,smb_size);
1524 bzero(cli->inbuf,smb_size);
1526 set_message(cli->outbuf,8,10,True);
1528 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1529 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1530 cli_setup_packet(cli);
1532 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1533 SSVAL(cli->outbuf,smb_vwv2,fnum);
1534 CVAL(cli->outbuf,smb_vwv3) = 0;
1535 SIVALS(cli->outbuf, smb_vwv4, timeout);
1536 SSVAL(cli->outbuf,smb_vwv6,1);
1537 SSVAL(cli->outbuf,smb_vwv7,0);
1539 p = smb_buf(cli->outbuf);
1540 SSVAL(p, 0, cli->pid);
1541 SIVAL(p, 2, offset);
1544 cli_send_smb(cli, True);
1545 if (!cli_receive_smb(cli)) {
1549 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1558 /****************************************************************************
1559 issue a single SMBread and don't wait for a reply
1560 ****************************************************************************/
1561 static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
1564 bzero(cli->outbuf,smb_size);
1565 bzero(cli->inbuf,smb_size);
1567 set_message(cli->outbuf,10,0,True);
1569 CVAL(cli->outbuf,smb_com) = SMBreadX;
1570 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1571 cli_setup_packet(cli);
1573 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1574 SSVAL(cli->outbuf,smb_vwv2,fnum);
1575 SIVAL(cli->outbuf,smb_vwv3,offset);
1576 SSVAL(cli->outbuf,smb_vwv5,size);
1577 SSVAL(cli->outbuf,smb_vwv6,size);
1578 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1580 cli_send_smb(cli, True);
1583 /****************************************************************************
1585 ****************************************************************************/
1586 size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
1592 int mpx = MAX(cli->max_mux-1, 1);
1593 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1595 int blocks = (size + (block-1)) / block;
1597 if (size == 0) return 0;
1599 while (received < blocks) {
1602 while (issued - received < mpx && issued < blocks) {
1603 int size1 = MIN(block, size-issued*block);
1604 cli_issue_read(cli, fnum, offset+issued*block, size1, issued);
1608 if (!cli_receive_smb(cli)) {
1613 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1614 size2 = SVAL(cli->inbuf, smb_vwv5);
1616 if (cli_error(cli, NULL, NULL))
1618 blocks = MIN(blocks, mid-1);
1623 blocks = MIN(blocks, mid-1);
1624 /* this distinguishes EOF from an error */
1625 total = MAX(total, 0);
1629 if (size2 > block) {
1630 DEBUG(0,("server returned more than we wanted!\n"));
1633 if (mid >= issued) {
1634 DEBUG(0,("invalid mid from server!\n"));
1637 p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
1639 memcpy(buf+mid*block, p, size2);
1641 total = MAX(total, mid*block + size2);
1644 while (received < issued) {
1645 cli_receive_smb(cli);
1653 /****************************************************************************
1654 issue a single SMBwrite and don't wait for a reply
1655 ****************************************************************************/
1656 static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf,
1661 bzero(cli->outbuf,smb_size);
1662 bzero(cli->inbuf,smb_size);
1664 set_message(cli->outbuf,12,size,True);
1666 CVAL(cli->outbuf,smb_com) = SMBwriteX;
1667 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1668 cli_setup_packet(cli);
1670 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1671 SSVAL(cli->outbuf,smb_vwv2,fnum);
1673 SIVAL(cli->outbuf,smb_vwv3,offset);
1674 SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0);
1675 SSVAL(cli->outbuf,smb_vwv7,mode);
1677 SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0);
1678 SSVAL(cli->outbuf,smb_vwv10,size);
1679 SSVAL(cli->outbuf,smb_vwv11,
1680 smb_buf(cli->outbuf) - smb_base(cli->outbuf));
1682 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
1683 memcpy(p, buf, size);
1685 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1687 cli_send_smb(cli, True);
1690 /****************************************************************************
1692 write_mode: 0x0001 disallow write cacheing
1693 0x0002 return bytes remaining
1694 0x0004 use raw named pipe protocol
1695 0x0008 start of message mode named pipe protocol
1696 ****************************************************************************/
1697 ssize_t cli_write(struct cli_state *cli,
1698 int fnum, uint16 write_mode,
1699 char *buf, off_t offset, size_t size)
1704 int mpx = MAX(cli->max_mux-1, 1);
1705 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1707 int blocks = (size + (block-1)) / block;
1709 if (size == 0) return 0;
1711 while (received < blocks) {
1714 while (issued - received < mpx && issued < blocks) {
1715 int size1 = MIN(block, size-issued*block);
1716 cli_issue_write(cli, fnum, offset+issued*block,
1723 if (!cli_receive_smb(cli)) {
1728 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1729 size2 = SVAL(cli->inbuf, smb_vwv2);
1731 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1732 blocks = MIN(blocks, mid-1);
1737 blocks = MIN(blocks, mid-1);
1738 /* this distinguishes EOF from an error */
1739 total = MAX(total, 0);
1745 total = MAX(total, mid*block + size2);
1748 while (received < issued) {
1749 cli_receive_smb(cli);
1757 /****************************************************************************
1758 do a SMBgetattrE call
1759 ****************************************************************************/
1760 BOOL cli_getattrE(struct cli_state *cli, int fd,
1761 uint16 *attr, size_t *size,
1762 time_t *c_time, time_t *a_time, time_t *m_time)
1764 bzero(cli->outbuf,smb_size);
1765 bzero(cli->inbuf,smb_size);
1767 set_message(cli->outbuf,2,0,True);
1769 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
1770 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1771 cli_setup_packet(cli);
1773 SSVAL(cli->outbuf,smb_vwv0,fd);
1775 cli_send_smb(cli, True);
1776 if (!cli_receive_smb(cli)) {
1780 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1785 *size = IVAL(cli->inbuf, smb_vwv6);
1789 *attr = SVAL(cli->inbuf,smb_vwv10);
1793 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
1797 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
1801 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
1808 /****************************************************************************
1810 ****************************************************************************/
1811 BOOL cli_getatr(struct cli_state *cli, char *fname,
1812 uint16 *attr, size_t *size, time_t *t)
1816 bzero(cli->outbuf,smb_size);
1817 bzero(cli->inbuf,smb_size);
1819 set_message(cli->outbuf,0,strlen(fname)+2,True);
1821 CVAL(cli->outbuf,smb_com) = SMBgetatr;
1822 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1823 cli_setup_packet(cli);
1825 p = smb_buf(cli->outbuf);
1827 pstrcpy(p+1, fname);
1829 cli_send_smb(cli, True);
1830 if (!cli_receive_smb(cli)) {
1834 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1839 *size = IVAL(cli->inbuf, smb_vwv3);
1843 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1847 *attr = SVAL(cli->inbuf,smb_vwv0);
1855 /****************************************************************************
1857 ****************************************************************************/
1858 BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
1862 bzero(cli->outbuf,smb_size);
1863 bzero(cli->inbuf,smb_size);
1865 set_message(cli->outbuf,8,strlen(fname)+4,True);
1867 CVAL(cli->outbuf,smb_com) = SMBsetatr;
1868 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1869 cli_setup_packet(cli);
1871 SSVAL(cli->outbuf,smb_vwv0, attr);
1872 put_dos_date3(cli->outbuf,smb_vwv1, t);
1874 p = smb_buf(cli->outbuf);
1876 pstrcpy(p+1, fname);
1877 p = skip_string(p,1);
1880 cli_send_smb(cli, True);
1881 if (!cli_receive_smb(cli)) {
1885 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1892 /****************************************************************************
1893 send a qpathinfo call
1894 ****************************************************************************/
1895 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
1896 time_t *c_time, time_t *a_time, time_t *m_time,
1897 size_t *size, uint16 *mode)
1901 uint16 setup = TRANSACT2_QPATHINFO;
1903 char *rparam=NULL, *rdata=NULL;
1906 time_t (*date_fn)(void *);
1908 param_len = strlen(fname) + 7;
1910 memset(param, 0, param_len);
1911 SSVAL(param, 0, SMB_INFO_STANDARD);
1912 pstrcpy(¶m[6], fname);
1915 ret = (cli_send_trans(cli, SMBtrans2,
1916 NULL, 0, /* Name, length */
1917 -1, 0, /* fid, flags */
1918 &setup, 1, 0, /* setup, length, max */
1919 param, param_len, 10, /* param, length, max */
1920 NULL, data_len, cli->max_xmit /* data, length, max */
1922 cli_receive_trans(cli, SMBtrans2,
1923 &rparam, ¶m_len,
1924 &rdata, &data_len));
1926 /* we need to work around a Win95 bug - sometimes
1927 it gives ERRSRV/ERRerror temprarily */
1930 cli_error(cli, &eclass, &ecode);
1931 if (eclass != ERRSRV || ecode != ERRerror) break;
1934 } while (count-- && ret==False);
1936 if (!ret || !rdata || data_len < 22) {
1941 date_fn = make_unix_date;
1943 date_fn = make_unix_date2;
1947 *c_time = date_fn(rdata+0);
1950 *a_time = date_fn(rdata+4);
1953 *m_time = date_fn(rdata+8);
1956 *size = IVAL(rdata, 12);
1959 *mode = SVAL(rdata,l1_attrFile);
1962 if (rdata) free(rdata);
1963 if (rparam) free(rparam);
1967 /****************************************************************************
1968 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1969 ****************************************************************************/
1970 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
1971 time_t *c_time, time_t *a_time, time_t *m_time,
1972 time_t *w_time, size_t *size, uint16 *mode,
1977 uint16 setup = TRANSACT2_QPATHINFO;
1979 char *rparam=NULL, *rdata=NULL;
1981 param_len = strlen(fname) + 7;
1983 memset(param, 0, param_len);
1984 SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1985 pstrcpy(¶m[6], fname);
1987 if (!cli_send_trans(cli, SMBtrans2,
1988 NULL, 0, /* name, length */
1989 -1, 0, /* fid, flags */
1990 &setup, 1, 0, /* setup, length, max */
1991 param, param_len, 10, /* param, length, max */
1992 NULL, data_len, cli->max_xmit /* data, length, max */
1997 if (!cli_receive_trans(cli, SMBtrans2,
1998 &rparam, ¶m_len,
1999 &rdata, &data_len)) {
2003 if (!rdata || data_len < 22) {
2008 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
2011 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
2014 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
2017 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
2020 *mode = SVAL(rdata, 32);
2023 *size = IVAL(rdata, 40);
2026 *ino = IVAL(rdata, 64);
2029 if (rdata) free(rdata);
2030 if (rparam) free(rparam);
2035 /****************************************************************************
2036 send a qfileinfo call
2037 ****************************************************************************/
2038 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
2039 uint16 *mode, size_t *size,
2040 time_t *c_time, time_t *a_time, time_t *m_time,
2041 time_t *w_time, SMB_INO_T *ino)
2045 uint16 setup = TRANSACT2_QFILEINFO;
2047 char *rparam=NULL, *rdata=NULL;
2049 /* if its a win95 server then fail this - win95 totally screws it
2051 if (cli->win95) return False;
2055 memset(param, 0, param_len);
2056 SSVAL(param, 0, fnum);
2057 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
2059 if (!cli_send_trans(cli, SMBtrans2,
2060 NULL, 0, /* name, length */
2061 -1, 0, /* fid, flags */
2062 &setup, 1, 0, /* setup, length, max */
2063 param, param_len, 2, /* param, length, max */
2064 NULL, data_len, cli->max_xmit /* data, length, max */
2069 if (!cli_receive_trans(cli, SMBtrans2,
2070 &rparam, ¶m_len,
2071 &rdata, &data_len)) {
2075 if (!rdata || data_len < 68) {
2080 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
2083 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
2086 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
2089 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
2092 *mode = SVAL(rdata, 32);
2095 *size = IVAL(rdata, 40);
2098 *ino = IVAL(rdata, 64);
2101 if (rdata) free(rdata);
2102 if (rparam) free(rparam);
2107 /****************************************************************************
2108 interpret a long filename structure - this is mostly guesses at the moment
2109 The length of the structure is returned
2110 The structure of a long filename depends on the info level. 260 is used
2111 by NT and 2 is used by OS/2
2112 ****************************************************************************/
2113 static int interpret_long_filename(int level,char *p,file_info *finfo)
2115 extern file_info def_finfo;
2118 memcpy(finfo,&def_finfo,sizeof(*finfo));
2122 case 1: /* OS/2 understands this */
2124 /* these dates are converted to GMT by make_unix_date */
2125 finfo->ctime = make_unix_date2(p+4);
2126 finfo->atime = make_unix_date2(p+8);
2127 finfo->mtime = make_unix_date2(p+12);
2128 finfo->size = IVAL(p,16);
2129 finfo->mode = CVAL(p,24);
2130 pstrcpy(finfo->name,p+27);
2132 return(28 + CVAL(p,26));
2134 case 2: /* this is what OS/2 uses mostly */
2136 /* these dates are converted to GMT by make_unix_date */
2137 finfo->ctime = make_unix_date2(p+4);
2138 finfo->atime = make_unix_date2(p+8);
2139 finfo->mtime = make_unix_date2(p+12);
2140 finfo->size = IVAL(p,16);
2141 finfo->mode = CVAL(p,24);
2142 pstrcpy(finfo->name,p+31);
2144 return(32 + CVAL(p,30));
2146 /* levels 3 and 4 are untested */
2149 /* these dates are probably like the other ones */
2150 finfo->ctime = make_unix_date2(p+8);
2151 finfo->atime = make_unix_date2(p+12);
2152 finfo->mtime = make_unix_date2(p+16);
2153 finfo->size = IVAL(p,20);
2154 finfo->mode = CVAL(p,28);
2155 pstrcpy(finfo->name,p+33);
2157 return(SVAL(p,4)+4);
2161 /* these dates are probably like the other ones */
2162 finfo->ctime = make_unix_date2(p+8);
2163 finfo->atime = make_unix_date2(p+12);
2164 finfo->mtime = make_unix_date2(p+16);
2165 finfo->size = IVAL(p,20);
2166 finfo->mode = CVAL(p,28);
2167 pstrcpy(finfo->name,p+37);
2169 return(SVAL(p,4)+4);
2171 case 260: /* NT uses this, but also accepts 2 */
2173 int ret = SVAL(p,0);
2175 p += 4; /* next entry offset */
2176 p += 4; /* fileindex */
2178 /* these dates appear to arrive in a
2179 weird way. It seems to be localtime
2180 plus the serverzone given in the
2181 initial connect. This is GMT when
2182 DST is not in effect and one hour
2183 from GMT otherwise. Can this really
2186 I suppose this could be called
2187 kludge-GMT. Is is the GMT you get
2188 by using the current DST setting on
2189 a different localtime. It will be
2190 cheap to calculate, I suppose, as
2191 no DST tables will be needed */
2193 finfo->ctime = interpret_long_date(p); p += 8;
2194 finfo->atime = interpret_long_date(p); p += 8;
2195 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
2196 finfo->size = IVAL(p,0); p += 8;
2197 p += 8; /* alloc size */
2198 finfo->mode = CVAL(p,0); p += 4;
2199 namelen = IVAL(p,0); p += 4;
2200 p += 4; /* EA size */
2201 p += 2; /* short name len? */
2202 p += 24; /* short name? */
2203 StrnCpy(finfo->name,p,namelen);
2209 DEBUG(1,("Unknown long filename format %d\n",level));
2214 /****************************************************************************
2215 do a directory listing, calling fn on each file found
2216 ****************************************************************************/
2217 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
2218 void (*fn)(file_info *, const char *))
2220 int max_matches = 512;
2221 /* NT uses 260, OS/2 uses 2. Both accept 1. */
2222 int info_level = cli->protocol<PROTOCOL_NT1?1:260;
2227 char *dirlist = NULL;
2228 int dirlist_len = 0;
2229 int total_received = -1;
2231 int ff_resume_key = 0;
2232 int ff_searchcount=0;
2235 int ff_dir_handle=0;
2237 char *rparam=NULL, *rdata=NULL;
2238 int param_len, data_len;
2245 while (ff_eos == 0) {
2247 if (loop_count > 200) {
2248 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
2252 param_len = 12+strlen(mask)+1;
2255 setup = TRANSACT2_FINDFIRST;
2256 SSVAL(param,0,attribute); /* attribute */
2257 SSVAL(param,2,max_matches); /* max count */
2258 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
2259 SSVAL(param,6,info_level);
2261 pstrcpy(param+12,mask);
2263 setup = TRANSACT2_FINDNEXT;
2264 SSVAL(param,0,ff_dir_handle);
2265 SSVAL(param,2,max_matches); /* max count */
2266 SSVAL(param,4,info_level);
2267 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
2268 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
2269 pstrcpy(param+12,mask);
2271 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
2272 ff_dir_handle,ff_resume_key,ff_lastname,mask));
2275 if (!cli_send_trans(cli, SMBtrans2,
2276 NULL, 0, /* Name, length */
2277 -1, 0, /* fid, flags */
2278 &setup, 1, 0, /* setup, length, max */
2279 param, param_len, 10, /* param, length, max */
2281 cli->max_xmit /* data, length, max */
2286 if (!cli_receive_trans(cli, SMBtrans2,
2287 &rparam, ¶m_len,
2288 &rdata, &data_len)) {
2289 /* we need to work around a Win95 bug - sometimes
2290 it gives ERRSRV/ERRerror temprarily */
2293 cli_error(cli, &eclass, &ecode);
2294 if (eclass != ERRSRV || ecode != ERRerror) break;
2299 if (total_received == -1) total_received = 0;
2301 /* parse out some important return info */
2304 ff_dir_handle = SVAL(p,0);
2305 ff_searchcount = SVAL(p,2);
2307 ff_lastname = SVAL(p,8);
2309 ff_searchcount = SVAL(p,0);
2311 ff_lastname = SVAL(p,6);
2314 if (ff_searchcount == 0)
2317 /* point to the data bytes */
2320 /* we might need the lastname for continuations */
2321 if (ff_lastname > 0) {
2326 StrnCpy(mask,p+ff_lastname,
2327 data_len-ff_lastname);
2330 pstrcpy(mask,p + ff_lastname + 1);
2338 /* and add them to the dirlist pool */
2339 dirlist = Realloc(dirlist,dirlist_len + data_len);
2342 DEBUG(0,("Failed to expand dirlist\n"));
2346 /* put in a length for the last entry, to ensure we can chain entries
2347 into the next packet */
2348 for (p2=p,i=0;i<(ff_searchcount-1);i++)
2349 p2 += interpret_long_filename(info_level,p2,NULL);
2350 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
2352 /* grab the data for later use */
2353 memcpy(dirlist+dirlist_len,p,data_len);
2354 dirlist_len += data_len;
2356 total_received += ff_searchcount;
2358 if (rdata) free(rdata); rdata = NULL;
2359 if (rparam) free(rparam); rparam = NULL;
2361 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
2362 ff_searchcount,ff_eos,ff_resume_key));
2367 for (p=dirlist,i=0;i<total_received;i++) {
2368 p += interpret_long_filename(info_level,p,&finfo);
2372 /* free up the dirlist buffer */
2373 if (dirlist) free(dirlist);
2374 return(total_received);
2378 /****************************************************************************
2379 Send a SamOEMChangePassword command
2380 ****************************************************************************/
2382 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
2383 const char *old_password)
2385 char param[16+sizeof(fstring)];
2388 fstring upper_case_old_pw;
2389 fstring upper_case_new_pw;
2390 unsigned char old_pw_hash[16];
2391 unsigned char new_pw_hash[16];
2394 char *rparam = NULL;
2398 if (strlen(user) >= sizeof(fstring)-1) {
2399 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
2403 SSVAL(p,0,214); /* SamOEMChangePassword command. */
2406 p = skip_string(p,1);
2407 pstrcpy(p, "B516B16");
2408 p = skip_string(p,1);
2410 p = skip_string(p,1);
2414 param_len = PTR_DIFF(p,param);
2417 * Get the Lanman hash of the old password, we
2418 * use this as the key to make_oem_passwd_hash().
2420 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
2421 fstrcpy(upper_case_old_pw, old_password);
2422 strupper(upper_case_old_pw);
2423 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
2425 if (!make_oem_passwd_hash( data, new_password, old_pw_hash, False))
2431 * Now place the old password hash in the data.
2433 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
2434 fstrcpy(upper_case_new_pw, new_password);
2435 strupper(upper_case_new_pw);
2437 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
2439 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
2443 if (!cli_send_trans(cli,SMBtrans,
2444 PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */
2445 0,0, /* fid, flags */
2446 NULL,0,0, /* setup, length, max */
2447 param,param_len,2, /* param, length, max */
2448 data,data_len,0 /* data, length, max */
2451 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
2456 if (cli_receive_trans(cli,SMBtrans,
2460 cli->rap_error = SVAL(rparam,0);
2468 return (cli->rap_error == 0);
2471 /****************************************************************************
2472 send a negprot command
2473 ****************************************************************************/
2474 BOOL cli_negprot(struct cli_state *cli)
2480 bzero(cli->outbuf,smb_size);
2482 /* setup the protocol strings */
2483 for (plength=0,numprots=0;
2484 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2486 plength += strlen(prots[numprots].name)+2;
2488 set_message(cli->outbuf,0,plength,True);
2490 p = smb_buf(cli->outbuf);
2492 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2495 pstrcpy(p,prots[numprots].name);
2499 CVAL(cli->outbuf,smb_com) = SMBnegprot;
2500 cli_setup_packet(cli);
2502 CVAL(smb_buf(cli->outbuf),0) = 2;
2504 cli_send_smb(cli, True);
2505 if (!cli_receive_smb(cli))
2510 if (CVAL(cli->inbuf,smb_rcls) != 0 ||
2511 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
2515 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
2518 if (cli->protocol >= PROTOCOL_NT1)
2520 char *buf = smb_buf(cli->inbuf);
2521 int bcc = SVAL(cli->inbuf,smb_vwv+2*(CVAL(cli->inbuf,smb_wct)));
2523 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
2524 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
2525 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
2526 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
2527 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
2528 /* this time arrives in real GMT */
2529 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
2531 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
2532 if (IS_BITS_SET_ALL(cli->capabilities, CAP_RAW_MODE))
2534 cli->readbraw_supported = True;
2535 cli->writebraw_supported = True;
2538 if (IS_BITS_SET_ALL(cli->capabilities, CAP_EXTENDED_SECURITY))
2540 /* oops, some kerberos-related nonsense. */
2541 /* expect to have to use NTLMSSP-over-SMB */
2542 DEBUG(10,("unknown kerberos-related (?) blob\n"));
2543 memset(cli->cryptkey, 0, 8);
2544 cli->server_domain[0] = 0;
2548 memcpy(cli->cryptkey, buf,8);
2551 unibuf_to_ascii(cli->server_domain, buf+8,
2552 sizeof(cli->server_domain));
2556 cli->server_domain[0] = 0;
2558 DEBUG(5,("server's domain: %s bcc: %d\n",
2559 cli->server_domain, bcc));
2562 else if (cli->protocol >= PROTOCOL_LANMAN1)
2564 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
2565 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
2566 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
2567 cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
2568 /* this time is converted to GMT by make_unix_date */
2569 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
2570 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
2571 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
2572 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2574 /* the old core protocol */
2576 cli->serverzone = TimeDiff(time(NULL));
2579 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2585 /****************************************************************************
2586 send a session request. see rfc1002.txt 4.3 and 4.3.2
2587 ****************************************************************************/
2588 BOOL cli_session_request(struct cli_state *cli,
2589 struct nmb_name *calling, struct nmb_name *called)
2593 /* send a session request (RFC 1002) */
2595 memcpy(&(cli->calling), calling, sizeof(*calling));
2596 memcpy(&(cli->called ), called , sizeof(*called ));
2598 if (cli->port == 445)
2603 /* put in the destination name */
2604 p = cli->outbuf+len;
2605 name_mangle(cli->called .name, p, cli->called .name_type);
2609 p = cli->outbuf+len;
2610 name_mangle(cli->calling.name, p, cli->calling.name_type);
2613 /* setup the packet length */
2614 _smb_setlen(cli->outbuf,len);
2615 CVAL(cli->outbuf,0) = 0x81;
2619 #endif /* WITH_SSL */
2621 cli_send_smb(cli, True);
2622 DEBUG(5,("Sent session request\n"));
2624 if (!cli_receive_smb(cli))
2628 if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
2629 if (!sslutil_fd_is_ssl(cli->fd)){
2630 if (sslutil_connect(cli->fd) == 0)
2634 #endif /* WITH_SSL */
2636 if (CVAL(cli->inbuf,0) != 0x82) {
2637 /* This is the wrong place to put the error... JRA. */
2638 cli->rap_error = CVAL(cli->inbuf,0);
2645 /****************************************************************************
2646 open the client sockets
2647 ****************************************************************************/
2648 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
2650 extern struct in_addr ipzero;
2651 int port = cli->port;
2653 fstrcpy(cli->desthost, host);
2655 if (!ip || ip_equal(*ip, ipzero)) {
2656 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
2659 if (ip) *ip = cli->dest_ip;
2665 if (port == 0) port = SMB_PORT2;
2667 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2668 port, cli->timeout);
2677 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2678 port, cli->timeout);
2679 if (cli->fd == -1) return False;
2688 /****************************************************************************
2689 initialise a client structure
2690 ****************************************************************************/
2691 struct cli_state *cli_initialise(struct cli_state *cli)
2694 cli = (struct cli_state *)malloc(sizeof(*cli));
2700 if (cli->initialised) {
2709 cli->pid = (uint16)getpid();
2711 cli->vuid = UID_FIELD_INVALID;
2712 cli->protocol = PROTOCOL_NT1;
2713 cli->timeout = 20000;
2714 cli->bufsize = CLI_BUFFER_SIZE+4;
2715 cli->max_xmit = cli->bufsize;
2716 cli->outbuf = (char *)malloc(cli->bufsize);
2717 cli->inbuf = (char *)malloc(cli->bufsize);
2718 if (!cli->outbuf || !cli->inbuf)
2723 cli->initialised = 1;
2724 cli->capabilities = CAP_DFS;
2729 /****************************************************************************
2730 close the socket descriptor
2731 ****************************************************************************/
2732 void cli_close_socket(struct cli_state *cli)
2737 sslutil_disconnect(cli->fd);
2739 #endif /* WITH_SSL */
2747 /****************************************************************************
2748 shutdown a client structure
2749 ****************************************************************************/
2750 void cli_shutdown(struct cli_state *cli)
2752 DEBUG(10,("cli_shutdown\n"));
2761 cli_close_socket(cli);
2762 memset(cli, 0, sizeof(*cli));
2766 /****************************************************************************
2767 return error codes for the last packet
2768 returns 0 if there was no error and the best approx of a unix errno
2771 for 32 bit "warnings", a return code of 0 is expected.
2773 ****************************************************************************/
2774 int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
2780 if (!cli->initialised)
2782 DEBUG(0,("cli_error: client state uninitialised!\n"));
2786 flgs2 = SVAL(cli->inbuf,smb_flg2);
2788 if (eclass) *eclass = 0;
2791 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES)
2793 /* 32 bit error codes detected */
2794 uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
2795 if (num) *num = nt_err;
2796 DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
2797 if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0;
2799 switch (nt_err & 0xFFFFFF)
2801 case NT_STATUS_ACCESS_VIOLATION : return EACCES;
2802 case NT_STATUS_NO_SUCH_FILE : return ENOENT;
2803 case NT_STATUS_NO_SUCH_DEVICE : return ENODEV;
2804 case NT_STATUS_INVALID_HANDLE : return EBADF;
2805 case NT_STATUS_NO_MEMORY : return ENOMEM;
2806 case NT_STATUS_ACCESS_DENIED : return EACCES;
2807 case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
2808 case NT_STATUS_SHARING_VIOLATION : return EBUSY;
2809 case NT_STATUS_OBJECT_PATH_INVALID : return ENOTDIR;
2810 case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
2813 /* for all other cases - a default code */
2817 rcls = CVAL(cli->inbuf,smb_rcls);
2818 code = SVAL(cli->inbuf,smb_err);
2819 if (rcls == 0) return 0;
2821 if (eclass) *eclass = rcls;
2822 if (num ) *num = code;
2824 if (rcls == ERRDOS) {
2826 case ERRbadfile: return ENOENT;
2827 case ERRbadpath: return ENOTDIR;
2828 case ERRnoaccess: return EACCES;
2829 case ERRfilexists: return EEXIST;
2830 case ERRrename: return EEXIST;
2831 case ERRbadshare: return EBUSY;
2832 case ERRlock: return EBUSY;
2833 case ERRmoredata: return 0; /* Informational only */
2836 if (rcls == ERRSRV) {
2838 case ERRbadpw: return EPERM;
2839 case ERRaccess: return EACCES;
2840 case ERRnoresource: return ENOMEM;
2841 case ERRinvdevice: return ENODEV;
2842 case ERRinvnetname: return ENODEV;
2845 /* for other cases */
2849 /****************************************************************************
2850 set socket options on a open connection
2851 ****************************************************************************/
2852 void cli_sockopt(struct cli_state *cli, char *options)
2854 set_socket_options(cli->fd, options);
2857 /****************************************************************************
2858 set the PID to use for smb messages. Return the old pid.
2859 ****************************************************************************/
2860 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
2862 uint16 ret = cli->pid;
2867 /****************************************************************************
2868 re-establishes a connection
2869 ****************************************************************************/
2870 BOOL cli_reestablish_connection(struct cli_state *cli)
2872 struct nmb_name calling;
2873 struct nmb_name called;
2877 BOOL do_tcon = False;
2878 int oldfd = cli->fd;
2880 if (!cli->initialised || cli->fd == -1)
2882 DEBUG(3,("cli_reestablish_connection: not connected\n"));
2886 /* copy the parameters necessary to re-establish the connection */
2895 fstrcpy(share, cli->share);
2896 fstrcpy(dev , cli->dev);
2899 memcpy(&called , &(cli->called ), sizeof(called ));
2900 memcpy(&calling, &(cli->calling), sizeof(calling));
2901 fstrcpy(dest_host, cli->desthost);
2903 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2904 nmb_namestr(&calling), nmb_namestr(&called),
2905 inet_ntoa(cli->dest_ip),
2906 cli->user_name, cli->domain));
2910 if (cli_establish_connection(cli,
2911 dest_host, &cli->dest_ip,
2913 share, dev, False, do_tcon))
2915 if (cli->fd != oldfd)
2917 if (dup2(cli->fd, oldfd) == oldfd)
2919 cli_close_socket(cli);
2927 /****************************************************************************
2928 establishes a connection right up to doing tconX, reading in a password.
2929 ****************************************************************************/
2930 BOOL cli_establish_connection(struct cli_state *cli,
2931 char *dest_host, struct in_addr *dest_ip,
2932 struct nmb_name *calling, struct nmb_name *called,
2933 char *service, char *service_type,
2934 BOOL do_shutdown, BOOL do_tcon)
2939 nmb_safe_namestr(calling, callingstr, sizeof(callingstr));
2940 nmb_safe_namestr(called , calledstr , sizeof(calledstr ));
2942 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s] with NTLM%s\n",
2943 callingstr, calledstr, inet_ntoa(*dest_ip),
2944 cli->user_name, cli->domain,
2945 cli->use_ntlmv2 ? "v2" : "v1"));
2947 /* establish connection */
2949 if ((!cli->initialised))
2956 if (!cli_connect(cli, dest_host, dest_ip))
2958 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
2959 callingstr, inet_ntoa(*dest_ip)));
2964 if (!cli_session_request(cli, calling, called))
2966 DEBUG(1,("failed session request\n"));
2974 if (!cli_negprot(cli))
2976 DEBUG(1,("failed negprot\n"));
2984 if (cli->domain[0] == 0)
2986 safe_strcpy(cli->domain, cli->server_domain,
2987 sizeof(cli->domain));
2990 if (IS_BITS_SET_ALL(cli->capabilities, CAP_EXTENDED_SECURITY))
2992 /* common to both session setups */
2996 char *e = pwd_buf + sizeof(pwd_buf);
2998 /* 1st session setup */
3001 0x60, 0x40, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
3002 0x05, 0x02, 0xa0, 0x36, 0x30, 0x34, 0xa0, 0x0e,
3003 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
3004 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa2, 0x22,
3007 /* 2nd session setup */
3009 char pwd_data_2[8] =
3011 0xa1, 0x51, 0x30, 0x4f, 0xa2, 0x4d, 0x04, 0x4b
3014 char pwd_data_2[8] =
3016 0xa1, 0x51, 0x30, 0x4f, 0xa2, 0x4d, 0x04, 0x4b
3018 prs_struct auth_resp;
3025 memset(pwd_buf, 0, sizeof(pwd_buf));
3026 memcpy(pwd_buf, pwd_data, sizeof(pwd_data));
3027 p = pwd_buf + sizeof(pwd_data);
3029 safe_strcpy(p, "NTLMSSP", PTR_DIFF(e, p) - 1);
3030 p = skip_string(p, 1);
3033 if (cli->ntlmssp_cli_flgs == 0)
3035 cli->ntlmssp_cli_flgs =
3036 NTLMSSP_NEGOTIATE_UNICODE |
3037 NTLMSSP_NEGOTIATE_OEM |
3038 NTLMSSP_NEGOTIATE_SIGN |
3039 NTLMSSP_NEGOTIATE_SEAL |
3040 NTLMSSP_NEGOTIATE_LM_KEY |
3041 NTLMSSP_NEGOTIATE_NTLM |
3042 NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
3043 NTLMSSP_NEGOTIATE_00001000 |
3044 NTLMSSP_NEGOTIATE_00002000;
3046 cli->ntlmssp_cli_flgs = 0x80008207;
3049 SIVAL(p, 0, cli->ntlmssp_cli_flgs);
3051 p += 16; /* skip some NULL space */
3052 CVAL(p, 0) = 0; p++; /* alignment */
3054 buf_len = PTR_DIFF(p, pwd_buf);
3056 /* first session negotiation stage */
3057 if (!cli_session_setup_x(cli, cli->user_name,
3062 DEBUG(1,("failed session setup\n"));
3070 DEBUG(1,("1st session setup ok\n"));
3072 if (*cli->server_domain || *cli->server_os || *cli->server_type)
3074 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
3080 p = smb_buf(cli->inbuf) + 0x2f;
3081 cli->ntlmssp_cli_flgs = IVAL(p, 0); /* 0x80808a05; */
3083 memcpy(cli->cryptkey, p, 8);
3084 #ifdef DEBUG_PASSWORD
3085 DEBUG(100,("cli_session_setup_x: ntlmssp %8x\n",
3086 cli->ntlmssp_cli_flgs));
3088 DEBUG(100,("cli_session_setup_x: crypt key\n"));
3089 dump_data(100, cli->cryptkey, 8);
3091 prs_init(&auth_resp, 1024, 4, SAFETY_MARGIN, False);
3093 pwd_make_lm_nt_owf(&cli->pwd, cli->cryptkey);
3095 create_ntlmssp_resp(&cli->pwd, cli->domain,
3096 cli->user_name, cli->calling.name,
3097 cli->ntlmssp_cli_flgs,
3099 prs_link(NULL, &auth_resp, NULL);
3101 memset(pwd_buf, 0, sizeof(pwd_buf));
3104 CVAL(p, 0) = 0xa1; p++;
3105 CVAL(p, 0) = 0x82; p++;
3106 p_gssapi = p; p+= 2;
3107 CVAL(p, 0) = 0x30; p++;
3108 CVAL(p, 0) = 0x82; p++;
3111 CVAL(p, 0) = 0xa2; p++;
3112 CVAL(p, 0) = 0x82; p++;
3114 CVAL(p, 0) = 0x04; p++;
3115 CVAL(p, 0) = 0x82; p++;
3120 safe_strcpy(p, "NTLMSSP", PTR_DIFF(e, p) - 1);
3121 p = skip_string(p, 1);
3125 resp_len = mem_buf_len(auth_resp.data);
3126 mem_buf_copy(p, auth_resp.data, 0, resp_len);
3127 prs_mem_free(&auth_resp);
3131 buf_len = PTR_DIFF(p, pwd_buf);
3132 gssapi_len = PTR_DIFF(p, p_gssapi_end) + 12;
3134 *p_gssapi++ = (gssapi_len >> 8) & 0xff;
3135 *p_gssapi++ = gssapi_len & 0xff;
3140 *p_gssapi++ = (gssapi_len >> 8) & 0xff;
3141 *p_gssapi++ = gssapi_len & 0xff;
3145 *p_oem++ = (gssapi_len >> 8) & 0xff;
3146 *p_oem++ = gssapi_len & 0xff;
3151 *p_oem++ = (gssapi_len >> 8) & 0xff;
3152 *p_oem++ = gssapi_len & 0xff;
3154 /* second session negotiation stage */
3155 if (!cli_session_setup_x(cli, cli->user_name,
3160 DEBUG(1,("failed session setup\n"));
3168 DEBUG(1,("2nd session setup ok\n"));
3172 if (!cli_send_tconX(cli, service, service_type,
3176 DEBUG(1,("failed tcon_X\n"));
3185 else if (cli->pwd.cleartext || cli->pwd.null_pwd)
3187 fstring passwd, ntpasswd;
3188 int pass_len = 0, ntpass_len = 0;
3190 if (cli->pwd.null_pwd)
3192 /* attempt null session */
3193 passwd[0] = ntpasswd[0] = 0;
3194 pass_len = ntpass_len = 1;
3198 /* attempt clear-text session */
3199 pwd_get_cleartext(&(cli->pwd), passwd);
3200 pass_len = strlen(passwd);
3203 /* attempt clear-text session */
3204 if (!cli_session_setup(cli, cli->user_name,
3206 ntpasswd, ntpass_len,
3209 DEBUG(1,("failed session setup\n"));
3218 if (!cli_send_tconX(cli, service, service_type,
3219 (char*)passwd, strlen(passwd)))
3221 DEBUG(1,("failed tcon_X\n"));
3232 /* attempt encrypted session */
3233 unsigned char lm_sess_pwd[24];
3234 unsigned char nt_sess_pwd[128];
3235 size_t nt_sess_pwd_len;
3237 if (cli->use_ntlmv2 != False)
3239 DEBUG(10,("cli_establish_connection: NTLMv2\n"));
3240 pwd_make_lm_nt_owf2(&(cli->pwd), cli->cryptkey,
3241 cli->user_name, calling->name, cli->domain);
3245 DEBUG(10,("cli_establish_connection: NTLMv1\n"));
3246 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
3249 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd,
3252 /* attempt encrypted session */
3253 if (!cli_session_setup_x(cli, cli->user_name,
3254 (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
3255 (char*)nt_sess_pwd, nt_sess_pwd_len,
3258 DEBUG(1,("failed session setup\n"));
3260 if (cli->use_ntlmv2 == Auto)
3262 DEBUG(10,("NTLMv2 failed. Using NTLMv1\n"));
3263 cli->use_ntlmv2 = False;
3266 fstrcpy(cli->share, service);
3267 fstrcpy(cli->dev, service_type);
3269 fstrcpy(cli->desthost, dest_host);
3270 cli_close_socket(cli);
3271 return cli_establish_connection(cli,
3274 service, service_type,
3275 do_shutdown, do_tcon);
3285 DEBUG(1,("session setup ok\n"));
3287 if (*cli->server_domain || *cli->server_os || *cli->server_type)
3289 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
3297 if (!cli_send_tconX(cli, service, service_type,
3298 (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
3300 DEBUG(1,("failed tcon_X\n"));
3318 /****************************************************************************
3319 connect to one of multiple servers: don't care which
3320 ****************************************************************************/
3321 BOOL cli_connect_serverlist(struct cli_state *cli, char *p)
3323 extern pstring global_myname;
3324 extern pstring scope;
3325 fstring remote_machine;
3326 struct in_addr dest_ip;
3327 struct nmb_name calling, called, stupid_smbserver_called;
3328 BOOL connected_ok = False;
3331 * Treat each name in the 'password server =' line as a potential
3332 * PDC/BDC. Contact each in turn and try and authenticate.
3335 while(p && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine)))
3339 if (!cli_initialise(cli))
3341 DEBUG(0,("cli_connect_serverlist: unable to initialize client connection.\n"));
3345 standard_sub_basic(remote_machine);
3346 strupper(remote_machine);
3348 if (!resolve_name( remote_machine, &dest_ip, 0x20))
3350 DEBUG(1,("cli_connect_serverlist: Can't resolve address for %s\n", remote_machine));
3354 if ((lp_security() != SEC_USER) && (ismyip(dest_ip)))
3356 DEBUG(1,("cli_connect_serverlist: Password server loop - not using password server %s\n", remote_machine));
3360 make_nmb_name(&calling, global_myname , 0x0 , scope);
3361 make_nmb_name(&called , remote_machine, 0x20, scope);
3362 /* stupid microsoft destruction of the ability of netbios
3363 * to provide multiple netbios servers on one host.
3365 make_nmb_name(&stupid_smbserver_called , "*SMBSERVER", 0x20, scope);
3367 pwd_set_nullpwd(&cli->pwd);
3369 if (!cli_establish_connection(cli, remote_machine, &dest_ip,
3373 !cli_establish_connection(cli, remote_machine, &dest_ip,
3374 &calling, &stupid_smbserver_called,
3382 if (cli->protocol < PROTOCOL_LANMAN2 ||
3383 !IS_BITS_SET_ALL(cli->sec_mode, 1))
3385 DEBUG(1,("cli_connect_serverlist: machine %s isn't in user level security mode\n",
3392 * We have an anonymous connection to IPC$.
3395 connected_ok = True;
3401 DEBUG(0,("cli_connect_serverlist: Domain password server not available.\n"));
3405 return connected_ok;
3408 /****************************************************************************
3410 ****************************************************************************/
3411 int cli_printjob_del(struct cli_state *cli, int job)
3413 char *rparam = NULL;
3416 int rdrcnt,rprcnt, ret = -1;
3419 bzero(param,sizeof(param));
3422 SSVAL(p,0,81); /* DosPrintJobDel() */
3425 p = skip_string(p,1);
3427 p = skip_string(p,1);
3432 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
3433 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
3434 &rparam, &rprcnt, /* return params, length */
3435 &rdata, &rdrcnt)) { /* return data, length */
3436 ret = SVAL(rparam,0);
3439 if (rparam) free(rparam);
3440 if (rdata) free(rdata);
3446 /****************************************************************************
3447 call fn() on each entry in a print queue
3448 ****************************************************************************/
3449 int cli_print_queue(struct cli_state *cli,
3450 void (*fn)(struct print_job_info *))
3452 char *rparam = NULL;
3460 bzero(param,sizeof(param));
3463 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
3465 pstrcpy(p,"zWrLeh"); /* parameter description? */
3466 p = skip_string(p,1);
3467 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
3468 p = skip_string(p,1);
3469 pstrcpy(p,cli->share); /* name of queue */
3470 p = skip_string(p,1);
3471 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
3472 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
3474 pstrcpy(p,""); /* subformat */
3475 p = skip_string(p,1);
3477 DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
3480 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
3481 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
3482 &rparam, &rprcnt, /* return params, length */
3483 &rdata, &rdrcnt)) { /* return data, length */
3485 result_code = SVAL(rparam,0);
3486 converter = SVAL(rparam,2); /* conversion factor */
3488 if (result_code == 0) {
3489 struct print_job_info job;
3493 for (i = 0; i < SVAL(rparam,4); ++i) {
3495 job.priority = SVAL(p,2);
3497 fix_char_ptr(SVAL(p,4), converter,
3499 job.t = make_unix_date3(p + 12);
3500 job.size = IVAL(p,16);
3501 fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
3510 /* If any parameters or data were returned, free the storage. */
3511 if(rparam) free(rparam);
3512 if(rdata) free(rdata);
3517 /****************************************************************************
3518 check for existance of a dir
3519 ****************************************************************************/
3520 BOOL cli_chkpath(struct cli_state *cli, char *path)
3525 fstrcpy(path2,path);
3526 trim_string(path2,NULL,"\\");
3527 if (!*path2) *path2 = '\\';
3529 bzero(cli->outbuf,smb_size);
3530 set_message(cli->outbuf,0,4 + strlen(path2),True);
3531 SCVAL(cli->outbuf,smb_com,SMBchkpth);
3532 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3533 cli_setup_packet(cli);
3535 p = smb_buf(cli->outbuf);
3539 cli_send_smb(cli, True);
3540 if (!cli_receive_smb(cli)) {
3544 if (cli_error(cli, NULL, NULL)) return False;
3550 /****************************************************************************
3551 start a message sequence
3552 ****************************************************************************/
3553 BOOL cli_message_start(struct cli_state *cli, char *host, char *username,
3558 /* send a SMBsendstrt command */
3559 bzero(cli->outbuf,smb_size);
3560 set_message(cli->outbuf,0,0,True);
3561 CVAL(cli->outbuf,smb_com) = SMBsendstrt;
3562 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3563 cli_setup_packet(cli);
3565 p = smb_buf(cli->outbuf);
3567 pstrcpy(p,username);
3568 p = skip_string(p,1);
3571 p = skip_string(p,1);
3573 set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
3575 cli_send_smb(cli, True);
3577 if (!cli_receive_smb(cli)) {
3581 if (cli_error(cli, NULL, NULL)) return False;
3583 *grp = SVAL(cli->inbuf,smb_vwv0);
3589 /****************************************************************************
3591 ****************************************************************************/
3592 BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp)
3596 bzero(cli->outbuf,smb_size);
3597 set_message(cli->outbuf,1,len+3,True);
3598 CVAL(cli->outbuf,smb_com) = SMBsendtxt;
3599 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3600 cli_setup_packet(cli);
3602 SSVAL(cli->outbuf,smb_vwv0,grp);
3604 p = smb_buf(cli->outbuf);
3607 memcpy(p+3,msg,len);
3608 cli_send_smb(cli, True);
3610 if (!cli_receive_smb(cli)) {
3614 if (cli_error(cli, NULL, NULL)) return False;
3619 /****************************************************************************
3621 ****************************************************************************/
3622 BOOL cli_message_end(struct cli_state *cli, int grp)
3624 bzero(cli->outbuf,smb_size);
3625 set_message(cli->outbuf,1,0,True);
3626 CVAL(cli->outbuf,smb_com) = SMBsendend;
3627 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3629 SSVAL(cli->outbuf,smb_vwv0,grp);
3631 cli_setup_packet(cli);
3633 cli_send_smb(cli, True);
3635 if (!cli_receive_smb(cli)) {
3639 if (cli_error(cli, NULL, NULL)) return False;
3645 /****************************************************************************
3647 ****************************************************************************/
3648 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3650 bzero(cli->outbuf,smb_size);
3651 set_message(cli->outbuf,0,0,True);
3652 CVAL(cli->outbuf,smb_com) = SMBdskattr;
3653 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3654 cli_setup_packet(cli);
3656 cli_send_smb(cli, True);
3657 if (!cli_receive_smb(cli)) {
3661 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
3662 *total = SVAL(cli->inbuf,smb_vwv0);
3663 *avail = SVAL(cli->inbuf,smb_vwv3);