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.
28 extern int DEBUGLEVEL;
31 * set the port that will be used for connections by the client
34 void copy_user_creds(struct user_credentials *to, const struct user_credentials *from)
36 safe_strcpy(to->domain , from->domain , sizeof(from->domain )-1);
37 safe_strcpy(to->user_name, from->user_name, sizeof(from->user_name)-1);
38 memcpy(&to->pwd, &from->pwd, sizeof(from->pwd));
39 to->ntlmssp_flags = from->ntlmssp_flags;
42 int cli_set_port(struct cli_state *cli, int port)
48 return cli->port; /* return it incase caller wants it */
52 /****************************************************************************
53 copy a string (unicode or otherwise) into an SMB buffer. skips a string
55 ****************************************************************************/
56 static char *cli_put_string(struct cli_state *cli, char *p, const char *str,
59 uint16 flgs2 = SVAL(cli->outbuf, smb_flg2);
60 if (IS_BITS_SET_ALL(flgs2, FLAGS2_UNICODE_STRINGS))
62 p = align2(p, cli->outbuf);
63 p = ascii_to_unibuf(p, str, 1024);
74 p = skip_string(p, 1);
83 /****************************************************************************
84 copy a string (unicode or otherwise) into an SMB buffer. skips a string
86 ****************************************************************************/
87 static const char *cli_get_string(struct cli_state *cli, char *p,
88 char *str, size_t str_len)
90 uint16 flgs2 = SVAL(cli->inbuf,smb_flg2);
91 if (IS_BITS_SET_ALL(flgs2, FLAGS2_UNICODE_STRINGS))
93 return unibuf_to_ascii(str, p, str_len);
97 safe_strcpy(str, p, str_len-1);
98 return skip_string(p, 1);
102 /****************************************************************************
104 ****************************************************************************/
105 static BOOL cli_receive_smb(struct cli_state *cli)
107 return client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
110 /****************************************************************************
111 send an smb to a fd and re-establish if necessary
112 ****************************************************************************/
113 static BOOL cli_send_smb(struct cli_state *cli, BOOL show)
118 BOOL reestablished=False;
120 len = smb_len(cli->outbuf) + 4;
124 uint8 msg_type = CVAL(cli->outbuf, 0);
127 show_msg(cli->outbuf);
131 dump_data(10, cli->outbuf, len);
135 while (nwritten < len) {
136 ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
137 if (ret <= 0 && errno == EPIPE && !reestablished)
139 DEBUG(5,("cli_send_smb: write error (%s) - reconnecting\n",
142 if (cli_reestablish_connection(cli)) {
143 reestablished = True;
149 DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",
159 /******************************************************
160 Return an error message - either an SMB error or a RAP
162 *******************************************************/
164 char *cli_errstr(struct cli_state *cli)
166 static fstring error_message;
167 cli_safe_errstr(cli, error_message, sizeof(error_message));
168 return error_message;
171 /****************************************************************************
172 return a description of an SMB error
173 ****************************************************************************/
174 void cli_safe_smb_errstr(struct cli_state *cli, char *msg, size_t len)
176 smb_safe_errstr(cli->inbuf, msg, len);
179 /*****************************************************
180 RAP error codes - a small start but will be extended.
181 *******************************************************/
189 {5, "User has insufficient privilege" },
190 {86, "The specified password is invalid" },
191 {2226, "Operation only permitted on a Primary Domain Controller" },
192 {2242, "The password of this user has expired." },
193 {2243, "The password of this user cannot change." },
194 {2244, "This password cannot be used now (password history conflict)." },
195 {2245, "The password is shorter than required." },
196 {2246, "The password of this user is too recent to change."},
200 /****************************************************************************
201 return a description of a RAP error
202 ****************************************************************************/
203 BOOL get_safe_rap_errstr(int rap_error, char *err_msg, size_t msglen)
207 slprintf(err_msg, msglen - 1, "RAP code %d", rap_error);
209 for (i = 0; rap_errmap[i].message != NULL; i++)
211 if (rap_errmap[i].err == rap_error)
213 safe_strcpy( err_msg, rap_errmap[i].message, msglen);
220 /****************************************************************************
221 return a description of an SMB error
222 ****************************************************************************/
223 void cli_safe_errstr(struct cli_state *cli, char *err_msg, size_t msglen)
229 * Errors are of three kinds - smb errors,
230 * dealt with by cli_smb_errstr, NT errors,
231 * whose code is in cli.nt_error, and rap
232 * errors, whose error code is in cli.rap_error.
235 cli_error(cli, &errclass, &errnum);
239 cli_safe_smb_errstr(cli, err_msg, msglen);
241 else if (cli->nt_error)
244 * Was it an NT error ?
247 (void)get_safe_nt_error_msg(cli->nt_error, err_msg, msglen);
252 * Must have been a rap error.
254 (void)get_safe_rap_errstr(cli->rap_error, err_msg, msglen);
257 /****************************************************************************
258 setup basics in a outgoing packet
259 ****************************************************************************/
260 static void cli_setup_packet(struct cli_state *cli)
263 flgs2 |= FLAGS2_LONG_PATH_COMPONENTS;
264 flgs2 |= FLAGS2_32_BIT_ERROR_CODES;
265 flgs2 |= FLAGS2_EXT_SEC;
267 flgs2 |= FLAGS2_UNICODE_STRINGS;
272 SSVAL(cli->outbuf,smb_pid,cli->pid);
273 SSVAL(cli->outbuf,smb_uid,cli->vuid);
274 SSVAL(cli->outbuf,smb_mid,cli->mid);
276 if (cli->protocol > PROTOCOL_CORE)
278 SCVAL(cli->outbuf,smb_flg,0x8);
279 SSVAL(cli->outbuf,smb_flg2,flgs2);
284 /*****************************************************************************
285 Convert a character pointer in a cli_call_api() response to a form we can use.
286 This function contains code to prevent core dumps if the server returns
288 *****************************************************************************/
289 static char *fix_char_ptr(unsigned int datap, unsigned int converter,
290 char *rdata, int rdrcnt)
292 if (datap == 0) { /* turn NULL pointers into zero length strings */
295 unsigned int offset = datap - converter;
297 if (offset >= rdrcnt) {
298 DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
299 datap, converter, rdrcnt));
302 return &rdata[offset];
307 /****************************************************************************
308 send a SMB trans or trans2 request
309 ****************************************************************************/
310 BOOL cli_send_trans(struct cli_state *cli, int trans,
311 char *name, int pipe_name_len,
313 uint16 *setup, int lsetup, int msetup,
314 char *param, int lparam, int mparam,
315 char *data, int ldata, int mdata)
318 int this_ldata,this_lparam;
319 int tot_data=0,tot_param=0;
320 char *outdata,*outparam;
323 this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
324 this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
326 bzero(cli->outbuf,smb_size);
327 set_message(cli->outbuf,14+lsetup,0,True);
328 CVAL(cli->outbuf,smb_com) = trans;
329 SSVAL(cli->outbuf,smb_tid, cli->cnum);
330 cli_setup_packet(cli);
332 outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len+1 : 3);
333 outdata = outparam+this_lparam;
335 /* primary request */
336 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
337 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
338 SSVAL(cli->outbuf,smb_mprcnt,mparam); /* mprcnt */
339 SSVAL(cli->outbuf,smb_mdrcnt,mdata); /* mdrcnt */
340 SCVAL(cli->outbuf,smb_msrcnt,msetup); /* msrcnt */
341 SSVAL(cli->outbuf,smb_flags,flags); /* flags */
342 SIVAL(cli->outbuf,smb_timeout,0); /* timeout */
343 SSVAL(cli->outbuf,smb_pscnt,this_lparam); /* pscnt */
344 SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
345 SSVAL(cli->outbuf,smb_dscnt,this_ldata); /* dscnt */
346 SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
347 SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */
348 for (i=0;i<lsetup;i++) /* setup[] */
349 SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
350 p = smb_buf(cli->outbuf);
351 if (trans==SMBtrans) {
352 memcpy(p,name, pipe_name_len + 1); /* name[] */
354 *p++ = 0; /* put in a null smb_name */
355 *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */
357 if (this_lparam) /* param[] */
358 memcpy(outparam,param,this_lparam);
359 if (this_ldata) /* data[] */
360 memcpy(outdata,data,this_ldata);
361 set_message(cli->outbuf,14+lsetup, /* wcnt, bcc */
362 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
364 cli_send_smb(cli, True);
366 if (this_ldata < ldata || this_lparam < lparam) {
367 /* receive interim response */
368 if (!cli_receive_smb(cli) ||
369 CVAL(cli->inbuf,smb_rcls) != 0) {
373 tot_data = this_ldata;
374 tot_param = this_lparam;
376 while (tot_data < ldata || tot_param < lparam) {
377 this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
378 this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
380 set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
381 CVAL(cli->outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
383 outparam = smb_buf(cli->outbuf);
384 outdata = outparam+this_lparam;
386 /* secondary request */
387 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
388 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
389 SSVAL(cli->outbuf,smb_spscnt,this_lparam); /* pscnt */
390 SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
391 SSVAL(cli->outbuf,smb_spsdisp,tot_param); /* psdisp */
392 SSVAL(cli->outbuf,smb_sdscnt,this_ldata); /* dscnt */
393 SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
394 SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */
395 if (trans==SMBtrans2)
396 SSVALS(cli->outbuf,smb_sfid,fid); /* fid */
397 if (this_lparam) /* param[] */
398 memcpy(outparam,param,this_lparam);
399 if (this_ldata) /* data[] */
400 memcpy(outdata,data,this_ldata);
401 set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
402 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
404 cli_send_smb(cli, True);
406 tot_data += this_ldata;
407 tot_param += this_lparam;
415 /****************************************************************************
416 receive a SMB trans or trans2 response allocating the necessary memory
417 ****************************************************************************/
418 static BOOL cli_receive_trans(struct cli_state *cli,int trans,
419 char **param, int *param_len,
420 char **data, int *data_len)
424 int this_data,this_param;
426 *data_len = *param_len = 0;
428 if (!cli_receive_smb(cli))
432 if (CVAL(cli->inbuf,smb_com) != trans) {
433 DEBUG(0,("Expected %s response, got command 0x%02x\n",
434 trans==SMBtrans?"SMBtrans":"SMBtrans2",
435 CVAL(cli->inbuf,smb_com)));
439 if (cli_error(cli, NULL, NULL))
444 /* parse out the lengths */
445 total_data = SVAL(cli->inbuf,smb_tdrcnt);
446 total_param = SVAL(cli->inbuf,smb_tprcnt);
449 *data = Realloc(*data,total_data);
450 *param = Realloc(*param,total_param);
453 this_data = SVAL(cli->inbuf,smb_drcnt);
454 this_param = SVAL(cli->inbuf,smb_prcnt);
456 if (this_data + *data_len > total_data ||
457 this_param + *param_len > total_param) {
458 DEBUG(1,("Data overflow in cli_receive_trans\n"));
463 memcpy(*data + SVAL(cli->inbuf,smb_drdisp),
464 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff),
467 memcpy(*param + SVAL(cli->inbuf,smb_prdisp),
468 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff),
470 *data_len += this_data;
471 *param_len += this_param;
473 /* parse out the total lengths again - they can shrink! */
474 total_data = SVAL(cli->inbuf,smb_tdrcnt);
475 total_param = SVAL(cli->inbuf,smb_tprcnt);
477 if (total_data <= *data_len && total_param <= *param_len)
480 if (!cli_receive_smb(cli))
484 if (CVAL(cli->inbuf,smb_com) != trans) {
485 DEBUG(0,("Expected %s response, got command 0x%02x\n",
486 trans==SMBtrans?"SMBtrans":"SMBtrans2",
487 CVAL(cli->inbuf,smb_com)));
491 if (cli_error(cli, NULL, NULL))
500 /****************************************************************************
501 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
502 ****************************************************************************/
503 BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name, int pipe_name_len,
504 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
505 char *params, uint32 param_count, uint32 max_param_count,
506 char *data, uint32 data_count, uint32 max_data_count,
507 char **rparam, uint32 *rparam_count,
508 char **rdata, uint32 *rdata_count)
510 if (pipe_name_len == 0)
511 pipe_name_len = strlen(pipe_name);
513 cli_send_trans(cli, SMBtrans,
514 pipe_name, pipe_name_len,
515 0,0, /* fid, flags */
516 setup, setup_count, max_setup_count,
517 params, param_count, max_param_count,
518 data, data_count, max_data_count);
520 return (cli_receive_trans(cli, SMBtrans,
521 rparam, (int *)rparam_count,
522 rdata, (int *)rdata_count));
525 /****************************************************************************
527 ****************************************************************************/
528 BOOL cli_api(struct cli_state *cli,
529 char *param, int prcnt, int mprcnt,
530 char *data, int drcnt, int mdrcnt,
531 char **rparam, int *rprcnt,
532 char **rdata, int *rdrcnt)
534 cli_send_trans(cli,SMBtrans,
535 PIPE_LANMAN,strlen(PIPE_LANMAN), /* Name, length */
536 0,0, /* fid, flags */
537 NULL,0,0, /* Setup, length, max */
538 param, prcnt, mprcnt, /* Params, length, max */
539 data, drcnt, mdrcnt /* Data, length, max */
542 return (cli_receive_trans(cli,SMBtrans,
548 /****************************************************************************
549 perform a NetWkstaUserLogon
550 ****************************************************************************/
551 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
559 memset(param, 0, sizeof(param));
561 /* send a SMBtrans command with api NetWkstaUserLogon */
563 SSVAL(p,0,132); /* api number */
565 pstrcpy(p,"OOWb54WrLh");
566 p = skip_string(p,1);
567 pstrcpy(p,"WB21BWDWWDDDDDDDzzzD");
568 p = skip_string(p,1);
577 pstrcpy(p, workstation);
580 SSVAL(p, 0, CLI_BUFFER_SIZE);
582 SSVAL(p, 0, CLI_BUFFER_SIZE);
586 param, PTR_DIFF(p,param),1024, /* param, length, max */
587 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
588 &rparam, &rprcnt, /* return params, return size */
589 &rdata, &rdrcnt /* return data, return size */
591 cli->rap_error = SVAL(rparam,0);
594 if (cli->rap_error == 0) {
595 DEBUG(4,("NetWkstaUserLogon success\n"));
596 cli->privileges = SVAL(p, 24);
597 fstrcpy(cli->eff_name,p+2);
599 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
607 return (cli->rap_error == 0);
610 /****************************************************************************
611 call a NetShareEnum - try and browse available connections on a host
612 ****************************************************************************/
613 BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *))
622 /* now send a SMBtrans command with api RNetShareEnum */
624 SSVAL(p,0,0); /* api number */
627 p = skip_string(p,1);
629 p = skip_string(p,1);
635 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
636 NULL, 0, 0xFFFF, /* data, length, maxlen */
637 &rparam, &rprcnt, /* return params, length */
638 &rdata, &rdrcnt)) /* return data, length */
640 int res = SVAL(rparam,0);
641 int converter=SVAL(rparam,2);
644 if (res == 0 || res == ERRmoredata) {
645 count=SVAL(rparam,4);
648 for (i=0;i<count;i++,p+=20) {
650 int type = SVAL(p,14);
651 int comment_offset = IVAL(p,16) & 0xFFFF;
652 char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
653 fn(sname, type, cmnt);
656 DEBUG(4,("NetShareEnum res=%d\n", res));
659 DEBUG(4,("NetShareEnum failed\n"));
671 /****************************************************************************
672 call a NetServerEnum for the specified workgroup and servertype mask.
673 This function then calls the specified callback function for each name returned.
675 The callback function takes 3 arguments: the machine name, the server type and
677 ****************************************************************************/
678 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
679 void (*fn)(const char *, uint32, const char *))
689 /* send a SMBtrans command with api NetServerEnum */
691 SSVAL(p,0,0x68); /* api number */
693 pstrcpy(p,"WrLehDz");
694 p = skip_string(p,1);
696 pstrcpy(p,"B16BBDz");
698 p = skip_string(p,1);
700 SSVAL(p,2,CLI_BUFFER_SIZE);
705 pstrcpy(p, workgroup);
706 p = skip_string(p,1);
709 param, PTR_DIFF(p,param), 8, /* params, length, max */
710 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
711 &rparam, &rprcnt, /* return params, return size */
712 &rdata, &rdrcnt /* return data, return size */
714 int res = SVAL(rparam,0);
715 int converter=SVAL(rparam,2);
718 if (res == 0 || res == ERRmoredata) {
719 count=SVAL(rparam,4);
722 for (i = 0;i < count;i++, p += 26) {
724 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
725 char *cmnt = comment_offset?(rdata+comment_offset):"";
726 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
728 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
730 fn(sname, stype, cmnt);
752 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
753 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
754 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
755 {PROTOCOL_LANMAN1,"LANMAN1.0"},
756 {PROTOCOL_LANMAN2,"LM1.2X002"},
757 {PROTOCOL_LANMAN2,"Samba"},
758 {PROTOCOL_NT1,"NT LANMAN 1.0"},
759 {PROTOCOL_NT1,"NT LM 0.12"},
764 /****************************************************************************
766 ****************************************************************************/
767 BOOL cli_session_setup_x(struct cli_state *cli,
769 char *pass, int passlen,
770 char *ntpass, int ntpasslen,
776 BOOL esec = cli->capabilities & CAP_EXTENDED_SECURITY;
778 DEBUG(100,("cli_session_setup. extended security: %s\n",
781 #ifdef DEBUG_PASSWORD
782 DEBUG(100,("cli_session_setup. pass, ntpass\n"));
783 dump_data(100, pass, passlen);
784 dump_data(100, ntpass, ntpasslen);
787 if (cli->protocol < PROTOCOL_LANMAN1)
792 /* send a session setup command */
793 bzero(cli->outbuf,smb_size);
795 if (cli->protocol < PROTOCOL_NT1)
797 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
798 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
799 cli_setup_packet(cli);
801 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
802 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
803 SSVAL(cli->outbuf,smb_vwv3,2);
804 SSVAL(cli->outbuf,smb_vwv4,1);
805 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
806 SSVAL(cli->outbuf,smb_vwv7,passlen);
807 p = smb_buf(cli->outbuf);
808 memcpy(p,pass,passlen);
815 set_message(cli->outbuf,12,0,True);
816 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
817 cli_setup_packet(cli);
819 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
820 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
821 SSVAL(cli->outbuf,smb_vwv3,2);
822 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
823 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
824 SSVAL(cli->outbuf,smb_vwv7,passlen);
825 SIVAL(cli->outbuf,smb_vwv10, CAP_EXTENDED_SECURITY|CAP_STATUS32|CAP_UNICODE);
826 p = smb_buf(cli->outbuf);
827 memcpy(p,pass,passlen);
830 p = cli_put_string(cli, p, "Unix", False);
831 p = cli_put_string(cli, p, "Samba", False);
832 p = cli_put_string(cli, p, "", False);
835 set_message(cli->outbuf,12,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
839 set_message(cli->outbuf,13,0,True);
840 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
841 cli_setup_packet(cli);
843 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
844 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
845 SSVAL(cli->outbuf,smb_vwv3,2);
846 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
847 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
848 SSVAL(cli->outbuf,smb_vwv7,passlen);
849 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
850 SIVAL(cli->outbuf,smb_vwv11, 0);
851 p = smb_buf(cli->outbuf);
852 memcpy(p,pass,passlen);
853 p += SVAL(cli->outbuf,smb_vwv7);
854 memcpy(p,ntpass,ntpasslen);
855 p += SVAL(cli->outbuf,smb_vwv8);
857 p = cli_put_string(cli, p, user, False);
858 strupper(user_domain);
859 p = cli_put_string(cli, p, user_domain, False);
860 p = cli_put_string(cli, p, "Unix", True);
861 p = cli_put_string(cli, p, "Samba", False);
863 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
866 cli_send_smb(cli, True);
867 if (!cli_receive_smb(cli))
869 DEBUG(10,("cli_session_setup_x: receive smb failed\n"));
873 if (cli_error(cli, &eclass, &ecode))
875 uint16 flgs2 = SVAL(cli->inbuf,smb_flg2);
876 if (IS_BITS_CLR_ALL(flgs2, FLAGS2_32_BIT_ERROR_CODES))
878 if (ecode != ERRmoredata || !esec)
883 else if (ecode != 0xC0000016) /* STATUS_MORE_PROCESSING_REQD */
889 /* use the returned vuid from now on */
890 cli->vuid = SVAL(cli->inbuf,smb_uid);
892 if (cli->protocol >= PROTOCOL_NT1)
900 * Save off some of the connected server
907 server_os = smb_buf(cli->inbuf);
908 server_type = skip_string(server_os,1);
909 server_domain = skip_string(server_type,1);
911 fstrcpy(cli->server_os, server_os);
912 fstrcpy(cli->server_type, server_type);
913 fstrcpy(cli->server_domain, server_domain);
920 static BOOL cli_calc_session_pwds(struct cli_state *cli,
922 char *pword, char *ntpword,
923 char *pass, int *passlen,
924 char *ntpass, int *ntpasslen,
928 BOOL ntpass_ok = ntpass != NULL && ntpasslen != NULL;
930 if (pass == NULL || passlen == NULL)
932 DEBUG(0,("cli_calc_session_pwds: pass and passlen are NULL\n"));
935 if ((ntpass != NULL || ntpasslen != NULL) &&
936 (ntpass == NULL || ntpasslen == NULL))
938 DEBUG(0,("cli_calc_session_pwds: ntpasswd pointers invalid\n"));
942 #ifdef DEBUG_PASSWORD
943 DEBUG(100,("cli_calc_session_pwds. pass, ntpass\n"));
944 dump_data(100, pass, *passlen);
947 dump_data(100, ntpass, *ntpasslen);
950 if (!IS_BITS_SET_ALL(cli->sec_mode, 1))
952 /* if in share level security then don't send a password now */
962 else if ((*passlen == 0 || *passlen == 1) && (pass[0] == '\0'))
964 /* Null session connect. */
980 if (*passlen == 24 && *ntpasslen >= 24)
982 if (IS_BITS_SET_ALL(cli->sec_mode, 2))
984 /* encrypted password, implicit from 24-byte lengths */
985 memcpy(pword , pass , *passlen);
986 memcpy(ntpword, ntpass, *ntpasslen);
990 DEBUG(0,("cli_calc_session_pwds: encrypted passwords not supported by server\n"));
994 else if (*ntpasslen == 0 || !IS_BITS_SET_ALL(cli->sec_mode, 2))
996 /* plain-text password: server doesn't support encrypted. */
997 fstrcpy(pword, pass);
998 fstrcpy(ntpword, "");
1001 else if (ntpasslen != NULL)
1003 if (cli->use_ntlmv2 != False)
1005 DEBUG(10,("cli_establish_connection: NTLMv2\n"));
1006 pwd_make_lm_nt_owf2(&(cli->usr.pwd), cli->cryptkey,
1007 cli->usr.user_name, myhostname,
1012 DEBUG(10,("cli_establish_connection: NTLMv1\n"));
1013 pwd_make_lm_nt_owf(&(cli->usr.pwd), cli->cryptkey);
1016 pwd_get_lm_nt_owf(&(cli->usr.pwd), pass, ntpass,
1017 ntpasslen, sess_key);
1024 /****************************************************************************
1025 send a session setup
1026 ****************************************************************************/
1027 BOOL cli_session_setup(struct cli_state *cli,
1028 char *myhostname, char *user,
1029 char *pass, int passlen,
1030 char *ntpass, int ntpasslen,
1033 fstring pword, ntpword;
1035 if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1)
1040 fstrcpy(cli->usr.user_name, user);
1042 return cli_calc_session_pwds(cli, myhostname, pword, ntpword,
1044 ntpass, &ntpasslen, cli->sess_key,
1046 cli_session_setup_x(cli, user, pass, passlen, ntpass, ntpasslen,
1050 /****************************************************************************
1052 *****************************************************************************/
1054 BOOL cli_ulogoff(struct cli_state *cli)
1056 bzero(cli->outbuf,smb_size);
1057 set_message(cli->outbuf,2,0,True);
1058 CVAL(cli->outbuf,smb_com) = SMBulogoffX;
1059 cli_setup_packet(cli);
1060 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1061 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1063 cli_send_smb(cli, True);
1064 if (!cli_receive_smb(cli))
1067 return CVAL(cli->inbuf,smb_rcls) == 0;
1070 /****************************************************************************
1072 ****************************************************************************/
1073 BOOL cli_send_tconX(struct cli_state *cli,
1074 char *share, char *dev, char *pass, int passlen)
1076 fstring fullshare, pword;
1078 bzero(cli->outbuf,smb_size);
1079 bzero(cli->inbuf,smb_size);
1081 fstrcpy(cli->share, share);
1083 /* in user level security don't send a password now */
1084 if (cli->sec_mode & 1) {
1089 if ((cli->sec_mode & 2) && *pass && passlen != 24) {
1091 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
1093 memcpy(pword, pass, passlen);
1096 slprintf(fullshare, sizeof(fullshare)-1,
1097 "\\\\%s\\%s", cli->desthost, share);
1098 strupper(fullshare);
1100 set_message(cli->outbuf,4, 0, True);
1101 CVAL(cli->outbuf,smb_com) = SMBtconX;
1102 cli_setup_packet(cli);
1104 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1105 SSVAL(cli->outbuf,smb_vwv3,passlen);
1107 p = smb_buf(cli->outbuf);
1108 memcpy(p,pword,passlen);
1110 p = cli_put_string(cli, p, fullshare, False);
1112 p = skip_string(p, 1);
1114 set_message(cli->outbuf,4,PTR_DIFF(p, smb_buf(cli->outbuf)),False);
1116 SCVAL(cli->inbuf,smb_rcls, 1);
1118 cli_send_smb(cli, True);
1119 if (!cli_receive_smb(cli))
1122 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1126 fstrcpy(cli->dev, "A:");
1128 if (cli->protocol >= PROTOCOL_NT1)
1130 cli_get_string(cli, smb_buf(cli->inbuf),
1131 cli->dev, sizeof(cli->dev));
1134 if (strcasecmp(share,"IPC$")==0) {
1135 fstrcpy(cli->dev, "IPC");
1138 /* only grab the device if we have a recent protocol level */
1139 if (cli->protocol >= PROTOCOL_NT1 && smb_buflen(cli->inbuf) == 3)
1141 /* almost certainly win95 - enable bug fixes */
1145 cli->cnum = SVAL(cli->inbuf,smb_tid);
1150 /****************************************************************************
1151 send a tree disconnect
1152 ****************************************************************************/
1153 BOOL cli_tdis(struct cli_state *cli)
1155 bzero(cli->outbuf,smb_size);
1156 set_message(cli->outbuf,0,0,True);
1157 CVAL(cli->outbuf,smb_com) = SMBtdis;
1158 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1159 cli_setup_packet(cli);
1161 cli_send_smb(cli, True);
1162 if (!cli_receive_smb(cli))
1165 return CVAL(cli->inbuf,smb_rcls) == 0;
1168 /****************************************************************************
1170 ****************************************************************************/
1171 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
1175 bzero(cli->outbuf,smb_size);
1176 bzero(cli->inbuf,smb_size);
1178 set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
1180 CVAL(cli->outbuf,smb_com) = SMBmv;
1181 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1182 cli_setup_packet(cli);
1184 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
1186 p = smb_buf(cli->outbuf);
1188 pstrcpy(p,fname_src);
1189 p = skip_string(p,1);
1191 pstrcpy(p,fname_dst);
1193 cli_send_smb(cli, True);
1194 if (!cli_receive_smb(cli)) {
1198 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1205 /****************************************************************************
1207 ****************************************************************************/
1208 BOOL cli_unlink(struct cli_state *cli, char *fname)
1212 bzero(cli->outbuf,smb_size);
1213 bzero(cli->inbuf,smb_size);
1215 set_message(cli->outbuf,1, 2 + strlen(fname),True);
1217 CVAL(cli->outbuf,smb_com) = SMBunlink;
1218 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1219 cli_setup_packet(cli);
1221 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
1223 p = smb_buf(cli->outbuf);
1227 cli_send_smb(cli, True);
1228 if (!cli_receive_smb(cli)) {
1232 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1239 /****************************************************************************
1241 ****************************************************************************/
1242 BOOL cli_mkdir(struct cli_state *cli, char *dname)
1246 bzero(cli->outbuf,smb_size);
1247 bzero(cli->inbuf,smb_size);
1249 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1251 CVAL(cli->outbuf,smb_com) = SMBmkdir;
1252 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1253 cli_setup_packet(cli);
1255 p = smb_buf(cli->outbuf);
1259 cli_send_smb(cli, True);
1260 if (!cli_receive_smb(cli)) {
1264 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1271 /****************************************************************************
1273 ****************************************************************************/
1274 BOOL cli_rmdir(struct cli_state *cli, char *dname)
1278 bzero(cli->outbuf,smb_size);
1279 bzero(cli->inbuf,smb_size);
1281 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1283 CVAL(cli->outbuf,smb_com) = SMBrmdir;
1284 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1285 cli_setup_packet(cli);
1287 p = smb_buf(cli->outbuf);
1291 cli_send_smb(cli, True);
1292 if (!cli_receive_smb(cli)) {
1296 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1305 /****************************************************************************
1307 ****************************************************************************/
1308 int cli_nt_create(struct cli_state *cli, const char *fname)
1312 bzero(cli->outbuf,smb_size);
1313 bzero(cli->inbuf,smb_size);
1315 set_message(cli->outbuf,24,1 + strlen(fname),True);
1317 CVAL(cli->outbuf,smb_com) = SMBntcreateX;
1318 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1319 cli_setup_packet(cli);
1321 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1322 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0x06);
1323 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
1324 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, 0x2019f);
1325 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0);
1326 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03);
1327 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01);
1328 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0);
1329 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
1330 SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname));
1332 p = smb_buf(cli->outbuf);
1334 p = skip_string(p,1);
1336 cli_send_smb(cli, True);
1337 if (!cli_receive_smb(cli)) {
1341 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1345 return SVAL(cli->inbuf,smb_vwv2 + 1);
1349 /****************************************************************************
1351 ****************************************************************************/
1352 int cli_open(struct cli_state *cli, const char *fname,
1353 int flags, int share_mode)
1357 unsigned accessmode=0;
1359 /* you must open for RW not just write - otherwise getattrE doesn't
1361 if ((flags & O_ACCMODE) == O_WRONLY && strncmp(cli->dev, "LPT", 3)) {
1362 flags = (flags & ~O_ACCMODE) | O_RDWR;
1365 if (flags & O_CREAT)
1367 if (!(flags & O_EXCL)) {
1368 if (flags & O_TRUNC)
1374 accessmode = (share_mode<<4);
1376 if ((flags & O_ACCMODE) == O_RDWR) {
1378 } else if ((flags & O_ACCMODE) == O_WRONLY) {
1383 if ((flags & O_SYNC) == O_SYNC) {
1384 accessmode |= (1<<14);
1388 bzero(cli->outbuf,smb_size);
1389 bzero(cli->inbuf,smb_size);
1391 set_message(cli->outbuf,15,1 + strlen(fname),True);
1393 CVAL(cli->outbuf,smb_com) = SMBopenX;
1394 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1395 cli_setup_packet(cli);
1397 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1398 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1399 SSVAL(cli->outbuf,smb_vwv3,accessmode);
1400 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1401 SSVAL(cli->outbuf,smb_vwv5,0);
1402 SSVAL(cli->outbuf,smb_vwv8,openfn);
1404 p = smb_buf(cli->outbuf);
1405 p = cli_put_string(cli, p, fname, False);
1407 set_message(cli->outbuf,15,PTR_DIFF(p, smb_buf(cli->outbuf)),False);
1409 cli_send_smb(cli, True);
1410 if (!cli_receive_smb(cli)) {
1414 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1418 return SVAL(cli->inbuf,smb_vwv2);
1424 /****************************************************************************
1426 ****************************************************************************/
1427 BOOL cli_close(struct cli_state *cli, int fnum)
1429 bzero(cli->outbuf,smb_size);
1430 bzero(cli->inbuf,smb_size);
1432 set_message(cli->outbuf,3,0,True);
1434 CVAL(cli->outbuf,smb_com) = SMBclose;
1435 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1436 cli_setup_packet(cli);
1438 SSVAL(cli->outbuf,smb_vwv0,fnum);
1439 SIVALS(cli->outbuf,smb_vwv1,-1);
1441 cli_send_smb(cli, True);
1442 if (!cli_receive_smb(cli)) {
1446 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1454 /****************************************************************************
1456 ****************************************************************************/
1457 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1460 int saved_timeout = cli->timeout;
1462 bzero(cli->outbuf,smb_size);
1463 bzero(cli->inbuf,smb_size);
1465 set_message(cli->outbuf,8,10,True);
1467 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1468 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1469 cli_setup_packet(cli);
1471 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1472 SSVAL(cli->outbuf,smb_vwv2,fnum);
1473 CVAL(cli->outbuf,smb_vwv3) = 0;
1474 SIVALS(cli->outbuf, smb_vwv4, timeout);
1475 SSVAL(cli->outbuf,smb_vwv6,0);
1476 SSVAL(cli->outbuf,smb_vwv7,1);
1478 p = smb_buf(cli->outbuf);
1479 SSVAL(p, 0, cli->pid);
1480 SIVAL(p, 2, offset);
1482 cli_send_smb(cli, True);
1484 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout;
1486 if (!cli_receive_smb(cli)) {
1487 cli->timeout = saved_timeout;
1491 cli->timeout = saved_timeout;
1493 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1500 /****************************************************************************
1502 ****************************************************************************/
1503 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1507 bzero(cli->outbuf,smb_size);
1508 bzero(cli->inbuf,smb_size);
1510 set_message(cli->outbuf,8,10,True);
1512 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1513 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1514 cli_setup_packet(cli);
1516 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1517 SSVAL(cli->outbuf,smb_vwv2,fnum);
1518 CVAL(cli->outbuf,smb_vwv3) = 0;
1519 SIVALS(cli->outbuf, smb_vwv4, timeout);
1520 SSVAL(cli->outbuf,smb_vwv6,1);
1521 SSVAL(cli->outbuf,smb_vwv7,0);
1523 p = smb_buf(cli->outbuf);
1524 SSVAL(p, 0, cli->pid);
1525 SIVAL(p, 2, offset);
1528 cli_send_smb(cli, True);
1529 if (!cli_receive_smb(cli)) {
1533 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1542 /****************************************************************************
1543 issue a single SMBread and don't wait for a reply
1544 ****************************************************************************/
1545 static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
1548 bzero(cli->outbuf,smb_size);
1549 bzero(cli->inbuf,smb_size);
1551 set_message(cli->outbuf,10,0,True);
1553 CVAL(cli->outbuf,smb_com) = SMBreadX;
1554 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1555 cli_setup_packet(cli);
1557 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1558 SSVAL(cli->outbuf,smb_vwv2,fnum);
1559 SIVAL(cli->outbuf,smb_vwv3,offset);
1560 SSVAL(cli->outbuf,smb_vwv5,size);
1561 SSVAL(cli->outbuf,smb_vwv6,size);
1562 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1564 cli_send_smb(cli, True);
1567 /****************************************************************************
1569 ****************************************************************************/
1570 size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
1576 int mpx = MAX(cli->max_mux-1, 1);
1577 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1579 int blocks = (size + (block-1)) / block;
1581 if (size == 0) return 0;
1583 while (received < blocks)
1587 while (issued - received < mpx && issued < blocks) {
1588 int size1 = MIN(block, size-issued*block);
1589 cli_issue_read(cli, fnum, offset+issued*block, size1, issued);
1593 if (!cli_receive_smb(cli)) {
1598 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1599 size2 = SVAL(cli->inbuf, smb_vwv5);
1601 if (cli_error(cli, NULL, NULL))
1603 blocks = MIN(blocks, mid-1);
1608 blocks = MIN(blocks, mid-1);
1609 /* this distinguishes EOF from an error */
1610 total = MAX(total, 0);
1614 if (size2 > block) {
1615 DEBUG(0,("server returned more than we wanted!\n"));
1618 if (mid >= issued) {
1619 DEBUG(0,("invalid mid from server!\n"));
1622 p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
1624 memcpy(buf+mid*block, p, size2);
1626 total = MAX(total, mid*block + size2);
1629 while (received < issued) {
1630 cli_receive_smb(cli);
1638 /****************************************************************************
1639 issue a single SMBwrite and don't wait for a reply
1640 ****************************************************************************/
1641 static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf,
1646 bzero(cli->outbuf,smb_size);
1647 bzero(cli->inbuf,smb_size);
1649 set_message(cli->outbuf,12,size,True);
1651 CVAL(cli->outbuf,smb_com) = SMBwriteX;
1652 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1653 cli_setup_packet(cli);
1655 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1656 SSVAL(cli->outbuf,smb_vwv2,fnum);
1658 SIVAL(cli->outbuf,smb_vwv3,offset);
1659 SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0);
1660 SSVAL(cli->outbuf,smb_vwv7,mode);
1662 SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0);
1663 SSVAL(cli->outbuf,smb_vwv10,size);
1664 SSVAL(cli->outbuf,smb_vwv11,
1665 smb_buf(cli->outbuf) - smb_base(cli->outbuf));
1667 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
1668 memcpy(p, buf, size);
1670 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1672 cli_send_smb(cli, True);
1675 /****************************************************************************
1677 write_mode: 0x0001 disallow write cacheing
1678 0x0002 return bytes remaining
1679 0x0004 use raw named pipe protocol
1680 0x0008 start of message mode named pipe protocol
1681 ****************************************************************************/
1682 ssize_t cli_write(struct cli_state *cli,
1683 int fnum, uint16 write_mode,
1684 char *buf, off_t offset, size_t size)
1689 int mpx = MAX(cli->max_mux-1, 1);
1690 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1692 int blocks = (size + (block-1)) / block;
1694 if (size == 0) return 0;
1696 while (received < blocks) {
1699 while (issued - received < mpx && issued < blocks) {
1700 int size1 = MIN(block, size-issued*block);
1701 cli_issue_write(cli, fnum, offset+issued*block,
1708 if (!cli_receive_smb(cli)) {
1713 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1714 size2 = SVAL(cli->inbuf, smb_vwv2);
1716 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1717 blocks = MIN(blocks, mid-1);
1722 blocks = MIN(blocks, mid-1);
1723 /* this distinguishes EOF from an error */
1724 total = MAX(total, 0);
1730 total = MAX(total, mid*block + size2);
1733 while (received < issued) {
1734 cli_receive_smb(cli);
1742 /****************************************************************************
1743 do a SMBgetattrE call
1744 ****************************************************************************/
1745 BOOL cli_getattrE(struct cli_state *cli, int fd,
1746 uint16 *attr, size_t *size,
1747 time_t *c_time, time_t *a_time, time_t *m_time)
1749 bzero(cli->outbuf,smb_size);
1750 bzero(cli->inbuf,smb_size);
1752 set_message(cli->outbuf,2,0,True);
1754 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
1755 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1756 cli_setup_packet(cli);
1758 SSVAL(cli->outbuf,smb_vwv0,fd);
1760 cli_send_smb(cli, True);
1761 if (!cli_receive_smb(cli)) {
1765 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1770 *size = IVAL(cli->inbuf, smb_vwv6);
1774 *attr = SVAL(cli->inbuf,smb_vwv10);
1778 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
1782 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
1786 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
1793 /****************************************************************************
1795 ****************************************************************************/
1796 BOOL cli_getatr(struct cli_state *cli, char *fname,
1797 uint16 *attr, size_t *size, time_t *t)
1801 bzero(cli->outbuf,smb_size);
1802 bzero(cli->inbuf,smb_size);
1804 set_message(cli->outbuf,0,strlen(fname)+2,True);
1806 CVAL(cli->outbuf,smb_com) = SMBgetatr;
1807 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1808 cli_setup_packet(cli);
1810 p = smb_buf(cli->outbuf);
1812 pstrcpy(p+1, fname);
1814 cli_send_smb(cli, True);
1815 if (!cli_receive_smb(cli)) {
1819 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1824 *size = IVAL(cli->inbuf, smb_vwv3);
1828 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1832 *attr = SVAL(cli->inbuf,smb_vwv0);
1840 /****************************************************************************
1842 ****************************************************************************/
1843 BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
1847 bzero(cli->outbuf,smb_size);
1848 bzero(cli->inbuf,smb_size);
1850 set_message(cli->outbuf,8,strlen(fname)+4,True);
1852 CVAL(cli->outbuf,smb_com) = SMBsetatr;
1853 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1854 cli_setup_packet(cli);
1856 SSVAL(cli->outbuf,smb_vwv0, attr);
1857 put_dos_date3(cli->outbuf,smb_vwv1, t);
1859 p = smb_buf(cli->outbuf);
1861 pstrcpy(p+1, fname);
1862 p = skip_string(p,1);
1865 cli_send_smb(cli, True);
1866 if (!cli_receive_smb(cli)) {
1870 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1877 /****************************************************************************
1878 send a qpathinfo call
1879 ****************************************************************************/
1880 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
1881 time_t *c_time, time_t *a_time, time_t *m_time,
1882 size_t *size, uint16 *mode)
1886 uint16 setup = TRANSACT2_QPATHINFO;
1888 char *rparam=NULL, *rdata=NULL;
1891 time_t (*date_fn)(void *);
1893 param_len = strlen(fname) + 7;
1895 memset(param, 0, param_len);
1896 SSVAL(param, 0, SMB_INFO_STANDARD);
1897 pstrcpy(¶m[6], fname);
1900 ret = (cli_send_trans(cli, SMBtrans2,
1901 NULL, 0, /* Name, length */
1902 -1, 0, /* fid, flags */
1903 &setup, 1, 0, /* setup, length, max */
1904 param, param_len, 10, /* param, length, max */
1905 NULL, data_len, cli->max_xmit /* data, length, max */
1907 cli_receive_trans(cli, SMBtrans2,
1908 &rparam, ¶m_len,
1909 &rdata, &data_len));
1911 /* we need to work around a Win95 bug - sometimes
1912 it gives ERRSRV/ERRerror temprarily */
1915 cli_error(cli, &eclass, &ecode);
1916 if (eclass != ERRSRV || ecode != ERRerror) break;
1919 } while (count-- && ret==False);
1921 if (!ret || !rdata || data_len < 22) {
1926 date_fn = make_unix_date;
1928 date_fn = make_unix_date2;
1932 *c_time = date_fn(rdata+0);
1935 *a_time = date_fn(rdata+4);
1938 *m_time = date_fn(rdata+8);
1941 *size = IVAL(rdata, 12);
1944 *mode = SVAL(rdata,l1_attrFile);
1947 if (rdata) free(rdata);
1948 if (rparam) free(rparam);
1952 /****************************************************************************
1953 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1954 ****************************************************************************/
1955 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
1956 time_t *c_time, time_t *a_time, time_t *m_time,
1957 time_t *w_time, size_t *size, uint16 *mode,
1962 uint16 setup = TRANSACT2_QPATHINFO;
1964 char *rparam=NULL, *rdata=NULL;
1966 param_len = strlen(fname) + 7;
1968 memset(param, 0, param_len);
1969 SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1970 pstrcpy(¶m[6], fname);
1972 if (!cli_send_trans(cli, SMBtrans2,
1973 NULL, 0, /* name, length */
1974 -1, 0, /* fid, flags */
1975 &setup, 1, 0, /* setup, length, max */
1976 param, param_len, 10, /* param, length, max */
1977 NULL, data_len, cli->max_xmit /* data, length, max */
1982 if (!cli_receive_trans(cli, SMBtrans2,
1983 &rparam, ¶m_len,
1984 &rdata, &data_len)) {
1988 if (!rdata || data_len < 22) {
1993 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1996 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1999 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
2002 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
2005 *mode = SVAL(rdata, 32);
2008 *size = IVAL(rdata, 40);
2011 *ino = IVAL(rdata, 64);
2014 if (rdata) free(rdata);
2015 if (rparam) free(rparam);
2020 /****************************************************************************
2021 send a qfileinfo call
2022 ****************************************************************************/
2023 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
2024 uint16 *mode, size_t *size,
2025 time_t *c_time, time_t *a_time, time_t *m_time,
2026 time_t *w_time, SMB_INO_T *ino)
2030 uint16 setup = TRANSACT2_QFILEINFO;
2032 char *rparam=NULL, *rdata=NULL;
2034 /* if its a win95 server then fail this - win95 totally screws it
2036 if (cli->win95) return False;
2040 memset(param, 0, param_len);
2041 SSVAL(param, 0, fnum);
2042 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
2044 if (!cli_send_trans(cli, SMBtrans2,
2045 NULL, 0, /* name, length */
2046 -1, 0, /* fid, flags */
2047 &setup, 1, 0, /* setup, length, max */
2048 param, param_len, 2, /* param, length, max */
2049 NULL, data_len, cli->max_xmit /* data, length, max */
2054 if (!cli_receive_trans(cli, SMBtrans2,
2055 &rparam, ¶m_len,
2056 &rdata, &data_len)) {
2060 if (!rdata || data_len < 68) {
2065 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
2068 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
2071 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
2074 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
2077 *mode = SVAL(rdata, 32);
2080 *size = IVAL(rdata, 40);
2083 *ino = IVAL(rdata, 64);
2086 if (rdata) free(rdata);
2087 if (rparam) free(rparam);
2092 /****************************************************************************
2093 interpret a long filename structure - this is mostly guesses at the moment
2094 The length of the structure is returned
2095 The structure of a long filename depends on the info level. 260 is used
2096 by NT and 2 is used by OS/2
2097 ****************************************************************************/
2098 static int interpret_long_filename(int level,char *p,file_info *finfo)
2100 extern file_info def_finfo;
2103 memcpy(finfo,&def_finfo,sizeof(*finfo));
2107 case 1: /* OS/2 understands this */
2109 /* these dates are converted to GMT by make_unix_date */
2110 finfo->ctime = make_unix_date2(p+4);
2111 finfo->atime = make_unix_date2(p+8);
2112 finfo->mtime = make_unix_date2(p+12);
2113 finfo->size = IVAL(p,16);
2114 finfo->mode = CVAL(p,24);
2115 pstrcpy(finfo->name,p+27);
2117 return(28 + CVAL(p,26));
2119 case 2: /* this is what OS/2 uses mostly */
2121 /* these dates are converted to GMT by make_unix_date */
2122 finfo->ctime = make_unix_date2(p+4);
2123 finfo->atime = make_unix_date2(p+8);
2124 finfo->mtime = make_unix_date2(p+12);
2125 finfo->size = IVAL(p,16);
2126 finfo->mode = CVAL(p,24);
2127 pstrcpy(finfo->name,p+31);
2129 return(32 + CVAL(p,30));
2131 /* levels 3 and 4 are untested */
2134 /* these dates are probably like the other ones */
2135 finfo->ctime = make_unix_date2(p+8);
2136 finfo->atime = make_unix_date2(p+12);
2137 finfo->mtime = make_unix_date2(p+16);
2138 finfo->size = IVAL(p,20);
2139 finfo->mode = CVAL(p,28);
2140 pstrcpy(finfo->name,p+33);
2142 return(SVAL(p,4)+4);
2146 /* these dates are probably like the other ones */
2147 finfo->ctime = make_unix_date2(p+8);
2148 finfo->atime = make_unix_date2(p+12);
2149 finfo->mtime = make_unix_date2(p+16);
2150 finfo->size = IVAL(p,20);
2151 finfo->mode = CVAL(p,28);
2152 pstrcpy(finfo->name,p+37);
2154 return(SVAL(p,4)+4);
2156 case 260: /* NT uses this, but also accepts 2 */
2158 int ret = SVAL(p,0);
2160 p += 4; /* next entry offset */
2161 p += 4; /* fileindex */
2163 /* these dates appear to arrive in a
2164 weird way. It seems to be localtime
2165 plus the serverzone given in the
2166 initial connect. This is GMT when
2167 DST is not in effect and one hour
2168 from GMT otherwise. Can this really
2171 I suppose this could be called
2172 kludge-GMT. Is is the GMT you get
2173 by using the current DST setting on
2174 a different localtime. It will be
2175 cheap to calculate, I suppose, as
2176 no DST tables will be needed */
2178 finfo->ctime = interpret_long_date(p); p += 8;
2179 finfo->atime = interpret_long_date(p); p += 8;
2180 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
2181 finfo->size = IVAL(p,0); p += 8;
2182 p += 8; /* alloc size */
2183 finfo->mode = CVAL(p,0); p += 4;
2184 namelen = IVAL(p,0); p += 4;
2185 p += 4; /* EA size */
2186 p += 2; /* short name len? */
2187 p += 24; /* short name? */
2188 StrnCpy(finfo->name,p,namelen);
2194 DEBUG(1,("Unknown long filename format %d\n",level));
2199 /****************************************************************************
2200 do a directory listing, calling fn on each file found
2201 ****************************************************************************/
2202 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
2203 void (*fn)(file_info *, const char *))
2205 int max_matches = 512;
2206 /* NT uses 260, OS/2 uses 2. Both accept 1. */
2207 int info_level = cli->protocol<PROTOCOL_NT1?1:260;
2212 char *dirlist = NULL;
2213 int dirlist_len = 0;
2214 int total_received = -1;
2216 int ff_resume_key = 0;
2217 int ff_searchcount=0;
2220 int ff_dir_handle=0;
2222 char *rparam=NULL, *rdata=NULL;
2223 int param_len, data_len;
2230 while (ff_eos == 0) {
2232 if (loop_count > 200) {
2233 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
2237 param_len = 12+strlen(mask)+1;
2240 setup = TRANSACT2_FINDFIRST;
2241 SSVAL(param,0,attribute); /* attribute */
2242 SSVAL(param,2,max_matches); /* max count */
2243 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
2244 SSVAL(param,6,info_level);
2246 pstrcpy(param+12,mask);
2248 setup = TRANSACT2_FINDNEXT;
2249 SSVAL(param,0,ff_dir_handle);
2250 SSVAL(param,2,max_matches); /* max count */
2251 SSVAL(param,4,info_level);
2252 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
2253 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
2254 pstrcpy(param+12,mask);
2256 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
2257 ff_dir_handle,ff_resume_key,ff_lastname,mask));
2260 if (!cli_send_trans(cli, SMBtrans2,
2261 NULL, 0, /* Name, length */
2262 -1, 0, /* fid, flags */
2263 &setup, 1, 0, /* setup, length, max */
2264 param, param_len, 10, /* param, length, max */
2266 cli->max_xmit /* data, length, max */
2271 if (!cli_receive_trans(cli, SMBtrans2,
2272 &rparam, ¶m_len,
2273 &rdata, &data_len)) {
2274 /* we need to work around a Win95 bug - sometimes
2275 it gives ERRSRV/ERRerror temprarily */
2278 cli_error(cli, &eclass, &ecode);
2279 if (eclass != ERRSRV || ecode != ERRerror) break;
2284 if (total_received == -1) total_received = 0;
2286 /* parse out some important return info */
2289 ff_dir_handle = SVAL(p,0);
2290 ff_searchcount = SVAL(p,2);
2292 ff_lastname = SVAL(p,8);
2294 ff_searchcount = SVAL(p,0);
2296 ff_lastname = SVAL(p,6);
2299 if (ff_searchcount == 0)
2302 /* point to the data bytes */
2305 /* we might need the lastname for continuations */
2306 if (ff_lastname > 0) {
2311 StrnCpy(mask,p+ff_lastname,
2312 data_len-ff_lastname);
2315 pstrcpy(mask,p + ff_lastname + 1);
2323 /* and add them to the dirlist pool */
2324 dirlist = Realloc(dirlist,dirlist_len + data_len);
2327 DEBUG(0,("Failed to expand dirlist\n"));
2331 /* put in a length for the last entry, to ensure we can chain entries
2332 into the next packet */
2333 for (p2=p,i=0;i<(ff_searchcount-1);i++)
2334 p2 += interpret_long_filename(info_level,p2,NULL);
2335 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
2337 /* grab the data for later use */
2338 memcpy(dirlist+dirlist_len,p,data_len);
2339 dirlist_len += data_len;
2341 total_received += ff_searchcount;
2343 if (rdata) free(rdata); rdata = NULL;
2344 if (rparam) free(rparam); rparam = NULL;
2346 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
2347 ff_searchcount,ff_eos,ff_resume_key));
2352 for (p=dirlist,i=0;i<total_received;i++) {
2353 p += interpret_long_filename(info_level,p,&finfo);
2357 /* free up the dirlist buffer */
2358 if (dirlist) free(dirlist);
2359 return(total_received);
2363 /****************************************************************************
2364 Send a SamOEMChangePassword command
2365 ****************************************************************************/
2367 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
2368 const char *old_password)
2370 char param[16+sizeof(fstring)];
2373 fstring upper_case_old_pw;
2374 fstring upper_case_new_pw;
2375 unsigned char old_pw_hash[16];
2376 unsigned char new_pw_hash[16];
2379 char *rparam = NULL;
2383 if (strlen(user) >= sizeof(fstring)-1) {
2384 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
2388 SSVAL(p,0,214); /* SamOEMChangePassword command. */
2391 p = skip_string(p,1);
2392 pstrcpy(p, "B516B16");
2393 p = skip_string(p,1);
2395 p = skip_string(p,1);
2399 param_len = PTR_DIFF(p,param);
2402 * Get the Lanman hash of the old password, we
2403 * use this as the key to make_oem_passwd_hash().
2405 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
2406 fstrcpy(upper_case_old_pw, old_password);
2407 strupper(upper_case_old_pw);
2408 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
2410 if (!make_oem_passwd_hash( data, new_password, old_pw_hash, False))
2416 * Now place the old password hash in the data.
2418 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
2419 fstrcpy(upper_case_new_pw, new_password);
2420 strupper(upper_case_new_pw);
2422 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
2424 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
2428 if (!cli_send_trans(cli,SMBtrans,
2429 PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */
2430 0,0, /* fid, flags */
2431 NULL,0,0, /* setup, length, max */
2432 param,param_len,2, /* param, length, max */
2433 data,data_len,0 /* data, length, max */
2436 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
2441 if (cli_receive_trans(cli,SMBtrans,
2445 cli->rap_error = SVAL(rparam,0);
2453 return (cli->rap_error == 0);
2456 /****************************************************************************
2457 send a negprot command
2458 ****************************************************************************/
2459 BOOL cli_negprot(struct cli_state *cli)
2465 bzero(cli->outbuf,smb_size);
2467 /* setup the protocol strings */
2468 for (plength=0,numprots=0;
2469 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2471 plength += strlen(prots[numprots].name)+2;
2473 set_message(cli->outbuf,0,plength,True);
2475 p = smb_buf(cli->outbuf);
2477 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2480 pstrcpy(p,prots[numprots].name);
2484 CVAL(cli->outbuf,smb_com) = SMBnegprot;
2485 cli_setup_packet(cli);
2487 CVAL(smb_buf(cli->outbuf),0) = 2;
2489 cli_send_smb(cli, True);
2490 if (!cli_receive_smb(cli))
2495 if (CVAL(cli->inbuf,smb_rcls) != 0 ||
2496 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
2500 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
2503 if (cli->protocol >= PROTOCOL_NT1)
2505 char *buf = smb_buf(cli->inbuf);
2506 int bcc = SVAL(cli->inbuf,smb_vwv+2*(CVAL(cli->inbuf,smb_wct)));
2508 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
2509 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
2510 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
2511 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
2512 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
2513 /* this time arrives in real GMT */
2514 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
2516 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
2517 if (IS_BITS_SET_ALL(cli->capabilities, CAP_RAW_MODE))
2519 cli->readbraw_supported = True;
2520 cli->writebraw_supported = True;
2523 if (IS_BITS_SET_ALL(cli->capabilities, CAP_EXTENDED_SECURITY))
2525 /* oops, some kerberos-related nonsense. */
2526 /* expect to have to use NTLMSSP-over-SMB */
2527 DEBUG(10,("unknown kerberos-related (?) blob\n"));
2528 memset(cli->cryptkey, 0, 8);
2529 cli->server_domain[0] = 0;
2533 memcpy(cli->cryptkey, buf,8);
2536 unibuf_to_ascii(cli->server_domain, buf+8,
2537 sizeof(cli->server_domain));
2541 cli->server_domain[0] = 0;
2543 DEBUG(5,("server's domain: %s bcc: %d\n",
2544 cli->server_domain, bcc));
2547 else if (cli->protocol >= PROTOCOL_LANMAN1)
2549 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
2550 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
2551 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
2552 cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
2553 /* this time is converted to GMT by make_unix_date */
2554 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
2555 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
2556 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
2557 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2559 /* the old core protocol */
2561 cli->serverzone = TimeDiff(time(NULL));
2564 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2570 /****************************************************************************
2571 send a session request. see rfc1002.txt 4.3 and 4.3.2
2572 ****************************************************************************/
2573 BOOL cli_session_request(struct cli_state *cli,
2574 struct nmb_name *calling, struct nmb_name *called)
2578 /* send a session request (RFC 1002) */
2580 memcpy(&(cli->calling), calling, sizeof(*calling));
2581 memcpy(&(cli->called ), called , sizeof(*called ));
2583 if (cli->port == 445)
2588 /* put in the destination name */
2589 p = cli->outbuf+len;
2590 name_mangle(cli->called .name, p, cli->called .name_type);
2594 p = cli->outbuf+len;
2595 name_mangle(cli->calling.name, p, cli->calling.name_type);
2598 /* setup the packet length */
2599 _smb_setlen(cli->outbuf,len);
2600 CVAL(cli->outbuf,0) = 0x81;
2604 #endif /* WITH_SSL */
2606 cli_send_smb(cli, True);
2607 DEBUG(5,("Sent session request\n"));
2609 if (!cli_receive_smb(cli))
2613 if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
2614 if (!sslutil_fd_is_ssl(cli->fd)){
2615 if (sslutil_connect(cli->fd) == 0)
2619 #endif /* WITH_SSL */
2621 if (CVAL(cli->inbuf,0) != 0x82) {
2622 /* This is the wrong place to put the error... JRA. */
2623 cli->rap_error = CVAL(cli->inbuf,0);
2630 /****************************************************************************
2631 open the client sockets
2632 ****************************************************************************/
2633 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
2635 extern struct in_addr ipzero;
2636 int port = cli->port;
2638 fstrcpy(cli->desthost, host);
2640 if (!ip || ip_equal(*ip, ipzero)) {
2641 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
2644 if (ip) *ip = cli->dest_ip;
2650 if (port == 0) port = SMB_PORT2;
2652 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2653 port, cli->timeout);
2662 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2663 port, cli->timeout);
2664 if (cli->fd == -1) return False;
2673 /****************************************************************************
2674 initialise a client structure
2675 ****************************************************************************/
2676 void cli_init_creds(struct cli_state *cli, const struct user_credentials *usr)
2678 copy_user_creds(&cli->usr, usr);
2679 cli->ntlmssp_cli_flgs = usr->ntlmssp_flags;
2682 /****************************************************************************
2683 initialise a client structure
2684 ****************************************************************************/
2685 struct cli_state *cli_initialise(struct cli_state *cli)
2688 cli = (struct cli_state *)malloc(sizeof(*cli));
2694 if (cli->initialised) {
2703 cli->pid = (uint16)getpid();
2705 cli->vuid = UID_FIELD_INVALID;
2706 cli->protocol = PROTOCOL_NT1;
2707 cli->timeout = 20000;
2708 cli->bufsize = CLI_BUFFER_SIZE+4;
2709 cli->max_xmit = cli->bufsize;
2710 cli->outbuf = (char *)malloc(cli->bufsize);
2711 cli->inbuf = (char *)malloc(cli->bufsize);
2712 if (!cli->outbuf || !cli->inbuf)
2717 cli->initialised = 1;
2718 cli->capabilities = CAP_DFS;
2723 /****************************************************************************
2724 close the socket descriptor
2725 ****************************************************************************/
2726 void cli_close_socket(struct cli_state *cli)
2731 sslutil_disconnect(cli->fd);
2733 #endif /* WITH_SSL */
2741 /****************************************************************************
2742 shutdown a client structure
2743 ****************************************************************************/
2744 void cli_shutdown(struct cli_state *cli)
2746 DEBUG(10,("cli_shutdown\n"));
2755 cli_close_socket(cli);
2756 memset(cli, 0, sizeof(*cli));
2760 /****************************************************************************
2761 return error codes for the last packet
2762 returns 0 if there was no error and the best approx of a unix errno
2765 for 32 bit "warnings", a return code of 0 is expected.
2767 ****************************************************************************/
2768 int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
2774 if (!cli->initialised)
2776 DEBUG(0,("cli_error: client state uninitialised!\n"));
2780 flgs2 = SVAL(cli->inbuf,smb_flg2);
2782 if (eclass) *eclass = 0;
2785 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES)
2787 /* 32 bit error codes detected */
2788 uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
2789 if (num) *num = nt_err;
2790 DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
2791 if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0;
2793 switch (nt_err & 0xFFFFFF)
2795 case NT_STATUS_ACCESS_VIOLATION : return EACCES;
2796 case NT_STATUS_NO_SUCH_FILE : return ENOENT;
2797 case NT_STATUS_NO_SUCH_DEVICE : return ENODEV;
2798 case NT_STATUS_INVALID_HANDLE : return EBADF;
2799 case NT_STATUS_NO_MEMORY : return ENOMEM;
2800 case NT_STATUS_ACCESS_DENIED : return EACCES;
2801 case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
2802 case NT_STATUS_SHARING_VIOLATION : return EBUSY;
2803 case NT_STATUS_OBJECT_PATH_INVALID : return ENOTDIR;
2804 case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
2807 /* for all other cases - a default code */
2811 rcls = CVAL(cli->inbuf,smb_rcls);
2812 code = SVAL(cli->inbuf,smb_err);
2813 if (rcls == 0) return 0;
2815 if (eclass) *eclass = rcls;
2816 if (num ) *num = code;
2818 if (rcls == ERRDOS) {
2820 case ERRbadfile: return ENOENT;
2821 case ERRbadpath: return ENOTDIR;
2822 case ERRnoaccess: return EACCES;
2823 case ERRfilexists: return EEXIST;
2824 case ERRrename: return EEXIST;
2825 case ERRbadshare: return EBUSY;
2826 case ERRlock: return EBUSY;
2827 case ERRmoredata: return 0; /* Informational only */
2830 if (rcls == ERRSRV) {
2832 case ERRbadpw: return EPERM;
2833 case ERRaccess: return EACCES;
2834 case ERRnoresource: return ENOMEM;
2835 case ERRinvdevice: return ENODEV;
2836 case ERRinvnetname: return ENODEV;
2839 /* for other cases */
2843 /****************************************************************************
2844 set socket options on a open connection
2845 ****************************************************************************/
2846 void cli_sockopt(struct cli_state *cli, char *options)
2848 set_socket_options(cli->fd, options);
2851 /****************************************************************************
2852 set the PID to use for smb messages. Return the old pid.
2853 ****************************************************************************/
2854 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
2856 uint16 ret = cli->pid;
2861 /****************************************************************************
2862 re-establishes a connection
2863 ****************************************************************************/
2864 BOOL cli_reestablish_connection(struct cli_state *cli)
2866 struct nmb_name calling;
2867 struct nmb_name called;
2871 BOOL do_tcon = False;
2872 int oldfd = cli->fd;
2874 if (!cli->initialised || cli->fd == -1)
2876 DEBUG(3,("cli_reestablish_connection: not connected\n"));
2880 /* copy the parameters necessary to re-establish the connection */
2889 fstrcpy(share, cli->share);
2890 fstrcpy(dev , cli->dev);
2893 memcpy(&called , &(cli->called ), sizeof(called ));
2894 memcpy(&calling, &(cli->calling), sizeof(calling));
2895 fstrcpy(dest_host, cli->desthost);
2897 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2898 nmb_namestr(&calling), nmb_namestr(&called),
2899 inet_ntoa(cli->dest_ip),
2900 cli->usr.user_name, cli->usr.domain));
2904 if (cli_establish_connection(cli,
2905 dest_host, &cli->dest_ip,
2907 share, dev, False, do_tcon))
2909 if (cli->fd != oldfd)
2911 if (dup2(cli->fd, oldfd) == oldfd)
2913 cli_close_socket(cli);
2921 /****************************************************************************
2922 establishes a connection right up to doing tconX, reading in a password.
2923 ****************************************************************************/
2924 BOOL cli_establish_connection(struct cli_state *cli,
2925 char *dest_host, struct in_addr *dest_ip,
2926 struct nmb_name *calling, struct nmb_name *called,
2927 char *service, char *service_type,
2928 BOOL do_shutdown, BOOL do_tcon)
2933 nmb_safe_namestr(calling, callingstr, sizeof(callingstr));
2934 nmb_safe_namestr(called , calledstr , sizeof(calledstr ));
2936 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s] with NTLM%s\n",
2937 callingstr, calledstr, inet_ntoa(*dest_ip),
2938 cli->usr.user_name, cli->usr.domain,
2939 cli->use_ntlmv2 ? "v2" : "v1"));
2941 /* establish connection */
2943 if ((!cli->initialised))
2950 if (!cli_connect(cli, dest_host, dest_ip))
2952 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
2953 callingstr, inet_ntoa(*dest_ip)));
2958 if (!cli_session_request(cli, calling, called))
2960 DEBUG(1,("failed session request\n"));
2968 if (!cli_negprot(cli))
2970 DEBUG(1,("failed negprot\n"));
2978 if (cli->usr.domain[0] == 0)
2980 safe_strcpy(cli->usr.domain, cli->server_domain,
2981 sizeof(cli->usr.domain));
2984 if (IS_BITS_SET_ALL(cli->capabilities, CAP_EXTENDED_SECURITY))
2986 /* common to both session setups */
2990 char *e = pwd_buf + sizeof(pwd_buf);
2992 /* 1st session setup */
2995 0x60, 0x40, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05,
2996 0x05, 0x02, 0xa0, 0x36, 0x30, 0x34, 0xa0, 0x0e,
2997 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
2998 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa2, 0x22,
3001 /* 2nd session setup */
3003 char pwd_data_2[8] =
3005 0xa1, 0x51, 0x30, 0x4f, 0xa2, 0x4d, 0x04, 0x4b
3008 char pwd_data_2[8] =
3010 0xa1, 0x51, 0x30, 0x4f, 0xa2, 0x4d, 0x04, 0x4b
3012 prs_struct auth_resp;
3019 memset(pwd_buf, 0, sizeof(pwd_buf));
3020 memcpy(pwd_buf, pwd_data, sizeof(pwd_data));
3021 p = pwd_buf + sizeof(pwd_data);
3023 safe_strcpy(p, "NTLMSSP", PTR_DIFF(e, p) - 1);
3024 p = skip_string(p, 1);
3027 if (cli->ntlmssp_cli_flgs == 0)
3029 cli->ntlmssp_cli_flgs =
3030 NTLMSSP_NEGOTIATE_UNICODE |
3031 NTLMSSP_NEGOTIATE_OEM |
3032 NTLMSSP_NEGOTIATE_SIGN |
3033 NTLMSSP_NEGOTIATE_SEAL |
3034 NTLMSSP_NEGOTIATE_LM_KEY |
3035 NTLMSSP_NEGOTIATE_NTLM |
3036 NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
3037 NTLMSSP_NEGOTIATE_00001000 |
3038 NTLMSSP_NEGOTIATE_00002000;
3040 cli->ntlmssp_cli_flgs = 0x80008207;
3043 SIVAL(p, 0, cli->ntlmssp_cli_flgs);
3045 p += 16; /* skip some NULL space */
3046 CVAL(p, 0) = 0; p++; /* alignment */
3048 buf_len = PTR_DIFF(p, pwd_buf);
3050 /* first session negotiation stage */
3051 if (!cli_session_setup_x(cli, cli->usr.user_name,
3056 DEBUG(1,("failed session setup\n"));
3064 DEBUG(1,("1st session setup ok\n"));
3066 if (*cli->server_domain || *cli->server_os || *cli->server_type)
3068 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
3074 p = smb_buf(cli->inbuf) + 0x2f;
3075 cli->ntlmssp_cli_flgs = IVAL(p, 0); /* 0x80808a05; */
3077 memcpy(cli->cryptkey, p, 8);
3078 #ifdef DEBUG_PASSWORD
3079 DEBUG(100,("cli_session_setup_x: ntlmssp %8x\n",
3080 cli->ntlmssp_cli_flgs));
3082 DEBUG(100,("cli_session_setup_x: crypt key\n"));
3083 dump_data(100, cli->cryptkey, 8);
3085 prs_init(&auth_resp, 1024, 4, SAFETY_MARGIN, False);
3087 if (cli->use_ntlmv2 != False)
3089 DEBUG(10,("cli_establish_connection: NTLMv2\n"));
3090 pwd_make_lm_nt_owf2(&(cli->usr.pwd), cli->cryptkey,
3091 cli->usr.user_name, calling->name, cli->usr.domain);
3095 DEBUG(10,("cli_establish_connection: NTLMv1\n"));
3096 pwd_make_lm_nt_owf(&(cli->usr.pwd), cli->cryptkey);
3099 create_ntlmssp_resp(&cli->usr.pwd, cli->usr.domain,
3100 cli->usr.user_name, cli->calling.name,
3101 cli->ntlmssp_cli_flgs,
3103 prs_link(NULL, &auth_resp, NULL);
3105 memset(pwd_buf, 0, sizeof(pwd_buf));
3108 CVAL(p, 0) = 0xa1; p++;
3109 CVAL(p, 0) = 0x82; p++;
3110 p_gssapi = p; p+= 2;
3111 CVAL(p, 0) = 0x30; p++;
3112 CVAL(p, 0) = 0x82; p++;
3115 CVAL(p, 0) = 0xa2; p++;
3116 CVAL(p, 0) = 0x82; p++;
3118 CVAL(p, 0) = 0x04; p++;
3119 CVAL(p, 0) = 0x82; p++;
3124 safe_strcpy(p, "NTLMSSP", PTR_DIFF(e, p) - 1);
3125 p = skip_string(p, 1);
3129 resp_len = mem_buf_len(auth_resp.data);
3130 mem_buf_copy(p, auth_resp.data, 0, resp_len);
3131 prs_mem_free(&auth_resp);
3135 buf_len = PTR_DIFF(p, pwd_buf);
3136 gssapi_len = PTR_DIFF(p, p_gssapi_end) + 12;
3138 *p_gssapi++ = (gssapi_len >> 8) & 0xff;
3139 *p_gssapi++ = gssapi_len & 0xff;
3144 *p_gssapi++ = (gssapi_len >> 8) & 0xff;
3145 *p_gssapi++ = gssapi_len & 0xff;
3149 *p_oem++ = (gssapi_len >> 8) & 0xff;
3150 *p_oem++ = gssapi_len & 0xff;
3155 *p_oem++ = (gssapi_len >> 8) & 0xff;
3156 *p_oem++ = gssapi_len & 0xff;
3158 /* second session negotiation stage */
3159 if (!cli_session_setup_x(cli, cli->usr.user_name,
3164 DEBUG(1,("failed session setup\n"));
3172 DEBUG(1,("2nd session setup ok\n"));
3176 if (!cli_send_tconX(cli, service, service_type,
3180 DEBUG(1,("failed tcon_X\n"));
3189 else if (cli->usr.pwd.cleartext || cli->usr.pwd.null_pwd)
3191 fstring passwd, ntpasswd;
3192 int pass_len = 0, ntpass_len = 0;
3194 if (cli->usr.pwd.null_pwd)
3196 /* attempt null session */
3197 passwd[0] = ntpasswd[0] = 0;
3198 pass_len = ntpass_len = 1;
3202 /* attempt clear-text session */
3203 pwd_get_cleartext(&(cli->usr.pwd), passwd);
3204 pass_len = strlen(passwd);
3207 /* attempt clear-text session */
3208 if (!cli_session_setup(cli, calling->name,
3211 ntpasswd, ntpass_len,
3214 DEBUG(1,("failed session setup\n"));
3223 if (!cli_send_tconX(cli, service, service_type,
3224 (char*)passwd, strlen(passwd)))
3226 DEBUG(1,("failed tcon_X\n"));
3237 /* attempt encrypted session */
3238 unsigned char lm_sess_pwd[24];
3239 unsigned char nt_sess_pwd[128];
3240 size_t nt_sess_pwd_len;
3242 if (cli->use_ntlmv2 != False)
3244 DEBUG(10,("cli_establish_connection: NTLMv2\n"));
3245 pwd_make_lm_nt_owf2(&(cli->usr.pwd), cli->cryptkey,
3246 cli->usr.user_name, calling->name, cli->usr.domain);
3250 DEBUG(10,("cli_establish_connection: NTLMv1\n"));
3251 pwd_make_lm_nt_owf(&(cli->usr.pwd), cli->cryptkey);
3254 pwd_get_lm_nt_owf(&(cli->usr.pwd), lm_sess_pwd, nt_sess_pwd,
3255 &nt_sess_pwd_len, cli->sess_key);
3257 /* attempt encrypted session */
3258 if (!cli_session_setup_x(cli, cli->usr.user_name,
3259 (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
3260 (char*)nt_sess_pwd, nt_sess_pwd_len,
3263 DEBUG(1,("failed session setup\n"));
3265 if (cli->use_ntlmv2 == Auto)
3267 DEBUG(10,("NTLMv2 failed. Using NTLMv1\n"));
3268 cli->use_ntlmv2 = False;
3271 fstrcpy(cli->share, service);
3272 fstrcpy(cli->dev, service_type);
3274 fstrcpy(cli->desthost, dest_host);
3275 cli_close_socket(cli);
3276 return cli_establish_connection(cli,
3279 service, service_type,
3280 do_shutdown, do_tcon);
3290 DEBUG(1,("session setup ok\n"));
3292 if (*cli->server_domain || *cli->server_os || *cli->server_type)
3294 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
3302 if (!cli_send_tconX(cli, service, service_type,
3303 (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
3305 DEBUG(1,("failed tcon_X\n"));
3323 /****************************************************************************
3324 connect to one of multiple servers: don't care which
3325 ****************************************************************************/
3326 BOOL cli_connect_serverlist(struct cli_state *cli, char *p)
3328 extern pstring global_myname;
3329 extern pstring scope;
3330 fstring remote_machine;
3332 struct in_addr dest_ip;
3333 struct nmb_name calling, called, stupid_smbserver_called;
3334 BOOL connected_ok = False;
3337 * Treat each name in the 'password server =' line as a potential
3338 * PDC/BDC. Contact each in turn and try and authenticate.
3341 while(p && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine)))
3345 if (!cli_initialise(cli))
3347 DEBUG(0,("cli_connect_serverlist: unable to initialize client connection.\n"));
3351 standard_sub_basic(remote_machine);
3352 strupper(remote_machine);
3354 if (!resolve_srv_name( remote_machine, desthost, &dest_ip))
3356 DEBUG(1,("cli_connect_serverlist: Can't resolve address for %s\n", remote_machine));
3360 if ((lp_security() != SEC_USER) && (ismyip(dest_ip)))
3362 DEBUG(1,("cli_connect_serverlist: Password server loop - not using password server %s\n", remote_machine));
3366 make_nmb_name(&calling, global_myname, 0x0 , scope);
3367 make_nmb_name(&called , desthost , 0x20, scope);
3368 /* stupid microsoft destruction of the ability of netbios
3369 * to provide multiple netbios servers on one host.
3371 make_nmb_name(&stupid_smbserver_called , "*SMBSERVER", 0x20, scope);
3373 pwd_set_nullpwd(&cli->usr.pwd);
3375 if (!cli_establish_connection(cli, desthost, &dest_ip,
3379 !cli_establish_connection(cli, desthost, &dest_ip,
3380 &calling, &stupid_smbserver_called,
3388 if (cli->protocol < PROTOCOL_LANMAN2 ||
3389 !IS_BITS_SET_ALL(cli->sec_mode, 1))
3391 DEBUG(1,("cli_connect_serverlist: machine %s isn't in user level security mode\n",
3398 * We have an anonymous connection to IPC$.
3401 connected_ok = True;
3407 DEBUG(0,("cli_connect_serverlist: Domain password server not available.\n"));
3411 return connected_ok;
3414 /****************************************************************************
3416 ****************************************************************************/
3417 int cli_printjob_del(struct cli_state *cli, int job)
3419 char *rparam = NULL;
3422 int rdrcnt,rprcnt, ret = -1;
3425 bzero(param,sizeof(param));
3428 SSVAL(p,0,81); /* DosPrintJobDel() */
3431 p = skip_string(p,1);
3433 p = skip_string(p,1);
3438 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
3439 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
3440 &rparam, &rprcnt, /* return params, length */
3441 &rdata, &rdrcnt)) { /* return data, length */
3442 ret = SVAL(rparam,0);
3445 if (rparam) free(rparam);
3446 if (rdata) free(rdata);
3452 /****************************************************************************
3453 call fn() on each entry in a print queue
3454 ****************************************************************************/
3455 int cli_print_queue(struct cli_state *cli,
3456 void (*fn)(struct print_job_info *))
3458 char *rparam = NULL;
3466 bzero(param,sizeof(param));
3469 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
3471 pstrcpy(p,"zWrLeh"); /* parameter description? */
3472 p = skip_string(p,1);
3473 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
3474 p = skip_string(p,1);
3475 pstrcpy(p,cli->share); /* name of queue */
3476 p = skip_string(p,1);
3477 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
3478 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
3480 pstrcpy(p,""); /* subformat */
3481 p = skip_string(p,1);
3483 DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
3486 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
3487 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
3488 &rparam, &rprcnt, /* return params, length */
3489 &rdata, &rdrcnt)) { /* return data, length */
3491 result_code = SVAL(rparam,0);
3492 converter = SVAL(rparam,2); /* conversion factor */
3494 if (result_code == 0) {
3495 struct print_job_info job;
3499 for (i = 0; i < SVAL(rparam,4); ++i) {
3501 job.priority = SVAL(p,2);
3503 fix_char_ptr(SVAL(p,4), converter,
3505 job.t = make_unix_date3(p + 12);
3506 job.size = IVAL(p,16);
3507 fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
3516 /* If any parameters or data were returned, free the storage. */
3517 if(rparam) free(rparam);
3518 if(rdata) free(rdata);
3523 /****************************************************************************
3524 check for existance of a dir
3525 ****************************************************************************/
3526 BOOL cli_chkpath(struct cli_state *cli, char *path)
3531 fstrcpy(path2,path);
3532 trim_string(path2,NULL,"\\");
3533 if (!*path2) *path2 = '\\';
3535 bzero(cli->outbuf,smb_size);
3536 set_message(cli->outbuf,0,4 + strlen(path2),True);
3537 SCVAL(cli->outbuf,smb_com,SMBchkpth);
3538 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3539 cli_setup_packet(cli);
3541 p = smb_buf(cli->outbuf);
3545 cli_send_smb(cli, True);
3546 if (!cli_receive_smb(cli)) {
3550 if (cli_error(cli, NULL, NULL)) return False;
3556 /****************************************************************************
3557 start a message sequence
3558 ****************************************************************************/
3559 BOOL cli_message_start(struct cli_state *cli, char *host, char *username,
3564 /* send a SMBsendstrt command */
3565 bzero(cli->outbuf,smb_size);
3566 set_message(cli->outbuf,0,0,True);
3567 CVAL(cli->outbuf,smb_com) = SMBsendstrt;
3568 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3569 cli_setup_packet(cli);
3571 p = smb_buf(cli->outbuf);
3573 pstrcpy(p,username);
3574 p = skip_string(p,1);
3577 p = skip_string(p,1);
3579 set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
3581 cli_send_smb(cli, True);
3583 if (!cli_receive_smb(cli)) {
3587 if (cli_error(cli, NULL, NULL)) return False;
3589 *grp = SVAL(cli->inbuf,smb_vwv0);
3595 /****************************************************************************
3597 ****************************************************************************/
3598 BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp)
3602 bzero(cli->outbuf,smb_size);
3603 set_message(cli->outbuf,1,len+3,True);
3604 CVAL(cli->outbuf,smb_com) = SMBsendtxt;
3605 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3606 cli_setup_packet(cli);
3608 SSVAL(cli->outbuf,smb_vwv0,grp);
3610 p = smb_buf(cli->outbuf);
3613 memcpy(p+3,msg,len);
3614 cli_send_smb(cli, True);
3616 if (!cli_receive_smb(cli)) {
3620 if (cli_error(cli, NULL, NULL)) return False;
3625 /****************************************************************************
3627 ****************************************************************************/
3628 BOOL cli_message_end(struct cli_state *cli, int grp)
3630 bzero(cli->outbuf,smb_size);
3631 set_message(cli->outbuf,1,0,True);
3632 CVAL(cli->outbuf,smb_com) = SMBsendend;
3633 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3635 SSVAL(cli->outbuf,smb_vwv0,grp);
3637 cli_setup_packet(cli);
3639 cli_send_smb(cli, True);
3641 if (!cli_receive_smb(cli)) {
3645 if (cli_error(cli, NULL, NULL)) return False;
3651 /****************************************************************************
3653 ****************************************************************************/
3654 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3656 bzero(cli->outbuf,smb_size);
3657 set_message(cli->outbuf,0,0,True);
3658 CVAL(cli->outbuf,smb_com) = SMBdskattr;
3659 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3660 cli_setup_packet(cli);
3662 cli_send_smb(cli, True);
3663 if (!cli_receive_smb(cli)) {
3667 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
3668 *total = SVAL(cli->inbuf,smb_vwv0);
3669 *avail = SVAL(cli->inbuf,smb_vwv3);