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;
334 *data_len = *param_len = 0;
336 if (!cli_receive_smb(cli))
340 if (CVAL(cli->inbuf,smb_com) != trans) {
341 DEBUG(0,("Expected %s response, got command 0x%02x\n",
342 trans==SMBtrans?"SMBtrans":"SMBtrans2",
343 CVAL(cli->inbuf,smb_com)));
347 /* DOS error "more data" is an acceptable error code */
348 if (cli_error(cli, &eclass, &num) && !(eclass == ERRDOS && num == ERRmoredata))
353 /* parse out the lengths */
354 total_data = SVAL(cli->inbuf,smb_tdrcnt);
355 total_param = SVAL(cli->inbuf,smb_tprcnt);
358 *data = Realloc(*data,total_data);
359 *param = Realloc(*param,total_param);
362 this_data = SVAL(cli->inbuf,smb_drcnt);
363 this_param = SVAL(cli->inbuf,smb_prcnt);
365 if (this_data + *data_len > total_data ||
366 this_param + *param_len > total_param) {
367 DEBUG(1,("Data overflow in cli_receive_trans\n"));
372 memcpy(*data + SVAL(cli->inbuf,smb_drdisp),
373 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff),
376 memcpy(*param + SVAL(cli->inbuf,smb_prdisp),
377 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff),
379 *data_len += this_data;
380 *param_len += this_param;
382 /* parse out the total lengths again - they can shrink! */
383 total_data = SVAL(cli->inbuf,smb_tdrcnt);
384 total_param = SVAL(cli->inbuf,smb_tprcnt);
386 if (total_data <= *data_len && total_param <= *param_len)
389 if (!cli_receive_smb(cli))
393 if (CVAL(cli->inbuf,smb_com) != trans) {
394 DEBUG(0,("Expected %s response, got command 0x%02x\n",
395 trans==SMBtrans?"SMBtrans":"SMBtrans2",
396 CVAL(cli->inbuf,smb_com)));
399 /* DOS error "more data" is an acceptable error code */
400 if (cli_error(cli, &eclass, &num) && eclass != ERRDOS && num != ERRmoredata)
409 /****************************************************************************
410 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
411 ****************************************************************************/
412 BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name, int pipe_name_len,
413 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
414 char *params, uint32 param_count, uint32 max_param_count,
415 char *data, uint32 data_count, uint32 max_data_count,
416 char **rparam, uint32 *rparam_count,
417 char **rdata, uint32 *rdata_count)
419 if (pipe_name_len == 0)
420 pipe_name_len = strlen(pipe_name);
422 cli_send_trans(cli, SMBtrans,
423 pipe_name, pipe_name_len,
424 0,0, /* fid, flags */
425 setup, setup_count, max_setup_count,
426 params, param_count, max_param_count,
427 data, data_count, max_data_count);
429 return (cli_receive_trans(cli, SMBtrans,
430 rparam, (int *)rparam_count,
431 rdata, (int *)rdata_count));
434 /****************************************************************************
436 ****************************************************************************/
437 BOOL cli_api(struct cli_state *cli,
438 char *param, int prcnt, int mprcnt,
439 char *data, int drcnt, int mdrcnt,
440 char **rparam, int *rprcnt,
441 char **rdata, int *rdrcnt)
443 cli_send_trans(cli,SMBtrans,
444 PIPE_LANMAN,strlen(PIPE_LANMAN), /* Name, length */
445 0,0, /* fid, flags */
446 NULL,0,0, /* Setup, length, max */
447 param, prcnt, mprcnt, /* Params, length, max */
448 data, drcnt, mdrcnt /* Data, length, max */
451 return (cli_receive_trans(cli,SMBtrans,
457 /****************************************************************************
458 perform a NetWkstaUserLogon
459 ****************************************************************************/
460 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
468 memset(param, 0, sizeof(param));
470 /* send a SMBtrans command with api NetWkstaUserLogon */
472 SSVAL(p,0,132); /* api number */
474 pstrcpy(p,"OOWb54WrLh");
475 p = skip_string(p,1);
476 pstrcpy(p,"WB21BWDWWDDDDDDDzzzD");
477 p = skip_string(p,1);
486 pstrcpy(p, workstation);
489 SSVAL(p, 0, CLI_BUFFER_SIZE);
491 SSVAL(p, 0, CLI_BUFFER_SIZE);
495 param, PTR_DIFF(p,param),1024, /* param, length, max */
496 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
497 &rparam, &rprcnt, /* return params, return size */
498 &rdata, &rdrcnt /* return data, return size */
500 cli->rap_error = SVAL(rparam,0);
503 if (cli->rap_error == 0) {
504 DEBUG(4,("NetWkstaUserLogon success\n"));
505 cli->privilages = SVAL(p, 24);
506 fstrcpy(cli->eff_name,p+2);
508 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
516 return (cli->rap_error == 0);
519 /****************************************************************************
520 call a NetShareEnum - try and browse available connections on a host
521 ****************************************************************************/
522 BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *))
531 /* now send a SMBtrans command with api RNetShareEnum */
533 SSVAL(p,0,0); /* api number */
536 p = skip_string(p,1);
538 p = skip_string(p,1);
544 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
545 NULL, 0, 0xFFFF, /* data, length, maxlen */
546 &rparam, &rprcnt, /* return params, length */
547 &rdata, &rdrcnt)) /* return data, length */
549 int res = SVAL(rparam,0);
550 int converter=SVAL(rparam,2);
553 if (res == 0 || res == ERRmoredata) {
554 count=SVAL(rparam,4);
557 for (i=0;i<count;i++,p+=20) {
559 int type = SVAL(p,14);
560 int comment_offset = IVAL(p,16) & 0xFFFF;
561 char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
562 fn(sname, type, cmnt);
565 DEBUG(4,("NetShareEnum res=%d\n", res));
568 DEBUG(4,("NetShareEnum failed\n"));
580 /****************************************************************************
581 call a NetServerEnum for the specified workgroup and servertype mask.
582 This function then calls the specified callback function for each name returned.
584 The callback function takes 3 arguments: the machine name, the server type and
586 ****************************************************************************/
587 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
588 void (*fn)(const char *, uint32, const char *))
598 /* send a SMBtrans command with api NetServerEnum */
600 SSVAL(p,0,0x68); /* api number */
602 pstrcpy(p,"WrLehDz");
603 p = skip_string(p,1);
605 pstrcpy(p,"B16BBDz");
607 p = skip_string(p,1);
609 SSVAL(p,2,CLI_BUFFER_SIZE);
614 pstrcpy(p, workgroup);
615 p = skip_string(p,1);
618 param, PTR_DIFF(p,param), 8, /* params, length, max */
619 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
620 &rparam, &rprcnt, /* return params, return size */
621 &rdata, &rdrcnt /* return data, return size */
623 int res = SVAL(rparam,0);
624 int converter=SVAL(rparam,2);
627 if (res == 0 || res == ERRmoredata) {
628 count=SVAL(rparam,4);
631 for (i = 0;i < count;i++, p += 26) {
633 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
634 char *cmnt = comment_offset?(rdata+comment_offset):"";
635 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
637 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
639 fn(sname, stype, cmnt);
661 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
662 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
663 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
664 {PROTOCOL_LANMAN1,"LANMAN1.0"},
665 {PROTOCOL_LANMAN2,"LM1.2X002"},
666 {PROTOCOL_LANMAN2,"Samba"},
667 {PROTOCOL_NT1,"NT LANMAN 1.0"},
668 {PROTOCOL_NT1,"NT LM 0.12"},
673 /****************************************************************************
675 ****************************************************************************/
676 BOOL cli_session_setup(struct cli_state *cli,
678 char *pass, int passlen,
679 char *ntpass, int ntpasslen,
683 fstring pword, ntpword;
685 if (cli->protocol < PROTOCOL_LANMAN1)
688 if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
692 if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0')) {
693 /* Null session connect. */
697 if ((cli->sec_mode & 2) && passlen != 24) {
700 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
701 SMBNTencrypt((uchar *)ntpass,(uchar *)cli->cryptkey,(uchar *)ntpword);
703 fstrcpy(pword, pass);
704 fstrcpy(ntpword, "");
709 /* if in share level security then don't send a password now */
710 if (!(cli->sec_mode & 1)) {
713 fstrcpy(ntpword, "");
717 /* send a session setup command */
718 bzero(cli->outbuf,smb_size);
720 if (cli->protocol < PROTOCOL_NT1)
722 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
723 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
724 cli_setup_packet(cli);
726 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
727 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
728 SSVAL(cli->outbuf,smb_vwv3,2);
729 SSVAL(cli->outbuf,smb_vwv4,1);
730 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
731 SSVAL(cli->outbuf,smb_vwv7,passlen);
732 p = smb_buf(cli->outbuf);
733 memcpy(p,pword,passlen);
740 set_message(cli->outbuf,13,0,True);
741 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
742 cli_setup_packet(cli);
744 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
745 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
746 SSVAL(cli->outbuf,smb_vwv3,2);
747 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
748 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
749 SSVAL(cli->outbuf,smb_vwv7,passlen);
750 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
751 SSVAL(cli->outbuf,smb_vwv11,0);
752 p = smb_buf(cli->outbuf);
753 memcpy(p,pword,passlen);
754 p += SVAL(cli->outbuf,smb_vwv7);
755 memcpy(p,ntpword,ntpasslen);
756 p += SVAL(cli->outbuf,smb_vwv8);
759 p = skip_string(p,1);
760 pstrcpy(p,workgroup);
762 p = skip_string(p,1);
763 pstrcpy(p,"Unix");p = skip_string(p,1);
764 pstrcpy(p,"Samba");p = skip_string(p,1);
765 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
768 cli_send_smb(cli, True);
769 if (!cli_receive_smb(cli))
771 DEBUG(10,("cli_session_setup: receive smb failed\n"));
775 if (CVAL(cli->inbuf,smb_rcls) != 0) {
779 /* use the returned vuid from now on */
780 cli->vuid = SVAL(cli->inbuf,smb_uid);
782 if (cli->protocol >= PROTOCOL_NT1) {
784 * Save off some of the connected server
787 char *server_domain,*server_os,*server_type;
788 server_os = smb_buf(cli->inbuf);
789 server_type = skip_string(server_os,1);
790 server_domain = skip_string(server_type,1);
791 fstrcpy(cli->server_os, server_os);
792 fstrcpy(cli->server_type, server_type);
793 fstrcpy(cli->server_domain, server_domain);
796 fstrcpy(cli->user_name, user);
801 /****************************************************************************
803 *****************************************************************************/
805 BOOL cli_ulogoff(struct cli_state *cli)
807 bzero(cli->outbuf,smb_size);
808 set_message(cli->outbuf,2,0,True);
809 CVAL(cli->outbuf,smb_com) = SMBulogoffX;
810 cli_setup_packet(cli);
811 SSVAL(cli->outbuf,smb_vwv0,0xFF);
812 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
814 cli_send_smb(cli, True);
815 if (!cli_receive_smb(cli))
818 return CVAL(cli->inbuf,smb_rcls) == 0;
821 /****************************************************************************
823 ****************************************************************************/
824 BOOL cli_send_tconX(struct cli_state *cli,
825 char *share, char *dev, char *pass, int passlen)
827 fstring fullshare, pword;
829 bzero(cli->outbuf,smb_size);
830 bzero(cli->inbuf,smb_size);
832 fstrcpy(cli->share, share);
834 /* in user level security don't send a password now */
835 if (cli->sec_mode & 1) {
840 if ((cli->sec_mode & 2) && *pass && passlen != 24) {
842 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
844 memcpy(pword, pass, passlen);
847 slprintf(fullshare, sizeof(fullshare)-1,
848 "\\\\%s\\%s", cli->desthost, share);
851 set_message(cli->outbuf,4,
852 2 + strlen(fullshare) + passlen + strlen(dev),True);
853 CVAL(cli->outbuf,smb_com) = SMBtconX;
854 cli_setup_packet(cli);
856 SSVAL(cli->outbuf,smb_vwv0,0xFF);
857 SSVAL(cli->outbuf,smb_vwv3,passlen);
859 p = smb_buf(cli->outbuf);
860 memcpy(p,pword,passlen);
862 fstrcpy(p,fullshare);
863 p = skip_string(p,1);
866 SCVAL(cli->inbuf,smb_rcls, 1);
868 cli_send_smb(cli, True);
869 if (!cli_receive_smb(cli))
872 if (CVAL(cli->inbuf,smb_rcls) != 0) {
876 fstrcpy(cli->dev, "A:");
878 if (cli->protocol >= PROTOCOL_NT1) {
879 fstrcpy(cli->dev, smb_buf(cli->inbuf));
882 if (strcasecmp(share,"IPC$")==0) {
883 fstrcpy(cli->dev, "IPC");
886 /* only grab the device if we have a recent protocol level */
887 if (cli->protocol >= PROTOCOL_NT1 &&
888 smb_buflen(cli->inbuf) == 3) {
889 /* almost certainly win95 - enable bug fixes */
893 cli->cnum = SVAL(cli->inbuf,smb_tid);
898 /****************************************************************************
899 send a tree disconnect
900 ****************************************************************************/
901 BOOL cli_tdis(struct cli_state *cli)
903 bzero(cli->outbuf,smb_size);
904 set_message(cli->outbuf,0,0,True);
905 CVAL(cli->outbuf,smb_com) = SMBtdis;
906 SSVAL(cli->outbuf,smb_tid,cli->cnum);
907 cli_setup_packet(cli);
909 cli_send_smb(cli, True);
910 if (!cli_receive_smb(cli))
913 return CVAL(cli->inbuf,smb_rcls) == 0;
916 /****************************************************************************
918 ****************************************************************************/
919 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
923 bzero(cli->outbuf,smb_size);
924 bzero(cli->inbuf,smb_size);
926 set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
928 CVAL(cli->outbuf,smb_com) = SMBmv;
929 SSVAL(cli->outbuf,smb_tid,cli->cnum);
930 cli_setup_packet(cli);
932 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
934 p = smb_buf(cli->outbuf);
936 pstrcpy(p,fname_src);
937 p = skip_string(p,1);
939 pstrcpy(p,fname_dst);
941 cli_send_smb(cli, True);
942 if (!cli_receive_smb(cli)) {
946 if (CVAL(cli->inbuf,smb_rcls) != 0) {
953 /****************************************************************************
955 ****************************************************************************/
956 BOOL cli_unlink(struct cli_state *cli, char *fname)
960 bzero(cli->outbuf,smb_size);
961 bzero(cli->inbuf,smb_size);
963 set_message(cli->outbuf,1, 2 + strlen(fname),True);
965 CVAL(cli->outbuf,smb_com) = SMBunlink;
966 SSVAL(cli->outbuf,smb_tid,cli->cnum);
967 cli_setup_packet(cli);
969 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
971 p = smb_buf(cli->outbuf);
975 cli_send_smb(cli, True);
976 if (!cli_receive_smb(cli)) {
980 if (CVAL(cli->inbuf,smb_rcls) != 0) {
987 /****************************************************************************
989 ****************************************************************************/
990 BOOL cli_mkdir(struct cli_state *cli, char *dname)
994 bzero(cli->outbuf,smb_size);
995 bzero(cli->inbuf,smb_size);
997 set_message(cli->outbuf,0, 2 + strlen(dname),True);
999 CVAL(cli->outbuf,smb_com) = SMBmkdir;
1000 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1001 cli_setup_packet(cli);
1003 p = smb_buf(cli->outbuf);
1007 cli_send_smb(cli, True);
1008 if (!cli_receive_smb(cli)) {
1012 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1019 /****************************************************************************
1021 ****************************************************************************/
1022 BOOL cli_rmdir(struct cli_state *cli, char *dname)
1026 bzero(cli->outbuf,smb_size);
1027 bzero(cli->inbuf,smb_size);
1029 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1031 CVAL(cli->outbuf,smb_com) = SMBrmdir;
1032 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1033 cli_setup_packet(cli);
1035 p = smb_buf(cli->outbuf);
1039 cli_send_smb(cli, True);
1040 if (!cli_receive_smb(cli)) {
1044 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1053 /****************************************************************************
1055 ****************************************************************************/
1056 int cli_nt_create(struct cli_state *cli, char *fname)
1060 bzero(cli->outbuf,smb_size);
1061 bzero(cli->inbuf,smb_size);
1063 set_message(cli->outbuf,24,1 + strlen(fname),True);
1065 CVAL(cli->outbuf,smb_com) = SMBntcreateX;
1066 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1067 cli_setup_packet(cli);
1069 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1070 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0x06);
1071 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
1072 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, 0x2019f);
1073 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0);
1074 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03);
1075 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01);
1076 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0);
1077 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
1078 SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname));
1080 p = smb_buf(cli->outbuf);
1082 p = skip_string(p,1);
1084 cli_send_smb(cli, True);
1085 if (!cli_receive_smb(cli)) {
1089 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1093 return SVAL(cli->inbuf,smb_vwv2 + 1);
1097 /****************************************************************************
1099 ****************************************************************************/
1100 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
1104 unsigned accessmode=0;
1106 /* you must open for RW not just write - otherwise getattrE doesn't
1108 if ((flags & O_ACCMODE) == O_WRONLY && strncmp(cli->dev, "LPT", 3)) {
1109 flags = (flags & ~O_ACCMODE) | O_RDWR;
1112 if (flags & O_CREAT)
1114 if (!(flags & O_EXCL)) {
1115 if (flags & O_TRUNC)
1121 accessmode = (share_mode<<4);
1123 if ((flags & O_ACCMODE) == O_RDWR) {
1125 } else if ((flags & O_ACCMODE) == O_WRONLY) {
1130 if ((flags & O_SYNC) == O_SYNC) {
1131 accessmode |= (1<<14);
1135 bzero(cli->outbuf,smb_size);
1136 bzero(cli->inbuf,smb_size);
1138 set_message(cli->outbuf,15,1 + strlen(fname),True);
1140 CVAL(cli->outbuf,smb_com) = SMBopenX;
1141 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1142 cli_setup_packet(cli);
1144 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1145 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1146 SSVAL(cli->outbuf,smb_vwv3,accessmode);
1147 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1148 SSVAL(cli->outbuf,smb_vwv5,0);
1149 SSVAL(cli->outbuf,smb_vwv8,openfn);
1151 p = smb_buf(cli->outbuf);
1153 p = skip_string(p,1);
1155 cli_send_smb(cli, True);
1156 if (!cli_receive_smb(cli)) {
1160 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1164 return SVAL(cli->inbuf,smb_vwv2);
1170 /****************************************************************************
1172 ****************************************************************************/
1173 BOOL cli_close(struct cli_state *cli, int fnum)
1175 bzero(cli->outbuf,smb_size);
1176 bzero(cli->inbuf,smb_size);
1178 set_message(cli->outbuf,3,0,True);
1180 CVAL(cli->outbuf,smb_com) = SMBclose;
1181 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1182 cli_setup_packet(cli);
1184 SSVAL(cli->outbuf,smb_vwv0,fnum);
1185 SIVALS(cli->outbuf,smb_vwv1,-1);
1187 cli_send_smb(cli, True);
1188 if (!cli_receive_smb(cli)) {
1192 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1200 /****************************************************************************
1202 ****************************************************************************/
1203 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1206 int saved_timeout = cli->timeout;
1208 bzero(cli->outbuf,smb_size);
1209 bzero(cli->inbuf,smb_size);
1211 set_message(cli->outbuf,8,10,True);
1213 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1214 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1215 cli_setup_packet(cli);
1217 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1218 SSVAL(cli->outbuf,smb_vwv2,fnum);
1219 CVAL(cli->outbuf,smb_vwv3) = 0;
1220 SIVALS(cli->outbuf, smb_vwv4, timeout);
1221 SSVAL(cli->outbuf,smb_vwv6,0);
1222 SSVAL(cli->outbuf,smb_vwv7,1);
1224 p = smb_buf(cli->outbuf);
1225 SSVAL(p, 0, cli->pid);
1226 SIVAL(p, 2, offset);
1228 cli_send_smb(cli, True);
1230 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout;
1232 if (!cli_receive_smb(cli)) {
1233 cli->timeout = saved_timeout;
1237 cli->timeout = saved_timeout;
1239 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1246 /****************************************************************************
1248 ****************************************************************************/
1249 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1253 bzero(cli->outbuf,smb_size);
1254 bzero(cli->inbuf,smb_size);
1256 set_message(cli->outbuf,8,10,True);
1258 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1259 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1260 cli_setup_packet(cli);
1262 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1263 SSVAL(cli->outbuf,smb_vwv2,fnum);
1264 CVAL(cli->outbuf,smb_vwv3) = 0;
1265 SIVALS(cli->outbuf, smb_vwv4, timeout);
1266 SSVAL(cli->outbuf,smb_vwv6,1);
1267 SSVAL(cli->outbuf,smb_vwv7,0);
1269 p = smb_buf(cli->outbuf);
1270 SSVAL(p, 0, cli->pid);
1271 SIVAL(p, 2, offset);
1274 cli_send_smb(cli, True);
1275 if (!cli_receive_smb(cli)) {
1279 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1288 /****************************************************************************
1289 issue a single SMBread and don't wait for a reply
1290 ****************************************************************************/
1291 static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
1294 bzero(cli->outbuf,smb_size);
1295 bzero(cli->inbuf,smb_size);
1297 set_message(cli->outbuf,10,0,True);
1299 CVAL(cli->outbuf,smb_com) = SMBreadX;
1300 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1301 cli_setup_packet(cli);
1303 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1304 SSVAL(cli->outbuf,smb_vwv2,fnum);
1305 SIVAL(cli->outbuf,smb_vwv3,offset);
1306 SSVAL(cli->outbuf,smb_vwv5,size);
1307 SSVAL(cli->outbuf,smb_vwv6,size);
1308 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1310 cli_send_smb(cli, True);
1313 /****************************************************************************
1315 ****************************************************************************/
1316 size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
1322 int mpx = MAX(cli->max_mux-1, 1);
1323 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1325 int blocks = (size + (block-1)) / block;
1327 if (size == 0) return 0;
1329 while (received < blocks) {
1332 while (issued - received < mpx && issued < blocks) {
1333 int size1 = MIN(block, size-issued*block);
1334 cli_issue_read(cli, fnum, offset+issued*block, size1, issued);
1338 if (!cli_receive_smb(cli)) {
1343 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1344 size2 = SVAL(cli->inbuf, smb_vwv5);
1346 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1347 blocks = MIN(blocks, mid-1);
1352 blocks = MIN(blocks, mid-1);
1353 /* this distinguishes EOF from an error */
1354 total = MAX(total, 0);
1358 if (size2 > block) {
1359 DEBUG(0,("server returned more than we wanted!\n"));
1362 if (mid >= issued) {
1363 DEBUG(0,("invalid mid from server!\n"));
1366 p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
1368 memcpy(buf+mid*block, p, size2);
1370 total = MAX(total, mid*block + size2);
1373 while (received < issued) {
1374 cli_receive_smb(cli);
1382 /****************************************************************************
1383 issue a single SMBwrite and don't wait for a reply
1384 ****************************************************************************/
1385 static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf,
1390 bzero(cli->outbuf,smb_size);
1391 bzero(cli->inbuf,smb_size);
1393 set_message(cli->outbuf,12,size,True);
1395 CVAL(cli->outbuf,smb_com) = SMBwriteX;
1396 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1397 cli_setup_packet(cli);
1399 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1400 SSVAL(cli->outbuf,smb_vwv2,fnum);
1402 SIVAL(cli->outbuf,smb_vwv3,offset);
1403 SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0);
1404 SSVAL(cli->outbuf,smb_vwv7,mode);
1406 SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0);
1407 SSVAL(cli->outbuf,smb_vwv10,size);
1408 SSVAL(cli->outbuf,smb_vwv11,
1409 smb_buf(cli->outbuf) - smb_base(cli->outbuf));
1411 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
1412 memcpy(p, buf, size);
1414 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1416 cli_send_smb(cli, True);
1419 /****************************************************************************
1421 write_mode: 0x0001 disallow write cacheing
1422 0x0002 return bytes remaining
1423 0x0004 use raw named pipe protocol
1424 0x0008 start of message mode named pipe protocol
1425 ****************************************************************************/
1426 ssize_t cli_write(struct cli_state *cli,
1427 int fnum, uint16 write_mode,
1428 char *buf, off_t offset, size_t size)
1433 int mpx = MAX(cli->max_mux-1, 1);
1434 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1436 int blocks = (size + (block-1)) / block;
1438 if (size == 0) return 0;
1440 while (received < blocks) {
1443 while (issued - received < mpx && issued < blocks) {
1444 int size1 = MIN(block, size-issued*block);
1445 cli_issue_write(cli, fnum, offset+issued*block,
1452 if (!cli_receive_smb(cli)) {
1457 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1458 size2 = SVAL(cli->inbuf, smb_vwv2);
1460 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1461 blocks = MIN(blocks, mid-1);
1466 blocks = MIN(blocks, mid-1);
1467 /* this distinguishes EOF from an error */
1468 total = MAX(total, 0);
1474 total = MAX(total, mid*block + size2);
1477 while (received < issued) {
1478 cli_receive_smb(cli);
1486 /****************************************************************************
1487 do a SMBgetattrE call
1488 ****************************************************************************/
1489 BOOL cli_getattrE(struct cli_state *cli, int fd,
1490 uint16 *attr, size_t *size,
1491 time_t *c_time, time_t *a_time, time_t *m_time)
1493 bzero(cli->outbuf,smb_size);
1494 bzero(cli->inbuf,smb_size);
1496 set_message(cli->outbuf,2,0,True);
1498 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
1499 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1500 cli_setup_packet(cli);
1502 SSVAL(cli->outbuf,smb_vwv0,fd);
1504 cli_send_smb(cli, True);
1505 if (!cli_receive_smb(cli)) {
1509 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1514 *size = IVAL(cli->inbuf, smb_vwv6);
1518 *attr = SVAL(cli->inbuf,smb_vwv10);
1522 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
1526 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
1530 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
1537 /****************************************************************************
1539 ****************************************************************************/
1540 BOOL cli_getatr(struct cli_state *cli, char *fname,
1541 uint16 *attr, size_t *size, time_t *t)
1545 bzero(cli->outbuf,smb_size);
1546 bzero(cli->inbuf,smb_size);
1548 set_message(cli->outbuf,0,strlen(fname)+2,True);
1550 CVAL(cli->outbuf,smb_com) = SMBgetatr;
1551 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1552 cli_setup_packet(cli);
1554 p = smb_buf(cli->outbuf);
1556 pstrcpy(p+1, fname);
1558 cli_send_smb(cli, True);
1559 if (!cli_receive_smb(cli)) {
1563 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1568 *size = IVAL(cli->inbuf, smb_vwv3);
1572 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1576 *attr = SVAL(cli->inbuf,smb_vwv0);
1584 /****************************************************************************
1586 ****************************************************************************/
1587 BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
1591 bzero(cli->outbuf,smb_size);
1592 bzero(cli->inbuf,smb_size);
1594 set_message(cli->outbuf,8,strlen(fname)+4,True);
1596 CVAL(cli->outbuf,smb_com) = SMBsetatr;
1597 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1598 cli_setup_packet(cli);
1600 SSVAL(cli->outbuf,smb_vwv0, attr);
1601 put_dos_date3(cli->outbuf,smb_vwv1, t);
1603 p = smb_buf(cli->outbuf);
1605 pstrcpy(p+1, fname);
1606 p = skip_string(p,1);
1609 cli_send_smb(cli, True);
1610 if (!cli_receive_smb(cli)) {
1614 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1621 /****************************************************************************
1622 send a qpathinfo call
1623 ****************************************************************************/
1624 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
1625 time_t *c_time, time_t *a_time, time_t *m_time,
1626 size_t *size, uint16 *mode)
1630 uint16 setup = TRANSACT2_QPATHINFO;
1632 char *rparam=NULL, *rdata=NULL;
1635 time_t (*date_fn)(void *);
1637 param_len = strlen(fname) + 7;
1639 memset(param, 0, param_len);
1640 SSVAL(param, 0, SMB_INFO_STANDARD);
1641 pstrcpy(¶m[6], fname);
1644 ret = (cli_send_trans(cli, SMBtrans2,
1645 NULL, 0, /* Name, length */
1646 -1, 0, /* fid, flags */
1647 &setup, 1, 0, /* setup, length, max */
1648 param, param_len, 10, /* param, length, max */
1649 NULL, data_len, cli->max_xmit /* data, length, max */
1651 cli_receive_trans(cli, SMBtrans2,
1652 &rparam, ¶m_len,
1653 &rdata, &data_len));
1655 /* we need to work around a Win95 bug - sometimes
1656 it gives ERRSRV/ERRerror temprarily */
1659 cli_error(cli, &eclass, &ecode);
1660 if (eclass != ERRSRV || ecode != ERRerror) break;
1663 } while (count-- && ret==False);
1665 if (!ret || !rdata || data_len < 22) {
1670 date_fn = make_unix_date;
1672 date_fn = make_unix_date2;
1676 *c_time = date_fn(rdata+0);
1679 *a_time = date_fn(rdata+4);
1682 *m_time = date_fn(rdata+8);
1685 *size = IVAL(rdata, 12);
1688 *mode = SVAL(rdata,l1_attrFile);
1691 if (rdata) free(rdata);
1692 if (rparam) free(rparam);
1696 /****************************************************************************
1697 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1698 ****************************************************************************/
1699 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
1700 time_t *c_time, time_t *a_time, time_t *m_time,
1701 time_t *w_time, size_t *size, uint16 *mode,
1706 uint16 setup = TRANSACT2_QPATHINFO;
1708 char *rparam=NULL, *rdata=NULL;
1710 param_len = strlen(fname) + 7;
1712 memset(param, 0, param_len);
1713 SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1714 pstrcpy(¶m[6], fname);
1716 if (!cli_send_trans(cli, SMBtrans2,
1717 NULL, 0, /* name, length */
1718 -1, 0, /* fid, flags */
1719 &setup, 1, 0, /* setup, length, max */
1720 param, param_len, 10, /* param, length, max */
1721 NULL, data_len, cli->max_xmit /* data, length, max */
1726 if (!cli_receive_trans(cli, SMBtrans2,
1727 &rparam, ¶m_len,
1728 &rdata, &data_len)) {
1732 if (!rdata || data_len < 22) {
1737 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1740 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1743 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1746 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1749 *mode = SVAL(rdata, 32);
1752 *size = IVAL(rdata, 40);
1755 *ino = IVAL(rdata, 64);
1758 if (rdata) free(rdata);
1759 if (rparam) free(rparam);
1764 /****************************************************************************
1765 send a qfileinfo call
1766 ****************************************************************************/
1767 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
1768 uint16 *mode, size_t *size,
1769 time_t *c_time, time_t *a_time, time_t *m_time,
1770 time_t *w_time, SMB_INO_T *ino)
1774 uint16 setup = TRANSACT2_QFILEINFO;
1776 char *rparam=NULL, *rdata=NULL;
1778 /* if its a win95 server then fail this - win95 totally screws it
1780 if (cli->win95) return False;
1784 memset(param, 0, param_len);
1785 SSVAL(param, 0, fnum);
1786 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
1788 if (!cli_send_trans(cli, SMBtrans2,
1789 NULL, 0, /* name, length */
1790 -1, 0, /* fid, flags */
1791 &setup, 1, 0, /* setup, length, max */
1792 param, param_len, 2, /* param, length, max */
1793 NULL, data_len, cli->max_xmit /* data, length, max */
1798 if (!cli_receive_trans(cli, SMBtrans2,
1799 &rparam, ¶m_len,
1800 &rdata, &data_len)) {
1804 if (!rdata || data_len < 68) {
1809 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1812 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1815 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1818 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1821 *mode = SVAL(rdata, 32);
1824 *size = IVAL(rdata, 40);
1827 *ino = IVAL(rdata, 64);
1830 if (rdata) free(rdata);
1831 if (rparam) free(rparam);
1836 /****************************************************************************
1837 interpret a long filename structure - this is mostly guesses at the moment
1838 The length of the structure is returned
1839 The structure of a long filename depends on the info level. 260 is used
1840 by NT and 2 is used by OS/2
1841 ****************************************************************************/
1842 static int interpret_long_filename(int level,char *p,file_info *finfo)
1844 extern file_info def_finfo;
1847 memcpy(finfo,&def_finfo,sizeof(*finfo));
1851 case 1: /* OS/2 understands this */
1853 /* these dates are converted to GMT by make_unix_date */
1854 finfo->ctime = make_unix_date2(p+4);
1855 finfo->atime = make_unix_date2(p+8);
1856 finfo->mtime = make_unix_date2(p+12);
1857 finfo->size = IVAL(p,16);
1858 finfo->mode = CVAL(p,24);
1859 pstrcpy(finfo->name,p+27);
1861 return(28 + CVAL(p,26));
1863 case 2: /* this is what OS/2 uses mostly */
1865 /* these dates are converted to GMT by make_unix_date */
1866 finfo->ctime = make_unix_date2(p+4);
1867 finfo->atime = make_unix_date2(p+8);
1868 finfo->mtime = make_unix_date2(p+12);
1869 finfo->size = IVAL(p,16);
1870 finfo->mode = CVAL(p,24);
1871 pstrcpy(finfo->name,p+31);
1873 return(32 + CVAL(p,30));
1875 /* levels 3 and 4 are untested */
1878 /* these dates are probably like the other ones */
1879 finfo->ctime = make_unix_date2(p+8);
1880 finfo->atime = make_unix_date2(p+12);
1881 finfo->mtime = make_unix_date2(p+16);
1882 finfo->size = IVAL(p,20);
1883 finfo->mode = CVAL(p,28);
1884 pstrcpy(finfo->name,p+33);
1886 return(SVAL(p,4)+4);
1890 /* these dates are probably like the other ones */
1891 finfo->ctime = make_unix_date2(p+8);
1892 finfo->atime = make_unix_date2(p+12);
1893 finfo->mtime = make_unix_date2(p+16);
1894 finfo->size = IVAL(p,20);
1895 finfo->mode = CVAL(p,28);
1896 pstrcpy(finfo->name,p+37);
1898 return(SVAL(p,4)+4);
1900 case 260: /* NT uses this, but also accepts 2 */
1902 int ret = SVAL(p,0);
1904 p += 4; /* next entry offset */
1905 p += 4; /* fileindex */
1907 /* these dates appear to arrive in a
1908 weird way. It seems to be localtime
1909 plus the serverzone given in the
1910 initial connect. This is GMT when
1911 DST is not in effect and one hour
1912 from GMT otherwise. Can this really
1915 I suppose this could be called
1916 kludge-GMT. Is is the GMT you get
1917 by using the current DST setting on
1918 a different localtime. It will be
1919 cheap to calculate, I suppose, as
1920 no DST tables will be needed */
1922 finfo->ctime = interpret_long_date(p); p += 8;
1923 finfo->atime = interpret_long_date(p); p += 8;
1924 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
1925 finfo->size = IVAL(p,0); p += 8;
1926 p += 8; /* alloc size */
1927 finfo->mode = CVAL(p,0); p += 4;
1928 namelen = IVAL(p,0); p += 4;
1929 p += 4; /* EA size */
1930 p += 2; /* short name len? */
1931 p += 24; /* short name? */
1932 StrnCpy(finfo->name,p,namelen);
1938 DEBUG(1,("Unknown long filename format %d\n",level));
1943 /****************************************************************************
1944 do a directory listing, calling fn on each file found
1945 ****************************************************************************/
1946 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
1947 void (*fn)(file_info *, const char *))
1949 int max_matches = 512;
1950 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1951 int info_level = cli->protocol<PROTOCOL_NT1?1:260;
1956 char *dirlist = NULL;
1957 int dirlist_len = 0;
1958 int total_received = -1;
1960 int ff_resume_key = 0;
1961 int ff_searchcount=0;
1964 int ff_dir_handle=0;
1966 char *rparam=NULL, *rdata=NULL;
1967 int param_len, data_len;
1974 while (ff_eos == 0) {
1976 if (loop_count > 200) {
1977 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
1981 param_len = 12+strlen(mask)+1;
1984 setup = TRANSACT2_FINDFIRST;
1985 SSVAL(param,0,attribute); /* attribute */
1986 SSVAL(param,2,max_matches); /* max count */
1987 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
1988 SSVAL(param,6,info_level);
1990 pstrcpy(param+12,mask);
1992 setup = TRANSACT2_FINDNEXT;
1993 SSVAL(param,0,ff_dir_handle);
1994 SSVAL(param,2,max_matches); /* max count */
1995 SSVAL(param,4,info_level);
1996 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
1997 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
1998 pstrcpy(param+12,mask);
2000 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
2001 ff_dir_handle,ff_resume_key,ff_lastname,mask));
2004 if (!cli_send_trans(cli, SMBtrans2,
2005 NULL, 0, /* Name, length */
2006 -1, 0, /* fid, flags */
2007 &setup, 1, 0, /* setup, length, max */
2008 param, param_len, 10, /* param, length, max */
2010 cli->max_xmit /* data, length, max */
2015 if (!cli_receive_trans(cli, SMBtrans2,
2016 &rparam, ¶m_len,
2017 &rdata, &data_len)) {
2018 /* we need to work around a Win95 bug - sometimes
2019 it gives ERRSRV/ERRerror temprarily */
2022 cli_error(cli, &eclass, &ecode);
2023 if (eclass != ERRSRV || ecode != ERRerror) break;
2028 if (total_received == -1) total_received = 0;
2030 /* parse out some important return info */
2033 ff_dir_handle = SVAL(p,0);
2034 ff_searchcount = SVAL(p,2);
2036 ff_lastname = SVAL(p,8);
2038 ff_searchcount = SVAL(p,0);
2040 ff_lastname = SVAL(p,6);
2043 if (ff_searchcount == 0)
2046 /* point to the data bytes */
2049 /* we might need the lastname for continuations */
2050 if (ff_lastname > 0) {
2055 StrnCpy(mask,p+ff_lastname,
2056 data_len-ff_lastname);
2059 pstrcpy(mask,p + ff_lastname + 1);
2067 /* and add them to the dirlist pool */
2068 dirlist = Realloc(dirlist,dirlist_len + data_len);
2071 DEBUG(0,("Failed to expand dirlist\n"));
2075 /* put in a length for the last entry, to ensure we can chain entries
2076 into the next packet */
2077 for (p2=p,i=0;i<(ff_searchcount-1);i++)
2078 p2 += interpret_long_filename(info_level,p2,NULL);
2079 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
2081 /* grab the data for later use */
2082 memcpy(dirlist+dirlist_len,p,data_len);
2083 dirlist_len += data_len;
2085 total_received += ff_searchcount;
2087 if (rdata) free(rdata); rdata = NULL;
2088 if (rparam) free(rparam); rparam = NULL;
2090 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
2091 ff_searchcount,ff_eos,ff_resume_key));
2096 for (p=dirlist,i=0;i<total_received;i++) {
2097 p += interpret_long_filename(info_level,p,&finfo);
2101 /* free up the dirlist buffer */
2102 if (dirlist) free(dirlist);
2103 return(total_received);
2107 /****************************************************************************
2108 Send a SamOEMChangePassword command
2109 ****************************************************************************/
2111 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
2112 const char *old_password)
2114 char param[16+sizeof(fstring)];
2117 fstring upper_case_old_pw;
2118 fstring upper_case_new_pw;
2119 unsigned char old_pw_hash[16];
2120 unsigned char new_pw_hash[16];
2123 char *rparam = NULL;
2127 if (strlen(user) >= sizeof(fstring)-1) {
2128 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
2132 SSVAL(p,0,214); /* SamOEMChangePassword command. */
2135 p = skip_string(p,1);
2136 pstrcpy(p, "B516B16");
2137 p = skip_string(p,1);
2139 p = skip_string(p,1);
2143 param_len = PTR_DIFF(p,param);
2146 * Get the Lanman hash of the old password, we
2147 * use this as the key to make_oem_passwd_hash().
2149 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
2150 fstrcpy(upper_case_old_pw, old_password);
2151 strupper(upper_case_old_pw);
2152 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
2154 if (!make_oem_passwd_hash( data, new_password, old_pw_hash, False))
2160 * Now place the old password hash in the data.
2162 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
2163 fstrcpy(upper_case_new_pw, new_password);
2164 strupper(upper_case_new_pw);
2166 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
2168 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
2172 if (!cli_send_trans(cli,SMBtrans,
2173 PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */
2174 0,0, /* fid, flags */
2175 NULL,0,0, /* setup, length, max */
2176 param,param_len,2, /* param, length, max */
2177 data,data_len,0 /* data, length, max */
2180 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
2185 if (cli_receive_trans(cli,SMBtrans,
2189 cli->rap_error = SVAL(rparam,0);
2197 return (cli->rap_error == 0);
2200 /****************************************************************************
2201 send a negprot command
2202 ****************************************************************************/
2203 BOOL cli_negprot(struct cli_state *cli)
2209 bzero(cli->outbuf,smb_size);
2211 /* setup the protocol strings */
2212 for (plength=0,numprots=0;
2213 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2215 plength += strlen(prots[numprots].name)+2;
2217 set_message(cli->outbuf,0,plength,True);
2219 p = smb_buf(cli->outbuf);
2221 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2224 pstrcpy(p,prots[numprots].name);
2228 CVAL(cli->outbuf,smb_com) = SMBnegprot;
2229 cli_setup_packet(cli);
2231 CVAL(smb_buf(cli->outbuf),0) = 2;
2233 cli_send_smb(cli, True);
2234 if (!cli_receive_smb(cli))
2239 if (CVAL(cli->inbuf,smb_rcls) != 0 ||
2240 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
2244 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
2247 if (cli->protocol >= PROTOCOL_NT1) {
2249 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
2250 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
2251 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
2252 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
2253 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
2254 /* this time arrives in real GMT */
2255 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
2256 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2257 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
2258 if (cli->capabilities & 1) {
2259 cli->readbraw_supported = True;
2260 cli->writebraw_supported = True;
2262 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2263 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
2264 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
2265 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
2266 cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
2267 /* this time is converted to GMT by make_unix_date */
2268 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
2269 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
2270 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
2271 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2273 /* the old core protocol */
2275 cli->serverzone = TimeDiff(time(NULL));
2278 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2284 /****************************************************************************
2285 send a session request. see rfc1002.txt 4.3 and 4.3.2
2286 ****************************************************************************/
2287 BOOL cli_session_request(struct cli_state *cli,
2288 struct nmb_name *calling, struct nmb_name *called)
2292 /* send a session request (RFC 1002) */
2294 memcpy(&(cli->calling), calling, sizeof(*calling));
2295 memcpy(&(cli->called ), called , sizeof(*called ));
2297 /* put in the destination name */
2298 p = cli->outbuf+len;
2299 name_mangle(cli->called .name, p, cli->called .name_type);
2303 p = cli->outbuf+len;
2304 name_mangle(cli->calling.name, p, cli->calling.name_type);
2307 /* setup the packet length */
2308 _smb_setlen(cli->outbuf,len);
2309 CVAL(cli->outbuf,0) = 0x81;
2313 #endif /* WITH_SSL */
2315 cli_send_smb(cli, False);
2316 DEBUG(5,("Sent session request\n"));
2318 if (!cli_receive_smb(cli))
2322 if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
2323 if (!sslutil_fd_is_ssl(cli->fd)){
2324 if (sslutil_connect(cli->fd) == 0)
2328 #endif /* WITH_SSL */
2330 if (CVAL(cli->inbuf,0) != 0x82) {
2331 /* This is the wrong place to put the error... JRA. */
2332 cli->rap_error = CVAL(cli->inbuf,0);
2339 /****************************************************************************
2340 open the client sockets
2341 ****************************************************************************/
2342 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
2344 extern struct in_addr ipzero;
2346 fstrcpy(cli->desthost, host);
2348 if (!ip || ip_equal(*ip, ipzero)) {
2349 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
2352 if (ip) *ip = cli->dest_ip;
2358 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2367 /****************************************************************************
2368 initialise a client structure
2369 ****************************************************************************/
2370 struct cli_state *cli_initialise(struct cli_state *cli)
2373 cli = (struct cli_state *)malloc(sizeof(*cli));
2379 if (cli->initialised) {
2387 cli->pid = (uint16)getpid();
2389 cli->vuid = UID_FIELD_INVALID;
2390 cli->protocol = PROTOCOL_NT1;
2391 cli->timeout = 20000;
2392 cli->bufsize = CLI_BUFFER_SIZE+4;
2393 cli->max_xmit = cli->bufsize;
2394 cli->outbuf = (char *)malloc(cli->bufsize);
2395 cli->inbuf = (char *)malloc(cli->bufsize);
2396 if (!cli->outbuf || !cli->inbuf)
2401 cli->initialised = 1;
2406 /****************************************************************************
2407 shutdown a client structure
2408 ****************************************************************************/
2409 void cli_shutdown(struct cli_state *cli)
2411 DEBUG(10,("cli_shutdown\n"));
2422 sslutil_disconnect(cli->fd);
2423 #endif /* WITH_SSL */
2428 memset(cli, 0, sizeof(*cli));
2432 /****************************************************************************
2433 return error codes for the last packet
2434 returns 0 if there was no error and the best approx of a unix errno
2437 for 32 bit "warnings", a return code of 0 is expected.
2439 ****************************************************************************/
2440 int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
2446 if (!cli->initialised)
2448 DEBUG(0,("cli_error: client state uninitialised!\n"));
2452 flgs2 = SVAL(cli->inbuf,smb_flg2);
2454 if (eclass) *eclass = 0;
2457 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
2458 /* 32 bit error codes detected */
2459 uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
2460 if (num) *num = nt_err;
2461 DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
2462 if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0;
2464 switch (nt_err & 0xFFFFFF) {
2465 case NT_STATUS_ACCESS_VIOLATION: return EACCES;
2466 case NT_STATUS_NO_SUCH_FILE: return ENOENT;
2467 case NT_STATUS_NO_SUCH_DEVICE: return ENODEV;
2468 case NT_STATUS_INVALID_HANDLE: return EBADF;
2469 case NT_STATUS_NO_MEMORY: return ENOMEM;
2470 case NT_STATUS_ACCESS_DENIED: return EACCES;
2471 case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
2472 case NT_STATUS_SHARING_VIOLATION: return EBUSY;
2473 case NT_STATUS_OBJECT_PATH_INVALID: return ENOTDIR;
2474 case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
2477 /* for all other cases - a default code */
2481 rcls = CVAL(cli->inbuf,smb_rcls);
2482 code = SVAL(cli->inbuf,smb_err);
2483 if (rcls == 0) return 0;
2485 if (eclass) *eclass = rcls;
2486 if (num ) *num = code;
2488 if (rcls == ERRDOS) {
2490 case ERRbadfile: return ENOENT;
2491 case ERRbadpath: return ENOTDIR;
2492 case ERRnoaccess: return EACCES;
2493 case ERRfilexists: return EEXIST;
2494 case ERRrename: return EEXIST;
2495 case ERRbadshare: return EBUSY;
2496 case ERRlock: return EBUSY;
2499 if (rcls == ERRSRV) {
2501 case ERRbadpw: return EPERM;
2502 case ERRaccess: return EACCES;
2503 case ERRnoresource: return ENOMEM;
2504 case ERRinvdevice: return ENODEV;
2505 case ERRinvnetname: return ENODEV;
2508 /* for other cases */
2512 /****************************************************************************
2513 set socket options on a open connection
2514 ****************************************************************************/
2515 void cli_sockopt(struct cli_state *cli, char *options)
2517 set_socket_options(cli->fd, options);
2520 /****************************************************************************
2521 set the PID to use for smb messages. Return the old pid.
2522 ****************************************************************************/
2523 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
2525 uint16 ret = cli->pid;
2530 /****************************************************************************
2531 re-establishes a connection
2532 ****************************************************************************/
2533 BOOL cli_reestablish_connection(struct cli_state *cli)
2535 struct nmb_name calling;
2536 struct nmb_name called;
2540 BOOL do_tcon = False;
2541 int oldfd = cli->fd;
2543 if (!cli->initialised || cli->fd == -1)
2545 DEBUG(3,("cli_reestablish_connection: not connected\n"));
2549 /* copy the parameters necessary to re-establish the connection */
2553 fstrcpy(share, cli->share);
2554 fstrcpy(dev , cli->dev);
2558 memcpy(&called , &(cli->called ), sizeof(called ));
2559 memcpy(&calling, &(cli->calling), sizeof(calling));
2560 fstrcpy(dest_host, cli->full_dest_host_name);
2562 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2563 nmb_namestr(&calling), nmb_namestr(&called),
2564 inet_ntoa(cli->dest_ip),
2565 cli->user_name, cli->domain));
2569 if (cli_establish_connection(cli,
2570 dest_host, &cli->dest_ip,
2572 share, dev, False, do_tcon)) {
2573 if (cli->fd != oldfd) {
2574 if (dup2(cli->fd, oldfd) == oldfd) {
2583 /****************************************************************************
2584 establishes a connection right up to doing tconX, reading in a password.
2585 ****************************************************************************/
2586 BOOL cli_establish_connection(struct cli_state *cli,
2587 char *dest_host, struct in_addr *dest_ip,
2588 struct nmb_name *calling, struct nmb_name *called,
2589 char *service, char *service_type,
2590 BOOL do_shutdown, BOOL do_tcon)
2592 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
2593 nmb_namestr(calling), nmb_namestr(called), inet_ntoa(*dest_ip),
2594 cli->user_name, cli->domain));
2596 /* establish connection */
2598 if ((!cli->initialised))
2605 if (!cli_connect(cli, dest_host, dest_ip))
2607 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
2608 nmb_namestr(calling), inet_ntoa(*dest_ip)));
2613 if (!cli_session_request(cli, calling, called))
2615 DEBUG(1,("failed session request\n"));
2621 if (!cli_negprot(cli))
2623 DEBUG(1,("failed negprot\n"));
2629 if (cli->pwd.cleartext || cli->pwd.null_pwd)
2634 if (cli->pwd.null_pwd)
2636 /* attempt null session */
2642 /* attempt clear-text session */
2643 pwd_get_cleartext(&(cli->pwd), passwd);
2644 pass_len = strlen(passwd);
2647 /* attempt clear-text session */
2648 if (!cli_session_setup(cli, cli->user_name,
2653 DEBUG(1,("failed session setup\n"));
2662 if (!cli_send_tconX(cli, service, service_type,
2663 (char*)passwd, strlen(passwd)))
2665 DEBUG(1,("failed tcon_X\n"));
2676 /* attempt encrypted session */
2677 unsigned char nt_sess_pwd[24];
2678 unsigned char lm_sess_pwd[24];
2680 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
2681 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
2682 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
2684 /* attempt encrypted session */
2685 if (!cli_session_setup(cli, cli->user_name,
2686 (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
2687 (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
2690 DEBUG(1,("failed session setup\n"));
2700 if (!cli_send_tconX(cli, service, service_type,
2701 (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
2703 DEBUG(1,("failed tcon_X\n"));
2722 /****************************************************************************
2723 connect to one of multiple servers: don't care which
2724 ****************************************************************************/
2725 BOOL cli_connect_serverlist(struct cli_state *cli, char *p)
2727 extern pstring global_myname;
2728 extern pstring scope;
2729 fstring remote_machine;
2730 struct in_addr dest_ip;
2731 struct nmb_name calling, called, stupid_smbserver_called;
2732 BOOL connected_ok = False;
2735 * Treat each name in the 'password server =' line as a potential
2736 * PDC/BDC. Contact each in turn and try and authenticate.
2739 while(p && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine)))
2743 if (!cli_initialise(cli))
2745 DEBUG(0,("cli_connect_serverlist: unable to initialize client connection.\n"));
2749 standard_sub_basic(remote_machine);
2750 strupper(remote_machine);
2752 if (!resolve_name( remote_machine, &dest_ip, 0x20))
2754 DEBUG(1,("cli_connect_serverlist: Can't resolve address for %s\n", remote_machine));
2758 if (ismyip(dest_ip))
2760 DEBUG(1,("cli_connect_serverlist: Password server loop - not using password server %s\n", remote_machine));
2764 make_nmb_name(&calling, global_myname , 0x0 , scope);
2765 make_nmb_name(&called , remote_machine, 0x20, scope);
2766 /* stupid microsoft destruction of the ability of netbios
2767 * to provide multiple netbios servers on one host.
2769 make_nmb_name(&stupid_smbserver_called , "*SMBSERVER", 0x20, scope);
2771 pwd_set_nullpwd(&cli->pwd);
2773 if (!cli_establish_connection(cli, remote_machine, &dest_ip,
2777 !cli_establish_connection(cli, remote_machine, &dest_ip,
2778 &calling, &stupid_smbserver_called,
2786 if (cli->protocol < PROTOCOL_LANMAN2 ||
2787 !IS_BITS_SET_ALL(cli->sec_mode, 1))
2789 DEBUG(1,("cli_connect_serverlist: machine %s isn't in user level security mode\n",
2796 * We have an anonymous connection to IPC$.
2799 connected_ok = True;
2805 DEBUG(0,("cli_connect_serverlist: Domain password server not available.\n"));
2809 return connected_ok;
2812 /****************************************************************************
2814 ****************************************************************************/
2815 int cli_printjob_del(struct cli_state *cli, int job)
2817 char *rparam = NULL;
2820 int rdrcnt,rprcnt, ret = -1;
2823 bzero(param,sizeof(param));
2826 SSVAL(p,0,81); /* DosPrintJobDel() */
2829 p = skip_string(p,1);
2831 p = skip_string(p,1);
2836 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2837 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2838 &rparam, &rprcnt, /* return params, length */
2839 &rdata, &rdrcnt)) { /* return data, length */
2840 ret = SVAL(rparam,0);
2843 if (rparam) free(rparam);
2844 if (rdata) free(rdata);
2850 /****************************************************************************
2851 call fn() on each entry in a print queue
2852 ****************************************************************************/
2853 int cli_print_queue(struct cli_state *cli,
2854 void (*fn)(struct print_job_info *))
2856 char *rparam = NULL;
2864 bzero(param,sizeof(param));
2867 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2869 pstrcpy(p,"zWrLeh"); /* parameter description? */
2870 p = skip_string(p,1);
2871 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
2872 p = skip_string(p,1);
2873 pstrcpy(p,cli->share); /* name of queue */
2874 p = skip_string(p,1);
2875 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2876 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2878 pstrcpy(p,""); /* subformat */
2879 p = skip_string(p,1);
2881 DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
2884 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2885 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2886 &rparam, &rprcnt, /* return params, length */
2887 &rdata, &rdrcnt)) { /* return data, length */
2889 result_code = SVAL(rparam,0);
2890 converter = SVAL(rparam,2); /* conversion factor */
2892 if (result_code == 0) {
2893 struct print_job_info job;
2897 for (i = 0; i < SVAL(rparam,4); ++i) {
2899 job.priority = SVAL(p,2);
2901 fix_char_ptr(SVAL(p,4), converter,
2903 job.t = make_unix_date3(p + 12);
2904 job.size = IVAL(p,16);
2905 fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
2914 /* If any parameters or data were returned, free the storage. */
2915 if(rparam) free(rparam);
2916 if(rdata) free(rdata);
2921 /****************************************************************************
2922 check for existance of a dir
2923 ****************************************************************************/
2924 BOOL cli_chkpath(struct cli_state *cli, char *path)
2929 fstrcpy(path2,path);
2930 trim_string(path2,NULL,"\\");
2931 if (!*path2) *path2 = '\\';
2933 bzero(cli->outbuf,smb_size);
2934 set_message(cli->outbuf,0,4 + strlen(path2),True);
2935 SCVAL(cli->outbuf,smb_com,SMBchkpth);
2936 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2937 cli_setup_packet(cli);
2939 p = smb_buf(cli->outbuf);
2943 cli_send_smb(cli, True);
2944 if (!cli_receive_smb(cli)) {
2948 if (cli_error(cli, NULL, NULL)) return False;
2954 /****************************************************************************
2955 start a message sequence
2956 ****************************************************************************/
2957 BOOL cli_message_start(struct cli_state *cli, char *host, char *username,
2962 /* send a SMBsendstrt command */
2963 bzero(cli->outbuf,smb_size);
2964 set_message(cli->outbuf,0,0,True);
2965 CVAL(cli->outbuf,smb_com) = SMBsendstrt;
2966 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2967 cli_setup_packet(cli);
2969 p = smb_buf(cli->outbuf);
2971 pstrcpy(p,username);
2972 p = skip_string(p,1);
2975 p = skip_string(p,1);
2977 set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
2979 cli_send_smb(cli, True);
2981 if (!cli_receive_smb(cli)) {
2985 if (cli_error(cli, NULL, NULL)) return False;
2987 *grp = SVAL(cli->inbuf,smb_vwv0);
2993 /****************************************************************************
2995 ****************************************************************************/
2996 BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp)
3000 bzero(cli->outbuf,smb_size);
3001 set_message(cli->outbuf,1,len+3,True);
3002 CVAL(cli->outbuf,smb_com) = SMBsendtxt;
3003 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3004 cli_setup_packet(cli);
3006 SSVAL(cli->outbuf,smb_vwv0,grp);
3008 p = smb_buf(cli->outbuf);
3011 memcpy(p+3,msg,len);
3012 cli_send_smb(cli, True);
3014 if (!cli_receive_smb(cli)) {
3018 if (cli_error(cli, NULL, NULL)) return False;
3023 /****************************************************************************
3025 ****************************************************************************/
3026 BOOL cli_message_end(struct cli_state *cli, int grp)
3028 bzero(cli->outbuf,smb_size);
3029 set_message(cli->outbuf,1,0,True);
3030 CVAL(cli->outbuf,smb_com) = SMBsendend;
3031 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3033 SSVAL(cli->outbuf,smb_vwv0,grp);
3035 cli_setup_packet(cli);
3037 cli_send_smb(cli, True);
3039 if (!cli_receive_smb(cli)) {
3043 if (cli_error(cli, NULL, NULL)) return False;
3049 /****************************************************************************
3051 ****************************************************************************/
3052 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3054 bzero(cli->outbuf,smb_size);
3055 set_message(cli->outbuf,0,0,True);
3056 CVAL(cli->outbuf,smb_com) = SMBdskattr;
3057 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3058 cli_setup_packet(cli);
3060 cli_send_smb(cli, True);
3061 if (!cli_receive_smb(cli)) {
3065 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
3066 *total = SVAL(cli->inbuf,smb_vwv0);
3067 *avail = SVAL(cli->inbuf,smb_vwv3);