2 Unix SMB/Netbios implementation.
4 SMB client generic functions
5 Copyright (C) Andrew Tridgell 1994-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 extern int DEBUGLEVEL;
31 /****************************************************************************
33 ****************************************************************************/
34 static BOOL cli_receive_smb(struct cli_state *cli)
36 return client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
39 /****************************************************************************
40 send an smb to a fd and re-establish if necessary
41 ****************************************************************************/
42 static BOOL cli_send_smb(struct cli_state *cli, BOOL show)
47 BOOL reestablished=False;
51 show_msg(cli->outbuf);
54 len = smb_len(cli->outbuf) + 4;
56 while (nwritten < len) {
57 ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
58 if (ret <= 0 && errno == EPIPE && !reestablished)
60 DEBUG(5,("cli_send_smb: write error (%s) - reconnecting\n",
63 if (cli_reestablish_connection(cli)) {
70 DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",
80 /*****************************************************
81 RAP error codes - a small start but will be extended.
82 *******************************************************/
90 {5, "User has insufficient privilege" },
91 {86, "The specified password is invalid" },
92 {2226, "Operation only permitted on a Primary Domain Controller" },
93 {2242, "The password of this user has expired." },
94 {2243, "The password of this user cannot change." },
95 {2244, "This password cannot be used now (password history conflict)." },
96 {2245, "The password is shorter than required." },
97 {2246, "The password of this user is too recent to change."},
101 /****************************************************************************
102 return a description of an SMB error
103 ****************************************************************************/
104 static char *cli_smb_errstr(struct cli_state *cli)
106 return smb_errstr(cli->inbuf);
109 /******************************************************
110 Return an error message - either an SMB error or a RAP
112 *******************************************************/
114 char *cli_errstr(struct cli_state *cli)
116 static fstring error_message;
122 * Errors are of three kinds - smb errors,
123 * dealt with by cli_smb_errstr, NT errors,
124 * whose code is in cli.nt_error, and rap
125 * errors, whose error code is in cli.rap_error.
128 cli_error(cli, &errclass, &errnum);
132 return cli_smb_errstr(cli);
136 * Was it an NT error ?
141 char *nt_msg = get_nt_error_msg(cli->nt_error);
145 slprintf(error_message, sizeof(fstring) - 1, "NT code %d", cli->nt_error);
149 fstrcpy(error_message, nt_msg);
152 return error_message;
156 * Must have been a rap error.
159 slprintf(error_message, sizeof(error_message) - 1, "code %d", cli->rap_error);
161 for (i = 0; rap_errmap[i].message != NULL; i++)
163 if (rap_errmap[i].err == cli->rap_error)
165 fstrcpy( error_message, rap_errmap[i].message);
170 return error_message;
173 /****************************************************************************
174 setup basics in a outgoing packet
175 ****************************************************************************/
176 static void cli_setup_packet(struct cli_state *cli)
180 SSVAL(cli->outbuf,smb_pid,cli->pid);
181 SSVAL(cli->outbuf,smb_uid,cli->vuid);
182 SSVAL(cli->outbuf,smb_mid,cli->mid);
183 if (cli->protocol > PROTOCOL_CORE) {
184 SCVAL(cli->outbuf,smb_flg,0x8);
185 SSVAL(cli->outbuf,smb_flg2,0x1);
190 /*****************************************************************************
191 Convert a character pointer in a cli_call_api() response to a form we can use.
192 This function contains code to prevent core dumps if the server returns
194 *****************************************************************************/
195 static char *fix_char_ptr(unsigned int datap, unsigned int converter,
196 char *rdata, int rdrcnt)
198 if (datap == 0) { /* turn NULL pointers into zero length strings */
201 unsigned int offset = datap - converter;
203 if (offset >= rdrcnt) {
204 DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
205 datap, converter, rdrcnt));
208 return &rdata[offset];
213 /****************************************************************************
214 send a SMB trans or trans2 request
215 ****************************************************************************/
216 static BOOL cli_send_trans(struct cli_state *cli, int trans,
217 char *name, int pipe_name_len,
219 uint16 *setup, int lsetup, int msetup,
220 char *param, int lparam, int mparam,
221 char *data, int ldata, int mdata)
224 int this_ldata,this_lparam;
225 int tot_data=0,tot_param=0;
226 char *outdata,*outparam;
229 this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
230 this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
232 bzero(cli->outbuf,smb_size);
233 set_message(cli->outbuf,14+lsetup,0,True);
234 CVAL(cli->outbuf,smb_com) = trans;
235 SSVAL(cli->outbuf,smb_tid, cli->cnum);
236 cli_setup_packet(cli);
238 outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len+1 : 3);
239 outdata = outparam+this_lparam;
241 /* primary request */
242 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
243 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
244 SSVAL(cli->outbuf,smb_mprcnt,mparam); /* mprcnt */
245 SSVAL(cli->outbuf,smb_mdrcnt,mdata); /* mdrcnt */
246 SCVAL(cli->outbuf,smb_msrcnt,msetup); /* msrcnt */
247 SSVAL(cli->outbuf,smb_flags,flags); /* flags */
248 SIVAL(cli->outbuf,smb_timeout,0); /* timeout */
249 SSVAL(cli->outbuf,smb_pscnt,this_lparam); /* pscnt */
250 SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
251 SSVAL(cli->outbuf,smb_dscnt,this_ldata); /* dscnt */
252 SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
253 SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */
254 for (i=0;i<lsetup;i++) /* setup[] */
255 SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
256 p = smb_buf(cli->outbuf);
257 if (trans==SMBtrans) {
258 memcpy(p,name, pipe_name_len + 1); /* name[] */
260 *p++ = 0; /* put in a null smb_name */
261 *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */
263 if (this_lparam) /* param[] */
264 memcpy(outparam,param,this_lparam);
265 if (this_ldata) /* data[] */
266 memcpy(outdata,data,this_ldata);
267 set_message(cli->outbuf,14+lsetup, /* wcnt, bcc */
268 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
270 cli_send_smb(cli, True);
272 if (this_ldata < ldata || this_lparam < lparam) {
273 /* receive interim response */
274 if (!cli_receive_smb(cli) ||
275 CVAL(cli->inbuf,smb_rcls) != 0) {
279 tot_data = this_ldata;
280 tot_param = this_lparam;
282 while (tot_data < ldata || tot_param < lparam) {
283 this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
284 this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
286 set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
287 CVAL(cli->outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
289 outparam = smb_buf(cli->outbuf);
290 outdata = outparam+this_lparam;
292 /* secondary request */
293 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
294 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
295 SSVAL(cli->outbuf,smb_spscnt,this_lparam); /* pscnt */
296 SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
297 SSVAL(cli->outbuf,smb_spsdisp,tot_param); /* psdisp */
298 SSVAL(cli->outbuf,smb_sdscnt,this_ldata); /* dscnt */
299 SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
300 SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */
301 if (trans==SMBtrans2)
302 SSVALS(cli->outbuf,smb_sfid,fid); /* fid */
303 if (this_lparam) /* param[] */
304 memcpy(outparam,param,this_lparam);
305 if (this_ldata) /* data[] */
306 memcpy(outdata,data,this_ldata);
307 set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
308 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
310 cli_send_smb(cli, True);
312 tot_data += this_ldata;
313 tot_param += this_lparam;
321 /****************************************************************************
322 receive a SMB trans or trans2 response allocating the necessary memory
323 ****************************************************************************/
324 static BOOL cli_receive_trans(struct cli_state *cli,int trans,
325 char **param, int *param_len,
326 char **data, int *data_len)
330 int this_data,this_param;
332 *data_len = *param_len = 0;
334 if (!cli_receive_smb(cli))
338 if (CVAL(cli->inbuf,smb_com) != trans) {
339 DEBUG(0,("Expected %s response, got command 0x%02x\n",
340 trans==SMBtrans?"SMBtrans":"SMBtrans2",
341 CVAL(cli->inbuf,smb_com)));
345 if (cli_error(cli, NULL, NULL))
350 /* parse out the lengths */
351 total_data = SVAL(cli->inbuf,smb_tdrcnt);
352 total_param = SVAL(cli->inbuf,smb_tprcnt);
355 *data = Realloc(*data,total_data);
356 *param = Realloc(*param,total_param);
359 this_data = SVAL(cli->inbuf,smb_drcnt);
360 this_param = SVAL(cli->inbuf,smb_prcnt);
362 if (this_data + *data_len > total_data ||
363 this_param + *param_len > total_param) {
364 DEBUG(1,("Data overflow in cli_receive_trans\n"));
369 memcpy(*data + SVAL(cli->inbuf,smb_drdisp),
370 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff),
373 memcpy(*param + SVAL(cli->inbuf,smb_prdisp),
374 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff),
376 *data_len += this_data;
377 *param_len += this_param;
379 /* parse out the total lengths again - they can shrink! */
380 total_data = SVAL(cli->inbuf,smb_tdrcnt);
381 total_param = SVAL(cli->inbuf,smb_tprcnt);
383 if (total_data <= *data_len && total_param <= *param_len)
386 if (!cli_receive_smb(cli))
390 if (CVAL(cli->inbuf,smb_com) != trans) {
391 DEBUG(0,("Expected %s response, got command 0x%02x\n",
392 trans==SMBtrans?"SMBtrans":"SMBtrans2",
393 CVAL(cli->inbuf,smb_com)));
396 if (cli_error(cli, NULL, NULL))
405 /****************************************************************************
406 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
407 ****************************************************************************/
408 BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name, int pipe_name_len,
409 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
410 char *params, uint32 param_count, uint32 max_param_count,
411 char *data, uint32 data_count, uint32 max_data_count,
412 char **rparam, uint32 *rparam_count,
413 char **rdata, uint32 *rdata_count)
415 if (pipe_name_len == 0)
416 pipe_name_len = strlen(pipe_name);
418 cli_send_trans(cli, SMBtrans,
419 pipe_name, pipe_name_len,
420 0,0, /* fid, flags */
421 setup, setup_count, max_setup_count,
422 params, param_count, max_param_count,
423 data, data_count, max_data_count);
425 return (cli_receive_trans(cli, SMBtrans,
426 rparam, (int *)rparam_count,
427 rdata, (int *)rdata_count));
430 /****************************************************************************
432 ****************************************************************************/
433 BOOL cli_api(struct cli_state *cli,
434 char *param, int prcnt, int mprcnt,
435 char *data, int drcnt, int mdrcnt,
436 char **rparam, int *rprcnt,
437 char **rdata, int *rdrcnt)
439 cli_send_trans(cli,SMBtrans,
440 PIPE_LANMAN,strlen(PIPE_LANMAN), /* Name, length */
441 0,0, /* fid, flags */
442 NULL,0,0, /* Setup, length, max */
443 param, prcnt, mprcnt, /* Params, length, max */
444 data, drcnt, mdrcnt /* Data, length, max */
447 return (cli_receive_trans(cli,SMBtrans,
453 /****************************************************************************
454 perform a NetWkstaUserLogon
455 ****************************************************************************/
456 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
464 memset(param, 0, sizeof(param));
466 /* send a SMBtrans command with api NetWkstaUserLogon */
468 SSVAL(p,0,132); /* api number */
470 pstrcpy(p,"OOWb54WrLh");
471 p = skip_string(p,1);
472 pstrcpy(p,"WB21BWDWWDDDDDDDzzzD");
473 p = skip_string(p,1);
482 pstrcpy(p, workstation);
485 SSVAL(p, 0, CLI_BUFFER_SIZE);
487 SSVAL(p, 0, CLI_BUFFER_SIZE);
491 param, PTR_DIFF(p,param),1024, /* param, length, max */
492 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
493 &rparam, &rprcnt, /* return params, return size */
494 &rdata, &rdrcnt /* return data, return size */
496 cli->rap_error = SVAL(rparam,0);
499 if (cli->rap_error == 0) {
500 DEBUG(4,("NetWkstaUserLogon success\n"));
501 cli->privilages = SVAL(p, 24);
502 fstrcpy(cli->eff_name,p+2);
504 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
512 return (cli->rap_error == 0);
515 /****************************************************************************
516 call a NetShareEnum - try and browse available connections on a host
517 ****************************************************************************/
518 BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *))
527 /* now send a SMBtrans command with api RNetShareEnum */
529 SSVAL(p,0,0); /* api number */
532 p = skip_string(p,1);
534 p = skip_string(p,1);
540 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
541 NULL, 0, 0xFFFF, /* data, length, maxlen */
542 &rparam, &rprcnt, /* return params, length */
543 &rdata, &rdrcnt)) /* return data, length */
545 int res = SVAL(rparam,0);
546 int converter=SVAL(rparam,2);
549 if (res == 0 || res == ERRmoredata) {
550 count=SVAL(rparam,4);
553 for (i=0;i<count;i++,p+=20) {
555 int type = SVAL(p,14);
556 int comment_offset = IVAL(p,16) & 0xFFFF;
557 char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
558 fn(sname, type, cmnt);
561 DEBUG(4,("NetShareEnum res=%d\n", res));
564 DEBUG(4,("NetShareEnum failed\n"));
576 /****************************************************************************
577 call a NetServerEnum for the specified workgroup and servertype mask.
578 This function then calls the specified callback function for each name returned.
580 The callback function takes 3 arguments: the machine name, the server type and
582 ****************************************************************************/
583 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
584 void (*fn)(const char *, uint32, const char *))
594 /* send a SMBtrans command with api NetServerEnum */
596 SSVAL(p,0,0x68); /* api number */
598 pstrcpy(p,"WrLehDz");
599 p = skip_string(p,1);
601 pstrcpy(p,"B16BBDz");
603 p = skip_string(p,1);
605 SSVAL(p,2,CLI_BUFFER_SIZE);
610 pstrcpy(p, workgroup);
611 p = skip_string(p,1);
614 param, PTR_DIFF(p,param), 8, /* params, length, max */
615 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
616 &rparam, &rprcnt, /* return params, return size */
617 &rdata, &rdrcnt /* return data, return size */
619 int res = SVAL(rparam,0);
620 int converter=SVAL(rparam,2);
623 if (res == 0 || res == ERRmoredata) {
624 count=SVAL(rparam,4);
627 for (i = 0;i < count;i++, p += 26) {
629 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
630 char *cmnt = comment_offset?(rdata+comment_offset):"";
631 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
633 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
635 fn(sname, stype, cmnt);
657 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
658 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
659 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
660 {PROTOCOL_LANMAN1,"LANMAN1.0"},
661 {PROTOCOL_LANMAN2,"LM1.2X002"},
662 {PROTOCOL_LANMAN2,"Samba"},
663 {PROTOCOL_NT1,"NT LANMAN 1.0"},
664 {PROTOCOL_NT1,"NT LM 0.12"},
669 /****************************************************************************
671 ****************************************************************************/
672 BOOL cli_session_setup(struct cli_state *cli,
674 char *pass, int passlen,
675 char *ntpass, int ntpasslen,
679 fstring pword, ntpword;
681 if (cli->protocol < PROTOCOL_LANMAN1)
684 if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
688 if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0')) {
689 /* Null session connect. */
693 if ((cli->sec_mode & 2) && passlen != 24) {
696 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
697 SMBNTencrypt((uchar *)ntpass,(uchar *)cli->cryptkey,(uchar *)ntpword);
699 fstrcpy(pword, pass);
700 fstrcpy(ntpword, "");
705 /* if in share level security then don't send a password now */
706 if (!(cli->sec_mode & 1)) {
709 fstrcpy(ntpword, "");
713 /* send a session setup command */
714 bzero(cli->outbuf,smb_size);
716 if (cli->protocol < PROTOCOL_NT1)
718 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
719 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
720 cli_setup_packet(cli);
722 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
723 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
724 SSVAL(cli->outbuf,smb_vwv3,2);
725 SSVAL(cli->outbuf,smb_vwv4,1);
726 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
727 SSVAL(cli->outbuf,smb_vwv7,passlen);
728 p = smb_buf(cli->outbuf);
729 memcpy(p,pword,passlen);
736 set_message(cli->outbuf,13,0,True);
737 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
738 cli_setup_packet(cli);
740 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
741 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
742 SSVAL(cli->outbuf,smb_vwv3,2);
743 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
744 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
745 SSVAL(cli->outbuf,smb_vwv7,passlen);
746 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
747 SSVAL(cli->outbuf,smb_vwv11,0);
748 p = smb_buf(cli->outbuf);
749 memcpy(p,pword,passlen);
750 p += SVAL(cli->outbuf,smb_vwv7);
751 memcpy(p,ntpword,ntpasslen);
752 p += SVAL(cli->outbuf,smb_vwv8);
755 p = skip_string(p,1);
756 pstrcpy(p,workgroup);
758 p = skip_string(p,1);
759 pstrcpy(p,"Unix");p = skip_string(p,1);
760 pstrcpy(p,"Samba");p = skip_string(p,1);
761 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
764 cli_send_smb(cli, True);
765 if (!cli_receive_smb(cli))
767 DEBUG(10,("cli_session_setup: receive smb failed\n"));
771 if (CVAL(cli->inbuf,smb_rcls) != 0) {
775 /* use the returned vuid from now on */
776 cli->vuid = SVAL(cli->inbuf,smb_uid);
778 if (cli->protocol >= PROTOCOL_NT1) {
780 * Save off some of the connected server
783 char *server_domain,*server_os,*server_type;
784 server_os = smb_buf(cli->inbuf);
785 server_type = skip_string(server_os,1);
786 server_domain = skip_string(server_type,1);
787 fstrcpy(cli->server_os, server_os);
788 fstrcpy(cli->server_type, server_type);
789 fstrcpy(cli->server_domain, server_domain);
792 fstrcpy(cli->user_name, user);
797 /****************************************************************************
799 *****************************************************************************/
801 BOOL cli_ulogoff(struct cli_state *cli)
803 bzero(cli->outbuf,smb_size);
804 set_message(cli->outbuf,2,0,True);
805 CVAL(cli->outbuf,smb_com) = SMBulogoffX;
806 cli_setup_packet(cli);
807 SSVAL(cli->outbuf,smb_vwv0,0xFF);
808 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
810 cli_send_smb(cli, True);
811 if (!cli_receive_smb(cli))
814 return CVAL(cli->inbuf,smb_rcls) == 0;
817 /****************************************************************************
819 ****************************************************************************/
820 BOOL cli_send_tconX(struct cli_state *cli,
821 char *share, char *dev, char *pass, int passlen)
823 fstring fullshare, pword;
825 bzero(cli->outbuf,smb_size);
826 bzero(cli->inbuf,smb_size);
828 fstrcpy(cli->share, share);
830 /* in user level security don't send a password now */
831 if (cli->sec_mode & 1) {
836 if ((cli->sec_mode & 2) && *pass && passlen != 24) {
838 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
840 memcpy(pword, pass, passlen);
843 slprintf(fullshare, sizeof(fullshare)-1,
844 "\\\\%s\\%s", cli->desthost, share);
847 set_message(cli->outbuf,4,
848 2 + strlen(fullshare) + passlen + strlen(dev),True);
849 CVAL(cli->outbuf,smb_com) = SMBtconX;
850 cli_setup_packet(cli);
852 SSVAL(cli->outbuf,smb_vwv0,0xFF);
853 SSVAL(cli->outbuf,smb_vwv3,passlen);
855 p = smb_buf(cli->outbuf);
856 memcpy(p,pword,passlen);
858 fstrcpy(p,fullshare);
859 p = skip_string(p,1);
862 SCVAL(cli->inbuf,smb_rcls, 1);
864 cli_send_smb(cli, True);
865 if (!cli_receive_smb(cli))
868 if (CVAL(cli->inbuf,smb_rcls) != 0) {
872 fstrcpy(cli->dev, "A:");
874 if (cli->protocol >= PROTOCOL_NT1) {
875 fstrcpy(cli->dev, smb_buf(cli->inbuf));
878 if (strcasecmp(share,"IPC$")==0) {
879 fstrcpy(cli->dev, "IPC");
882 /* only grab the device if we have a recent protocol level */
883 if (cli->protocol >= PROTOCOL_NT1 &&
884 smb_buflen(cli->inbuf) == 3) {
885 /* almost certainly win95 - enable bug fixes */
889 cli->cnum = SVAL(cli->inbuf,smb_tid);
894 /****************************************************************************
895 send a tree disconnect
896 ****************************************************************************/
897 BOOL cli_tdis(struct cli_state *cli)
899 bzero(cli->outbuf,smb_size);
900 set_message(cli->outbuf,0,0,True);
901 CVAL(cli->outbuf,smb_com) = SMBtdis;
902 SSVAL(cli->outbuf,smb_tid,cli->cnum);
903 cli_setup_packet(cli);
905 cli_send_smb(cli, True);
906 if (!cli_receive_smb(cli))
909 return CVAL(cli->inbuf,smb_rcls) == 0;
912 /****************************************************************************
914 ****************************************************************************/
915 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
919 bzero(cli->outbuf,smb_size);
920 bzero(cli->inbuf,smb_size);
922 set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
924 CVAL(cli->outbuf,smb_com) = SMBmv;
925 SSVAL(cli->outbuf,smb_tid,cli->cnum);
926 cli_setup_packet(cli);
928 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
930 p = smb_buf(cli->outbuf);
932 pstrcpy(p,fname_src);
933 p = skip_string(p,1);
935 pstrcpy(p,fname_dst);
937 cli_send_smb(cli, True);
938 if (!cli_receive_smb(cli)) {
942 if (CVAL(cli->inbuf,smb_rcls) != 0) {
949 /****************************************************************************
951 ****************************************************************************/
952 BOOL cli_unlink(struct cli_state *cli, char *fname)
956 bzero(cli->outbuf,smb_size);
957 bzero(cli->inbuf,smb_size);
959 set_message(cli->outbuf,1, 2 + strlen(fname),True);
961 CVAL(cli->outbuf,smb_com) = SMBunlink;
962 SSVAL(cli->outbuf,smb_tid,cli->cnum);
963 cli_setup_packet(cli);
965 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
967 p = smb_buf(cli->outbuf);
971 cli_send_smb(cli, True);
972 if (!cli_receive_smb(cli)) {
976 if (CVAL(cli->inbuf,smb_rcls) != 0) {
983 /****************************************************************************
985 ****************************************************************************/
986 BOOL cli_mkdir(struct cli_state *cli, char *dname)
990 bzero(cli->outbuf,smb_size);
991 bzero(cli->inbuf,smb_size);
993 set_message(cli->outbuf,0, 2 + strlen(dname),True);
995 CVAL(cli->outbuf,smb_com) = SMBmkdir;
996 SSVAL(cli->outbuf,smb_tid,cli->cnum);
997 cli_setup_packet(cli);
999 p = smb_buf(cli->outbuf);
1003 cli_send_smb(cli, True);
1004 if (!cli_receive_smb(cli)) {
1008 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1015 /****************************************************************************
1017 ****************************************************************************/
1018 BOOL cli_rmdir(struct cli_state *cli, char *dname)
1022 bzero(cli->outbuf,smb_size);
1023 bzero(cli->inbuf,smb_size);
1025 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1027 CVAL(cli->outbuf,smb_com) = SMBrmdir;
1028 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1029 cli_setup_packet(cli);
1031 p = smb_buf(cli->outbuf);
1035 cli_send_smb(cli, True);
1036 if (!cli_receive_smb(cli)) {
1040 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1049 /****************************************************************************
1051 ****************************************************************************/
1052 int cli_nt_create(struct cli_state *cli, char *fname)
1056 bzero(cli->outbuf,smb_size);
1057 bzero(cli->inbuf,smb_size);
1059 set_message(cli->outbuf,24,1 + strlen(fname),True);
1061 CVAL(cli->outbuf,smb_com) = SMBntcreateX;
1062 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1063 cli_setup_packet(cli);
1065 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1066 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0x06);
1067 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
1068 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, 0x2019f);
1069 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0);
1070 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03);
1071 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01);
1072 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0);
1073 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
1074 SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname));
1076 p = smb_buf(cli->outbuf);
1078 p = skip_string(p,1);
1080 cli_send_smb(cli, True);
1081 if (!cli_receive_smb(cli)) {
1085 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1089 return SVAL(cli->inbuf,smb_vwv2 + 1);
1093 /****************************************************************************
1095 ****************************************************************************/
1096 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
1100 unsigned accessmode=0;
1102 /* you must open for RW not just write - otherwise getattrE doesn't
1104 if ((flags & O_ACCMODE) == O_WRONLY && strncmp(cli->dev, "LPT", 3)) {
1105 flags = (flags & ~O_ACCMODE) | O_RDWR;
1108 if (flags & O_CREAT)
1110 if (!(flags & O_EXCL)) {
1111 if (flags & O_TRUNC)
1117 accessmode = (share_mode<<4);
1119 if ((flags & O_ACCMODE) == O_RDWR) {
1121 } else if ((flags & O_ACCMODE) == O_WRONLY) {
1126 if ((flags & O_SYNC) == O_SYNC) {
1127 accessmode |= (1<<14);
1131 bzero(cli->outbuf,smb_size);
1132 bzero(cli->inbuf,smb_size);
1134 set_message(cli->outbuf,15,1 + strlen(fname),True);
1136 CVAL(cli->outbuf,smb_com) = SMBopenX;
1137 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1138 cli_setup_packet(cli);
1140 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1141 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1142 SSVAL(cli->outbuf,smb_vwv3,accessmode);
1143 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1144 SSVAL(cli->outbuf,smb_vwv5,0);
1145 SSVAL(cli->outbuf,smb_vwv8,openfn);
1147 p = smb_buf(cli->outbuf);
1149 p = skip_string(p,1);
1151 cli_send_smb(cli, True);
1152 if (!cli_receive_smb(cli)) {
1156 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1160 return SVAL(cli->inbuf,smb_vwv2);
1166 /****************************************************************************
1168 ****************************************************************************/
1169 BOOL cli_close(struct cli_state *cli, int fnum)
1171 bzero(cli->outbuf,smb_size);
1172 bzero(cli->inbuf,smb_size);
1174 set_message(cli->outbuf,3,0,True);
1176 CVAL(cli->outbuf,smb_com) = SMBclose;
1177 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1178 cli_setup_packet(cli);
1180 SSVAL(cli->outbuf,smb_vwv0,fnum);
1181 SIVALS(cli->outbuf,smb_vwv1,-1);
1183 cli_send_smb(cli, True);
1184 if (!cli_receive_smb(cli)) {
1188 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1196 /****************************************************************************
1198 ****************************************************************************/
1199 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1202 int saved_timeout = cli->timeout;
1204 bzero(cli->outbuf,smb_size);
1205 bzero(cli->inbuf,smb_size);
1207 set_message(cli->outbuf,8,10,True);
1209 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1210 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1211 cli_setup_packet(cli);
1213 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1214 SSVAL(cli->outbuf,smb_vwv2,fnum);
1215 CVAL(cli->outbuf,smb_vwv3) = 0;
1216 SIVALS(cli->outbuf, smb_vwv4, timeout);
1217 SSVAL(cli->outbuf,smb_vwv6,0);
1218 SSVAL(cli->outbuf,smb_vwv7,1);
1220 p = smb_buf(cli->outbuf);
1221 SSVAL(p, 0, cli->pid);
1222 SIVAL(p, 2, offset);
1224 cli_send_smb(cli, True);
1226 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout;
1228 if (!cli_receive_smb(cli)) {
1229 cli->timeout = saved_timeout;
1233 cli->timeout = saved_timeout;
1235 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1242 /****************************************************************************
1244 ****************************************************************************/
1245 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1249 bzero(cli->outbuf,smb_size);
1250 bzero(cli->inbuf,smb_size);
1252 set_message(cli->outbuf,8,10,True);
1254 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1255 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1256 cli_setup_packet(cli);
1258 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1259 SSVAL(cli->outbuf,smb_vwv2,fnum);
1260 CVAL(cli->outbuf,smb_vwv3) = 0;
1261 SIVALS(cli->outbuf, smb_vwv4, timeout);
1262 SSVAL(cli->outbuf,smb_vwv6,1);
1263 SSVAL(cli->outbuf,smb_vwv7,0);
1265 p = smb_buf(cli->outbuf);
1266 SSVAL(p, 0, cli->pid);
1267 SIVAL(p, 2, offset);
1270 cli_send_smb(cli, True);
1271 if (!cli_receive_smb(cli)) {
1275 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1284 /****************************************************************************
1285 issue a single SMBread and don't wait for a reply
1286 ****************************************************************************/
1287 static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
1290 bzero(cli->outbuf,smb_size);
1291 bzero(cli->inbuf,smb_size);
1293 set_message(cli->outbuf,10,0,True);
1295 CVAL(cli->outbuf,smb_com) = SMBreadX;
1296 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1297 cli_setup_packet(cli);
1299 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1300 SSVAL(cli->outbuf,smb_vwv2,fnum);
1301 SIVAL(cli->outbuf,smb_vwv3,offset);
1302 SSVAL(cli->outbuf,smb_vwv5,size);
1303 SSVAL(cli->outbuf,smb_vwv6,size);
1304 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1306 cli_send_smb(cli, True);
1309 /****************************************************************************
1311 ****************************************************************************/
1312 size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
1318 int mpx = MAX(cli->max_mux-1, 1);
1319 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1321 int blocks = (size + (block-1)) / block;
1323 if (size == 0) return 0;
1325 while (received < blocks) {
1328 while (issued - received < mpx && issued < blocks) {
1329 int size1 = MIN(block, size-issued*block);
1330 cli_issue_read(cli, fnum, offset+issued*block, size1, issued);
1334 if (!cli_receive_smb(cli)) {
1339 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1340 size2 = SVAL(cli->inbuf, smb_vwv5);
1342 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1343 blocks = MIN(blocks, mid-1);
1348 blocks = MIN(blocks, mid-1);
1349 /* this distinguishes EOF from an error */
1350 total = MAX(total, 0);
1354 if (size2 > block) {
1355 DEBUG(0,("server returned more than we wanted!\n"));
1358 if (mid >= issued) {
1359 DEBUG(0,("invalid mid from server!\n"));
1362 p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
1364 memcpy(buf+mid*block, p, size2);
1366 total = MAX(total, mid*block + size2);
1369 while (received < issued) {
1370 cli_receive_smb(cli);
1378 /****************************************************************************
1379 issue a single SMBwrite and don't wait for a reply
1380 ****************************************************************************/
1381 static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf,
1386 bzero(cli->outbuf,smb_size);
1387 bzero(cli->inbuf,smb_size);
1389 set_message(cli->outbuf,12,size,True);
1391 CVAL(cli->outbuf,smb_com) = SMBwriteX;
1392 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1393 cli_setup_packet(cli);
1395 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1396 SSVAL(cli->outbuf,smb_vwv2,fnum);
1398 SIVAL(cli->outbuf,smb_vwv3,offset);
1399 SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0);
1400 SSVAL(cli->outbuf,smb_vwv7,mode);
1402 SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0);
1403 SSVAL(cli->outbuf,smb_vwv10,size);
1404 SSVAL(cli->outbuf,smb_vwv11,
1405 smb_buf(cli->outbuf) - smb_base(cli->outbuf));
1407 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
1408 memcpy(p, buf, size);
1410 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1412 cli_send_smb(cli, True);
1415 /****************************************************************************
1417 write_mode: 0x0001 disallow write cacheing
1418 0x0002 return bytes remaining
1419 0x0004 use raw named pipe protocol
1420 0x0008 start of message mode named pipe protocol
1421 ****************************************************************************/
1422 ssize_t cli_write(struct cli_state *cli,
1423 int fnum, uint16 write_mode,
1424 char *buf, off_t offset, size_t size)
1429 int mpx = MAX(cli->max_mux-1, 1);
1430 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1432 int blocks = (size + (block-1)) / block;
1434 if (size == 0) return 0;
1436 while (received < blocks) {
1439 while (issued - received < mpx && issued < blocks) {
1440 int size1 = MIN(block, size-issued*block);
1441 cli_issue_write(cli, fnum, offset+issued*block,
1448 if (!cli_receive_smb(cli)) {
1453 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1454 size2 = SVAL(cli->inbuf, smb_vwv2);
1456 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1457 blocks = MIN(blocks, mid-1);
1462 blocks = MIN(blocks, mid-1);
1463 /* this distinguishes EOF from an error */
1464 total = MAX(total, 0);
1470 total = MAX(total, mid*block + size2);
1473 while (received < issued) {
1474 cli_receive_smb(cli);
1482 /****************************************************************************
1483 do a SMBgetattrE call
1484 ****************************************************************************/
1485 BOOL cli_getattrE(struct cli_state *cli, int fd,
1486 uint16 *attr, size_t *size,
1487 time_t *c_time, time_t *a_time, time_t *m_time)
1489 bzero(cli->outbuf,smb_size);
1490 bzero(cli->inbuf,smb_size);
1492 set_message(cli->outbuf,2,0,True);
1494 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
1495 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1496 cli_setup_packet(cli);
1498 SSVAL(cli->outbuf,smb_vwv0,fd);
1500 cli_send_smb(cli, True);
1501 if (!cli_receive_smb(cli)) {
1505 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1510 *size = IVAL(cli->inbuf, smb_vwv6);
1514 *attr = SVAL(cli->inbuf,smb_vwv10);
1518 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
1522 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
1526 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
1533 /****************************************************************************
1535 ****************************************************************************/
1536 BOOL cli_getatr(struct cli_state *cli, char *fname,
1537 uint16 *attr, size_t *size, time_t *t)
1541 bzero(cli->outbuf,smb_size);
1542 bzero(cli->inbuf,smb_size);
1544 set_message(cli->outbuf,0,strlen(fname)+2,True);
1546 CVAL(cli->outbuf,smb_com) = SMBgetatr;
1547 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1548 cli_setup_packet(cli);
1550 p = smb_buf(cli->outbuf);
1552 pstrcpy(p+1, fname);
1554 cli_send_smb(cli, True);
1555 if (!cli_receive_smb(cli)) {
1559 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1564 *size = IVAL(cli->inbuf, smb_vwv3);
1568 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1572 *attr = SVAL(cli->inbuf,smb_vwv0);
1580 /****************************************************************************
1582 ****************************************************************************/
1583 BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
1587 bzero(cli->outbuf,smb_size);
1588 bzero(cli->inbuf,smb_size);
1590 set_message(cli->outbuf,8,strlen(fname)+4,True);
1592 CVAL(cli->outbuf,smb_com) = SMBsetatr;
1593 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1594 cli_setup_packet(cli);
1596 SSVAL(cli->outbuf,smb_vwv0, attr);
1597 put_dos_date3(cli->outbuf,smb_vwv1, t);
1599 p = smb_buf(cli->outbuf);
1601 pstrcpy(p+1, fname);
1602 p = skip_string(p,1);
1605 cli_send_smb(cli, True);
1606 if (!cli_receive_smb(cli)) {
1610 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1617 /****************************************************************************
1618 send a qpathinfo call
1619 ****************************************************************************/
1620 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
1621 time_t *c_time, time_t *a_time, time_t *m_time,
1622 size_t *size, uint16 *mode)
1626 uint16 setup = TRANSACT2_QPATHINFO;
1628 char *rparam=NULL, *rdata=NULL;
1631 time_t (*date_fn)(void *);
1633 param_len = strlen(fname) + 7;
1635 memset(param, 0, param_len);
1636 SSVAL(param, 0, SMB_INFO_STANDARD);
1637 pstrcpy(¶m[6], fname);
1640 ret = (cli_send_trans(cli, SMBtrans2,
1641 NULL, 0, /* Name, length */
1642 -1, 0, /* fid, flags */
1643 &setup, 1, 0, /* setup, length, max */
1644 param, param_len, 10, /* param, length, max */
1645 NULL, data_len, cli->max_xmit /* data, length, max */
1647 cli_receive_trans(cli, SMBtrans2,
1648 &rparam, ¶m_len,
1649 &rdata, &data_len));
1651 /* we need to work around a Win95 bug - sometimes
1652 it gives ERRSRV/ERRerror temprarily */
1655 cli_error(cli, &eclass, &ecode);
1656 if (eclass != ERRSRV || ecode != ERRerror) break;
1659 } while (count-- && ret==False);
1661 if (!ret || !rdata || data_len < 22) {
1666 date_fn = make_unix_date;
1668 date_fn = make_unix_date2;
1672 *c_time = date_fn(rdata+0);
1675 *a_time = date_fn(rdata+4);
1678 *m_time = date_fn(rdata+8);
1681 *size = IVAL(rdata, 12);
1684 *mode = SVAL(rdata,l1_attrFile);
1687 if (rdata) free(rdata);
1688 if (rparam) free(rparam);
1692 /****************************************************************************
1693 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1694 ****************************************************************************/
1695 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
1696 time_t *c_time, time_t *a_time, time_t *m_time,
1697 time_t *w_time, size_t *size, uint16 *mode,
1702 uint16 setup = TRANSACT2_QPATHINFO;
1704 char *rparam=NULL, *rdata=NULL;
1706 param_len = strlen(fname) + 7;
1708 memset(param, 0, param_len);
1709 SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1710 pstrcpy(¶m[6], fname);
1712 if (!cli_send_trans(cli, SMBtrans2,
1713 NULL, 0, /* name, length */
1714 -1, 0, /* fid, flags */
1715 &setup, 1, 0, /* setup, length, max */
1716 param, param_len, 10, /* param, length, max */
1717 NULL, data_len, cli->max_xmit /* data, length, max */
1722 if (!cli_receive_trans(cli, SMBtrans2,
1723 &rparam, ¶m_len,
1724 &rdata, &data_len)) {
1728 if (!rdata || data_len < 22) {
1733 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1736 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1739 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1742 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1745 *mode = SVAL(rdata, 32);
1748 *size = IVAL(rdata, 40);
1751 *ino = IVAL(rdata, 64);
1754 if (rdata) free(rdata);
1755 if (rparam) free(rparam);
1760 /****************************************************************************
1761 send a qfileinfo call
1762 ****************************************************************************/
1763 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
1764 uint16 *mode, size_t *size,
1765 time_t *c_time, time_t *a_time, time_t *m_time,
1766 time_t *w_time, SMB_INO_T *ino)
1770 uint16 setup = TRANSACT2_QFILEINFO;
1772 char *rparam=NULL, *rdata=NULL;
1774 /* if its a win95 server then fail this - win95 totally screws it
1776 if (cli->win95) return False;
1780 memset(param, 0, param_len);
1781 SSVAL(param, 0, fnum);
1782 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
1784 if (!cli_send_trans(cli, SMBtrans2,
1785 NULL, 0, /* name, length */
1786 -1, 0, /* fid, flags */
1787 &setup, 1, 0, /* setup, length, max */
1788 param, param_len, 2, /* param, length, max */
1789 NULL, data_len, cli->max_xmit /* data, length, max */
1794 if (!cli_receive_trans(cli, SMBtrans2,
1795 &rparam, ¶m_len,
1796 &rdata, &data_len)) {
1800 if (!rdata || data_len < 68) {
1805 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1808 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1811 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1814 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1817 *mode = SVAL(rdata, 32);
1820 *size = IVAL(rdata, 40);
1823 *ino = IVAL(rdata, 64);
1826 if (rdata) free(rdata);
1827 if (rparam) free(rparam);
1832 /****************************************************************************
1833 interpret a long filename structure - this is mostly guesses at the moment
1834 The length of the structure is returned
1835 The structure of a long filename depends on the info level. 260 is used
1836 by NT and 2 is used by OS/2
1837 ****************************************************************************/
1838 static int interpret_long_filename(int level,char *p,file_info *finfo)
1840 extern file_info def_finfo;
1843 memcpy(finfo,&def_finfo,sizeof(*finfo));
1847 case 1: /* OS/2 understands this */
1849 /* these dates are converted to GMT by make_unix_date */
1850 finfo->ctime = make_unix_date2(p+4);
1851 finfo->atime = make_unix_date2(p+8);
1852 finfo->mtime = make_unix_date2(p+12);
1853 finfo->size = IVAL(p,16);
1854 finfo->mode = CVAL(p,24);
1855 pstrcpy(finfo->name,p+27);
1857 return(28 + CVAL(p,26));
1859 case 2: /* this is what OS/2 uses mostly */
1861 /* these dates are converted to GMT by make_unix_date */
1862 finfo->ctime = make_unix_date2(p+4);
1863 finfo->atime = make_unix_date2(p+8);
1864 finfo->mtime = make_unix_date2(p+12);
1865 finfo->size = IVAL(p,16);
1866 finfo->mode = CVAL(p,24);
1867 pstrcpy(finfo->name,p+31);
1869 return(32 + CVAL(p,30));
1871 /* levels 3 and 4 are untested */
1874 /* these dates are probably like the other ones */
1875 finfo->ctime = make_unix_date2(p+8);
1876 finfo->atime = make_unix_date2(p+12);
1877 finfo->mtime = make_unix_date2(p+16);
1878 finfo->size = IVAL(p,20);
1879 finfo->mode = CVAL(p,28);
1880 pstrcpy(finfo->name,p+33);
1882 return(SVAL(p,4)+4);
1886 /* these dates are probably like the other ones */
1887 finfo->ctime = make_unix_date2(p+8);
1888 finfo->atime = make_unix_date2(p+12);
1889 finfo->mtime = make_unix_date2(p+16);
1890 finfo->size = IVAL(p,20);
1891 finfo->mode = CVAL(p,28);
1892 pstrcpy(finfo->name,p+37);
1894 return(SVAL(p,4)+4);
1896 case 260: /* NT uses this, but also accepts 2 */
1898 int ret = SVAL(p,0);
1900 p += 4; /* next entry offset */
1901 p += 4; /* fileindex */
1903 /* these dates appear to arrive in a
1904 weird way. It seems to be localtime
1905 plus the serverzone given in the
1906 initial connect. This is GMT when
1907 DST is not in effect and one hour
1908 from GMT otherwise. Can this really
1911 I suppose this could be called
1912 kludge-GMT. Is is the GMT you get
1913 by using the current DST setting on
1914 a different localtime. It will be
1915 cheap to calculate, I suppose, as
1916 no DST tables will be needed */
1918 finfo->ctime = interpret_long_date(p); p += 8;
1919 finfo->atime = interpret_long_date(p); p += 8;
1920 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
1921 finfo->size = IVAL(p,0); p += 8;
1922 p += 8; /* alloc size */
1923 finfo->mode = CVAL(p,0); p += 4;
1924 namelen = IVAL(p,0); p += 4;
1925 p += 4; /* EA size */
1926 p += 2; /* short name len? */
1927 p += 24; /* short name? */
1928 StrnCpy(finfo->name,p,namelen);
1934 DEBUG(1,("Unknown long filename format %d\n",level));
1939 /****************************************************************************
1940 do a directory listing, calling fn on each file found
1941 ****************************************************************************/
1942 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
1943 void (*fn)(file_info *, const char *))
1945 int max_matches = 512;
1946 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1947 int info_level = cli->protocol<PROTOCOL_NT1?1:260;
1952 char *dirlist = NULL;
1953 int dirlist_len = 0;
1954 int total_received = -1;
1956 int ff_resume_key = 0;
1957 int ff_searchcount=0;
1960 int ff_dir_handle=0;
1962 char *rparam=NULL, *rdata=NULL;
1963 int param_len, data_len;
1970 while (ff_eos == 0) {
1972 if (loop_count > 200) {
1973 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
1977 param_len = 12+strlen(mask)+1;
1980 setup = TRANSACT2_FINDFIRST;
1981 SSVAL(param,0,attribute); /* attribute */
1982 SSVAL(param,2,max_matches); /* max count */
1983 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
1984 SSVAL(param,6,info_level);
1986 pstrcpy(param+12,mask);
1988 setup = TRANSACT2_FINDNEXT;
1989 SSVAL(param,0,ff_dir_handle);
1990 SSVAL(param,2,max_matches); /* max count */
1991 SSVAL(param,4,info_level);
1992 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
1993 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
1994 pstrcpy(param+12,mask);
1996 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
1997 ff_dir_handle,ff_resume_key,ff_lastname,mask));
2000 if (!cli_send_trans(cli, SMBtrans2,
2001 NULL, 0, /* Name, length */
2002 -1, 0, /* fid, flags */
2003 &setup, 1, 0, /* setup, length, max */
2004 param, param_len, 10, /* param, length, max */
2006 cli->max_xmit /* data, length, max */
2011 if (!cli_receive_trans(cli, SMBtrans2,
2012 &rparam, ¶m_len,
2013 &rdata, &data_len)) {
2014 /* we need to work around a Win95 bug - sometimes
2015 it gives ERRSRV/ERRerror temprarily */
2018 cli_error(cli, &eclass, &ecode);
2019 if (eclass != ERRSRV || ecode != ERRerror) break;
2024 if (total_received == -1) total_received = 0;
2026 /* parse out some important return info */
2029 ff_dir_handle = SVAL(p,0);
2030 ff_searchcount = SVAL(p,2);
2032 ff_lastname = SVAL(p,8);
2034 ff_searchcount = SVAL(p,0);
2036 ff_lastname = SVAL(p,6);
2039 if (ff_searchcount == 0)
2042 /* point to the data bytes */
2045 /* we might need the lastname for continuations */
2046 if (ff_lastname > 0) {
2051 StrnCpy(mask,p+ff_lastname,
2052 data_len-ff_lastname);
2055 pstrcpy(mask,p + ff_lastname + 1);
2063 /* and add them to the dirlist pool */
2064 dirlist = Realloc(dirlist,dirlist_len + data_len);
2067 DEBUG(0,("Failed to expand dirlist\n"));
2071 /* put in a length for the last entry, to ensure we can chain entries
2072 into the next packet */
2073 for (p2=p,i=0;i<(ff_searchcount-1);i++)
2074 p2 += interpret_long_filename(info_level,p2,NULL);
2075 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
2077 /* grab the data for later use */
2078 memcpy(dirlist+dirlist_len,p,data_len);
2079 dirlist_len += data_len;
2081 total_received += ff_searchcount;
2083 if (rdata) free(rdata); rdata = NULL;
2084 if (rparam) free(rparam); rparam = NULL;
2086 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
2087 ff_searchcount,ff_eos,ff_resume_key));
2092 for (p=dirlist,i=0;i<total_received;i++) {
2093 p += interpret_long_filename(info_level,p,&finfo);
2097 /* free up the dirlist buffer */
2098 if (dirlist) free(dirlist);
2099 return(total_received);
2103 /****************************************************************************
2104 Send a SamOEMChangePassword command
2105 ****************************************************************************/
2107 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
2108 const char *old_password)
2110 char param[16+sizeof(fstring)];
2113 fstring upper_case_old_pw;
2114 fstring upper_case_new_pw;
2115 unsigned char old_pw_hash[16];
2116 unsigned char new_pw_hash[16];
2119 char *rparam = NULL;
2123 if (strlen(user) >= sizeof(fstring)-1) {
2124 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
2128 SSVAL(p,0,214); /* SamOEMChangePassword command. */
2131 p = skip_string(p,1);
2132 pstrcpy(p, "B516B16");
2133 p = skip_string(p,1);
2135 p = skip_string(p,1);
2139 param_len = PTR_DIFF(p,param);
2142 * Get the Lanman hash of the old password, we
2143 * use this as the key to make_oem_passwd_hash().
2145 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
2146 fstrcpy(upper_case_old_pw, old_password);
2147 strupper(upper_case_old_pw);
2148 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
2150 if (!make_oem_passwd_hash( data, new_password, old_pw_hash, False))
2156 * Now place the old password hash in the data.
2158 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
2159 fstrcpy(upper_case_new_pw, new_password);
2160 strupper(upper_case_new_pw);
2162 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
2164 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
2168 if (!cli_send_trans(cli,SMBtrans,
2169 PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */
2170 0,0, /* fid, flags */
2171 NULL,0,0, /* setup, length, max */
2172 param,param_len,2, /* param, length, max */
2173 data,data_len,0 /* data, length, max */
2176 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
2181 if (cli_receive_trans(cli,SMBtrans,
2185 cli->rap_error = SVAL(rparam,0);
2193 return (cli->rap_error == 0);
2196 /****************************************************************************
2197 send a negprot command
2198 ****************************************************************************/
2199 BOOL cli_negprot(struct cli_state *cli)
2205 bzero(cli->outbuf,smb_size);
2207 /* setup the protocol strings */
2208 for (plength=0,numprots=0;
2209 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2211 plength += strlen(prots[numprots].name)+2;
2213 set_message(cli->outbuf,0,plength,True);
2215 p = smb_buf(cli->outbuf);
2217 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2220 pstrcpy(p,prots[numprots].name);
2224 CVAL(cli->outbuf,smb_com) = SMBnegprot;
2225 cli_setup_packet(cli);
2227 CVAL(smb_buf(cli->outbuf),0) = 2;
2229 cli_send_smb(cli, True);
2230 if (!cli_receive_smb(cli))
2235 if (CVAL(cli->inbuf,smb_rcls) != 0 ||
2236 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
2240 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
2243 if (cli->protocol >= PROTOCOL_NT1) {
2245 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
2246 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
2247 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
2248 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
2249 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
2250 /* this time arrives in real GMT */
2251 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
2252 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2253 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
2254 if (cli->capabilities & 1) {
2255 cli->readbraw_supported = True;
2256 cli->writebraw_supported = True;
2258 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2259 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
2260 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
2261 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
2262 cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
2263 /* this time is converted to GMT by make_unix_date */
2264 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
2265 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
2266 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
2267 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2269 /* the old core protocol */
2271 cli->serverzone = TimeDiff(time(NULL));
2274 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2280 /****************************************************************************
2281 send a session request. see rfc1002.txt 4.3 and 4.3.2
2282 ****************************************************************************/
2283 BOOL cli_session_request(struct cli_state *cli,
2284 struct nmb_name *calling, struct nmb_name *called)
2288 /* send a session request (RFC 1002) */
2290 memcpy(&(cli->calling), calling, sizeof(*calling));
2291 memcpy(&(cli->called ), called , sizeof(*called ));
2293 /* put in the destination name */
2294 p = cli->outbuf+len;
2295 name_mangle(cli->called .name, p, cli->called .name_type);
2299 p = cli->outbuf+len;
2300 name_mangle(cli->calling.name, p, cli->calling.name_type);
2303 /* setup the packet length */
2304 _smb_setlen(cli->outbuf,len);
2305 CVAL(cli->outbuf,0) = 0x81;
2309 #endif /* WITH_SSL */
2311 cli_send_smb(cli, False);
2312 DEBUG(5,("Sent session request\n"));
2314 if (!cli_receive_smb(cli))
2318 if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
2319 if (!sslutil_fd_is_ssl(cli->fd)){
2320 if (sslutil_connect(cli->fd) == 0)
2324 #endif /* WITH_SSL */
2326 if (CVAL(cli->inbuf,0) != 0x82) {
2327 /* This is the wrong place to put the error... JRA. */
2328 cli->rap_error = CVAL(cli->inbuf,0);
2335 /****************************************************************************
2336 open the client sockets
2337 ****************************************************************************/
2338 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
2340 extern struct in_addr ipzero;
2342 fstrcpy(cli->desthost, host);
2344 if (!ip || ip_equal(*ip, ipzero)) {
2345 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
2348 if (ip) *ip = cli->dest_ip;
2354 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2363 /****************************************************************************
2364 initialise a client structure
2365 ****************************************************************************/
2366 struct cli_state *cli_initialise(struct cli_state *cli)
2369 cli = (struct cli_state *)malloc(sizeof(*cli));
2375 if (cli->initialised) {
2383 cli->pid = (uint16)getpid();
2385 cli->vuid = UID_FIELD_INVALID;
2386 cli->protocol = PROTOCOL_NT1;
2387 cli->timeout = 20000;
2388 cli->bufsize = CLI_BUFFER_SIZE+4;
2389 cli->max_xmit = cli->bufsize;
2390 cli->outbuf = (char *)malloc(cli->bufsize);
2391 cli->inbuf = (char *)malloc(cli->bufsize);
2392 if (!cli->outbuf || !cli->inbuf)
2397 cli->initialised = 1;
2402 /****************************************************************************
2403 shutdown a client structure
2404 ****************************************************************************/
2405 void cli_shutdown(struct cli_state *cli)
2407 DEBUG(10,("cli_shutdown\n"));
2418 sslutil_disconnect(cli->fd);
2419 #endif /* WITH_SSL */
2424 memset(cli, 0, sizeof(*cli));
2428 /****************************************************************************
2429 return error codes for the last packet
2430 returns 0 if there was no error and the best approx of a unix errno
2433 for 32 bit "warnings", a return code of 0 is expected.
2435 ****************************************************************************/
2436 int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
2442 if (!cli->initialised)
2444 DEBUG(0,("cli_error: client state uninitialised!\n"));
2448 flgs2 = SVAL(cli->inbuf,smb_flg2);
2450 if (eclass) *eclass = 0;
2453 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
2454 /* 32 bit error codes detected */
2455 uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
2456 if (num) *num = nt_err;
2457 DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
2458 if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0;
2460 switch (nt_err & 0xFFFFFF) {
2461 case NT_STATUS_ACCESS_VIOLATION: return EACCES;
2462 case NT_STATUS_NO_SUCH_FILE: return ENOENT;
2463 case NT_STATUS_NO_SUCH_DEVICE: return ENODEV;
2464 case NT_STATUS_INVALID_HANDLE: return EBADF;
2465 case NT_STATUS_NO_MEMORY: return ENOMEM;
2466 case NT_STATUS_ACCESS_DENIED: return EACCES;
2467 case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
2468 case NT_STATUS_SHARING_VIOLATION: return EBUSY;
2469 case NT_STATUS_OBJECT_PATH_INVALID: return ENOTDIR;
2470 case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
2473 /* for all other cases - a default code */
2477 rcls = CVAL(cli->inbuf,smb_rcls);
2478 code = SVAL(cli->inbuf,smb_err);
2479 if (rcls == 0) return 0;
2481 if (eclass) *eclass = rcls;
2482 if (num ) *num = code;
2484 if (rcls == ERRDOS) {
2486 case ERRbadfile: return ENOENT;
2487 case ERRbadpath: return ENOTDIR;
2488 case ERRnoaccess: return EACCES;
2489 case ERRfilexists: return EEXIST;
2490 case ERRrename: return EEXIST;
2491 case ERRbadshare: return EBUSY;
2492 case ERRlock: return EBUSY;
2495 if (rcls == ERRSRV) {
2497 case ERRbadpw: return EPERM;
2498 case ERRaccess: return EACCES;
2499 case ERRnoresource: return ENOMEM;
2500 case ERRinvdevice: return ENODEV;
2501 case ERRinvnetname: return ENODEV;
2504 /* for other cases */
2508 /****************************************************************************
2509 set socket options on a open connection
2510 ****************************************************************************/
2511 void cli_sockopt(struct cli_state *cli, char *options)
2513 set_socket_options(cli->fd, options);
2516 /****************************************************************************
2517 set the PID to use for smb messages. Return the old pid.
2518 ****************************************************************************/
2519 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
2521 uint16 ret = cli->pid;
2526 /****************************************************************************
2527 re-establishes a connection
2528 ****************************************************************************/
2529 BOOL cli_reestablish_connection(struct cli_state *cli)
2531 struct nmb_name calling;
2532 struct nmb_name called;
2536 BOOL do_tcon = False;
2537 int oldfd = cli->fd;
2539 if (!cli->initialised || cli->fd == -1)
2541 DEBUG(3,("cli_reestablish_connection: not connected\n"));
2545 /* copy the parameters necessary to re-establish the connection */
2549 fstrcpy(share, cli->share);
2550 fstrcpy(dev , cli->dev);
2554 memcpy(&called , &(cli->called ), sizeof(called ));
2555 memcpy(&calling, &(cli->calling), sizeof(calling));
2556 fstrcpy(dest_host, cli->full_dest_host_name);
2558 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2559 nmb_namestr(&calling), nmb_namestr(&called),
2560 inet_ntoa(cli->dest_ip),
2561 cli->user_name, cli->domain));
2565 if (cli_establish_connection(cli,
2566 dest_host, &cli->dest_ip,
2568 share, dev, False, do_tcon)) {
2569 if (cli->fd != oldfd) {
2570 if (dup2(cli->fd, oldfd) == oldfd) {
2579 /****************************************************************************
2580 establishes a connection right up to doing tconX, reading in a password.
2581 ****************************************************************************/
2582 BOOL cli_establish_connection(struct cli_state *cli,
2583 char *dest_host, struct in_addr *dest_ip,
2584 struct nmb_name *calling, struct nmb_name *called,
2585 char *service, char *service_type,
2586 BOOL do_shutdown, BOOL do_tcon)
2588 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
2589 nmb_namestr(calling), nmb_namestr(called), inet_ntoa(*dest_ip),
2590 cli->user_name, cli->domain));
2592 /* establish connection */
2594 if ((!cli->initialised))
2601 if (!cli_connect(cli, dest_host, dest_ip))
2603 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
2604 nmb_namestr(calling), inet_ntoa(*dest_ip)));
2609 if (!cli_session_request(cli, calling, called))
2611 DEBUG(1,("failed session request\n"));
2617 if (!cli_negprot(cli))
2619 DEBUG(1,("failed negprot\n"));
2625 if (cli->pwd.cleartext || cli->pwd.null_pwd)
2630 if (cli->pwd.null_pwd)
2632 /* attempt null session */
2638 /* attempt clear-text session */
2639 pwd_get_cleartext(&(cli->pwd), passwd);
2640 pass_len = strlen(passwd);
2643 /* attempt clear-text session */
2644 if (!cli_session_setup(cli, cli->user_name,
2649 DEBUG(1,("failed session setup\n"));
2658 if (!cli_send_tconX(cli, service, service_type,
2659 (char*)passwd, strlen(passwd)))
2661 DEBUG(1,("failed tcon_X\n"));
2672 /* attempt encrypted session */
2673 unsigned char nt_sess_pwd[24];
2674 unsigned char lm_sess_pwd[24];
2676 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
2677 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
2678 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
2680 /* attempt encrypted session */
2681 if (!cli_session_setup(cli, cli->user_name,
2682 (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
2683 (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
2686 DEBUG(1,("failed session setup\n"));
2696 if (!cli_send_tconX(cli, service, service_type,
2697 (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
2699 DEBUG(1,("failed tcon_X\n"));
2718 /****************************************************************************
2719 connect to one of multiple servers: don't care which
2720 ****************************************************************************/
2721 BOOL cli_connect_serverlist(struct cli_state *cli, char *p)
2723 extern pstring global_myname;
2724 extern pstring scope;
2725 fstring remote_machine;
2726 struct in_addr dest_ip;
2727 struct nmb_name calling, called;
2728 BOOL connected_ok = False;
2732 if (!cli_initialise(cli))
2734 DEBUG(0,("cli_connect_serverlist: unable to initialize client connection.\n"));
2739 * Treat each name in the 'password server =' line as a potential
2740 * PDC/BDC. Contact each in turn and try and authenticate.
2743 while(p && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine)))
2745 standard_sub_basic(remote_machine);
2746 strupper(remote_machine);
2748 if (!resolve_name( remote_machine, &dest_ip, 0x20))
2750 DEBUG(1,("cli_connect_serverlist: Can't resolve address for %s\n", remote_machine));
2754 if (ismyip(dest_ip))
2756 DEBUG(1,("cli_connect_serverlist: Password server loop - not using password server %s\n", remote_machine));
2760 make_nmb_name(&calling, global_myname , 0x0 , scope);
2761 make_nmb_name(&called , remote_machine, 0x20, scope);
2763 pwd_set_nullpwd(&cli->pwd);
2765 if (!cli_establish_connection(cli, remote_machine, &dest_ip,
2774 if (!IS_BITS_SET_ALL(cli->sec_mode, 1))
2776 DEBUG(1,("cli_connect_serverlist: machine %s isn't in user level security mode\n",
2783 * We have an anonymous connection to IPC$.
2786 connected_ok = True;
2792 DEBUG(0,("cli_connect_serverlist: Domain password server not available.\n"));
2796 return connected_ok;
2799 /****************************************************************************
2801 ****************************************************************************/
2802 int cli_printjob_del(struct cli_state *cli, int job)
2804 char *rparam = NULL;
2807 int rdrcnt,rprcnt, ret = -1;
2810 bzero(param,sizeof(param));
2813 SSVAL(p,0,81); /* DosPrintJobDel() */
2816 p = skip_string(p,1);
2818 p = skip_string(p,1);
2823 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2824 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2825 &rparam, &rprcnt, /* return params, length */
2826 &rdata, &rdrcnt)) { /* return data, length */
2827 ret = SVAL(rparam,0);
2830 if (rparam) free(rparam);
2831 if (rdata) free(rdata);
2837 /****************************************************************************
2838 call fn() on each entry in a print queue
2839 ****************************************************************************/
2840 int cli_print_queue(struct cli_state *cli,
2841 void (*fn)(struct print_job_info *))
2843 char *rparam = NULL;
2851 bzero(param,sizeof(param));
2854 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2856 pstrcpy(p,"zWrLeh"); /* parameter description? */
2857 p = skip_string(p,1);
2858 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
2859 p = skip_string(p,1);
2860 pstrcpy(p,cli->share); /* name of queue */
2861 p = skip_string(p,1);
2862 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2863 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2865 pstrcpy(p,""); /* subformat */
2866 p = skip_string(p,1);
2868 DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
2871 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2872 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2873 &rparam, &rprcnt, /* return params, length */
2874 &rdata, &rdrcnt)) { /* return data, length */
2876 result_code = SVAL(rparam,0);
2877 converter = SVAL(rparam,2); /* conversion factor */
2879 if (result_code == 0) {
2880 struct print_job_info job;
2884 for (i = 0; i < SVAL(rparam,4); ++i) {
2886 job.priority = SVAL(p,2);
2888 fix_char_ptr(SVAL(p,4), converter,
2890 job.t = make_unix_date3(p + 12);
2891 job.size = IVAL(p,16);
2892 fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
2901 /* If any parameters or data were returned, free the storage. */
2902 if(rparam) free(rparam);
2903 if(rdata) free(rdata);
2908 /****************************************************************************
2909 check for existance of a dir
2910 ****************************************************************************/
2911 BOOL cli_chkpath(struct cli_state *cli, char *path)
2916 fstrcpy(path2,path);
2917 trim_string(path2,NULL,"\\");
2918 if (!*path2) *path2 = '\\';
2920 bzero(cli->outbuf,smb_size);
2921 set_message(cli->outbuf,0,4 + strlen(path2),True);
2922 SCVAL(cli->outbuf,smb_com,SMBchkpth);
2923 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2924 cli_setup_packet(cli);
2926 p = smb_buf(cli->outbuf);
2930 cli_send_smb(cli, True);
2931 if (!cli_receive_smb(cli)) {
2935 if (cli_error(cli, NULL, NULL)) return False;
2941 /****************************************************************************
2942 start a message sequence
2943 ****************************************************************************/
2944 BOOL cli_message_start(struct cli_state *cli, char *host, char *username,
2949 /* send a SMBsendstrt command */
2950 bzero(cli->outbuf,smb_size);
2951 set_message(cli->outbuf,0,0,True);
2952 CVAL(cli->outbuf,smb_com) = SMBsendstrt;
2953 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2954 cli_setup_packet(cli);
2956 p = smb_buf(cli->outbuf);
2958 pstrcpy(p,username);
2959 p = skip_string(p,1);
2962 p = skip_string(p,1);
2964 set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
2966 cli_send_smb(cli, True);
2968 if (!cli_receive_smb(cli)) {
2972 if (cli_error(cli, NULL, NULL)) return False;
2974 *grp = SVAL(cli->inbuf,smb_vwv0);
2980 /****************************************************************************
2982 ****************************************************************************/
2983 BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp)
2987 bzero(cli->outbuf,smb_size);
2988 set_message(cli->outbuf,1,len+3,True);
2989 CVAL(cli->outbuf,smb_com) = SMBsendtxt;
2990 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2991 cli_setup_packet(cli);
2993 SSVAL(cli->outbuf,smb_vwv0,grp);
2995 p = smb_buf(cli->outbuf);
2998 memcpy(p+3,msg,len);
2999 cli_send_smb(cli, True);
3001 if (!cli_receive_smb(cli)) {
3005 if (cli_error(cli, NULL, NULL)) return False;
3010 /****************************************************************************
3012 ****************************************************************************/
3013 BOOL cli_message_end(struct cli_state *cli, int grp)
3015 bzero(cli->outbuf,smb_size);
3016 set_message(cli->outbuf,1,0,True);
3017 CVAL(cli->outbuf,smb_com) = SMBsendend;
3018 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3020 SSVAL(cli->outbuf,smb_vwv0,grp);
3022 cli_setup_packet(cli);
3024 cli_send_smb(cli, True);
3026 if (!cli_receive_smb(cli)) {
3030 if (cli_error(cli, NULL, NULL)) return False;
3036 /****************************************************************************
3038 ****************************************************************************/
3039 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3041 bzero(cli->outbuf,smb_size);
3042 set_message(cli->outbuf,0,0,True);
3043 CVAL(cli->outbuf,smb_com) = SMBdskattr;
3044 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3045 cli_setup_packet(cli);
3047 cli_send_smb(cli, True);
3048 if (!cli_receive_smb(cli)) {
3052 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
3053 *total = SVAL(cli->inbuf,smb_vwv0);
3054 *avail = SVAL(cli->inbuf,smb_vwv3);