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 * set the port that will be used for connections by the client
34 int cli_set_port(struct cli_state *cli, int port)
40 return cli -> port; /* return it incase caller wants it */
44 /****************************************************************************
46 ****************************************************************************/
47 static BOOL cli_receive_smb(struct cli_state *cli)
49 return client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
52 /****************************************************************************
53 send an smb to a fd and re-establish if necessary
54 ****************************************************************************/
55 static BOOL cli_send_smb(struct cli_state *cli, BOOL show)
60 BOOL reestablished=False;
64 show_msg(cli->outbuf);
67 len = smb_len(cli->outbuf) + 4;
69 while (nwritten < len) {
70 ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
71 if (ret <= 0 && errno == EPIPE && !reestablished)
73 DEBUG(5,("cli_send_smb: write error (%s) - reconnecting\n",
76 if (cli_reestablish_connection(cli)) {
83 DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",
93 /*****************************************************
94 RAP error codes - a small start but will be extended.
95 *******************************************************/
103 {5, "User has insufficient privilege" },
104 {86, "The specified password is invalid" },
105 {2226, "Operation only permitted on a Primary Domain Controller" },
106 {2242, "The password of this user has expired." },
107 {2243, "The password of this user cannot change." },
108 {2244, "This password cannot be used now (password history conflict)." },
109 {2245, "The password is shorter than required." },
110 {2246, "The password of this user is too recent to change."},
114 /****************************************************************************
115 return a description of an SMB error
116 ****************************************************************************/
117 static char *cli_smb_errstr(struct cli_state *cli)
119 return smb_errstr(cli->inbuf);
122 /******************************************************
123 Return an error message - either an SMB error or a RAP
125 *******************************************************/
127 char *cli_errstr(struct cli_state *cli)
129 static fstring error_message;
135 * Errors are of three kinds - smb errors,
136 * dealt with by cli_smb_errstr, NT errors,
137 * whose code is in cli.nt_error, and rap
138 * errors, whose error code is in cli.rap_error.
141 cli_error(cli, &errclass, &errnum);
145 return cli_smb_errstr(cli);
149 * Was it an NT error ?
154 char *nt_msg = get_nt_error_msg(cli->nt_error);
158 slprintf(error_message, sizeof(fstring) - 1, "NT code %d", cli->nt_error);
162 fstrcpy(error_message, nt_msg);
165 return error_message;
169 * Must have been a rap error.
172 slprintf(error_message, sizeof(error_message) - 1, "code %d", cli->rap_error);
174 for (i = 0; rap_errmap[i].message != NULL; i++)
176 if (rap_errmap[i].err == cli->rap_error)
178 fstrcpy( error_message, rap_errmap[i].message);
183 return error_message;
186 /****************************************************************************
187 setup basics in a outgoing packet
188 ****************************************************************************/
189 static void cli_setup_packet(struct cli_state *cli)
193 SSVAL(cli->outbuf,smb_pid,cli->pid);
194 SSVAL(cli->outbuf,smb_uid,cli->vuid);
195 SSVAL(cli->outbuf,smb_mid,cli->mid);
196 if (cli->protocol > PROTOCOL_CORE) {
197 SCVAL(cli->outbuf,smb_flg,0x8);
198 SSVAL(cli->outbuf,smb_flg2,0x1);
203 /*****************************************************************************
204 Convert a character pointer in a cli_call_api() response to a form we can use.
205 This function contains code to prevent core dumps if the server returns
207 *****************************************************************************/
208 static char *fix_char_ptr(unsigned int datap, unsigned int converter,
209 char *rdata, int rdrcnt)
211 if (datap == 0) { /* turn NULL pointers into zero length strings */
214 unsigned int offset = datap - converter;
216 if (offset >= rdrcnt) {
217 DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
218 datap, converter, rdrcnt));
221 return &rdata[offset];
226 /****************************************************************************
227 send a SMB trans or trans2 request
228 ****************************************************************************/
229 static BOOL cli_send_trans(struct cli_state *cli, int trans,
230 char *name, int pipe_name_len,
232 uint16 *setup, int lsetup, int msetup,
233 char *param, int lparam, int mparam,
234 char *data, int ldata, int mdata)
237 int this_ldata,this_lparam;
238 int tot_data=0,tot_param=0;
239 char *outdata,*outparam;
242 this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
243 this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
245 bzero(cli->outbuf,smb_size);
246 set_message(cli->outbuf,14+lsetup,0,True);
247 CVAL(cli->outbuf,smb_com) = trans;
248 SSVAL(cli->outbuf,smb_tid, cli->cnum);
249 cli_setup_packet(cli);
251 outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len+1 : 3);
252 outdata = outparam+this_lparam;
254 /* primary request */
255 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
256 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
257 SSVAL(cli->outbuf,smb_mprcnt,mparam); /* mprcnt */
258 SSVAL(cli->outbuf,smb_mdrcnt,mdata); /* mdrcnt */
259 SCVAL(cli->outbuf,smb_msrcnt,msetup); /* msrcnt */
260 SSVAL(cli->outbuf,smb_flags,flags); /* flags */
261 SIVAL(cli->outbuf,smb_timeout,0); /* timeout */
262 SSVAL(cli->outbuf,smb_pscnt,this_lparam); /* pscnt */
263 SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
264 SSVAL(cli->outbuf,smb_dscnt,this_ldata); /* dscnt */
265 SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
266 SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */
267 for (i=0;i<lsetup;i++) /* setup[] */
268 SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
269 p = smb_buf(cli->outbuf);
270 if (trans==SMBtrans) {
271 memcpy(p,name, pipe_name_len + 1); /* name[] */
273 *p++ = 0; /* put in a null smb_name */
274 *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */
276 if (this_lparam) /* param[] */
277 memcpy(outparam,param,this_lparam);
278 if (this_ldata) /* data[] */
279 memcpy(outdata,data,this_ldata);
280 set_message(cli->outbuf,14+lsetup, /* wcnt, bcc */
281 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
283 cli_send_smb(cli, True);
285 if (this_ldata < ldata || this_lparam < lparam) {
286 /* receive interim response */
287 if (!cli_receive_smb(cli) ||
288 CVAL(cli->inbuf,smb_rcls) != 0) {
292 tot_data = this_ldata;
293 tot_param = this_lparam;
295 while (tot_data < ldata || tot_param < lparam) {
296 this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
297 this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
299 set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
300 CVAL(cli->outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
302 outparam = smb_buf(cli->outbuf);
303 outdata = outparam+this_lparam;
305 /* secondary request */
306 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
307 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
308 SSVAL(cli->outbuf,smb_spscnt,this_lparam); /* pscnt */
309 SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
310 SSVAL(cli->outbuf,smb_spsdisp,tot_param); /* psdisp */
311 SSVAL(cli->outbuf,smb_sdscnt,this_ldata); /* dscnt */
312 SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
313 SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */
314 if (trans==SMBtrans2)
315 SSVALS(cli->outbuf,smb_sfid,fid); /* fid */
316 if (this_lparam) /* param[] */
317 memcpy(outparam,param,this_lparam);
318 if (this_ldata) /* data[] */
319 memcpy(outdata,data,this_ldata);
320 set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
321 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
323 cli_send_smb(cli, True);
325 tot_data += this_ldata;
326 tot_param += this_lparam;
334 /****************************************************************************
335 receive a SMB trans or trans2 response allocating the necessary memory
336 ****************************************************************************/
337 static BOOL cli_receive_trans(struct cli_state *cli,int trans,
338 char **param, int *param_len,
339 char **data, int *data_len)
343 int this_data,this_param;
347 *data_len = *param_len = 0;
349 if (!cli_receive_smb(cli))
353 if (CVAL(cli->inbuf,smb_com) != trans) {
354 DEBUG(0,("Expected %s response, got command 0x%02x\n",
355 trans==SMBtrans?"SMBtrans":"SMBtrans2",
356 CVAL(cli->inbuf,smb_com)));
360 /* DOS error "more data" is an acceptable error code */
361 if (cli_error(cli, &eclass, &num) && !(eclass == ERRDOS && num == ERRmoredata))
366 /* parse out the lengths */
367 total_data = SVAL(cli->inbuf,smb_tdrcnt);
368 total_param = SVAL(cli->inbuf,smb_tprcnt);
371 *data = Realloc(*data,total_data);
372 *param = Realloc(*param,total_param);
375 this_data = SVAL(cli->inbuf,smb_drcnt);
376 this_param = SVAL(cli->inbuf,smb_prcnt);
378 if (this_data + *data_len > total_data ||
379 this_param + *param_len > total_param) {
380 DEBUG(1,("Data overflow in cli_receive_trans\n"));
385 memcpy(*data + SVAL(cli->inbuf,smb_drdisp),
386 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff),
389 memcpy(*param + SVAL(cli->inbuf,smb_prdisp),
390 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff),
392 *data_len += this_data;
393 *param_len += this_param;
395 /* parse out the total lengths again - they can shrink! */
396 total_data = SVAL(cli->inbuf,smb_tdrcnt);
397 total_param = SVAL(cli->inbuf,smb_tprcnt);
399 if (total_data <= *data_len && total_param <= *param_len)
402 if (!cli_receive_smb(cli))
406 if (CVAL(cli->inbuf,smb_com) != trans) {
407 DEBUG(0,("Expected %s response, got command 0x%02x\n",
408 trans==SMBtrans?"SMBtrans":"SMBtrans2",
409 CVAL(cli->inbuf,smb_com)));
412 /* DOS error "more data" is an acceptable error code */
413 if (cli_error(cli, &eclass, &num) && eclass != ERRDOS && num != ERRmoredata)
422 /****************************************************************************
423 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
424 ****************************************************************************/
425 BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name, int pipe_name_len,
426 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
427 char *params, uint32 param_count, uint32 max_param_count,
428 char *data, uint32 data_count, uint32 max_data_count,
429 char **rparam, uint32 *rparam_count,
430 char **rdata, uint32 *rdata_count)
432 if (pipe_name_len == 0)
433 pipe_name_len = strlen(pipe_name);
435 cli_send_trans(cli, SMBtrans,
436 pipe_name, pipe_name_len,
437 0,0, /* fid, flags */
438 setup, setup_count, max_setup_count,
439 params, param_count, max_param_count,
440 data, data_count, max_data_count);
442 return (cli_receive_trans(cli, SMBtrans,
443 rparam, (int *)rparam_count,
444 rdata, (int *)rdata_count));
447 /****************************************************************************
449 ****************************************************************************/
450 BOOL cli_api(struct cli_state *cli,
451 char *param, int prcnt, int mprcnt,
452 char *data, int drcnt, int mdrcnt,
453 char **rparam, int *rprcnt,
454 char **rdata, int *rdrcnt)
456 cli_send_trans(cli,SMBtrans,
457 PIPE_LANMAN,strlen(PIPE_LANMAN), /* Name, length */
458 0,0, /* fid, flags */
459 NULL,0,0, /* Setup, length, max */
460 param, prcnt, mprcnt, /* Params, length, max */
461 data, drcnt, mdrcnt /* Data, length, max */
464 return (cli_receive_trans(cli,SMBtrans,
470 /****************************************************************************
471 perform a NetWkstaUserLogon
472 ****************************************************************************/
473 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
481 memset(param, 0, sizeof(param));
483 /* send a SMBtrans command with api NetWkstaUserLogon */
485 SSVAL(p,0,132); /* api number */
487 pstrcpy(p,"OOWb54WrLh");
488 p = skip_string(p,1);
489 pstrcpy(p,"WB21BWDWWDDDDDDDzzzD");
490 p = skip_string(p,1);
499 pstrcpy(p, workstation);
502 SSVAL(p, 0, CLI_BUFFER_SIZE);
504 SSVAL(p, 0, CLI_BUFFER_SIZE);
508 param, PTR_DIFF(p,param),1024, /* param, length, max */
509 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
510 &rparam, &rprcnt, /* return params, return size */
511 &rdata, &rdrcnt /* return data, return size */
513 cli->rap_error = SVAL(rparam,0);
516 if (cli->rap_error == 0) {
517 DEBUG(4,("NetWkstaUserLogon success\n"));
518 cli->privilages = SVAL(p, 24);
519 fstrcpy(cli->eff_name,p+2);
521 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
529 return (cli->rap_error == 0);
532 /****************************************************************************
533 call a NetShareEnum - try and browse available connections on a host
534 ****************************************************************************/
535 BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *))
544 /* now send a SMBtrans command with api RNetShareEnum */
546 SSVAL(p,0,0); /* api number */
549 p = skip_string(p,1);
551 p = skip_string(p,1);
557 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
558 NULL, 0, 0xFFFF, /* data, length, maxlen */
559 &rparam, &rprcnt, /* return params, length */
560 &rdata, &rdrcnt)) /* return data, length */
562 int res = SVAL(rparam,0);
563 int converter=SVAL(rparam,2);
566 if (res == 0 || res == ERRmoredata) {
567 count=SVAL(rparam,4);
570 for (i=0;i<count;i++,p+=20) {
572 int type = SVAL(p,14);
573 int comment_offset = IVAL(p,16) & 0xFFFF;
574 char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
575 fn(sname, type, cmnt);
578 DEBUG(4,("NetShareEnum res=%d\n", res));
581 DEBUG(4,("NetShareEnum failed\n"));
593 /****************************************************************************
594 call a NetServerEnum for the specified workgroup and servertype mask.
595 This function then calls the specified callback function for each name returned.
597 The callback function takes 3 arguments: the machine name, the server type and
599 ****************************************************************************/
600 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
601 void (*fn)(const char *, uint32, const char *))
611 /* send a SMBtrans command with api NetServerEnum */
613 SSVAL(p,0,0x68); /* api number */
615 pstrcpy(p,"WrLehDz");
616 p = skip_string(p,1);
618 pstrcpy(p,"B16BBDz");
620 p = skip_string(p,1);
622 SSVAL(p,2,CLI_BUFFER_SIZE);
627 pstrcpy(p, workgroup);
628 p = skip_string(p,1);
631 param, PTR_DIFF(p,param), 8, /* params, length, max */
632 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
633 &rparam, &rprcnt, /* return params, return size */
634 &rdata, &rdrcnt /* return data, return size */
636 int res = SVAL(rparam,0);
637 int converter=SVAL(rparam,2);
640 if (res == 0 || res == ERRmoredata) {
641 count=SVAL(rparam,4);
644 for (i = 0;i < count;i++, p += 26) {
646 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
647 char *cmnt = comment_offset?(rdata+comment_offset):"";
648 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
650 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
652 fn(sname, stype, cmnt);
674 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
675 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
676 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
677 {PROTOCOL_LANMAN1,"LANMAN1.0"},
678 {PROTOCOL_LANMAN2,"LM1.2X002"},
679 {PROTOCOL_LANMAN2,"Samba"},
680 {PROTOCOL_NT1,"NT LANMAN 1.0"},
681 {PROTOCOL_NT1,"NT LM 0.12"},
686 /****************************************************************************
688 ****************************************************************************/
689 BOOL cli_session_setup(struct cli_state *cli,
691 char *pass, int passlen,
692 char *ntpass, int ntpasslen,
696 fstring pword, ntpword;
698 if (cli->protocol < PROTOCOL_LANMAN1)
703 if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1)
708 if (!IS_BITS_SET_ALL(cli->sec_mode, 1))
710 /* if in share level security then don't send a password now */
713 fstrcpy(ntpword, "");
716 else if ((passlen == 0 || passlen == 1) && (pass[0] == '\0'))
718 /* Null session connect. */
722 else if (passlen == 24 && ntpasslen == 24)
724 if (IS_BITS_SET_ALL(cli->sec_mode, 2))
726 /* encrypted password, implicit from 24-byte lengths */
727 memcpy(pword , pass , 24);
728 memcpy(ntpword, ntpass, 24);
732 DEBUG(0,("cli_session_setup: encrypted passwords not supported by server\n"));
736 else if (ntpasslen == 0 || !IS_BITS_SET_ALL(cli->sec_mode, 2))
738 /* plain-text password: server doesn't support encrypted. */
739 fstrcpy(pword, pass);
740 fstrcpy(ntpword, "");
743 else /* passlen != 0 && ntpasslen != 0 && server supports encryption */
745 /* plain-text password requesting to be encrypted */
746 uchar *key = (uchar *)cli->cryptkey;
747 SMBencrypt ((uchar *)pass , key,(uchar *)pword );
748 SMBNTencrypt((uchar *)ntpass, key,(uchar *)ntpword);
751 /* send a session setup command */
752 bzero(cli->outbuf,smb_size);
754 if (cli->protocol < PROTOCOL_NT1)
756 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
757 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
758 cli_setup_packet(cli);
760 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
761 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
762 SSVAL(cli->outbuf,smb_vwv3,2);
763 SSVAL(cli->outbuf,smb_vwv4,1);
764 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
765 SSVAL(cli->outbuf,smb_vwv7,passlen);
766 p = smb_buf(cli->outbuf);
767 memcpy(p,pword,passlen);
774 set_message(cli->outbuf,13,0,True);
775 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
776 cli_setup_packet(cli);
778 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
779 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
780 SSVAL(cli->outbuf,smb_vwv3,2);
781 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
782 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
783 SSVAL(cli->outbuf,smb_vwv7,passlen);
784 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
785 SSVAL(cli->outbuf,smb_vwv11,0);
786 p = smb_buf(cli->outbuf);
787 memcpy(p,pword,passlen);
788 p += SVAL(cli->outbuf,smb_vwv7);
789 memcpy(p,ntpword,ntpasslen);
790 p += SVAL(cli->outbuf,smb_vwv8);
793 p = skip_string(p,1);
794 pstrcpy(p,workgroup);
796 p = skip_string(p,1);
797 pstrcpy(p,"Unix");p = skip_string(p,1);
798 pstrcpy(p,"Samba");p = skip_string(p,1);
799 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
802 cli_send_smb(cli, True);
803 if (!cli_receive_smb(cli))
805 DEBUG(10,("cli_session_setup: receive smb failed\n"));
809 if (CVAL(cli->inbuf,smb_rcls) != 0) {
813 /* use the returned vuid from now on */
814 cli->vuid = SVAL(cli->inbuf,smb_uid);
816 if (cli->protocol >= PROTOCOL_NT1) {
818 * Save off some of the connected server
821 char *server_domain,*server_os,*server_type;
822 server_os = smb_buf(cli->inbuf);
823 server_type = skip_string(server_os,1);
824 server_domain = skip_string(server_type,1);
825 fstrcpy(cli->server_os, server_os);
826 fstrcpy(cli->server_type, server_type);
827 fstrcpy(cli->server_domain, server_domain);
830 fstrcpy(cli->user_name, user);
835 /****************************************************************************
837 *****************************************************************************/
839 BOOL cli_ulogoff(struct cli_state *cli)
841 bzero(cli->outbuf,smb_size);
842 set_message(cli->outbuf,2,0,True);
843 CVAL(cli->outbuf,smb_com) = SMBulogoffX;
844 cli_setup_packet(cli);
845 SSVAL(cli->outbuf,smb_vwv0,0xFF);
846 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
848 cli_send_smb(cli, True);
849 if (!cli_receive_smb(cli))
852 return CVAL(cli->inbuf,smb_rcls) == 0;
855 /****************************************************************************
857 ****************************************************************************/
858 BOOL cli_send_tconX(struct cli_state *cli,
859 char *share, char *dev, char *pass, int passlen)
861 fstring fullshare, pword;
863 bzero(cli->outbuf,smb_size);
864 bzero(cli->inbuf,smb_size);
866 fstrcpy(cli->share, share);
868 /* in user level security don't send a password now */
869 if (cli->sec_mode & 1) {
874 if ((cli->sec_mode & 2) && *pass && passlen != 24) {
876 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
878 memcpy(pword, pass, passlen);
881 slprintf(fullshare, sizeof(fullshare)-1,
882 "\\\\%s\\%s", cli->desthost, share);
885 set_message(cli->outbuf,4,
886 2 + strlen(fullshare) + passlen + strlen(dev),True);
887 CVAL(cli->outbuf,smb_com) = SMBtconX;
888 cli_setup_packet(cli);
890 SSVAL(cli->outbuf,smb_vwv0,0xFF);
891 SSVAL(cli->outbuf,smb_vwv3,passlen);
893 p = smb_buf(cli->outbuf);
894 memcpy(p,pword,passlen);
896 fstrcpy(p,fullshare);
897 p = skip_string(p,1);
900 SCVAL(cli->inbuf,smb_rcls, 1);
902 cli_send_smb(cli, True);
903 if (!cli_receive_smb(cli))
906 if (CVAL(cli->inbuf,smb_rcls) != 0) {
910 fstrcpy(cli->dev, "A:");
912 if (cli->protocol >= PROTOCOL_NT1) {
913 fstrcpy(cli->dev, smb_buf(cli->inbuf));
916 if (strcasecmp(share,"IPC$")==0) {
917 fstrcpy(cli->dev, "IPC");
920 /* only grab the device if we have a recent protocol level */
921 if (cli->protocol >= PROTOCOL_NT1 &&
922 smb_buflen(cli->inbuf) == 3) {
923 /* almost certainly win95 - enable bug fixes */
927 cli->cnum = SVAL(cli->inbuf,smb_tid);
932 /****************************************************************************
933 send a tree disconnect
934 ****************************************************************************/
935 BOOL cli_tdis(struct cli_state *cli)
937 bzero(cli->outbuf,smb_size);
938 set_message(cli->outbuf,0,0,True);
939 CVAL(cli->outbuf,smb_com) = SMBtdis;
940 SSVAL(cli->outbuf,smb_tid,cli->cnum);
941 cli_setup_packet(cli);
943 cli_send_smb(cli, True);
944 if (!cli_receive_smb(cli))
947 return CVAL(cli->inbuf,smb_rcls) == 0;
950 /****************************************************************************
952 ****************************************************************************/
953 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
957 bzero(cli->outbuf,smb_size);
958 bzero(cli->inbuf,smb_size);
960 set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
962 CVAL(cli->outbuf,smb_com) = SMBmv;
963 SSVAL(cli->outbuf,smb_tid,cli->cnum);
964 cli_setup_packet(cli);
966 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
968 p = smb_buf(cli->outbuf);
970 pstrcpy(p,fname_src);
971 p = skip_string(p,1);
973 pstrcpy(p,fname_dst);
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_unlink(struct cli_state *cli, char *fname)
994 bzero(cli->outbuf,smb_size);
995 bzero(cli->inbuf,smb_size);
997 set_message(cli->outbuf,1, 2 + strlen(fname),True);
999 CVAL(cli->outbuf,smb_com) = SMBunlink;
1000 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1001 cli_setup_packet(cli);
1003 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
1005 p = smb_buf(cli->outbuf);
1009 cli_send_smb(cli, True);
1010 if (!cli_receive_smb(cli)) {
1014 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1021 /****************************************************************************
1023 ****************************************************************************/
1024 BOOL cli_mkdir(struct cli_state *cli, char *dname)
1028 bzero(cli->outbuf,smb_size);
1029 bzero(cli->inbuf,smb_size);
1031 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1033 CVAL(cli->outbuf,smb_com) = SMBmkdir;
1034 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1035 cli_setup_packet(cli);
1037 p = smb_buf(cli->outbuf);
1041 cli_send_smb(cli, True);
1042 if (!cli_receive_smb(cli)) {
1046 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1053 /****************************************************************************
1055 ****************************************************************************/
1056 BOOL cli_rmdir(struct cli_state *cli, char *dname)
1060 bzero(cli->outbuf,smb_size);
1061 bzero(cli->inbuf,smb_size);
1063 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1065 CVAL(cli->outbuf,smb_com) = SMBrmdir;
1066 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1067 cli_setup_packet(cli);
1069 p = smb_buf(cli->outbuf);
1073 cli_send_smb(cli, True);
1074 if (!cli_receive_smb(cli)) {
1078 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1087 /****************************************************************************
1089 ****************************************************************************/
1090 int cli_nt_create(struct cli_state *cli, char *fname)
1094 bzero(cli->outbuf,smb_size);
1095 bzero(cli->inbuf,smb_size);
1097 set_message(cli->outbuf,24,1 + strlen(fname),True);
1099 CVAL(cli->outbuf,smb_com) = SMBntcreateX;
1100 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1101 cli_setup_packet(cli);
1103 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1104 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0x06);
1105 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
1106 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, 0x2019f);
1107 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0);
1108 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03);
1109 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01);
1110 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0);
1111 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
1112 SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname));
1114 p = smb_buf(cli->outbuf);
1116 p = skip_string(p,1);
1118 cli_send_smb(cli, True);
1119 if (!cli_receive_smb(cli)) {
1123 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1127 return SVAL(cli->inbuf,smb_vwv2 + 1);
1131 /****************************************************************************
1133 ****************************************************************************/
1134 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
1138 unsigned accessmode=0;
1140 /* you must open for RW not just write - otherwise getattrE doesn't
1142 if ((flags & O_ACCMODE) == O_WRONLY && strncmp(cli->dev, "LPT", 3)) {
1143 flags = (flags & ~O_ACCMODE) | O_RDWR;
1146 if (flags & O_CREAT)
1148 if (!(flags & O_EXCL)) {
1149 if (flags & O_TRUNC)
1155 accessmode = (share_mode<<4);
1157 if ((flags & O_ACCMODE) == O_RDWR) {
1159 } else if ((flags & O_ACCMODE) == O_WRONLY) {
1164 if ((flags & O_SYNC) == O_SYNC) {
1165 accessmode |= (1<<14);
1169 bzero(cli->outbuf,smb_size);
1170 bzero(cli->inbuf,smb_size);
1172 set_message(cli->outbuf,15,1 + strlen(fname),True);
1174 CVAL(cli->outbuf,smb_com) = SMBopenX;
1175 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1176 cli_setup_packet(cli);
1178 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1179 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1180 SSVAL(cli->outbuf,smb_vwv3,accessmode);
1181 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1182 SSVAL(cli->outbuf,smb_vwv5,0);
1183 SSVAL(cli->outbuf,smb_vwv8,openfn);
1185 p = smb_buf(cli->outbuf);
1187 p = skip_string(p,1);
1189 cli_send_smb(cli, True);
1190 if (!cli_receive_smb(cli)) {
1194 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1198 return SVAL(cli->inbuf,smb_vwv2);
1204 /****************************************************************************
1206 ****************************************************************************/
1207 BOOL cli_close(struct cli_state *cli, int fnum)
1209 bzero(cli->outbuf,smb_size);
1210 bzero(cli->inbuf,smb_size);
1212 set_message(cli->outbuf,3,0,True);
1214 CVAL(cli->outbuf,smb_com) = SMBclose;
1215 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1216 cli_setup_packet(cli);
1218 SSVAL(cli->outbuf,smb_vwv0,fnum);
1219 SIVALS(cli->outbuf,smb_vwv1,-1);
1221 cli_send_smb(cli, True);
1222 if (!cli_receive_smb(cli)) {
1226 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1234 /****************************************************************************
1236 ****************************************************************************/
1237 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1240 int saved_timeout = cli->timeout;
1242 bzero(cli->outbuf,smb_size);
1243 bzero(cli->inbuf,smb_size);
1245 set_message(cli->outbuf,8,10,True);
1247 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1248 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1249 cli_setup_packet(cli);
1251 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1252 SSVAL(cli->outbuf,smb_vwv2,fnum);
1253 CVAL(cli->outbuf,smb_vwv3) = 0;
1254 SIVALS(cli->outbuf, smb_vwv4, timeout);
1255 SSVAL(cli->outbuf,smb_vwv6,0);
1256 SSVAL(cli->outbuf,smb_vwv7,1);
1258 p = smb_buf(cli->outbuf);
1259 SSVAL(p, 0, cli->pid);
1260 SIVAL(p, 2, offset);
1262 cli_send_smb(cli, True);
1264 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout;
1266 if (!cli_receive_smb(cli)) {
1267 cli->timeout = saved_timeout;
1271 cli->timeout = saved_timeout;
1273 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1280 /****************************************************************************
1282 ****************************************************************************/
1283 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1287 bzero(cli->outbuf,smb_size);
1288 bzero(cli->inbuf,smb_size);
1290 set_message(cli->outbuf,8,10,True);
1292 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1293 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1294 cli_setup_packet(cli);
1296 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1297 SSVAL(cli->outbuf,smb_vwv2,fnum);
1298 CVAL(cli->outbuf,smb_vwv3) = 0;
1299 SIVALS(cli->outbuf, smb_vwv4, timeout);
1300 SSVAL(cli->outbuf,smb_vwv6,1);
1301 SSVAL(cli->outbuf,smb_vwv7,0);
1303 p = smb_buf(cli->outbuf);
1304 SSVAL(p, 0, cli->pid);
1305 SIVAL(p, 2, offset);
1308 cli_send_smb(cli, True);
1309 if (!cli_receive_smb(cli)) {
1313 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1322 /****************************************************************************
1323 issue a single SMBread and don't wait for a reply
1324 ****************************************************************************/
1325 static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
1328 bzero(cli->outbuf,smb_size);
1329 bzero(cli->inbuf,smb_size);
1331 set_message(cli->outbuf,10,0,True);
1333 CVAL(cli->outbuf,smb_com) = SMBreadX;
1334 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1335 cli_setup_packet(cli);
1337 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1338 SSVAL(cli->outbuf,smb_vwv2,fnum);
1339 SIVAL(cli->outbuf,smb_vwv3,offset);
1340 SSVAL(cli->outbuf,smb_vwv5,size);
1341 SSVAL(cli->outbuf,smb_vwv6,size);
1342 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1344 cli_send_smb(cli, True);
1347 /****************************************************************************
1349 ****************************************************************************/
1350 size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
1356 int mpx = MAX(cli->max_mux-1, 1);
1357 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1359 int blocks = (size + (block-1)) / block;
1361 if (size == 0) return 0;
1363 while (received < blocks) {
1366 while (issued - received < mpx && issued < blocks) {
1367 int size1 = MIN(block, size-issued*block);
1368 cli_issue_read(cli, fnum, offset+issued*block, size1, issued);
1372 if (!cli_receive_smb(cli)) {
1377 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1378 size2 = SVAL(cli->inbuf, smb_vwv5);
1380 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1381 blocks = MIN(blocks, mid-1);
1386 blocks = MIN(blocks, mid-1);
1387 /* this distinguishes EOF from an error */
1388 total = MAX(total, 0);
1392 if (size2 > block) {
1393 DEBUG(0,("server returned more than we wanted!\n"));
1396 if (mid >= issued) {
1397 DEBUG(0,("invalid mid from server!\n"));
1400 p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
1402 memcpy(buf+mid*block, p, size2);
1404 total = MAX(total, mid*block + size2);
1407 while (received < issued) {
1408 cli_receive_smb(cli);
1416 /****************************************************************************
1417 issue a single SMBwrite and don't wait for a reply
1418 ****************************************************************************/
1419 static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf,
1424 bzero(cli->outbuf,smb_size);
1425 bzero(cli->inbuf,smb_size);
1427 set_message(cli->outbuf,12,size,True);
1429 CVAL(cli->outbuf,smb_com) = SMBwriteX;
1430 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1431 cli_setup_packet(cli);
1433 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1434 SSVAL(cli->outbuf,smb_vwv2,fnum);
1436 SIVAL(cli->outbuf,smb_vwv3,offset);
1437 SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0);
1438 SSVAL(cli->outbuf,smb_vwv7,mode);
1440 SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0);
1441 SSVAL(cli->outbuf,smb_vwv10,size);
1442 SSVAL(cli->outbuf,smb_vwv11,
1443 smb_buf(cli->outbuf) - smb_base(cli->outbuf));
1445 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
1446 memcpy(p, buf, size);
1448 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1450 cli_send_smb(cli, True);
1453 /****************************************************************************
1455 write_mode: 0x0001 disallow write cacheing
1456 0x0002 return bytes remaining
1457 0x0004 use raw named pipe protocol
1458 0x0008 start of message mode named pipe protocol
1459 ****************************************************************************/
1460 ssize_t cli_write(struct cli_state *cli,
1461 int fnum, uint16 write_mode,
1462 char *buf, off_t offset, size_t size)
1467 int mpx = MAX(cli->max_mux-1, 1);
1468 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1470 int blocks = (size + (block-1)) / block;
1472 if (size == 0) return 0;
1474 while (received < blocks) {
1477 while (issued - received < mpx && issued < blocks) {
1478 int size1 = MIN(block, size-issued*block);
1479 cli_issue_write(cli, fnum, offset+issued*block,
1486 if (!cli_receive_smb(cli)) {
1491 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1492 size2 = SVAL(cli->inbuf, smb_vwv2);
1494 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1495 blocks = MIN(blocks, mid-1);
1500 blocks = MIN(blocks, mid-1);
1501 /* this distinguishes EOF from an error */
1502 total = MAX(total, 0);
1508 total = MAX(total, mid*block + size2);
1511 while (received < issued) {
1512 cli_receive_smb(cli);
1520 /****************************************************************************
1521 do a SMBgetattrE call
1522 ****************************************************************************/
1523 BOOL cli_getattrE(struct cli_state *cli, int fd,
1524 uint16 *attr, size_t *size,
1525 time_t *c_time, time_t *a_time, time_t *m_time)
1527 bzero(cli->outbuf,smb_size);
1528 bzero(cli->inbuf,smb_size);
1530 set_message(cli->outbuf,2,0,True);
1532 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
1533 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1534 cli_setup_packet(cli);
1536 SSVAL(cli->outbuf,smb_vwv0,fd);
1538 cli_send_smb(cli, True);
1539 if (!cli_receive_smb(cli)) {
1543 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1548 *size = IVAL(cli->inbuf, smb_vwv6);
1552 *attr = SVAL(cli->inbuf,smb_vwv10);
1556 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
1560 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
1564 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
1571 /****************************************************************************
1573 ****************************************************************************/
1574 BOOL cli_getatr(struct cli_state *cli, char *fname,
1575 uint16 *attr, size_t *size, time_t *t)
1579 bzero(cli->outbuf,smb_size);
1580 bzero(cli->inbuf,smb_size);
1582 set_message(cli->outbuf,0,strlen(fname)+2,True);
1584 CVAL(cli->outbuf,smb_com) = SMBgetatr;
1585 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1586 cli_setup_packet(cli);
1588 p = smb_buf(cli->outbuf);
1590 pstrcpy(p+1, fname);
1592 cli_send_smb(cli, True);
1593 if (!cli_receive_smb(cli)) {
1597 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1602 *size = IVAL(cli->inbuf, smb_vwv3);
1606 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1610 *attr = SVAL(cli->inbuf,smb_vwv0);
1618 /****************************************************************************
1620 ****************************************************************************/
1621 BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
1625 bzero(cli->outbuf,smb_size);
1626 bzero(cli->inbuf,smb_size);
1628 set_message(cli->outbuf,8,strlen(fname)+4,True);
1630 CVAL(cli->outbuf,smb_com) = SMBsetatr;
1631 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1632 cli_setup_packet(cli);
1634 SSVAL(cli->outbuf,smb_vwv0, attr);
1635 put_dos_date3(cli->outbuf,smb_vwv1, t);
1637 p = smb_buf(cli->outbuf);
1639 pstrcpy(p+1, fname);
1640 p = skip_string(p,1);
1643 cli_send_smb(cli, True);
1644 if (!cli_receive_smb(cli)) {
1648 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1655 /****************************************************************************
1656 send a qpathinfo call
1657 ****************************************************************************/
1658 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
1659 time_t *c_time, time_t *a_time, time_t *m_time,
1660 size_t *size, uint16 *mode)
1664 uint16 setup = TRANSACT2_QPATHINFO;
1666 char *rparam=NULL, *rdata=NULL;
1669 time_t (*date_fn)(void *);
1671 param_len = strlen(fname) + 7;
1673 memset(param, 0, param_len);
1674 SSVAL(param, 0, SMB_INFO_STANDARD);
1675 pstrcpy(¶m[6], fname);
1678 ret = (cli_send_trans(cli, SMBtrans2,
1679 NULL, 0, /* Name, length */
1680 -1, 0, /* fid, flags */
1681 &setup, 1, 0, /* setup, length, max */
1682 param, param_len, 10, /* param, length, max */
1683 NULL, data_len, cli->max_xmit /* data, length, max */
1685 cli_receive_trans(cli, SMBtrans2,
1686 &rparam, ¶m_len,
1687 &rdata, &data_len));
1689 /* we need to work around a Win95 bug - sometimes
1690 it gives ERRSRV/ERRerror temprarily */
1693 cli_error(cli, &eclass, &ecode);
1694 if (eclass != ERRSRV || ecode != ERRerror) break;
1697 } while (count-- && ret==False);
1699 if (!ret || !rdata || data_len < 22) {
1704 date_fn = make_unix_date;
1706 date_fn = make_unix_date2;
1710 *c_time = date_fn(rdata+0);
1713 *a_time = date_fn(rdata+4);
1716 *m_time = date_fn(rdata+8);
1719 *size = IVAL(rdata, 12);
1722 *mode = SVAL(rdata,l1_attrFile);
1725 if (rdata) free(rdata);
1726 if (rparam) free(rparam);
1730 /****************************************************************************
1731 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1732 ****************************************************************************/
1733 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
1734 time_t *c_time, time_t *a_time, time_t *m_time,
1735 time_t *w_time, size_t *size, uint16 *mode,
1740 uint16 setup = TRANSACT2_QPATHINFO;
1742 char *rparam=NULL, *rdata=NULL;
1744 param_len = strlen(fname) + 7;
1746 memset(param, 0, param_len);
1747 SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1748 pstrcpy(¶m[6], fname);
1750 if (!cli_send_trans(cli, SMBtrans2,
1751 NULL, 0, /* name, length */
1752 -1, 0, /* fid, flags */
1753 &setup, 1, 0, /* setup, length, max */
1754 param, param_len, 10, /* param, length, max */
1755 NULL, data_len, cli->max_xmit /* data, length, max */
1760 if (!cli_receive_trans(cli, SMBtrans2,
1761 &rparam, ¶m_len,
1762 &rdata, &data_len)) {
1766 if (!rdata || data_len < 22) {
1771 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1774 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1777 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1780 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1783 *mode = SVAL(rdata, 32);
1786 *size = IVAL(rdata, 40);
1789 *ino = IVAL(rdata, 64);
1792 if (rdata) free(rdata);
1793 if (rparam) free(rparam);
1798 /****************************************************************************
1799 send a qfileinfo call
1800 ****************************************************************************/
1801 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
1802 uint16 *mode, size_t *size,
1803 time_t *c_time, time_t *a_time, time_t *m_time,
1804 time_t *w_time, SMB_INO_T *ino)
1808 uint16 setup = TRANSACT2_QFILEINFO;
1810 char *rparam=NULL, *rdata=NULL;
1812 /* if its a win95 server then fail this - win95 totally screws it
1814 if (cli->win95) return False;
1818 memset(param, 0, param_len);
1819 SSVAL(param, 0, fnum);
1820 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
1822 if (!cli_send_trans(cli, SMBtrans2,
1823 NULL, 0, /* name, length */
1824 -1, 0, /* fid, flags */
1825 &setup, 1, 0, /* setup, length, max */
1826 param, param_len, 2, /* param, length, max */
1827 NULL, data_len, cli->max_xmit /* data, length, max */
1832 if (!cli_receive_trans(cli, SMBtrans2,
1833 &rparam, ¶m_len,
1834 &rdata, &data_len)) {
1838 if (!rdata || data_len < 68) {
1843 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1846 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1849 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1852 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1855 *mode = SVAL(rdata, 32);
1858 *size = IVAL(rdata, 40);
1861 *ino = IVAL(rdata, 64);
1864 if (rdata) free(rdata);
1865 if (rparam) free(rparam);
1870 /****************************************************************************
1871 interpret a long filename structure - this is mostly guesses at the moment
1872 The length of the structure is returned
1873 The structure of a long filename depends on the info level. 260 is used
1874 by NT and 2 is used by OS/2
1875 ****************************************************************************/
1876 static int interpret_long_filename(int level,char *p,file_info *finfo)
1878 extern file_info def_finfo;
1881 memcpy(finfo,&def_finfo,sizeof(*finfo));
1885 case 1: /* OS/2 understands this */
1887 /* these dates are converted to GMT by make_unix_date */
1888 finfo->ctime = make_unix_date2(p+4);
1889 finfo->atime = make_unix_date2(p+8);
1890 finfo->mtime = make_unix_date2(p+12);
1891 finfo->size = IVAL(p,16);
1892 finfo->mode = CVAL(p,24);
1893 pstrcpy(finfo->name,p+27);
1895 return(28 + CVAL(p,26));
1897 case 2: /* this is what OS/2 uses mostly */
1899 /* these dates are converted to GMT by make_unix_date */
1900 finfo->ctime = make_unix_date2(p+4);
1901 finfo->atime = make_unix_date2(p+8);
1902 finfo->mtime = make_unix_date2(p+12);
1903 finfo->size = IVAL(p,16);
1904 finfo->mode = CVAL(p,24);
1905 pstrcpy(finfo->name,p+31);
1907 return(32 + CVAL(p,30));
1909 /* levels 3 and 4 are untested */
1912 /* these dates are probably like the other ones */
1913 finfo->ctime = make_unix_date2(p+8);
1914 finfo->atime = make_unix_date2(p+12);
1915 finfo->mtime = make_unix_date2(p+16);
1916 finfo->size = IVAL(p,20);
1917 finfo->mode = CVAL(p,28);
1918 pstrcpy(finfo->name,p+33);
1920 return(SVAL(p,4)+4);
1924 /* these dates are probably like the other ones */
1925 finfo->ctime = make_unix_date2(p+8);
1926 finfo->atime = make_unix_date2(p+12);
1927 finfo->mtime = make_unix_date2(p+16);
1928 finfo->size = IVAL(p,20);
1929 finfo->mode = CVAL(p,28);
1930 pstrcpy(finfo->name,p+37);
1932 return(SVAL(p,4)+4);
1934 case 260: /* NT uses this, but also accepts 2 */
1936 int ret = SVAL(p,0);
1938 p += 4; /* next entry offset */
1939 p += 4; /* fileindex */
1941 /* these dates appear to arrive in a
1942 weird way. It seems to be localtime
1943 plus the serverzone given in the
1944 initial connect. This is GMT when
1945 DST is not in effect and one hour
1946 from GMT otherwise. Can this really
1949 I suppose this could be called
1950 kludge-GMT. Is is the GMT you get
1951 by using the current DST setting on
1952 a different localtime. It will be
1953 cheap to calculate, I suppose, as
1954 no DST tables will be needed */
1956 finfo->ctime = interpret_long_date(p); p += 8;
1957 finfo->atime = interpret_long_date(p); p += 8;
1958 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
1959 finfo->size = IVAL(p,0); p += 8;
1960 p += 8; /* alloc size */
1961 finfo->mode = CVAL(p,0); p += 4;
1962 namelen = IVAL(p,0); p += 4;
1963 p += 4; /* EA size */
1964 p += 2; /* short name len? */
1965 p += 24; /* short name? */
1966 StrnCpy(finfo->name,p,namelen);
1972 DEBUG(1,("Unknown long filename format %d\n",level));
1977 /****************************************************************************
1978 do a directory listing, calling fn on each file found
1979 ****************************************************************************/
1980 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
1981 void (*fn)(file_info *, const char *))
1983 int max_matches = 512;
1984 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1985 int info_level = cli->protocol<PROTOCOL_NT1?1:260;
1990 char *dirlist = NULL;
1991 int dirlist_len = 0;
1992 int total_received = -1;
1994 int ff_resume_key = 0;
1995 int ff_searchcount=0;
1998 int ff_dir_handle=0;
2000 char *rparam=NULL, *rdata=NULL;
2001 int param_len, data_len;
2008 while (ff_eos == 0) {
2010 if (loop_count > 200) {
2011 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
2015 param_len = 12+strlen(mask)+1;
2018 setup = TRANSACT2_FINDFIRST;
2019 SSVAL(param,0,attribute); /* attribute */
2020 SSVAL(param,2,max_matches); /* max count */
2021 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
2022 SSVAL(param,6,info_level);
2024 pstrcpy(param+12,mask);
2026 setup = TRANSACT2_FINDNEXT;
2027 SSVAL(param,0,ff_dir_handle);
2028 SSVAL(param,2,max_matches); /* max count */
2029 SSVAL(param,4,info_level);
2030 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
2031 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
2032 pstrcpy(param+12,mask);
2034 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
2035 ff_dir_handle,ff_resume_key,ff_lastname,mask));
2038 if (!cli_send_trans(cli, SMBtrans2,
2039 NULL, 0, /* Name, length */
2040 -1, 0, /* fid, flags */
2041 &setup, 1, 0, /* setup, length, max */
2042 param, param_len, 10, /* param, length, max */
2044 cli->max_xmit /* data, length, max */
2049 if (!cli_receive_trans(cli, SMBtrans2,
2050 &rparam, ¶m_len,
2051 &rdata, &data_len)) {
2052 /* we need to work around a Win95 bug - sometimes
2053 it gives ERRSRV/ERRerror temprarily */
2056 cli_error(cli, &eclass, &ecode);
2057 if (eclass != ERRSRV || ecode != ERRerror) break;
2062 if (total_received == -1) total_received = 0;
2064 /* parse out some important return info */
2067 ff_dir_handle = SVAL(p,0);
2068 ff_searchcount = SVAL(p,2);
2070 ff_lastname = SVAL(p,8);
2072 ff_searchcount = SVAL(p,0);
2074 ff_lastname = SVAL(p,6);
2077 if (ff_searchcount == 0)
2080 /* point to the data bytes */
2083 /* we might need the lastname for continuations */
2084 if (ff_lastname > 0) {
2089 StrnCpy(mask,p+ff_lastname,
2090 data_len-ff_lastname);
2093 pstrcpy(mask,p + ff_lastname + 1);
2101 /* and add them to the dirlist pool */
2102 dirlist = Realloc(dirlist,dirlist_len + data_len);
2105 DEBUG(0,("Failed to expand dirlist\n"));
2109 /* put in a length for the last entry, to ensure we can chain entries
2110 into the next packet */
2111 for (p2=p,i=0;i<(ff_searchcount-1);i++)
2112 p2 += interpret_long_filename(info_level,p2,NULL);
2113 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
2115 /* grab the data for later use */
2116 memcpy(dirlist+dirlist_len,p,data_len);
2117 dirlist_len += data_len;
2119 total_received += ff_searchcount;
2121 if (rdata) free(rdata); rdata = NULL;
2122 if (rparam) free(rparam); rparam = NULL;
2124 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
2125 ff_searchcount,ff_eos,ff_resume_key));
2130 for (p=dirlist,i=0;i<total_received;i++) {
2131 p += interpret_long_filename(info_level,p,&finfo);
2135 /* free up the dirlist buffer */
2136 if (dirlist) free(dirlist);
2137 return(total_received);
2141 /****************************************************************************
2142 Send a SamOEMChangePassword command
2143 ****************************************************************************/
2145 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
2146 const char *old_password)
2148 char param[16+sizeof(fstring)];
2151 fstring upper_case_old_pw;
2152 fstring upper_case_new_pw;
2153 unsigned char old_pw_hash[16];
2154 unsigned char new_pw_hash[16];
2157 char *rparam = NULL;
2161 if (strlen(user) >= sizeof(fstring)-1) {
2162 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
2166 SSVAL(p,0,214); /* SamOEMChangePassword command. */
2169 p = skip_string(p,1);
2170 pstrcpy(p, "B516B16");
2171 p = skip_string(p,1);
2173 p = skip_string(p,1);
2177 param_len = PTR_DIFF(p,param);
2180 * Get the Lanman hash of the old password, we
2181 * use this as the key to make_oem_passwd_hash().
2183 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
2184 fstrcpy(upper_case_old_pw, old_password);
2185 strupper(upper_case_old_pw);
2186 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
2188 if (!make_oem_passwd_hash( data, new_password, old_pw_hash, False))
2194 * Now place the old password hash in the data.
2196 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
2197 fstrcpy(upper_case_new_pw, new_password);
2198 strupper(upper_case_new_pw);
2200 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
2202 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
2206 if (!cli_send_trans(cli,SMBtrans,
2207 PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */
2208 0,0, /* fid, flags */
2209 NULL,0,0, /* setup, length, max */
2210 param,param_len,2, /* param, length, max */
2211 data,data_len,0 /* data, length, max */
2214 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
2219 if (cli_receive_trans(cli,SMBtrans,
2223 cli->rap_error = SVAL(rparam,0);
2231 return (cli->rap_error == 0);
2234 /****************************************************************************
2235 send a negprot command
2236 ****************************************************************************/
2237 BOOL cli_negprot(struct cli_state *cli)
2243 bzero(cli->outbuf,smb_size);
2245 /* setup the protocol strings */
2246 for (plength=0,numprots=0;
2247 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2249 plength += strlen(prots[numprots].name)+2;
2251 set_message(cli->outbuf,0,plength,True);
2253 p = smb_buf(cli->outbuf);
2255 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2258 pstrcpy(p,prots[numprots].name);
2262 CVAL(cli->outbuf,smb_com) = SMBnegprot;
2263 cli_setup_packet(cli);
2265 CVAL(smb_buf(cli->outbuf),0) = 2;
2267 cli_send_smb(cli, True);
2268 if (!cli_receive_smb(cli))
2273 if (CVAL(cli->inbuf,smb_rcls) != 0 ||
2274 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
2278 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
2281 if (cli->protocol >= PROTOCOL_NT1) {
2283 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
2284 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
2285 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
2286 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
2287 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
2288 /* this time arrives in real GMT */
2289 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
2290 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2291 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
2292 if (cli->capabilities & 1) {
2293 cli->readbraw_supported = True;
2294 cli->writebraw_supported = True;
2296 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2297 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
2298 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
2299 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
2300 cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
2301 /* this time is converted to GMT by make_unix_date */
2302 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
2303 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
2304 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
2305 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2307 /* the old core protocol */
2309 cli->serverzone = TimeDiff(time(NULL));
2312 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2318 /****************************************************************************
2319 send a session request. see rfc1002.txt 4.3 and 4.3.2
2320 ****************************************************************************/
2321 BOOL cli_session_request(struct cli_state *cli,
2322 struct nmb_name *calling, struct nmb_name *called)
2326 /* send a session request (RFC 1002) */
2328 memcpy(&(cli->calling), calling, sizeof(*calling));
2329 memcpy(&(cli->called ), called , sizeof(*called ));
2331 /* put in the destination name */
2332 p = cli->outbuf+len;
2333 name_mangle(cli->called .name, p, cli->called .name_type);
2337 p = cli->outbuf+len;
2338 name_mangle(cli->calling.name, p, cli->calling.name_type);
2341 /* setup the packet length */
2342 _smb_setlen(cli->outbuf,len);
2343 CVAL(cli->outbuf,0) = 0x81;
2347 #endif /* WITH_SSL */
2349 cli_send_smb(cli, False);
2350 DEBUG(5,("Sent session request\n"));
2352 if (!cli_receive_smb(cli))
2356 if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
2357 if (!sslutil_fd_is_ssl(cli->fd)){
2358 if (sslutil_connect(cli->fd) == 0)
2362 #endif /* WITH_SSL */
2364 if (CVAL(cli->inbuf,0) != 0x82) {
2365 /* This is the wrong place to put the error... JRA. */
2366 cli->rap_error = CVAL(cli->inbuf,0);
2373 /****************************************************************************
2374 open the client sockets
2375 ****************************************************************************/
2376 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
2378 extern struct in_addr ipzero;
2380 fstrcpy(cli->desthost, host);
2382 if (!ip || ip_equal(*ip, ipzero)) {
2383 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
2386 if (ip) *ip = cli->dest_ip;
2392 if (cli -> port == 0) cli -> port = 139;
2394 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2395 cli -> port, cli->timeout);
2403 /****************************************************************************
2404 initialise a client structure
2405 ****************************************************************************/
2406 struct cli_state *cli_initialise(struct cli_state *cli)
2409 cli = (struct cli_state *)malloc(sizeof(*cli));
2415 if (cli->initialised) {
2424 cli->pid = (uint16)getpid();
2426 cli->vuid = UID_FIELD_INVALID;
2427 cli->protocol = PROTOCOL_NT1;
2428 cli->timeout = 20000;
2429 cli->bufsize = CLI_BUFFER_SIZE+4;
2430 cli->max_xmit = cli->bufsize;
2431 cli->outbuf = (char *)malloc(cli->bufsize);
2432 cli->inbuf = (char *)malloc(cli->bufsize);
2433 if (!cli->outbuf || !cli->inbuf)
2438 cli->initialised = 1;
2443 /****************************************************************************
2444 shutdown a client structure
2445 ****************************************************************************/
2446 void cli_shutdown(struct cli_state *cli)
2448 DEBUG(10,("cli_shutdown\n"));
2459 sslutil_disconnect(cli->fd);
2460 #endif /* WITH_SSL */
2465 memset(cli, 0, sizeof(*cli));
2469 /****************************************************************************
2470 return error codes for the last packet
2471 returns 0 if there was no error and the best approx of a unix errno
2474 for 32 bit "warnings", a return code of 0 is expected.
2476 ****************************************************************************/
2477 int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
2483 if (!cli->initialised)
2485 DEBUG(0,("cli_error: client state uninitialised!\n"));
2489 flgs2 = SVAL(cli->inbuf,smb_flg2);
2491 if (eclass) *eclass = 0;
2494 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
2495 /* 32 bit error codes detected */
2496 uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
2497 if (num) *num = nt_err;
2498 DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
2499 if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0;
2501 switch (nt_err & 0xFFFFFF) {
2502 case NT_STATUS_ACCESS_VIOLATION: return EACCES;
2503 case NT_STATUS_NO_SUCH_FILE: return ENOENT;
2504 case NT_STATUS_NO_SUCH_DEVICE: return ENODEV;
2505 case NT_STATUS_INVALID_HANDLE: return EBADF;
2506 case NT_STATUS_NO_MEMORY: return ENOMEM;
2507 case NT_STATUS_ACCESS_DENIED: return EACCES;
2508 case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
2509 case NT_STATUS_SHARING_VIOLATION: return EBUSY;
2510 case NT_STATUS_OBJECT_PATH_INVALID: return ENOTDIR;
2511 case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
2514 /* for all other cases - a default code */
2518 rcls = CVAL(cli->inbuf,smb_rcls);
2519 code = SVAL(cli->inbuf,smb_err);
2520 if (rcls == 0) return 0;
2522 if (eclass) *eclass = rcls;
2523 if (num ) *num = code;
2525 if (rcls == ERRDOS) {
2527 case ERRbadfile: return ENOENT;
2528 case ERRbadpath: return ENOTDIR;
2529 case ERRnoaccess: return EACCES;
2530 case ERRfilexists: return EEXIST;
2531 case ERRrename: return EEXIST;
2532 case ERRbadshare: return EBUSY;
2533 case ERRlock: return EBUSY;
2536 if (rcls == ERRSRV) {
2538 case ERRbadpw: return EPERM;
2539 case ERRaccess: return EACCES;
2540 case ERRnoresource: return ENOMEM;
2541 case ERRinvdevice: return ENODEV;
2542 case ERRinvnetname: return ENODEV;
2545 /* for other cases */
2549 /****************************************************************************
2550 set socket options on a open connection
2551 ****************************************************************************/
2552 void cli_sockopt(struct cli_state *cli, char *options)
2554 set_socket_options(cli->fd, options);
2557 /****************************************************************************
2558 set the PID to use for smb messages. Return the old pid.
2559 ****************************************************************************/
2560 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
2562 uint16 ret = cli->pid;
2567 /****************************************************************************
2568 re-establishes a connection
2569 ****************************************************************************/
2570 BOOL cli_reestablish_connection(struct cli_state *cli)
2572 struct nmb_name calling;
2573 struct nmb_name called;
2577 BOOL do_tcon = False;
2578 int oldfd = cli->fd;
2580 if (!cli->initialised || cli->fd == -1)
2582 DEBUG(3,("cli_reestablish_connection: not connected\n"));
2586 /* copy the parameters necessary to re-establish the connection */
2590 fstrcpy(share, cli->share);
2591 fstrcpy(dev , cli->dev);
2595 memcpy(&called , &(cli->called ), sizeof(called ));
2596 memcpy(&calling, &(cli->calling), sizeof(calling));
2597 fstrcpy(dest_host, cli->full_dest_host_name);
2599 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2600 nmb_namestr(&calling), nmb_namestr(&called),
2601 inet_ntoa(cli->dest_ip),
2602 cli->user_name, cli->domain));
2606 if (cli_establish_connection(cli,
2607 dest_host, &cli->dest_ip,
2609 share, dev, False, do_tcon)) {
2610 if (cli->fd != oldfd) {
2611 if (dup2(cli->fd, oldfd) == oldfd) {
2620 /****************************************************************************
2621 establishes a connection right up to doing tconX, reading in a password.
2622 ****************************************************************************/
2623 BOOL cli_establish_connection(struct cli_state *cli,
2624 char *dest_host, struct in_addr *dest_ip,
2625 struct nmb_name *calling, struct nmb_name *called,
2626 char *service, char *service_type,
2627 BOOL do_shutdown, BOOL do_tcon)
2629 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
2630 nmb_namestr(calling), nmb_namestr(called), inet_ntoa(*dest_ip),
2631 cli->user_name, cli->domain));
2633 /* establish connection */
2635 if ((!cli->initialised))
2642 if (!cli_connect(cli, dest_host, dest_ip))
2644 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
2645 nmb_namestr(calling), inet_ntoa(*dest_ip)));
2650 if (!cli_session_request(cli, calling, called))
2652 DEBUG(1,("failed session request\n"));
2658 if (!cli_negprot(cli))
2660 DEBUG(1,("failed negprot\n"));
2666 if (cli->pwd.cleartext || cli->pwd.null_pwd)
2671 if (cli->pwd.null_pwd)
2673 /* attempt null session */
2679 /* attempt clear-text session */
2680 pwd_get_cleartext(&(cli->pwd), passwd);
2681 pass_len = strlen(passwd);
2684 /* attempt clear-text session */
2685 if (!cli_session_setup(cli, cli->user_name,
2690 DEBUG(1,("failed session setup\n"));
2699 if (!cli_send_tconX(cli, service, service_type,
2700 (char*)passwd, strlen(passwd)))
2702 DEBUG(1,("failed tcon_X\n"));
2713 /* attempt encrypted session */
2714 unsigned char nt_sess_pwd[24];
2715 unsigned char lm_sess_pwd[24];
2717 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
2718 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
2719 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
2721 /* attempt encrypted session */
2722 if (!cli_session_setup(cli, cli->user_name,
2723 (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
2724 (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
2727 DEBUG(1,("failed session setup\n"));
2737 if (!cli_send_tconX(cli, service, service_type,
2738 (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
2740 DEBUG(1,("failed tcon_X\n"));
2759 /****************************************************************************
2760 connect to one of multiple servers: don't care which
2761 ****************************************************************************/
2762 BOOL cli_connect_serverlist(struct cli_state *cli, char *p)
2764 extern pstring global_myname;
2765 extern pstring scope;
2766 fstring remote_machine;
2767 struct in_addr dest_ip;
2768 struct nmb_name calling, called, stupid_smbserver_called;
2769 BOOL connected_ok = False;
2772 * Treat each name in the 'password server =' line as a potential
2773 * PDC/BDC. Contact each in turn and try and authenticate.
2776 while(p && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine)))
2780 if (!cli_initialise(cli))
2782 DEBUG(0,("cli_connect_serverlist: unable to initialize client connection.\n"));
2786 standard_sub_basic(remote_machine);
2787 strupper(remote_machine);
2789 if (!resolve_name( remote_machine, &dest_ip, 0x20))
2791 DEBUG(1,("cli_connect_serverlist: Can't resolve address for %s\n", remote_machine));
2795 if ((lp_security() != SEC_USER) && (ismyip(dest_ip)))
2797 DEBUG(1,("cli_connect_serverlist: Password server loop - not using password server %s\n", remote_machine));
2801 make_nmb_name(&calling, global_myname , 0x0 , scope);
2802 make_nmb_name(&called , remote_machine, 0x20, scope);
2803 /* stupid microsoft destruction of the ability of netbios
2804 * to provide multiple netbios servers on one host.
2806 make_nmb_name(&stupid_smbserver_called , "*SMBSERVER", 0x20, scope);
2808 pwd_set_nullpwd(&cli->pwd);
2810 if (!cli_establish_connection(cli, remote_machine, &dest_ip,
2814 !cli_establish_connection(cli, remote_machine, &dest_ip,
2815 &calling, &stupid_smbserver_called,
2823 if (cli->protocol < PROTOCOL_LANMAN2 ||
2824 !IS_BITS_SET_ALL(cli->sec_mode, 1))
2826 DEBUG(1,("cli_connect_serverlist: machine %s isn't in user level security mode\n",
2833 * We have an anonymous connection to IPC$.
2836 connected_ok = True;
2842 DEBUG(0,("cli_connect_serverlist: Domain password server not available.\n"));
2846 return connected_ok;
2849 /****************************************************************************
2851 ****************************************************************************/
2852 int cli_printjob_del(struct cli_state *cli, int job)
2854 char *rparam = NULL;
2857 int rdrcnt,rprcnt, ret = -1;
2860 bzero(param,sizeof(param));
2863 SSVAL(p,0,81); /* DosPrintJobDel() */
2866 p = skip_string(p,1);
2868 p = skip_string(p,1);
2873 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2874 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2875 &rparam, &rprcnt, /* return params, length */
2876 &rdata, &rdrcnt)) { /* return data, length */
2877 ret = SVAL(rparam,0);
2880 if (rparam) free(rparam);
2881 if (rdata) free(rdata);
2887 /****************************************************************************
2888 call fn() on each entry in a print queue
2889 ****************************************************************************/
2890 int cli_print_queue(struct cli_state *cli,
2891 void (*fn)(struct print_job_info *))
2893 char *rparam = NULL;
2901 bzero(param,sizeof(param));
2904 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2906 pstrcpy(p,"zWrLeh"); /* parameter description? */
2907 p = skip_string(p,1);
2908 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
2909 p = skip_string(p,1);
2910 pstrcpy(p,cli->share); /* name of queue */
2911 p = skip_string(p,1);
2912 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2913 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2915 pstrcpy(p,""); /* subformat */
2916 p = skip_string(p,1);
2918 DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
2921 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2922 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2923 &rparam, &rprcnt, /* return params, length */
2924 &rdata, &rdrcnt)) { /* return data, length */
2926 result_code = SVAL(rparam,0);
2927 converter = SVAL(rparam,2); /* conversion factor */
2929 if (result_code == 0) {
2930 struct print_job_info job;
2934 for (i = 0; i < SVAL(rparam,4); ++i) {
2936 job.priority = SVAL(p,2);
2938 fix_char_ptr(SVAL(p,4), converter,
2940 job.t = make_unix_date3(p + 12);
2941 job.size = IVAL(p,16);
2942 fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
2951 /* If any parameters or data were returned, free the storage. */
2952 if(rparam) free(rparam);
2953 if(rdata) free(rdata);
2958 /****************************************************************************
2959 check for existance of a dir
2960 ****************************************************************************/
2961 BOOL cli_chkpath(struct cli_state *cli, char *path)
2966 fstrcpy(path2,path);
2967 trim_string(path2,NULL,"\\");
2968 if (!*path2) *path2 = '\\';
2970 bzero(cli->outbuf,smb_size);
2971 set_message(cli->outbuf,0,4 + strlen(path2),True);
2972 SCVAL(cli->outbuf,smb_com,SMBchkpth);
2973 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2974 cli_setup_packet(cli);
2976 p = smb_buf(cli->outbuf);
2980 cli_send_smb(cli, True);
2981 if (!cli_receive_smb(cli)) {
2985 if (cli_error(cli, NULL, NULL)) return False;
2991 /****************************************************************************
2992 start a message sequence
2993 ****************************************************************************/
2994 BOOL cli_message_start(struct cli_state *cli, char *host, char *username,
2999 /* send a SMBsendstrt command */
3000 bzero(cli->outbuf,smb_size);
3001 set_message(cli->outbuf,0,0,True);
3002 CVAL(cli->outbuf,smb_com) = SMBsendstrt;
3003 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3004 cli_setup_packet(cli);
3006 p = smb_buf(cli->outbuf);
3008 pstrcpy(p,username);
3009 p = skip_string(p,1);
3012 p = skip_string(p,1);
3014 set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
3016 cli_send_smb(cli, True);
3018 if (!cli_receive_smb(cli)) {
3022 if (cli_error(cli, NULL, NULL)) return False;
3024 *grp = SVAL(cli->inbuf,smb_vwv0);
3030 /****************************************************************************
3032 ****************************************************************************/
3033 BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp)
3037 bzero(cli->outbuf,smb_size);
3038 set_message(cli->outbuf,1,len+3,True);
3039 CVAL(cli->outbuf,smb_com) = SMBsendtxt;
3040 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3041 cli_setup_packet(cli);
3043 SSVAL(cli->outbuf,smb_vwv0,grp);
3045 p = smb_buf(cli->outbuf);
3048 memcpy(p+3,msg,len);
3049 cli_send_smb(cli, True);
3051 if (!cli_receive_smb(cli)) {
3055 if (cli_error(cli, NULL, NULL)) return False;
3060 /****************************************************************************
3062 ****************************************************************************/
3063 BOOL cli_message_end(struct cli_state *cli, int grp)
3065 bzero(cli->outbuf,smb_size);
3066 set_message(cli->outbuf,1,0,True);
3067 CVAL(cli->outbuf,smb_com) = SMBsendend;
3068 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3070 SSVAL(cli->outbuf,smb_vwv0,grp);
3072 cli_setup_packet(cli);
3074 cli_send_smb(cli, True);
3076 if (!cli_receive_smb(cli)) {
3080 if (cli_error(cli, NULL, NULL)) return False;
3086 /****************************************************************************
3088 ****************************************************************************/
3089 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3091 bzero(cli->outbuf,smb_size);
3092 set_message(cli->outbuf,0,0,True);
3093 CVAL(cli->outbuf,smb_com) = SMBdskattr;
3094 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3095 cli_setup_packet(cli);
3097 cli_send_smb(cli, True);
3098 if (!cli_receive_smb(cli)) {
3102 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
3103 *total = SVAL(cli->inbuf,smb_vwv0);
3104 *avail = SVAL(cli->inbuf,smb_vwv3);