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;
258 flgs2 |= FLAGS2_EXT_SEC;
260 flgs2 |= FLAGS2_UNICODE_STRINGS;
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"},
757 /****************************************************************************
759 ****************************************************************************/
760 BOOL cli_session_setup_x(struct cli_state *cli,
762 char *pass, int passlen,
763 char *ntpass, int ntpasslen,
769 BOOL esec = cli->capabilities & CAP_EXTENDED_SECURITY;
771 DEBUG(100,("cli_session_setup. extended security: %s\n",
774 #ifdef DEBUG_PASSWORD
775 DEBUG(100,("cli_session_setup. pass, ntpass\n"));
776 dump_data(100, pass, passlen);
777 dump_data(100, ntpass, ntpasslen);
780 if (cli->protocol < PROTOCOL_LANMAN1)
785 /* send a session setup command */
786 bzero(cli->outbuf,smb_size);
788 if (cli->protocol < PROTOCOL_NT1)
790 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
791 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
792 cli_setup_packet(cli);
794 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
795 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
796 SSVAL(cli->outbuf,smb_vwv3,2);
797 SSVAL(cli->outbuf,smb_vwv4,1);
798 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
799 SSVAL(cli->outbuf,smb_vwv7,passlen);
800 p = smb_buf(cli->outbuf);
801 memcpy(p,pass,passlen);
808 set_message(cli->outbuf,12,0,True);
809 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
810 cli_setup_packet(cli);
812 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
813 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
814 SSVAL(cli->outbuf,smb_vwv3,2);
815 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
816 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
817 SSVAL(cli->outbuf,smb_vwv7,passlen);
818 SIVAL(cli->outbuf,smb_vwv10, CAP_EXTENDED_SECURITY|CAP_STATUS32|CAP_UNICODE);
819 p = smb_buf(cli->outbuf);
820 memcpy(p,pass,passlen);
823 p = cli_put_string(cli, p, "Unix", False);
824 p = cli_put_string(cli, p, "Samba", False);
825 p = cli_put_string(cli, p, "", False);
828 set_message(cli->outbuf,12,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
832 set_message(cli->outbuf,13,0,True);
833 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
834 cli_setup_packet(cli);
836 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
837 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
838 SSVAL(cli->outbuf,smb_vwv3,2);
839 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
840 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
841 SSVAL(cli->outbuf,smb_vwv7,passlen);
842 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
843 SIVAL(cli->outbuf,smb_vwv11, 0);
844 p = smb_buf(cli->outbuf);
845 memcpy(p,pass,passlen);
846 p += SVAL(cli->outbuf,smb_vwv7);
847 memcpy(p,ntpass,ntpasslen);
848 p += SVAL(cli->outbuf,smb_vwv8);
850 p = cli_put_string(cli, p, user, False);
851 strupper(user_domain);
852 p = cli_put_string(cli, p, user_domain, False);
853 p = cli_put_string(cli, p, "Unix", True);
854 p = cli_put_string(cli, p, "Samba", False);
856 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
859 cli_send_smb(cli, True);
860 if (!cli_receive_smb(cli))
862 DEBUG(10,("cli_session_setup_x: receive smb failed\n"));
866 if (cli_error(cli, &eclass, &ecode))
868 uint16 flgs2 = SVAL(cli->inbuf,smb_flg2);
869 if (IS_BITS_CLR_ALL(flgs2, FLAGS2_32_BIT_ERROR_CODES))
871 if (ecode != ERRmoredata || !esec)
876 else if (ecode != 0xC0000016) /* STATUS_MORE_PROCESSING_REQD */
882 /* use the returned vuid from now on */
883 cli->vuid = SVAL(cli->inbuf,smb_uid);
885 if (cli->protocol >= PROTOCOL_NT1)
893 * Save off some of the connected server
900 server_os = smb_buf(cli->inbuf);
901 server_type = skip_string(server_os,1);
902 server_domain = skip_string(server_type,1);
904 fstrcpy(cli->server_os, server_os);
905 fstrcpy(cli->server_type, server_type);
906 fstrcpy(cli->server_domain, server_domain);
913 static BOOL cli_calc_session_pwds(struct cli_state *cli,
914 char *pword, char *ntpword,
915 char *pass, int *passlen,
916 char *ntpass, int *ntpasslen,
919 BOOL ntpass_ok = ntpass != NULL && ntpasslen != NULL;
921 if (pass == NULL || passlen == NULL)
923 DEBUG(0,("cli_calc_session_pwds: pass and passlen are NULL\n"));
926 if ((ntpass != NULL || ntpasslen != NULL) &&
927 (ntpass == NULL || ntpasslen == NULL))
929 DEBUG(0,("cli_calc_session_pwds: ntpasswd pointers invalid\n"));
933 #ifdef DEBUG_PASSWORD
934 DEBUG(100,("cli_calc_session_pwds. pass, ntpass\n"));
935 dump_data(100, pass, *passlen);
938 dump_data(100, ntpass, *ntpasslen);
941 if (!IS_BITS_SET_ALL(cli->sec_mode, 1))
943 /* if in share level security then don't send a password now */
953 else if ((*passlen == 0 || *passlen == 1) && (pass[0] == '\0'))
955 /* Null session connect. */
971 if (*passlen == 24 && *ntpasslen >= 24)
973 if (IS_BITS_SET_ALL(cli->sec_mode, 2))
975 /* encrypted password, implicit from 24-byte lengths */
976 memcpy(pword , pass , *passlen);
977 memcpy(ntpword, ntpass, *ntpasslen);
981 DEBUG(0,("cli_calc_session_pwds: encrypted passwords not supported by server\n"));
985 else if (*ntpasslen == 0 || !IS_BITS_SET_ALL(cli->sec_mode, 2))
987 /* plain-text password: server doesn't support encrypted. */
988 fstrcpy(pword, pass);
989 fstrcpy(ntpword, "");
992 else if (ntpasslen != NULL)
994 /* passlen != 0, ntpasslen != 0 && server supports encryption */
997 /* plain-text password requesting to be encrypted */
998 uchar *srv_key = (uchar *)cli->cryptkey;
1002 SMBgenclientchals(cli->lm_cli_chal,
1004 &cli->nt_cli_chal_len,
1008 nt_owf_gen(pword, nt_owf);
1009 ntv2_owf_gen(nt_owf, cli->user_name, cli->domain, kr);
1012 memcpy(pword, cli->lm_cli_chal, 8);
1013 SMBOWFencrypt_ntv2(kr,
1015 cli->lm_cli_chal, 8,
1020 memcpy(ntpword, cli->lm_cli_chal, cli->nt_cli_chal_len);
1021 SMBOWFencrypt_ntv2(kr,
1023 cli->nt_cli_chal, cli->nt_cli_chal_len,
1024 &ntpword[cli->nt_cli_chal_len]);
1025 *ntpasslen = cli->nt_cli_chal_len + 16;
1029 /* plain-text password requesting to be encrypted */
1030 uchar *key = (uchar *)cli->cryptkey;
1031 SMBencrypt ((uchar *)pass , key,(uchar *)pword );
1032 SMBNTencrypt((uchar *)ntpass, key,(uchar *)ntpword);
1040 /****************************************************************************
1041 send a session setup
1042 ****************************************************************************/
1043 BOOL cli_session_setup(struct cli_state *cli,
1045 char *pass, int passlen,
1046 char *ntpass, int ntpasslen,
1049 fstring pword, ntpword;
1051 if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1)
1056 fstrcpy(cli->user_name, user);
1058 return cli_calc_session_pwds(cli, pword, ntpword,
1060 ntpass, &ntpasslen, cli->use_ntlmv2) &&
1061 cli_session_setup_x(cli, user, pass, passlen, ntpass, ntpasslen,
1065 /****************************************************************************
1067 *****************************************************************************/
1069 BOOL cli_ulogoff(struct cli_state *cli)
1071 bzero(cli->outbuf,smb_size);
1072 set_message(cli->outbuf,2,0,True);
1073 CVAL(cli->outbuf,smb_com) = SMBulogoffX;
1074 cli_setup_packet(cli);
1075 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1076 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1078 cli_send_smb(cli, True);
1079 if (!cli_receive_smb(cli))
1082 return CVAL(cli->inbuf,smb_rcls) == 0;
1085 /****************************************************************************
1087 ****************************************************************************/
1088 BOOL cli_send_tconX(struct cli_state *cli,
1089 char *share, char *dev, char *pass, int passlen)
1091 fstring fullshare, pword;
1093 bzero(cli->outbuf,smb_size);
1094 bzero(cli->inbuf,smb_size);
1096 fstrcpy(cli->share, share);
1098 /* in user level security don't send a password now */
1099 if (cli->sec_mode & 1) {
1104 if ((cli->sec_mode & 2) && *pass && passlen != 24) {
1106 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
1108 memcpy(pword, pass, passlen);
1111 slprintf(fullshare, sizeof(fullshare)-1,
1112 "\\\\%s\\%s", cli->desthost, share);
1113 strupper(fullshare);
1115 set_message(cli->outbuf,4, 0, True);
1116 CVAL(cli->outbuf,smb_com) = SMBtconX;
1117 cli_setup_packet(cli);
1119 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1120 SSVAL(cli->outbuf,smb_vwv3,passlen);
1122 p = smb_buf(cli->outbuf);
1123 memcpy(p,pword,passlen);
1125 p = cli_put_string(cli, p, fullshare, False);
1127 p = skip_string(p, 1);
1129 set_message(cli->outbuf,4,PTR_DIFF(p, smb_buf(cli->outbuf)),False);
1131 SCVAL(cli->inbuf,smb_rcls, 1);
1133 cli_send_smb(cli, True);
1134 if (!cli_receive_smb(cli))
1137 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1141 fstrcpy(cli->dev, "A:");
1143 if (cli->protocol >= PROTOCOL_NT1)
1145 cli_get_string(cli, smb_buf(cli->inbuf),
1146 cli->dev, sizeof(cli->dev));
1149 if (strcasecmp(share,"IPC$")==0) {
1150 fstrcpy(cli->dev, "IPC");
1153 /* only grab the device if we have a recent protocol level */
1154 if (cli->protocol >= PROTOCOL_NT1 && smb_buflen(cli->inbuf) == 3)
1156 /* almost certainly win95 - enable bug fixes */
1160 cli->cnum = SVAL(cli->inbuf,smb_tid);
1165 /****************************************************************************
1166 send a tree disconnect
1167 ****************************************************************************/
1168 BOOL cli_tdis(struct cli_state *cli)
1170 bzero(cli->outbuf,smb_size);
1171 set_message(cli->outbuf,0,0,True);
1172 CVAL(cli->outbuf,smb_com) = SMBtdis;
1173 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1174 cli_setup_packet(cli);
1176 cli_send_smb(cli, True);
1177 if (!cli_receive_smb(cli))
1180 return CVAL(cli->inbuf,smb_rcls) == 0;
1183 /****************************************************************************
1185 ****************************************************************************/
1186 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
1190 bzero(cli->outbuf,smb_size);
1191 bzero(cli->inbuf,smb_size);
1193 set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
1195 CVAL(cli->outbuf,smb_com) = SMBmv;
1196 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1197 cli_setup_packet(cli);
1199 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
1201 p = smb_buf(cli->outbuf);
1203 pstrcpy(p,fname_src);
1204 p = skip_string(p,1);
1206 pstrcpy(p,fname_dst);
1208 cli_send_smb(cli, True);
1209 if (!cli_receive_smb(cli)) {
1213 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1220 /****************************************************************************
1222 ****************************************************************************/
1223 BOOL cli_unlink(struct cli_state *cli, char *fname)
1227 bzero(cli->outbuf,smb_size);
1228 bzero(cli->inbuf,smb_size);
1230 set_message(cli->outbuf,1, 2 + strlen(fname),True);
1232 CVAL(cli->outbuf,smb_com) = SMBunlink;
1233 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1234 cli_setup_packet(cli);
1236 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
1238 p = smb_buf(cli->outbuf);
1242 cli_send_smb(cli, True);
1243 if (!cli_receive_smb(cli)) {
1247 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1254 /****************************************************************************
1256 ****************************************************************************/
1257 BOOL cli_mkdir(struct cli_state *cli, char *dname)
1261 bzero(cli->outbuf,smb_size);
1262 bzero(cli->inbuf,smb_size);
1264 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1266 CVAL(cli->outbuf,smb_com) = SMBmkdir;
1267 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1268 cli_setup_packet(cli);
1270 p = smb_buf(cli->outbuf);
1274 cli_send_smb(cli, True);
1275 if (!cli_receive_smb(cli)) {
1279 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1286 /****************************************************************************
1288 ****************************************************************************/
1289 BOOL cli_rmdir(struct cli_state *cli, char *dname)
1293 bzero(cli->outbuf,smb_size);
1294 bzero(cli->inbuf,smb_size);
1296 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1298 CVAL(cli->outbuf,smb_com) = SMBrmdir;
1299 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1300 cli_setup_packet(cli);
1302 p = smb_buf(cli->outbuf);
1306 cli_send_smb(cli, True);
1307 if (!cli_receive_smb(cli)) {
1311 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1320 /****************************************************************************
1322 ****************************************************************************/
1323 int cli_nt_create(struct cli_state *cli, char *fname)
1327 bzero(cli->outbuf,smb_size);
1328 bzero(cli->inbuf,smb_size);
1330 set_message(cli->outbuf,24,1 + strlen(fname),True);
1332 CVAL(cli->outbuf,smb_com) = SMBntcreateX;
1333 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1334 cli_setup_packet(cli);
1336 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1337 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0x06);
1338 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
1339 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, 0x2019f);
1340 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0);
1341 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03);
1342 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01);
1343 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0);
1344 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
1345 SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname));
1347 p = smb_buf(cli->outbuf);
1349 p = skip_string(p,1);
1351 cli_send_smb(cli, True);
1352 if (!cli_receive_smb(cli)) {
1356 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1360 return SVAL(cli->inbuf,smb_vwv2 + 1);
1364 /****************************************************************************
1366 ****************************************************************************/
1367 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
1371 unsigned accessmode=0;
1373 /* you must open for RW not just write - otherwise getattrE doesn't
1375 if ((flags & O_ACCMODE) == O_WRONLY && strncmp(cli->dev, "LPT", 3)) {
1376 flags = (flags & ~O_ACCMODE) | O_RDWR;
1379 if (flags & O_CREAT)
1381 if (!(flags & O_EXCL)) {
1382 if (flags & O_TRUNC)
1388 accessmode = (share_mode<<4);
1390 if ((flags & O_ACCMODE) == O_RDWR) {
1392 } else if ((flags & O_ACCMODE) == O_WRONLY) {
1397 if ((flags & O_SYNC) == O_SYNC) {
1398 accessmode |= (1<<14);
1402 bzero(cli->outbuf,smb_size);
1403 bzero(cli->inbuf,smb_size);
1405 set_message(cli->outbuf,15,1 + strlen(fname),True);
1407 CVAL(cli->outbuf,smb_com) = SMBopenX;
1408 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1409 cli_setup_packet(cli);
1411 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1412 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1413 SSVAL(cli->outbuf,smb_vwv3,accessmode);
1414 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1415 SSVAL(cli->outbuf,smb_vwv5,0);
1416 SSVAL(cli->outbuf,smb_vwv8,openfn);
1418 p = smb_buf(cli->outbuf);
1419 p = cli_put_string(cli, p, fname, False);
1421 set_message(cli->outbuf,15,PTR_DIFF(p, smb_buf(cli->outbuf)),False);
1423 cli_send_smb(cli, True);
1424 if (!cli_receive_smb(cli)) {
1428 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1432 return SVAL(cli->inbuf,smb_vwv2);
1438 /****************************************************************************
1440 ****************************************************************************/
1441 BOOL cli_close(struct cli_state *cli, int fnum)
1443 bzero(cli->outbuf,smb_size);
1444 bzero(cli->inbuf,smb_size);
1446 set_message(cli->outbuf,3,0,True);
1448 CVAL(cli->outbuf,smb_com) = SMBclose;
1449 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1450 cli_setup_packet(cli);
1452 SSVAL(cli->outbuf,smb_vwv0,fnum);
1453 SIVALS(cli->outbuf,smb_vwv1,-1);
1455 cli_send_smb(cli, True);
1456 if (!cli_receive_smb(cli)) {
1460 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1468 /****************************************************************************
1470 ****************************************************************************/
1471 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1474 int saved_timeout = cli->timeout;
1476 bzero(cli->outbuf,smb_size);
1477 bzero(cli->inbuf,smb_size);
1479 set_message(cli->outbuf,8,10,True);
1481 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1482 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1483 cli_setup_packet(cli);
1485 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1486 SSVAL(cli->outbuf,smb_vwv2,fnum);
1487 CVAL(cli->outbuf,smb_vwv3) = 0;
1488 SIVALS(cli->outbuf, smb_vwv4, timeout);
1489 SSVAL(cli->outbuf,smb_vwv6,0);
1490 SSVAL(cli->outbuf,smb_vwv7,1);
1492 p = smb_buf(cli->outbuf);
1493 SSVAL(p, 0, cli->pid);
1494 SIVAL(p, 2, offset);
1496 cli_send_smb(cli, True);
1498 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout;
1500 if (!cli_receive_smb(cli)) {
1501 cli->timeout = saved_timeout;
1505 cli->timeout = saved_timeout;
1507 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1514 /****************************************************************************
1516 ****************************************************************************/
1517 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1521 bzero(cli->outbuf,smb_size);
1522 bzero(cli->inbuf,smb_size);
1524 set_message(cli->outbuf,8,10,True);
1526 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1527 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1528 cli_setup_packet(cli);
1530 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1531 SSVAL(cli->outbuf,smb_vwv2,fnum);
1532 CVAL(cli->outbuf,smb_vwv3) = 0;
1533 SIVALS(cli->outbuf, smb_vwv4, timeout);
1534 SSVAL(cli->outbuf,smb_vwv6,1);
1535 SSVAL(cli->outbuf,smb_vwv7,0);
1537 p = smb_buf(cli->outbuf);
1538 SSVAL(p, 0, cli->pid);
1539 SIVAL(p, 2, offset);
1542 cli_send_smb(cli, True);
1543 if (!cli_receive_smb(cli)) {
1547 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1556 /****************************************************************************
1557 issue a single SMBread and don't wait for a reply
1558 ****************************************************************************/
1559 static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
1562 bzero(cli->outbuf,smb_size);
1563 bzero(cli->inbuf,smb_size);
1565 set_message(cli->outbuf,10,0,True);
1567 CVAL(cli->outbuf,smb_com) = SMBreadX;
1568 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1569 cli_setup_packet(cli);
1571 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1572 SSVAL(cli->outbuf,smb_vwv2,fnum);
1573 SIVAL(cli->outbuf,smb_vwv3,offset);
1574 SSVAL(cli->outbuf,smb_vwv5,size);
1575 SSVAL(cli->outbuf,smb_vwv6,size);
1576 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1578 cli_send_smb(cli, True);
1581 /****************************************************************************
1583 ****************************************************************************/
1584 size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
1590 int mpx = MAX(cli->max_mux-1, 1);
1591 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1593 int blocks = (size + (block-1)) / block;
1595 if (size == 0) return 0;
1597 while (received < blocks)
1601 while (issued - received < mpx && issued < blocks) {
1602 int size1 = MIN(block, size-issued*block);
1603 cli_issue_read(cli, fnum, offset+issued*block, size1, issued);
1607 if (!cli_receive_smb(cli)) {
1612 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1613 size2 = SVAL(cli->inbuf, smb_vwv5);
1615 if (cli_error(cli, NULL, NULL))
1617 blocks = MIN(blocks, mid-1);
1622 blocks = MIN(blocks, mid-1);
1623 /* this distinguishes EOF from an error */
1624 total = MAX(total, 0);
1628 if (size2 > block) {
1629 DEBUG(0,("server returned more than we wanted!\n"));
1632 if (mid >= issued) {
1633 DEBUG(0,("invalid mid from server!\n"));
1636 p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
1638 memcpy(buf+mid*block, p, size2);
1640 total = MAX(total, mid*block + size2);
1643 while (received < issued) {
1644 cli_receive_smb(cli);
1652 /****************************************************************************
1653 issue a single SMBwrite and don't wait for a reply
1654 ****************************************************************************/
1655 static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf,
1660 bzero(cli->outbuf,smb_size);
1661 bzero(cli->inbuf,smb_size);
1663 set_message(cli->outbuf,12,size,True);
1665 CVAL(cli->outbuf,smb_com) = SMBwriteX;
1666 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1667 cli_setup_packet(cli);
1669 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1670 SSVAL(cli->outbuf,smb_vwv2,fnum);
1672 SIVAL(cli->outbuf,smb_vwv3,offset);
1673 SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0);
1674 SSVAL(cli->outbuf,smb_vwv7,mode);
1676 SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0);
1677 SSVAL(cli->outbuf,smb_vwv10,size);
1678 SSVAL(cli->outbuf,smb_vwv11,
1679 smb_buf(cli->outbuf) - smb_base(cli->outbuf));
1681 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
1682 memcpy(p, buf, size);
1684 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1686 cli_send_smb(cli, True);
1689 /****************************************************************************
1691 write_mode: 0x0001 disallow write cacheing
1692 0x0002 return bytes remaining
1693 0x0004 use raw named pipe protocol
1694 0x0008 start of message mode named pipe protocol
1695 ****************************************************************************/
1696 ssize_t cli_write(struct cli_state *cli,
1697 int fnum, uint16 write_mode,
1698 char *buf, off_t offset, size_t size)
1703 int mpx = MAX(cli->max_mux-1, 1);
1704 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1706 int blocks = (size + (block-1)) / block;
1708 if (size == 0) return 0;
1710 while (received < blocks) {
1713 while (issued - received < mpx && issued < blocks) {
1714 int size1 = MIN(block, size-issued*block);
1715 cli_issue_write(cli, fnum, offset+issued*block,
1722 if (!cli_receive_smb(cli)) {
1727 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1728 size2 = SVAL(cli->inbuf, smb_vwv2);
1730 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1731 blocks = MIN(blocks, mid-1);
1736 blocks = MIN(blocks, mid-1);
1737 /* this distinguishes EOF from an error */
1738 total = MAX(total, 0);
1744 total = MAX(total, mid*block + size2);
1747 while (received < issued) {
1748 cli_receive_smb(cli);
1756 /****************************************************************************
1757 do a SMBgetattrE call
1758 ****************************************************************************/
1759 BOOL cli_getattrE(struct cli_state *cli, int fd,
1760 uint16 *attr, size_t *size,
1761 time_t *c_time, time_t *a_time, time_t *m_time)
1763 bzero(cli->outbuf,smb_size);
1764 bzero(cli->inbuf,smb_size);
1766 set_message(cli->outbuf,2,0,True);
1768 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
1769 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1770 cli_setup_packet(cli);
1772 SSVAL(cli->outbuf,smb_vwv0,fd);
1774 cli_send_smb(cli, True);
1775 if (!cli_receive_smb(cli)) {
1779 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1784 *size = IVAL(cli->inbuf, smb_vwv6);
1788 *attr = SVAL(cli->inbuf,smb_vwv10);
1792 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
1796 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
1800 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
1807 /****************************************************************************
1809 ****************************************************************************/
1810 BOOL cli_getatr(struct cli_state *cli, char *fname,
1811 uint16 *attr, size_t *size, time_t *t)
1815 bzero(cli->outbuf,smb_size);
1816 bzero(cli->inbuf,smb_size);
1818 set_message(cli->outbuf,0,strlen(fname)+2,True);
1820 CVAL(cli->outbuf,smb_com) = SMBgetatr;
1821 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1822 cli_setup_packet(cli);
1824 p = smb_buf(cli->outbuf);
1826 pstrcpy(p+1, fname);
1828 cli_send_smb(cli, True);
1829 if (!cli_receive_smb(cli)) {
1833 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1838 *size = IVAL(cli->inbuf, smb_vwv3);
1842 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1846 *attr = SVAL(cli->inbuf,smb_vwv0);
1854 /****************************************************************************
1856 ****************************************************************************/
1857 BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
1861 bzero(cli->outbuf,smb_size);
1862 bzero(cli->inbuf,smb_size);
1864 set_message(cli->outbuf,8,strlen(fname)+4,True);
1866 CVAL(cli->outbuf,smb_com) = SMBsetatr;
1867 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1868 cli_setup_packet(cli);
1870 SSVAL(cli->outbuf,smb_vwv0, attr);
1871 put_dos_date3(cli->outbuf,smb_vwv1, t);
1873 p = smb_buf(cli->outbuf);
1875 pstrcpy(p+1, fname);
1876 p = skip_string(p,1);
1879 cli_send_smb(cli, True);
1880 if (!cli_receive_smb(cli)) {
1884 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1891 /****************************************************************************
1892 send a qpathinfo call
1893 ****************************************************************************/
1894 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
1895 time_t *c_time, time_t *a_time, time_t *m_time,
1896 size_t *size, uint16 *mode)
1900 uint16 setup = TRANSACT2_QPATHINFO;
1902 char *rparam=NULL, *rdata=NULL;
1905 time_t (*date_fn)(void *);
1907 param_len = strlen(fname) + 7;
1909 memset(param, 0, param_len);
1910 SSVAL(param, 0, SMB_INFO_STANDARD);
1911 pstrcpy(¶m[6], fname);
1914 ret = (cli_send_trans(cli, SMBtrans2,
1915 NULL, 0, /* Name, length */
1916 -1, 0, /* fid, flags */
1917 &setup, 1, 0, /* setup, length, max */
1918 param, param_len, 10, /* param, length, max */
1919 NULL, data_len, cli->max_xmit /* data, length, max */
1921 cli_receive_trans(cli, SMBtrans2,
1922 &rparam, ¶m_len,
1923 &rdata, &data_len));
1925 /* we need to work around a Win95 bug - sometimes
1926 it gives ERRSRV/ERRerror temprarily */
1929 cli_error(cli, &eclass, &ecode);
1930 if (eclass != ERRSRV || ecode != ERRerror) break;
1933 } while (count-- && ret==False);
1935 if (!ret || !rdata || data_len < 22) {
1940 date_fn = make_unix_date;
1942 date_fn = make_unix_date2;
1946 *c_time = date_fn(rdata+0);
1949 *a_time = date_fn(rdata+4);
1952 *m_time = date_fn(rdata+8);
1955 *size = IVAL(rdata, 12);
1958 *mode = SVAL(rdata,l1_attrFile);
1961 if (rdata) free(rdata);
1962 if (rparam) free(rparam);
1966 /****************************************************************************
1967 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1968 ****************************************************************************/
1969 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
1970 time_t *c_time, time_t *a_time, time_t *m_time,
1971 time_t *w_time, size_t *size, uint16 *mode,
1976 uint16 setup = TRANSACT2_QPATHINFO;
1978 char *rparam=NULL, *rdata=NULL;
1980 param_len = strlen(fname) + 7;
1982 memset(param, 0, param_len);
1983 SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1984 pstrcpy(¶m[6], fname);
1986 if (!cli_send_trans(cli, SMBtrans2,
1987 NULL, 0, /* name, length */
1988 -1, 0, /* fid, flags */
1989 &setup, 1, 0, /* setup, length, max */
1990 param, param_len, 10, /* param, length, max */
1991 NULL, data_len, cli->max_xmit /* data, length, max */
1996 if (!cli_receive_trans(cli, SMBtrans2,
1997 &rparam, ¶m_len,
1998 &rdata, &data_len)) {
2002 if (!rdata || data_len < 22) {
2007 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
2010 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
2013 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
2016 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
2019 *mode = SVAL(rdata, 32);
2022 *size = IVAL(rdata, 40);
2025 *ino = IVAL(rdata, 64);
2028 if (rdata) free(rdata);
2029 if (rparam) free(rparam);
2034 /****************************************************************************
2035 send a qfileinfo call
2036 ****************************************************************************/
2037 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
2038 uint16 *mode, size_t *size,
2039 time_t *c_time, time_t *a_time, time_t *m_time,
2040 time_t *w_time, SMB_INO_T *ino)
2044 uint16 setup = TRANSACT2_QFILEINFO;
2046 char *rparam=NULL, *rdata=NULL;
2048 /* if its a win95 server then fail this - win95 totally screws it
2050 if (cli->win95) return False;
2054 memset(param, 0, param_len);
2055 SSVAL(param, 0, fnum);
2056 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
2058 if (!cli_send_trans(cli, SMBtrans2,
2059 NULL, 0, /* name, length */
2060 -1, 0, /* fid, flags */
2061 &setup, 1, 0, /* setup, length, max */
2062 param, param_len, 2, /* param, length, max */
2063 NULL, data_len, cli->max_xmit /* data, length, max */
2068 if (!cli_receive_trans(cli, SMBtrans2,
2069 &rparam, ¶m_len,
2070 &rdata, &data_len)) {
2074 if (!rdata || data_len < 68) {
2079 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
2082 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
2085 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
2088 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
2091 *mode = SVAL(rdata, 32);
2094 *size = IVAL(rdata, 40);
2097 *ino = IVAL(rdata, 64);
2100 if (rdata) free(rdata);
2101 if (rparam) free(rparam);
2106 /****************************************************************************
2107 interpret a long filename structure - this is mostly guesses at the moment
2108 The length of the structure is returned
2109 The structure of a long filename depends on the info level. 260 is used
2110 by NT and 2 is used by OS/2
2111 ****************************************************************************/
2112 static int interpret_long_filename(int level,char *p,file_info *finfo)
2114 extern file_info def_finfo;
2117 memcpy(finfo,&def_finfo,sizeof(*finfo));
2121 case 1: /* OS/2 understands this */
2123 /* these dates are converted to GMT by make_unix_date */
2124 finfo->ctime = make_unix_date2(p+4);
2125 finfo->atime = make_unix_date2(p+8);
2126 finfo->mtime = make_unix_date2(p+12);
2127 finfo->size = IVAL(p,16);
2128 finfo->mode = CVAL(p,24);
2129 pstrcpy(finfo->name,p+27);
2131 return(28 + CVAL(p,26));
2133 case 2: /* this is what OS/2 uses mostly */
2135 /* these dates are converted to GMT by make_unix_date */
2136 finfo->ctime = make_unix_date2(p+4);
2137 finfo->atime = make_unix_date2(p+8);
2138 finfo->mtime = make_unix_date2(p+12);
2139 finfo->size = IVAL(p,16);
2140 finfo->mode = CVAL(p,24);
2141 pstrcpy(finfo->name,p+31);
2143 return(32 + CVAL(p,30));
2145 /* levels 3 and 4 are untested */
2148 /* these dates are probably like the other ones */
2149 finfo->ctime = make_unix_date2(p+8);
2150 finfo->atime = make_unix_date2(p+12);
2151 finfo->mtime = make_unix_date2(p+16);
2152 finfo->size = IVAL(p,20);
2153 finfo->mode = CVAL(p,28);
2154 pstrcpy(finfo->name,p+33);
2156 return(SVAL(p,4)+4);
2160 /* these dates are probably like the other ones */
2161 finfo->ctime = make_unix_date2(p+8);
2162 finfo->atime = make_unix_date2(p+12);
2163 finfo->mtime = make_unix_date2(p+16);
2164 finfo->size = IVAL(p,20);
2165 finfo->mode = CVAL(p,28);
2166 pstrcpy(finfo->name,p+37);
2168 return(SVAL(p,4)+4);
2170 case 260: /* NT uses this, but also accepts 2 */
2172 int ret = SVAL(p,0);
2174 p += 4; /* next entry offset */
2175 p += 4; /* fileindex */
2177 /* these dates appear to arrive in a
2178 weird way. It seems to be localtime
2179 plus the serverzone given in the
2180 initial connect. This is GMT when
2181 DST is not in effect and one hour
2182 from GMT otherwise. Can this really
2185 I suppose this could be called
2186 kludge-GMT. Is is the GMT you get
2187 by using the current DST setting on
2188 a different localtime. It will be
2189 cheap to calculate, I suppose, as
2190 no DST tables will be needed */
2192 finfo->ctime = interpret_long_date(p); p += 8;
2193 finfo->atime = interpret_long_date(p); p += 8;
2194 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
2195 finfo->size = IVAL(p,0); p += 8;
2196 p += 8; /* alloc size */
2197 finfo->mode = CVAL(p,0); p += 4;
2198 namelen = IVAL(p,0); p += 4;
2199 p += 4; /* EA size */
2200 p += 2; /* short name len? */
2201 p += 24; /* short name? */
2202 StrnCpy(finfo->name,p,namelen);
2208 DEBUG(1,("Unknown long filename format %d\n",level));
2213 /****************************************************************************
2214 do a directory listing, calling fn on each file found
2215 ****************************************************************************/
2216 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
2217 void (*fn)(file_info *, const char *))
2219 int max_matches = 512;
2220 /* NT uses 260, OS/2 uses 2. Both accept 1. */
2221 int info_level = cli->protocol<PROTOCOL_NT1?1:260;
2226 char *dirlist = NULL;
2227 int dirlist_len = 0;
2228 int total_received = -1;
2230 int ff_resume_key = 0;
2231 int ff_searchcount=0;
2234 int ff_dir_handle=0;
2236 char *rparam=NULL, *rdata=NULL;
2237 int param_len, data_len;
2244 while (ff_eos == 0) {
2246 if (loop_count > 200) {
2247 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
2251 param_len = 12+strlen(mask)+1;
2254 setup = TRANSACT2_FINDFIRST;
2255 SSVAL(param,0,attribute); /* attribute */
2256 SSVAL(param,2,max_matches); /* max count */
2257 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
2258 SSVAL(param,6,info_level);
2260 pstrcpy(param+12,mask);
2262 setup = TRANSACT2_FINDNEXT;
2263 SSVAL(param,0,ff_dir_handle);
2264 SSVAL(param,2,max_matches); /* max count */
2265 SSVAL(param,4,info_level);
2266 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
2267 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
2268 pstrcpy(param+12,mask);
2270 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
2271 ff_dir_handle,ff_resume_key,ff_lastname,mask));
2274 if (!cli_send_trans(cli, SMBtrans2,
2275 NULL, 0, /* Name, length */
2276 -1, 0, /* fid, flags */
2277 &setup, 1, 0, /* setup, length, max */
2278 param, param_len, 10, /* param, length, max */
2280 cli->max_xmit /* data, length, max */
2285 if (!cli_receive_trans(cli, SMBtrans2,
2286 &rparam, ¶m_len,
2287 &rdata, &data_len)) {
2288 /* we need to work around a Win95 bug - sometimes
2289 it gives ERRSRV/ERRerror temprarily */
2292 cli_error(cli, &eclass, &ecode);
2293 if (eclass != ERRSRV || ecode != ERRerror) break;
2298 if (total_received == -1) total_received = 0;
2300 /* parse out some important return info */
2303 ff_dir_handle = SVAL(p,0);
2304 ff_searchcount = SVAL(p,2);
2306 ff_lastname = SVAL(p,8);
2308 ff_searchcount = SVAL(p,0);
2310 ff_lastname = SVAL(p,6);
2313 if (ff_searchcount == 0)
2316 /* point to the data bytes */
2319 /* we might need the lastname for continuations */
2320 if (ff_lastname > 0) {
2325 StrnCpy(mask,p+ff_lastname,
2326 data_len-ff_lastname);
2329 pstrcpy(mask,p + ff_lastname + 1);
2337 /* and add them to the dirlist pool */
2338 dirlist = Realloc(dirlist,dirlist_len + data_len);
2341 DEBUG(0,("Failed to expand dirlist\n"));
2345 /* put in a length for the last entry, to ensure we can chain entries
2346 into the next packet */
2347 for (p2=p,i=0;i<(ff_searchcount-1);i++)
2348 p2 += interpret_long_filename(info_level,p2,NULL);
2349 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
2351 /* grab the data for later use */
2352 memcpy(dirlist+dirlist_len,p,data_len);
2353 dirlist_len += data_len;
2355 total_received += ff_searchcount;
2357 if (rdata) free(rdata); rdata = NULL;
2358 if (rparam) free(rparam); rparam = NULL;
2360 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
2361 ff_searchcount,ff_eos,ff_resume_key));
2366 for (p=dirlist,i=0;i<total_received;i++) {
2367 p += interpret_long_filename(info_level,p,&finfo);
2371 /* free up the dirlist buffer */
2372 if (dirlist) free(dirlist);
2373 return(total_received);
2377 /****************************************************************************
2378 Send a SamOEMChangePassword command
2379 ****************************************************************************/
2381 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
2382 const char *old_password)
2384 char param[16+sizeof(fstring)];
2387 fstring upper_case_old_pw;
2388 fstring upper_case_new_pw;
2389 unsigned char old_pw_hash[16];
2390 unsigned char new_pw_hash[16];
2393 char *rparam = NULL;
2397 if (strlen(user) >= sizeof(fstring)-1) {
2398 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
2402 SSVAL(p,0,214); /* SamOEMChangePassword command. */
2405 p = skip_string(p,1);
2406 pstrcpy(p, "B516B16");
2407 p = skip_string(p,1);
2409 p = skip_string(p,1);
2413 param_len = PTR_DIFF(p,param);
2416 * Get the Lanman hash of the old password, we
2417 * use this as the key to make_oem_passwd_hash().
2419 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
2420 fstrcpy(upper_case_old_pw, old_password);
2421 strupper(upper_case_old_pw);
2422 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
2424 if (!make_oem_passwd_hash( data, new_password, old_pw_hash, False))
2430 * Now place the old password hash in the data.
2432 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
2433 fstrcpy(upper_case_new_pw, new_password);
2434 strupper(upper_case_new_pw);
2436 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
2438 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
2442 if (!cli_send_trans(cli,SMBtrans,
2443 PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */
2444 0,0, /* fid, flags */
2445 NULL,0,0, /* setup, length, max */
2446 param,param_len,2, /* param, length, max */
2447 data,data_len,0 /* data, length, max */
2450 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
2455 if (cli_receive_trans(cli,SMBtrans,
2459 cli->rap_error = SVAL(rparam,0);
2467 return (cli->rap_error == 0);
2470 /****************************************************************************
2471 send a negprot command
2472 ****************************************************************************/
2473 BOOL cli_negprot(struct cli_state *cli)
2479 bzero(cli->outbuf,smb_size);
2481 /* setup the protocol strings */
2482 for (plength=0,numprots=0;
2483 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2485 plength += strlen(prots[numprots].name)+2;
2487 set_message(cli->outbuf,0,plength,True);
2489 p = smb_buf(cli->outbuf);
2491 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2494 pstrcpy(p,prots[numprots].name);
2498 CVAL(cli->outbuf,smb_com) = SMBnegprot;
2499 cli_setup_packet(cli);
2501 CVAL(smb_buf(cli->outbuf),0) = 2;
2503 cli_send_smb(cli, True);
2504 if (!cli_receive_smb(cli))
2509 if (CVAL(cli->inbuf,smb_rcls) != 0 ||
2510 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
2514 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
2517 if (cli->protocol >= PROTOCOL_NT1)
2519 char *buf = smb_buf(cli->inbuf);
2520 int bcc = SVAL(cli->inbuf,smb_vwv+2*(CVAL(cli->inbuf,smb_wct)));
2522 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
2523 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
2524 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
2525 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
2526 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
2527 /* this time arrives in real GMT */
2528 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
2530 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
2531 if (IS_BITS_SET_ALL(cli->capabilities, CAP_RAW_MODE))
2533 cli->readbraw_supported = True;
2534 cli->writebraw_supported = True;
2537 if (IS_BITS_SET_ALL(cli->capabilities, CAP_EXTENDED_SECURITY))
2539 /* oops, some kerberos-related nonsense. */
2540 /* expect to have to use NTLMSSP-over-SMB */
2541 DEBUG(10,("unknown kerberos-related (?) blob\n"));
2542 memset(cli->cryptkey, 0, 8);
2543 cli->server_domain[0] = 0;
2547 memcpy(cli->cryptkey, buf,8);
2550 unibuf_to_ascii(cli->server_domain, buf+8,
2551 sizeof(cli->server_domain));
2555 cli->server_domain[0] = 0;
2557 DEBUG(5,("server's domain: %s bcc: %d\n",
2558 cli->server_domain, bcc));
2561 else if (cli->protocol >= PROTOCOL_LANMAN1)
2563 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
2564 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
2565 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
2566 cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
2567 /* this time is converted to GMT by make_unix_date */
2568 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
2569 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
2570 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
2571 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2573 /* the old core protocol */
2575 cli->serverzone = TimeDiff(time(NULL));
2578 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2584 /****************************************************************************
2585 send a session request. see rfc1002.txt 4.3 and 4.3.2
2586 ****************************************************************************/
2587 BOOL cli_session_request(struct cli_state *cli,
2588 struct nmb_name *calling, struct nmb_name *called)
2592 /* send a session request (RFC 1002) */
2594 memcpy(&(cli->calling), calling, sizeof(*calling));
2595 memcpy(&(cli->called ), called , sizeof(*called ));
2597 if (cli->port == 445)
2602 /* put in the destination name */
2603 p = cli->outbuf+len;
2604 name_mangle(cli->called .name, p, cli->called .name_type);
2608 p = cli->outbuf+len;
2609 name_mangle(cli->calling.name, p, cli->calling.name_type);
2612 /* setup the packet length */
2613 _smb_setlen(cli->outbuf,len);
2614 CVAL(cli->outbuf,0) = 0x81;
2618 #endif /* WITH_SSL */
2620 cli_send_smb(cli, True);
2621 DEBUG(5,("Sent session request\n"));
2623 if (!cli_receive_smb(cli))
2627 if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
2628 if (!sslutil_fd_is_ssl(cli->fd)){
2629 if (sslutil_connect(cli->fd) == 0)
2633 #endif /* WITH_SSL */
2635 if (CVAL(cli->inbuf,0) != 0x82) {
2636 /* This is the wrong place to put the error... JRA. */
2637 cli->rap_error = CVAL(cli->inbuf,0);
2644 /****************************************************************************
2645 open the client sockets
2646 ****************************************************************************/
2647 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
2649 extern struct in_addr ipzero;
2650 int port = cli->port;
2652 fstrcpy(cli->desthost, host);
2654 if (!ip || ip_equal(*ip, ipzero)) {
2655 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
2658 if (ip) *ip = cli->dest_ip;
2664 if (port == 0) port = SMB_PORT2;
2666 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2667 port, cli->timeout);
2676 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2677 port, cli->timeout);
2678 if (cli->fd == -1) return False;
2687 /****************************************************************************
2688 initialise a client structure
2689 ****************************************************************************/
2690 struct cli_state *cli_initialise(struct cli_state *cli)
2693 cli = (struct cli_state *)malloc(sizeof(*cli));
2699 if (cli->initialised) {
2708 cli->pid = (uint16)getpid();
2710 cli->vuid = UID_FIELD_INVALID;
2711 cli->protocol = PROTOCOL_NT1;
2712 cli->timeout = 20000;
2713 cli->bufsize = CLI_BUFFER_SIZE+4;
2714 cli->max_xmit = cli->bufsize;
2715 cli->outbuf = (char *)malloc(cli->bufsize);
2716 cli->inbuf = (char *)malloc(cli->bufsize);
2717 if (!cli->outbuf || !cli->inbuf)
2722 cli->initialised = 1;
2723 cli->capabilities = CAP_DFS;
2728 /****************************************************************************
2729 close the socket descriptor
2730 ****************************************************************************/
2731 void cli_close_socket(struct cli_state *cli)
2736 sslutil_disconnect(cli->fd);
2738 #endif /* WITH_SSL */
2746 /****************************************************************************
2747 shutdown a client structure
2748 ****************************************************************************/
2749 void cli_shutdown(struct cli_state *cli)
2751 DEBUG(10,("cli_shutdown\n"));
2760 cli_close_socket(cli);
2761 memset(cli, 0, sizeof(*cli));
2765 /****************************************************************************
2766 return error codes for the last packet
2767 returns 0 if there was no error and the best approx of a unix errno
2770 for 32 bit "warnings", a return code of 0 is expected.
2772 ****************************************************************************/
2773 int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
2779 if (!cli->initialised)
2781 DEBUG(0,("cli_error: client state uninitialised!\n"));
2785 flgs2 = SVAL(cli->inbuf,smb_flg2);
2787 if (eclass) *eclass = 0;
2790 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES)
2792 /* 32 bit error codes detected */
2793 uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
2794 if (num) *num = nt_err;
2795 DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
2796 if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0;
2798 switch (nt_err & 0xFFFFFF)
2800 case NT_STATUS_ACCESS_VIOLATION : return EACCES;
2801 case NT_STATUS_NO_SUCH_FILE : return ENOENT;
2802 case NT_STATUS_NO_SUCH_DEVICE : return ENODEV;
2803 case NT_STATUS_INVALID_HANDLE : return EBADF;
2804 case NT_STATUS_NO_MEMORY : return ENOMEM;
2805 case NT_STATUS_ACCESS_DENIED : return EACCES;
2806 case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
2807 case NT_STATUS_SHARING_VIOLATION : return EBUSY;
2808 case NT_STATUS_OBJECT_PATH_INVALID : return ENOTDIR;
2809 case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
2812 /* for all other cases - a default code */
2816 rcls = CVAL(cli->inbuf,smb_rcls);
2817 code = SVAL(cli->inbuf,smb_err);
2818 if (rcls == 0) return 0;
2820 if (eclass) *eclass = rcls;
2821 if (num ) *num = code;
2823 if (rcls == ERRDOS) {
2825 case ERRbadfile: return ENOENT;
2826 case ERRbadpath: return ENOTDIR;
2827 case ERRnoaccess: return EACCES;
2828 case ERRfilexists: return EEXIST;
2829 case ERRrename: return EEXIST;
2830 case ERRbadshare: return EBUSY;
2831 case ERRlock: return EBUSY;
2832 case ERRmoredata: return 0; /* Informational only */
2835 if (rcls == ERRSRV) {
2837 case ERRbadpw: return EPERM;
2838 case ERRaccess: return EACCES;
2839 case ERRnoresource: return ENOMEM;
2840 case ERRinvdevice: return ENODEV;
2841 case ERRinvnetname: return ENODEV;
2844 /* for other cases */
2848 /****************************************************************************
2849 set socket options on a open connection
2850 ****************************************************************************/
2851 void cli_sockopt(struct cli_state *cli, char *options)
2853 set_socket_options(cli->fd, options);
2856 /****************************************************************************
2857 set the PID to use for smb messages. Return the old pid.
2858 ****************************************************************************/
2859 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
2861 uint16 ret = cli->pid;
2866 /****************************************************************************
2867 re-establishes a connection
2868 ****************************************************************************/
2869 BOOL cli_reestablish_connection(struct cli_state *cli)
2871 struct nmb_name calling;
2872 struct nmb_name called;
2876 BOOL do_tcon = False;
2877 int oldfd = cli->fd;
2879 if (!cli->initialised || cli->fd == -1)
2881 DEBUG(3,("cli_reestablish_connection: not connected\n"));
2885 /* copy the parameters necessary to re-establish the connection */
2894 fstrcpy(share, cli->share);
2895 fstrcpy(dev , cli->dev);
2898 memcpy(&called , &(cli->called ), sizeof(called ));
2899 memcpy(&calling, &(cli->calling), sizeof(calling));
2900 fstrcpy(dest_host, cli->desthost);
2902 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2903 nmb_namestr(&calling), nmb_namestr(&called),
2904 inet_ntoa(cli->dest_ip),
2905 cli->user_name, cli->domain));
2909 if (cli_establish_connection(cli,
2910 dest_host, &cli->dest_ip,
2912 share, dev, False, do_tcon))
2914 if (cli->fd != oldfd)
2916 if (dup2(cli->fd, oldfd) == oldfd)
2918 cli_close_socket(cli);
2926 /****************************************************************************
2927 establishes a connection right up to doing tconX, reading in a password.
2928 ****************************************************************************/
2929 BOOL cli_establish_connection(struct cli_state *cli,
2930 char *dest_host, struct in_addr *dest_ip,
2931 struct nmb_name *calling, struct nmb_name *called,
2932 char *service, char *service_type,
2933 BOOL do_shutdown, BOOL do_tcon)
2938 nmb_safe_namestr(calling, callingstr, sizeof(callingstr));
2939 nmb_safe_namestr(called , calledstr , sizeof(calledstr ));
2941 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s] with NTLM%s\n",
2942 callingstr, calledstr, inet_ntoa(*dest_ip),
2943 cli->user_name, cli->domain,
2944 cli->use_ntlmv2 ? "v2" : "v1"));
2946 /* establish connection */
2948 if ((!cli->initialised))
2955 if (!cli_connect(cli, dest_host, dest_ip))
2957 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
2958 callingstr, inet_ntoa(*dest_ip)));
2963 if (!cli_session_request(cli, calling, called))
2965 DEBUG(1,("failed session request\n"));
2973 if (!cli_negprot(cli))
2975 DEBUG(1,("failed negprot\n"));
2983 if (cli->domain[0] == 0)
2985 safe_strcpy(cli->domain, cli->server_domain,
2986 sizeof(cli->domain));
2989 if (IS_BITS_SET_ALL(cli->capabilities, CAP_EXTENDED_SECURITY))
2991 /* common to both session setups */
2995 char *e = pwd_buf + sizeof(pwd_buf);
2997 /* 1st session setup */
3000 0x60, 0x40, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
3001 0x05, 0x02, 0xa0, 0x36, 0x30, 0x34, 0xa0, 0x0e,
3002 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
3003 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa2, 0x22,
3006 /* 2nd session setup */
3008 char pwd_data_2[8] =
3010 0xa1, 0x51, 0x30, 0x4f, 0xa2, 0x4d, 0x04, 0x4b
3013 char pwd_data_2[8] =
3015 0xa1, 0x51, 0x30, 0x4f, 0xa2, 0x4d, 0x04, 0x4b
3017 prs_struct auth_resp;
3024 memset(pwd_buf, 0, sizeof(pwd_buf));
3025 memcpy(pwd_buf, pwd_data, sizeof(pwd_data));
3026 p = pwd_buf + sizeof(pwd_data);
3028 safe_strcpy(p, "NTLMSSP", PTR_DIFF(e, p) - 1);
3029 p = skip_string(p, 1);
3032 if (cli->ntlmssp_cli_flgs == 0)
3034 cli->ntlmssp_cli_flgs =
3035 NTLMSSP_NEGOTIATE_UNICODE |
3036 NTLMSSP_NEGOTIATE_OEM |
3037 NTLMSSP_NEGOTIATE_SIGN |
3038 NTLMSSP_NEGOTIATE_SEAL |
3039 NTLMSSP_NEGOTIATE_LM_KEY |
3040 NTLMSSP_NEGOTIATE_NTLM |
3041 NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
3042 NTLMSSP_NEGOTIATE_00001000 |
3043 NTLMSSP_NEGOTIATE_00002000;
3045 cli->ntlmssp_cli_flgs = 0x80008207;
3048 SIVAL(p, 0, cli->ntlmssp_cli_flgs);
3050 p += 16; /* skip some NULL space */
3051 CVAL(p, 0) = 0; p++; /* alignment */
3053 buf_len = PTR_DIFF(p, pwd_buf);
3055 /* first session negotiation stage */
3056 if (!cli_session_setup_x(cli, cli->user_name,
3061 DEBUG(1,("failed session setup\n"));
3069 DEBUG(1,("1st session setup ok\n"));
3071 if (*cli->server_domain || *cli->server_os || *cli->server_type)
3073 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
3079 p = smb_buf(cli->inbuf) + 0x2f;
3080 cli->ntlmssp_cli_flgs = IVAL(p, 0); /* 0x80808a05; */
3082 memcpy(cli->cryptkey, p, 8);
3083 #ifdef DEBUG_PASSWORD
3084 DEBUG(100,("cli_session_setup_x: ntlmssp %8x\n",
3085 cli->ntlmssp_cli_flgs));
3087 DEBUG(100,("cli_session_setup_x: crypt key\n"));
3088 dump_data(100, cli->cryptkey, 8);
3090 prs_init(&auth_resp, 1024, 4, SAFETY_MARGIN, False);
3092 if (cli->use_ntlmv2 != False)
3094 DEBUG(10,("cli_establish_connection: NTLMv2\n"));
3095 pwd_make_lm_nt_owf2(&(cli->pwd), cli->cryptkey,
3096 cli->user_name, calling->name, cli->domain);
3100 DEBUG(10,("cli_establish_connection: NTLMv1\n"));
3101 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
3104 create_ntlmssp_resp(&cli->pwd, cli->domain,
3105 cli->user_name, cli->calling.name,
3106 cli->ntlmssp_cli_flgs,
3108 prs_link(NULL, &auth_resp, NULL);
3110 memset(pwd_buf, 0, sizeof(pwd_buf));
3113 CVAL(p, 0) = 0xa1; p++;
3114 CVAL(p, 0) = 0x82; p++;
3115 p_gssapi = p; p+= 2;
3116 CVAL(p, 0) = 0x30; p++;
3117 CVAL(p, 0) = 0x82; p++;
3120 CVAL(p, 0) = 0xa2; p++;
3121 CVAL(p, 0) = 0x82; p++;
3123 CVAL(p, 0) = 0x04; p++;
3124 CVAL(p, 0) = 0x82; p++;
3129 safe_strcpy(p, "NTLMSSP", PTR_DIFF(e, p) - 1);
3130 p = skip_string(p, 1);
3134 resp_len = mem_buf_len(auth_resp.data);
3135 mem_buf_copy(p, auth_resp.data, 0, resp_len);
3136 prs_mem_free(&auth_resp);
3140 buf_len = PTR_DIFF(p, pwd_buf);
3141 gssapi_len = PTR_DIFF(p, p_gssapi_end) + 12;
3143 *p_gssapi++ = (gssapi_len >> 8) & 0xff;
3144 *p_gssapi++ = gssapi_len & 0xff;
3149 *p_gssapi++ = (gssapi_len >> 8) & 0xff;
3150 *p_gssapi++ = gssapi_len & 0xff;
3154 *p_oem++ = (gssapi_len >> 8) & 0xff;
3155 *p_oem++ = gssapi_len & 0xff;
3160 *p_oem++ = (gssapi_len >> 8) & 0xff;
3161 *p_oem++ = gssapi_len & 0xff;
3163 /* second session negotiation stage */
3164 if (!cli_session_setup_x(cli, cli->user_name,
3169 DEBUG(1,("failed session setup\n"));
3177 DEBUG(1,("2nd session setup ok\n"));
3181 if (!cli_send_tconX(cli, service, service_type,
3185 DEBUG(1,("failed tcon_X\n"));
3194 else if (cli->pwd.cleartext || cli->pwd.null_pwd)
3196 fstring passwd, ntpasswd;
3197 int pass_len = 0, ntpass_len = 0;
3199 if (cli->pwd.null_pwd)
3201 /* attempt null session */
3202 passwd[0] = ntpasswd[0] = 0;
3203 pass_len = ntpass_len = 1;
3207 /* attempt clear-text session */
3208 pwd_get_cleartext(&(cli->pwd), passwd);
3209 pass_len = strlen(passwd);
3212 /* attempt clear-text session */
3213 if (!cli_session_setup(cli, cli->user_name,
3215 ntpasswd, ntpass_len,
3218 DEBUG(1,("failed session setup\n"));
3227 if (!cli_send_tconX(cli, service, service_type,
3228 (char*)passwd, strlen(passwd)))
3230 DEBUG(1,("failed tcon_X\n"));
3241 /* attempt encrypted session */
3242 unsigned char lm_sess_pwd[24];
3243 unsigned char nt_sess_pwd[128];
3244 size_t nt_sess_pwd_len;
3246 if (cli->use_ntlmv2 != False)
3248 DEBUG(10,("cli_establish_connection: NTLMv2\n"));
3249 pwd_make_lm_nt_owf2(&(cli->pwd), cli->cryptkey,
3250 cli->user_name, calling->name, cli->domain);
3254 DEBUG(10,("cli_establish_connection: NTLMv1\n"));
3255 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
3258 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd,
3261 /* attempt encrypted session */
3262 if (!cli_session_setup_x(cli, cli->user_name,
3263 (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
3264 (char*)nt_sess_pwd, nt_sess_pwd_len,
3267 DEBUG(1,("failed session setup\n"));
3269 if (cli->use_ntlmv2 == Auto)
3271 DEBUG(10,("NTLMv2 failed. Using NTLMv1\n"));
3272 cli->use_ntlmv2 = False;
3275 fstrcpy(cli->share, service);
3276 fstrcpy(cli->dev, service_type);
3278 fstrcpy(cli->desthost, dest_host);
3279 cli_close_socket(cli);
3280 return cli_establish_connection(cli,
3283 service, service_type,
3284 do_shutdown, do_tcon);
3294 DEBUG(1,("session setup ok\n"));
3296 if (*cli->server_domain || *cli->server_os || *cli->server_type)
3298 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
3306 if (!cli_send_tconX(cli, service, service_type,
3307 (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
3309 DEBUG(1,("failed tcon_X\n"));
3327 /****************************************************************************
3328 connect to one of multiple servers: don't care which
3329 ****************************************************************************/
3330 BOOL cli_connect_serverlist(struct cli_state *cli, char *p)
3332 extern pstring global_myname;
3333 extern pstring scope;
3334 fstring remote_machine;
3335 struct in_addr dest_ip;
3336 struct nmb_name calling, called, stupid_smbserver_called;
3337 BOOL connected_ok = False;
3340 * Treat each name in the 'password server =' line as a potential
3341 * PDC/BDC. Contact each in turn and try and authenticate.
3344 while(p && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine)))
3348 if (!cli_initialise(cli))
3350 DEBUG(0,("cli_connect_serverlist: unable to initialize client connection.\n"));
3354 standard_sub_basic(remote_machine);
3355 strupper(remote_machine);
3357 if (!resolve_name( remote_machine, &dest_ip, 0x20))
3359 DEBUG(1,("cli_connect_serverlist: Can't resolve address for %s\n", remote_machine));
3363 if ((lp_security() != SEC_USER) && (ismyip(dest_ip)))
3365 DEBUG(1,("cli_connect_serverlist: Password server loop - not using password server %s\n", remote_machine));
3369 make_nmb_name(&calling, global_myname , 0x0 , scope);
3370 make_nmb_name(&called , remote_machine, 0x20, scope);
3371 /* stupid microsoft destruction of the ability of netbios
3372 * to provide multiple netbios servers on one host.
3374 make_nmb_name(&stupid_smbserver_called , "*SMBSERVER", 0x20, scope);
3376 pwd_set_nullpwd(&cli->pwd);
3378 if (!cli_establish_connection(cli, remote_machine, &dest_ip,
3382 !cli_establish_connection(cli, remote_machine, &dest_ip,
3383 &calling, &stupid_smbserver_called,
3391 if (cli->protocol < PROTOCOL_LANMAN2 ||
3392 !IS_BITS_SET_ALL(cli->sec_mode, 1))
3394 DEBUG(1,("cli_connect_serverlist: machine %s isn't in user level security mode\n",
3401 * We have an anonymous connection to IPC$.
3404 connected_ok = True;
3410 DEBUG(0,("cli_connect_serverlist: Domain password server not available.\n"));
3414 return connected_ok;
3417 /****************************************************************************
3419 ****************************************************************************/
3420 int cli_printjob_del(struct cli_state *cli, int job)
3422 char *rparam = NULL;
3425 int rdrcnt,rprcnt, ret = -1;
3428 bzero(param,sizeof(param));
3431 SSVAL(p,0,81); /* DosPrintJobDel() */
3434 p = skip_string(p,1);
3436 p = skip_string(p,1);
3441 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
3442 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
3443 &rparam, &rprcnt, /* return params, length */
3444 &rdata, &rdrcnt)) { /* return data, length */
3445 ret = SVAL(rparam,0);
3448 if (rparam) free(rparam);
3449 if (rdata) free(rdata);
3455 /****************************************************************************
3456 call fn() on each entry in a print queue
3457 ****************************************************************************/
3458 int cli_print_queue(struct cli_state *cli,
3459 void (*fn)(struct print_job_info *))
3461 char *rparam = NULL;
3469 bzero(param,sizeof(param));
3472 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
3474 pstrcpy(p,"zWrLeh"); /* parameter description? */
3475 p = skip_string(p,1);
3476 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
3477 p = skip_string(p,1);
3478 pstrcpy(p,cli->share); /* name of queue */
3479 p = skip_string(p,1);
3480 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
3481 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
3483 pstrcpy(p,""); /* subformat */
3484 p = skip_string(p,1);
3486 DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
3489 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
3490 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
3491 &rparam, &rprcnt, /* return params, length */
3492 &rdata, &rdrcnt)) { /* return data, length */
3494 result_code = SVAL(rparam,0);
3495 converter = SVAL(rparam,2); /* conversion factor */
3497 if (result_code == 0) {
3498 struct print_job_info job;
3502 for (i = 0; i < SVAL(rparam,4); ++i) {
3504 job.priority = SVAL(p,2);
3506 fix_char_ptr(SVAL(p,4), converter,
3508 job.t = make_unix_date3(p + 12);
3509 job.size = IVAL(p,16);
3510 fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
3519 /* If any parameters or data were returned, free the storage. */
3520 if(rparam) free(rparam);
3521 if(rdata) free(rdata);
3526 /****************************************************************************
3527 check for existance of a dir
3528 ****************************************************************************/
3529 BOOL cli_chkpath(struct cli_state *cli, char *path)
3534 fstrcpy(path2,path);
3535 trim_string(path2,NULL,"\\");
3536 if (!*path2) *path2 = '\\';
3538 bzero(cli->outbuf,smb_size);
3539 set_message(cli->outbuf,0,4 + strlen(path2),True);
3540 SCVAL(cli->outbuf,smb_com,SMBchkpth);
3541 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3542 cli_setup_packet(cli);
3544 p = smb_buf(cli->outbuf);
3548 cli_send_smb(cli, True);
3549 if (!cli_receive_smb(cli)) {
3553 if (cli_error(cli, NULL, NULL)) return False;
3559 /****************************************************************************
3560 start a message sequence
3561 ****************************************************************************/
3562 BOOL cli_message_start(struct cli_state *cli, char *host, char *username,
3567 /* send a SMBsendstrt command */
3568 bzero(cli->outbuf,smb_size);
3569 set_message(cli->outbuf,0,0,True);
3570 CVAL(cli->outbuf,smb_com) = SMBsendstrt;
3571 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3572 cli_setup_packet(cli);
3574 p = smb_buf(cli->outbuf);
3576 pstrcpy(p,username);
3577 p = skip_string(p,1);
3580 p = skip_string(p,1);
3582 set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
3584 cli_send_smb(cli, True);
3586 if (!cli_receive_smb(cli)) {
3590 if (cli_error(cli, NULL, NULL)) return False;
3592 *grp = SVAL(cli->inbuf,smb_vwv0);
3598 /****************************************************************************
3600 ****************************************************************************/
3601 BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp)
3605 bzero(cli->outbuf,smb_size);
3606 set_message(cli->outbuf,1,len+3,True);
3607 CVAL(cli->outbuf,smb_com) = SMBsendtxt;
3608 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3609 cli_setup_packet(cli);
3611 SSVAL(cli->outbuf,smb_vwv0,grp);
3613 p = smb_buf(cli->outbuf);
3616 memcpy(p+3,msg,len);
3617 cli_send_smb(cli, True);
3619 if (!cli_receive_smb(cli)) {
3623 if (cli_error(cli, NULL, NULL)) return False;
3628 /****************************************************************************
3630 ****************************************************************************/
3631 BOOL cli_message_end(struct cli_state *cli, int grp)
3633 bzero(cli->outbuf,smb_size);
3634 set_message(cli->outbuf,1,0,True);
3635 CVAL(cli->outbuf,smb_com) = SMBsendend;
3636 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3638 SSVAL(cli->outbuf,smb_vwv0,grp);
3640 cli_setup_packet(cli);
3642 cli_send_smb(cli, True);
3644 if (!cli_receive_smb(cli)) {
3648 if (cli_error(cli, NULL, NULL)) return False;
3654 /****************************************************************************
3656 ****************************************************************************/
3657 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3659 bzero(cli->outbuf,smb_size);
3660 set_message(cli->outbuf,0,0,True);
3661 CVAL(cli->outbuf,smb_com) = SMBdskattr;
3662 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3663 cli_setup_packet(cli);
3665 cli_send_smb(cli, True);
3666 if (!cli_receive_smb(cli)) {
3670 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
3671 *total = SVAL(cli->inbuf,smb_vwv0);
3672 *avail = SVAL(cli->inbuf,smb_vwv3);