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 /* encrypted password send, implicit from 24-byte lengths */
725 memcpy(pword, pass, 24);
726 memcpy(ntpword, ntpass, 24);
730 /* plain-text password send */
731 fstrcpy(pword, pass);
732 fstrcpy(ntpword, "");
736 /* send a session setup command */
737 bzero(cli->outbuf,smb_size);
739 if (cli->protocol < PROTOCOL_NT1)
741 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
742 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
743 cli_setup_packet(cli);
745 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
746 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
747 SSVAL(cli->outbuf,smb_vwv3,2);
748 SSVAL(cli->outbuf,smb_vwv4,1);
749 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
750 SSVAL(cli->outbuf,smb_vwv7,passlen);
751 p = smb_buf(cli->outbuf);
752 memcpy(p,pword,passlen);
759 set_message(cli->outbuf,13,0,True);
760 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
761 cli_setup_packet(cli);
763 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
764 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
765 SSVAL(cli->outbuf,smb_vwv3,2);
766 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
767 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
768 SSVAL(cli->outbuf,smb_vwv7,passlen);
769 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
770 SSVAL(cli->outbuf,smb_vwv11,0);
771 p = smb_buf(cli->outbuf);
772 memcpy(p,pword,passlen);
773 p += SVAL(cli->outbuf,smb_vwv7);
774 memcpy(p,ntpword,ntpasslen);
775 p += SVAL(cli->outbuf,smb_vwv8);
778 p = skip_string(p,1);
779 pstrcpy(p,workgroup);
781 p = skip_string(p,1);
782 pstrcpy(p,"Unix");p = skip_string(p,1);
783 pstrcpy(p,"Samba");p = skip_string(p,1);
784 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
787 cli_send_smb(cli, True);
788 if (!cli_receive_smb(cli))
790 DEBUG(10,("cli_session_setup: receive smb failed\n"));
794 if (CVAL(cli->inbuf,smb_rcls) != 0) {
798 /* use the returned vuid from now on */
799 cli->vuid = SVAL(cli->inbuf,smb_uid);
801 if (cli->protocol >= PROTOCOL_NT1) {
803 * Save off some of the connected server
806 char *server_domain,*server_os,*server_type;
807 server_os = smb_buf(cli->inbuf);
808 server_type = skip_string(server_os,1);
809 server_domain = skip_string(server_type,1);
810 fstrcpy(cli->server_os, server_os);
811 fstrcpy(cli->server_type, server_type);
812 fstrcpy(cli->server_domain, server_domain);
815 fstrcpy(cli->user_name, user);
820 /****************************************************************************
822 *****************************************************************************/
824 BOOL cli_ulogoff(struct cli_state *cli)
826 bzero(cli->outbuf,smb_size);
827 set_message(cli->outbuf,2,0,True);
828 CVAL(cli->outbuf,smb_com) = SMBulogoffX;
829 cli_setup_packet(cli);
830 SSVAL(cli->outbuf,smb_vwv0,0xFF);
831 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
833 cli_send_smb(cli, True);
834 if (!cli_receive_smb(cli))
837 return CVAL(cli->inbuf,smb_rcls) == 0;
840 /****************************************************************************
842 ****************************************************************************/
843 BOOL cli_send_tconX(struct cli_state *cli,
844 char *share, char *dev, char *pass, int passlen)
846 fstring fullshare, pword;
848 bzero(cli->outbuf,smb_size);
849 bzero(cli->inbuf,smb_size);
851 fstrcpy(cli->share, share);
853 /* in user level security don't send a password now */
854 if (cli->sec_mode & 1) {
859 if ((cli->sec_mode & 2) && *pass && passlen != 24) {
861 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
863 memcpy(pword, pass, passlen);
866 slprintf(fullshare, sizeof(fullshare)-1,
867 "\\\\%s\\%s", cli->desthost, share);
870 set_message(cli->outbuf,4,
871 2 + strlen(fullshare) + passlen + strlen(dev),True);
872 CVAL(cli->outbuf,smb_com) = SMBtconX;
873 cli_setup_packet(cli);
875 SSVAL(cli->outbuf,smb_vwv0,0xFF);
876 SSVAL(cli->outbuf,smb_vwv3,passlen);
878 p = smb_buf(cli->outbuf);
879 memcpy(p,pword,passlen);
881 fstrcpy(p,fullshare);
882 p = skip_string(p,1);
885 SCVAL(cli->inbuf,smb_rcls, 1);
887 cli_send_smb(cli, True);
888 if (!cli_receive_smb(cli))
891 if (CVAL(cli->inbuf,smb_rcls) != 0) {
895 fstrcpy(cli->dev, "A:");
897 if (cli->protocol >= PROTOCOL_NT1) {
898 fstrcpy(cli->dev, smb_buf(cli->inbuf));
901 if (strcasecmp(share,"IPC$")==0) {
902 fstrcpy(cli->dev, "IPC");
905 /* only grab the device if we have a recent protocol level */
906 if (cli->protocol >= PROTOCOL_NT1 &&
907 smb_buflen(cli->inbuf) == 3) {
908 /* almost certainly win95 - enable bug fixes */
912 cli->cnum = SVAL(cli->inbuf,smb_tid);
917 /****************************************************************************
918 send a tree disconnect
919 ****************************************************************************/
920 BOOL cli_tdis(struct cli_state *cli)
922 bzero(cli->outbuf,smb_size);
923 set_message(cli->outbuf,0,0,True);
924 CVAL(cli->outbuf,smb_com) = SMBtdis;
925 SSVAL(cli->outbuf,smb_tid,cli->cnum);
926 cli_setup_packet(cli);
928 cli_send_smb(cli, True);
929 if (!cli_receive_smb(cli))
932 return CVAL(cli->inbuf,smb_rcls) == 0;
935 /****************************************************************************
937 ****************************************************************************/
938 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
942 bzero(cli->outbuf,smb_size);
943 bzero(cli->inbuf,smb_size);
945 set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
947 CVAL(cli->outbuf,smb_com) = SMBmv;
948 SSVAL(cli->outbuf,smb_tid,cli->cnum);
949 cli_setup_packet(cli);
951 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
953 p = smb_buf(cli->outbuf);
955 pstrcpy(p,fname_src);
956 p = skip_string(p,1);
958 pstrcpy(p,fname_dst);
960 cli_send_smb(cli, True);
961 if (!cli_receive_smb(cli)) {
965 if (CVAL(cli->inbuf,smb_rcls) != 0) {
972 /****************************************************************************
974 ****************************************************************************/
975 BOOL cli_unlink(struct cli_state *cli, char *fname)
979 bzero(cli->outbuf,smb_size);
980 bzero(cli->inbuf,smb_size);
982 set_message(cli->outbuf,1, 2 + strlen(fname),True);
984 CVAL(cli->outbuf,smb_com) = SMBunlink;
985 SSVAL(cli->outbuf,smb_tid,cli->cnum);
986 cli_setup_packet(cli);
988 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
990 p = smb_buf(cli->outbuf);
994 cli_send_smb(cli, True);
995 if (!cli_receive_smb(cli)) {
999 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1006 /****************************************************************************
1008 ****************************************************************************/
1009 BOOL cli_mkdir(struct cli_state *cli, char *dname)
1013 bzero(cli->outbuf,smb_size);
1014 bzero(cli->inbuf,smb_size);
1016 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1018 CVAL(cli->outbuf,smb_com) = SMBmkdir;
1019 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1020 cli_setup_packet(cli);
1022 p = smb_buf(cli->outbuf);
1026 cli_send_smb(cli, True);
1027 if (!cli_receive_smb(cli)) {
1031 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1038 /****************************************************************************
1040 ****************************************************************************/
1041 BOOL cli_rmdir(struct cli_state *cli, char *dname)
1045 bzero(cli->outbuf,smb_size);
1046 bzero(cli->inbuf,smb_size);
1048 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1050 CVAL(cli->outbuf,smb_com) = SMBrmdir;
1051 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1052 cli_setup_packet(cli);
1054 p = smb_buf(cli->outbuf);
1058 cli_send_smb(cli, True);
1059 if (!cli_receive_smb(cli)) {
1063 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1072 /****************************************************************************
1074 ****************************************************************************/
1075 int cli_nt_create(struct cli_state *cli, char *fname)
1079 bzero(cli->outbuf,smb_size);
1080 bzero(cli->inbuf,smb_size);
1082 set_message(cli->outbuf,24,1 + strlen(fname),True);
1084 CVAL(cli->outbuf,smb_com) = SMBntcreateX;
1085 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1086 cli_setup_packet(cli);
1088 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1089 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0x06);
1090 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
1091 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, 0x2019f);
1092 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0);
1093 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03);
1094 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01);
1095 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0);
1096 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
1097 SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname));
1099 p = smb_buf(cli->outbuf);
1101 p = skip_string(p,1);
1103 cli_send_smb(cli, True);
1104 if (!cli_receive_smb(cli)) {
1108 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1112 return SVAL(cli->inbuf,smb_vwv2 + 1);
1116 /****************************************************************************
1118 ****************************************************************************/
1119 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
1123 unsigned accessmode=0;
1125 /* you must open for RW not just write - otherwise getattrE doesn't
1127 if ((flags & O_ACCMODE) == O_WRONLY && strncmp(cli->dev, "LPT", 3)) {
1128 flags = (flags & ~O_ACCMODE) | O_RDWR;
1131 if (flags & O_CREAT)
1133 if (!(flags & O_EXCL)) {
1134 if (flags & O_TRUNC)
1140 accessmode = (share_mode<<4);
1142 if ((flags & O_ACCMODE) == O_RDWR) {
1144 } else if ((flags & O_ACCMODE) == O_WRONLY) {
1149 if ((flags & O_SYNC) == O_SYNC) {
1150 accessmode |= (1<<14);
1154 bzero(cli->outbuf,smb_size);
1155 bzero(cli->inbuf,smb_size);
1157 set_message(cli->outbuf,15,1 + strlen(fname),True);
1159 CVAL(cli->outbuf,smb_com) = SMBopenX;
1160 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1161 cli_setup_packet(cli);
1163 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1164 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1165 SSVAL(cli->outbuf,smb_vwv3,accessmode);
1166 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1167 SSVAL(cli->outbuf,smb_vwv5,0);
1168 SSVAL(cli->outbuf,smb_vwv8,openfn);
1170 p = smb_buf(cli->outbuf);
1172 p = skip_string(p,1);
1174 cli_send_smb(cli, True);
1175 if (!cli_receive_smb(cli)) {
1179 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1183 return SVAL(cli->inbuf,smb_vwv2);
1189 /****************************************************************************
1191 ****************************************************************************/
1192 BOOL cli_close(struct cli_state *cli, int fnum)
1194 bzero(cli->outbuf,smb_size);
1195 bzero(cli->inbuf,smb_size);
1197 set_message(cli->outbuf,3,0,True);
1199 CVAL(cli->outbuf,smb_com) = SMBclose;
1200 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1201 cli_setup_packet(cli);
1203 SSVAL(cli->outbuf,smb_vwv0,fnum);
1204 SIVALS(cli->outbuf,smb_vwv1,-1);
1206 cli_send_smb(cli, True);
1207 if (!cli_receive_smb(cli)) {
1211 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1219 /****************************************************************************
1221 ****************************************************************************/
1222 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1225 int saved_timeout = cli->timeout;
1227 bzero(cli->outbuf,smb_size);
1228 bzero(cli->inbuf,smb_size);
1230 set_message(cli->outbuf,8,10,True);
1232 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1233 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1234 cli_setup_packet(cli);
1236 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1237 SSVAL(cli->outbuf,smb_vwv2,fnum);
1238 CVAL(cli->outbuf,smb_vwv3) = 0;
1239 SIVALS(cli->outbuf, smb_vwv4, timeout);
1240 SSVAL(cli->outbuf,smb_vwv6,0);
1241 SSVAL(cli->outbuf,smb_vwv7,1);
1243 p = smb_buf(cli->outbuf);
1244 SSVAL(p, 0, cli->pid);
1245 SIVAL(p, 2, offset);
1247 cli_send_smb(cli, True);
1249 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout;
1251 if (!cli_receive_smb(cli)) {
1252 cli->timeout = saved_timeout;
1256 cli->timeout = saved_timeout;
1258 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1265 /****************************************************************************
1267 ****************************************************************************/
1268 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1272 bzero(cli->outbuf,smb_size);
1273 bzero(cli->inbuf,smb_size);
1275 set_message(cli->outbuf,8,10,True);
1277 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1278 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1279 cli_setup_packet(cli);
1281 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1282 SSVAL(cli->outbuf,smb_vwv2,fnum);
1283 CVAL(cli->outbuf,smb_vwv3) = 0;
1284 SIVALS(cli->outbuf, smb_vwv4, timeout);
1285 SSVAL(cli->outbuf,smb_vwv6,1);
1286 SSVAL(cli->outbuf,smb_vwv7,0);
1288 p = smb_buf(cli->outbuf);
1289 SSVAL(p, 0, cli->pid);
1290 SIVAL(p, 2, offset);
1293 cli_send_smb(cli, True);
1294 if (!cli_receive_smb(cli)) {
1298 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1307 /****************************************************************************
1308 issue a single SMBread and don't wait for a reply
1309 ****************************************************************************/
1310 static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
1313 bzero(cli->outbuf,smb_size);
1314 bzero(cli->inbuf,smb_size);
1316 set_message(cli->outbuf,10,0,True);
1318 CVAL(cli->outbuf,smb_com) = SMBreadX;
1319 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1320 cli_setup_packet(cli);
1322 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1323 SSVAL(cli->outbuf,smb_vwv2,fnum);
1324 SIVAL(cli->outbuf,smb_vwv3,offset);
1325 SSVAL(cli->outbuf,smb_vwv5,size);
1326 SSVAL(cli->outbuf,smb_vwv6,size);
1327 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1329 cli_send_smb(cli, True);
1332 /****************************************************************************
1334 ****************************************************************************/
1335 size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
1341 int mpx = MAX(cli->max_mux-1, 1);
1342 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1344 int blocks = (size + (block-1)) / block;
1346 if (size == 0) return 0;
1348 while (received < blocks) {
1351 while (issued - received < mpx && issued < blocks) {
1352 int size1 = MIN(block, size-issued*block);
1353 cli_issue_read(cli, fnum, offset+issued*block, size1, issued);
1357 if (!cli_receive_smb(cli)) {
1362 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1363 size2 = SVAL(cli->inbuf, smb_vwv5);
1365 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1366 blocks = MIN(blocks, mid-1);
1371 blocks = MIN(blocks, mid-1);
1372 /* this distinguishes EOF from an error */
1373 total = MAX(total, 0);
1377 if (size2 > block) {
1378 DEBUG(0,("server returned more than we wanted!\n"));
1381 if (mid >= issued) {
1382 DEBUG(0,("invalid mid from server!\n"));
1385 p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
1387 memcpy(buf+mid*block, p, size2);
1389 total = MAX(total, mid*block + size2);
1392 while (received < issued) {
1393 cli_receive_smb(cli);
1401 /****************************************************************************
1402 issue a single SMBwrite and don't wait for a reply
1403 ****************************************************************************/
1404 static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf,
1409 bzero(cli->outbuf,smb_size);
1410 bzero(cli->inbuf,smb_size);
1412 set_message(cli->outbuf,12,size,True);
1414 CVAL(cli->outbuf,smb_com) = SMBwriteX;
1415 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1416 cli_setup_packet(cli);
1418 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1419 SSVAL(cli->outbuf,smb_vwv2,fnum);
1421 SIVAL(cli->outbuf,smb_vwv3,offset);
1422 SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0);
1423 SSVAL(cli->outbuf,smb_vwv7,mode);
1425 SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0);
1426 SSVAL(cli->outbuf,smb_vwv10,size);
1427 SSVAL(cli->outbuf,smb_vwv11,
1428 smb_buf(cli->outbuf) - smb_base(cli->outbuf));
1430 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
1431 memcpy(p, buf, size);
1433 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1435 cli_send_smb(cli, True);
1438 /****************************************************************************
1440 write_mode: 0x0001 disallow write cacheing
1441 0x0002 return bytes remaining
1442 0x0004 use raw named pipe protocol
1443 0x0008 start of message mode named pipe protocol
1444 ****************************************************************************/
1445 ssize_t cli_write(struct cli_state *cli,
1446 int fnum, uint16 write_mode,
1447 char *buf, off_t offset, size_t size)
1452 int mpx = MAX(cli->max_mux-1, 1);
1453 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1455 int blocks = (size + (block-1)) / block;
1457 if (size == 0) return 0;
1459 while (received < blocks) {
1462 while (issued - received < mpx && issued < blocks) {
1463 int size1 = MIN(block, size-issued*block);
1464 cli_issue_write(cli, fnum, offset+issued*block,
1471 if (!cli_receive_smb(cli)) {
1476 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1477 size2 = SVAL(cli->inbuf, smb_vwv2);
1479 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1480 blocks = MIN(blocks, mid-1);
1485 blocks = MIN(blocks, mid-1);
1486 /* this distinguishes EOF from an error */
1487 total = MAX(total, 0);
1493 total = MAX(total, mid*block + size2);
1496 while (received < issued) {
1497 cli_receive_smb(cli);
1505 /****************************************************************************
1506 do a SMBgetattrE call
1507 ****************************************************************************/
1508 BOOL cli_getattrE(struct cli_state *cli, int fd,
1509 uint16 *attr, size_t *size,
1510 time_t *c_time, time_t *a_time, time_t *m_time)
1512 bzero(cli->outbuf,smb_size);
1513 bzero(cli->inbuf,smb_size);
1515 set_message(cli->outbuf,2,0,True);
1517 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
1518 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1519 cli_setup_packet(cli);
1521 SSVAL(cli->outbuf,smb_vwv0,fd);
1523 cli_send_smb(cli, True);
1524 if (!cli_receive_smb(cli)) {
1528 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1533 *size = IVAL(cli->inbuf, smb_vwv6);
1537 *attr = SVAL(cli->inbuf,smb_vwv10);
1541 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
1545 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
1549 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
1556 /****************************************************************************
1558 ****************************************************************************/
1559 BOOL cli_getatr(struct cli_state *cli, char *fname,
1560 uint16 *attr, size_t *size, time_t *t)
1564 bzero(cli->outbuf,smb_size);
1565 bzero(cli->inbuf,smb_size);
1567 set_message(cli->outbuf,0,strlen(fname)+2,True);
1569 CVAL(cli->outbuf,smb_com) = SMBgetatr;
1570 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1571 cli_setup_packet(cli);
1573 p = smb_buf(cli->outbuf);
1575 pstrcpy(p+1, fname);
1577 cli_send_smb(cli, True);
1578 if (!cli_receive_smb(cli)) {
1582 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1587 *size = IVAL(cli->inbuf, smb_vwv3);
1591 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1595 *attr = SVAL(cli->inbuf,smb_vwv0);
1603 /****************************************************************************
1605 ****************************************************************************/
1606 BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
1610 bzero(cli->outbuf,smb_size);
1611 bzero(cli->inbuf,smb_size);
1613 set_message(cli->outbuf,8,strlen(fname)+4,True);
1615 CVAL(cli->outbuf,smb_com) = SMBsetatr;
1616 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1617 cli_setup_packet(cli);
1619 SSVAL(cli->outbuf,smb_vwv0, attr);
1620 put_dos_date3(cli->outbuf,smb_vwv1, t);
1622 p = smb_buf(cli->outbuf);
1624 pstrcpy(p+1, fname);
1625 p = skip_string(p,1);
1628 cli_send_smb(cli, True);
1629 if (!cli_receive_smb(cli)) {
1633 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1640 /****************************************************************************
1641 send a qpathinfo call
1642 ****************************************************************************/
1643 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
1644 time_t *c_time, time_t *a_time, time_t *m_time,
1645 size_t *size, uint16 *mode)
1649 uint16 setup = TRANSACT2_QPATHINFO;
1651 char *rparam=NULL, *rdata=NULL;
1654 time_t (*date_fn)(void *);
1656 param_len = strlen(fname) + 7;
1658 memset(param, 0, param_len);
1659 SSVAL(param, 0, SMB_INFO_STANDARD);
1660 pstrcpy(¶m[6], fname);
1663 ret = (cli_send_trans(cli, SMBtrans2,
1664 NULL, 0, /* Name, length */
1665 -1, 0, /* fid, flags */
1666 &setup, 1, 0, /* setup, length, max */
1667 param, param_len, 10, /* param, length, max */
1668 NULL, data_len, cli->max_xmit /* data, length, max */
1670 cli_receive_trans(cli, SMBtrans2,
1671 &rparam, ¶m_len,
1672 &rdata, &data_len));
1674 /* we need to work around a Win95 bug - sometimes
1675 it gives ERRSRV/ERRerror temprarily */
1678 cli_error(cli, &eclass, &ecode);
1679 if (eclass != ERRSRV || ecode != ERRerror) break;
1682 } while (count-- && ret==False);
1684 if (!ret || !rdata || data_len < 22) {
1689 date_fn = make_unix_date;
1691 date_fn = make_unix_date2;
1695 *c_time = date_fn(rdata+0);
1698 *a_time = date_fn(rdata+4);
1701 *m_time = date_fn(rdata+8);
1704 *size = IVAL(rdata, 12);
1707 *mode = SVAL(rdata,l1_attrFile);
1710 if (rdata) free(rdata);
1711 if (rparam) free(rparam);
1715 /****************************************************************************
1716 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1717 ****************************************************************************/
1718 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
1719 time_t *c_time, time_t *a_time, time_t *m_time,
1720 time_t *w_time, size_t *size, uint16 *mode,
1725 uint16 setup = TRANSACT2_QPATHINFO;
1727 char *rparam=NULL, *rdata=NULL;
1729 param_len = strlen(fname) + 7;
1731 memset(param, 0, param_len);
1732 SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1733 pstrcpy(¶m[6], fname);
1735 if (!cli_send_trans(cli, SMBtrans2,
1736 NULL, 0, /* name, length */
1737 -1, 0, /* fid, flags */
1738 &setup, 1, 0, /* setup, length, max */
1739 param, param_len, 10, /* param, length, max */
1740 NULL, data_len, cli->max_xmit /* data, length, max */
1745 if (!cli_receive_trans(cli, SMBtrans2,
1746 &rparam, ¶m_len,
1747 &rdata, &data_len)) {
1751 if (!rdata || data_len < 22) {
1756 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1759 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1762 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1765 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1768 *mode = SVAL(rdata, 32);
1771 *size = IVAL(rdata, 40);
1774 *ino = IVAL(rdata, 64);
1777 if (rdata) free(rdata);
1778 if (rparam) free(rparam);
1783 /****************************************************************************
1784 send a qfileinfo call
1785 ****************************************************************************/
1786 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
1787 uint16 *mode, size_t *size,
1788 time_t *c_time, time_t *a_time, time_t *m_time,
1789 time_t *w_time, SMB_INO_T *ino)
1793 uint16 setup = TRANSACT2_QFILEINFO;
1795 char *rparam=NULL, *rdata=NULL;
1797 /* if its a win95 server then fail this - win95 totally screws it
1799 if (cli->win95) return False;
1803 memset(param, 0, param_len);
1804 SSVAL(param, 0, fnum);
1805 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
1807 if (!cli_send_trans(cli, SMBtrans2,
1808 NULL, 0, /* name, length */
1809 -1, 0, /* fid, flags */
1810 &setup, 1, 0, /* setup, length, max */
1811 param, param_len, 2, /* param, length, max */
1812 NULL, data_len, cli->max_xmit /* data, length, max */
1817 if (!cli_receive_trans(cli, SMBtrans2,
1818 &rparam, ¶m_len,
1819 &rdata, &data_len)) {
1823 if (!rdata || data_len < 68) {
1828 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1831 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1834 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1837 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1840 *mode = SVAL(rdata, 32);
1843 *size = IVAL(rdata, 40);
1846 *ino = IVAL(rdata, 64);
1849 if (rdata) free(rdata);
1850 if (rparam) free(rparam);
1855 /****************************************************************************
1856 interpret a long filename structure - this is mostly guesses at the moment
1857 The length of the structure is returned
1858 The structure of a long filename depends on the info level. 260 is used
1859 by NT and 2 is used by OS/2
1860 ****************************************************************************/
1861 static int interpret_long_filename(int level,char *p,file_info *finfo)
1863 extern file_info def_finfo;
1866 memcpy(finfo,&def_finfo,sizeof(*finfo));
1870 case 1: /* OS/2 understands this */
1872 /* these dates are converted to GMT by make_unix_date */
1873 finfo->ctime = make_unix_date2(p+4);
1874 finfo->atime = make_unix_date2(p+8);
1875 finfo->mtime = make_unix_date2(p+12);
1876 finfo->size = IVAL(p,16);
1877 finfo->mode = CVAL(p,24);
1878 pstrcpy(finfo->name,p+27);
1880 return(28 + CVAL(p,26));
1882 case 2: /* this is what OS/2 uses mostly */
1884 /* these dates are converted to GMT by make_unix_date */
1885 finfo->ctime = make_unix_date2(p+4);
1886 finfo->atime = make_unix_date2(p+8);
1887 finfo->mtime = make_unix_date2(p+12);
1888 finfo->size = IVAL(p,16);
1889 finfo->mode = CVAL(p,24);
1890 pstrcpy(finfo->name,p+31);
1892 return(32 + CVAL(p,30));
1894 /* levels 3 and 4 are untested */
1897 /* these dates are probably like the other ones */
1898 finfo->ctime = make_unix_date2(p+8);
1899 finfo->atime = make_unix_date2(p+12);
1900 finfo->mtime = make_unix_date2(p+16);
1901 finfo->size = IVAL(p,20);
1902 finfo->mode = CVAL(p,28);
1903 pstrcpy(finfo->name,p+33);
1905 return(SVAL(p,4)+4);
1909 /* these dates are probably like the other ones */
1910 finfo->ctime = make_unix_date2(p+8);
1911 finfo->atime = make_unix_date2(p+12);
1912 finfo->mtime = make_unix_date2(p+16);
1913 finfo->size = IVAL(p,20);
1914 finfo->mode = CVAL(p,28);
1915 pstrcpy(finfo->name,p+37);
1917 return(SVAL(p,4)+4);
1919 case 260: /* NT uses this, but also accepts 2 */
1921 int ret = SVAL(p,0);
1923 p += 4; /* next entry offset */
1924 p += 4; /* fileindex */
1926 /* these dates appear to arrive in a
1927 weird way. It seems to be localtime
1928 plus the serverzone given in the
1929 initial connect. This is GMT when
1930 DST is not in effect and one hour
1931 from GMT otherwise. Can this really
1934 I suppose this could be called
1935 kludge-GMT. Is is the GMT you get
1936 by using the current DST setting on
1937 a different localtime. It will be
1938 cheap to calculate, I suppose, as
1939 no DST tables will be needed */
1941 finfo->ctime = interpret_long_date(p); p += 8;
1942 finfo->atime = interpret_long_date(p); p += 8;
1943 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
1944 finfo->size = IVAL(p,0); p += 8;
1945 p += 8; /* alloc size */
1946 finfo->mode = CVAL(p,0); p += 4;
1947 namelen = IVAL(p,0); p += 4;
1948 p += 4; /* EA size */
1949 p += 2; /* short name len? */
1950 p += 24; /* short name? */
1951 StrnCpy(finfo->name,p,namelen);
1957 DEBUG(1,("Unknown long filename format %d\n",level));
1962 /****************************************************************************
1963 do a directory listing, calling fn on each file found
1964 ****************************************************************************/
1965 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
1966 void (*fn)(file_info *, const char *))
1968 int max_matches = 512;
1969 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1970 int info_level = cli->protocol<PROTOCOL_NT1?1:260;
1975 char *dirlist = NULL;
1976 int dirlist_len = 0;
1977 int total_received = -1;
1979 int ff_resume_key = 0;
1980 int ff_searchcount=0;
1983 int ff_dir_handle=0;
1985 char *rparam=NULL, *rdata=NULL;
1986 int param_len, data_len;
1993 while (ff_eos == 0) {
1995 if (loop_count > 200) {
1996 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
2000 param_len = 12+strlen(mask)+1;
2003 setup = TRANSACT2_FINDFIRST;
2004 SSVAL(param,0,attribute); /* attribute */
2005 SSVAL(param,2,max_matches); /* max count */
2006 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
2007 SSVAL(param,6,info_level);
2009 pstrcpy(param+12,mask);
2011 setup = TRANSACT2_FINDNEXT;
2012 SSVAL(param,0,ff_dir_handle);
2013 SSVAL(param,2,max_matches); /* max count */
2014 SSVAL(param,4,info_level);
2015 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
2016 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
2017 pstrcpy(param+12,mask);
2019 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
2020 ff_dir_handle,ff_resume_key,ff_lastname,mask));
2023 if (!cli_send_trans(cli, SMBtrans2,
2024 NULL, 0, /* Name, length */
2025 -1, 0, /* fid, flags */
2026 &setup, 1, 0, /* setup, length, max */
2027 param, param_len, 10, /* param, length, max */
2029 cli->max_xmit /* data, length, max */
2034 if (!cli_receive_trans(cli, SMBtrans2,
2035 &rparam, ¶m_len,
2036 &rdata, &data_len)) {
2037 /* we need to work around a Win95 bug - sometimes
2038 it gives ERRSRV/ERRerror temprarily */
2041 cli_error(cli, &eclass, &ecode);
2042 if (eclass != ERRSRV || ecode != ERRerror) break;
2047 if (total_received == -1) total_received = 0;
2049 /* parse out some important return info */
2052 ff_dir_handle = SVAL(p,0);
2053 ff_searchcount = SVAL(p,2);
2055 ff_lastname = SVAL(p,8);
2057 ff_searchcount = SVAL(p,0);
2059 ff_lastname = SVAL(p,6);
2062 if (ff_searchcount == 0)
2065 /* point to the data bytes */
2068 /* we might need the lastname for continuations */
2069 if (ff_lastname > 0) {
2074 StrnCpy(mask,p+ff_lastname,
2075 data_len-ff_lastname);
2078 pstrcpy(mask,p + ff_lastname + 1);
2086 /* and add them to the dirlist pool */
2087 dirlist = Realloc(dirlist,dirlist_len + data_len);
2090 DEBUG(0,("Failed to expand dirlist\n"));
2094 /* put in a length for the last entry, to ensure we can chain entries
2095 into the next packet */
2096 for (p2=p,i=0;i<(ff_searchcount-1);i++)
2097 p2 += interpret_long_filename(info_level,p2,NULL);
2098 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
2100 /* grab the data for later use */
2101 memcpy(dirlist+dirlist_len,p,data_len);
2102 dirlist_len += data_len;
2104 total_received += ff_searchcount;
2106 if (rdata) free(rdata); rdata = NULL;
2107 if (rparam) free(rparam); rparam = NULL;
2109 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
2110 ff_searchcount,ff_eos,ff_resume_key));
2115 for (p=dirlist,i=0;i<total_received;i++) {
2116 p += interpret_long_filename(info_level,p,&finfo);
2120 /* free up the dirlist buffer */
2121 if (dirlist) free(dirlist);
2122 return(total_received);
2126 /****************************************************************************
2127 Send a SamOEMChangePassword command
2128 ****************************************************************************/
2130 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
2131 const char *old_password)
2133 char param[16+sizeof(fstring)];
2136 fstring upper_case_old_pw;
2137 fstring upper_case_new_pw;
2138 unsigned char old_pw_hash[16];
2139 unsigned char new_pw_hash[16];
2142 char *rparam = NULL;
2146 if (strlen(user) >= sizeof(fstring)-1) {
2147 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
2151 SSVAL(p,0,214); /* SamOEMChangePassword command. */
2154 p = skip_string(p,1);
2155 pstrcpy(p, "B516B16");
2156 p = skip_string(p,1);
2158 p = skip_string(p,1);
2162 param_len = PTR_DIFF(p,param);
2165 * Get the Lanman hash of the old password, we
2166 * use this as the key to make_oem_passwd_hash().
2168 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
2169 fstrcpy(upper_case_old_pw, old_password);
2170 strupper(upper_case_old_pw);
2171 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
2173 if (!make_oem_passwd_hash( data, new_password, old_pw_hash, False))
2179 * Now place the old password hash in the data.
2181 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
2182 fstrcpy(upper_case_new_pw, new_password);
2183 strupper(upper_case_new_pw);
2185 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
2187 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
2191 if (!cli_send_trans(cli,SMBtrans,
2192 PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */
2193 0,0, /* fid, flags */
2194 NULL,0,0, /* setup, length, max */
2195 param,param_len,2, /* param, length, max */
2196 data,data_len,0 /* data, length, max */
2199 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
2204 if (cli_receive_trans(cli,SMBtrans,
2208 cli->rap_error = SVAL(rparam,0);
2216 return (cli->rap_error == 0);
2219 /****************************************************************************
2220 send a negprot command
2221 ****************************************************************************/
2222 BOOL cli_negprot(struct cli_state *cli)
2228 bzero(cli->outbuf,smb_size);
2230 /* setup the protocol strings */
2231 for (plength=0,numprots=0;
2232 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2234 plength += strlen(prots[numprots].name)+2;
2236 set_message(cli->outbuf,0,plength,True);
2238 p = smb_buf(cli->outbuf);
2240 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2243 pstrcpy(p,prots[numprots].name);
2247 CVAL(cli->outbuf,smb_com) = SMBnegprot;
2248 cli_setup_packet(cli);
2250 CVAL(smb_buf(cli->outbuf),0) = 2;
2252 cli_send_smb(cli, True);
2253 if (!cli_receive_smb(cli))
2258 if (CVAL(cli->inbuf,smb_rcls) != 0 ||
2259 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
2263 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
2266 if (cli->protocol >= PROTOCOL_NT1) {
2268 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
2269 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
2270 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
2271 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
2272 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
2273 /* this time arrives in real GMT */
2274 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
2275 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2276 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
2277 if (cli->capabilities & 1) {
2278 cli->readbraw_supported = True;
2279 cli->writebraw_supported = True;
2281 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2282 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
2283 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
2284 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
2285 cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
2286 /* this time is converted to GMT by make_unix_date */
2287 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
2288 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
2289 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
2290 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2292 /* the old core protocol */
2294 cli->serverzone = TimeDiff(time(NULL));
2297 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2303 /****************************************************************************
2304 send a session request. see rfc1002.txt 4.3 and 4.3.2
2305 ****************************************************************************/
2306 BOOL cli_session_request(struct cli_state *cli,
2307 struct nmb_name *calling, struct nmb_name *called)
2311 /* send a session request (RFC 1002) */
2313 memcpy(&(cli->calling), calling, sizeof(*calling));
2314 memcpy(&(cli->called ), called , sizeof(*called ));
2316 /* put in the destination name */
2317 p = cli->outbuf+len;
2318 name_mangle(cli->called .name, p, cli->called .name_type);
2322 p = cli->outbuf+len;
2323 name_mangle(cli->calling.name, p, cli->calling.name_type);
2326 /* setup the packet length */
2327 _smb_setlen(cli->outbuf,len);
2328 CVAL(cli->outbuf,0) = 0x81;
2332 #endif /* WITH_SSL */
2334 cli_send_smb(cli, False);
2335 DEBUG(5,("Sent session request\n"));
2337 if (!cli_receive_smb(cli))
2341 if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
2342 if (!sslutil_fd_is_ssl(cli->fd)){
2343 if (sslutil_connect(cli->fd) == 0)
2347 #endif /* WITH_SSL */
2349 if (CVAL(cli->inbuf,0) != 0x82) {
2350 /* This is the wrong place to put the error... JRA. */
2351 cli->rap_error = CVAL(cli->inbuf,0);
2358 /****************************************************************************
2359 open the client sockets
2360 ****************************************************************************/
2361 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
2363 extern struct in_addr ipzero;
2365 fstrcpy(cli->desthost, host);
2367 if (!ip || ip_equal(*ip, ipzero)) {
2368 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
2371 if (ip) *ip = cli->dest_ip;
2377 if (cli -> port == 0) cli -> port = 139;
2379 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2380 cli -> port, cli->timeout);
2388 /****************************************************************************
2389 initialise a client structure
2390 ****************************************************************************/
2391 struct cli_state *cli_initialise(struct cli_state *cli)
2394 cli = (struct cli_state *)malloc(sizeof(*cli));
2400 if (cli->initialised) {
2409 cli->pid = (uint16)getpid();
2411 cli->vuid = UID_FIELD_INVALID;
2412 cli->protocol = PROTOCOL_NT1;
2413 cli->timeout = 20000;
2414 cli->bufsize = CLI_BUFFER_SIZE+4;
2415 cli->max_xmit = cli->bufsize;
2416 cli->outbuf = (char *)malloc(cli->bufsize);
2417 cli->inbuf = (char *)malloc(cli->bufsize);
2418 if (!cli->outbuf || !cli->inbuf)
2423 cli->initialised = 1;
2428 /****************************************************************************
2429 shutdown a client structure
2430 ****************************************************************************/
2431 void cli_shutdown(struct cli_state *cli)
2433 DEBUG(10,("cli_shutdown\n"));
2444 sslutil_disconnect(cli->fd);
2445 #endif /* WITH_SSL */
2450 memset(cli, 0, sizeof(*cli));
2454 /****************************************************************************
2455 return error codes for the last packet
2456 returns 0 if there was no error and the best approx of a unix errno
2459 for 32 bit "warnings", a return code of 0 is expected.
2461 ****************************************************************************/
2462 int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
2468 if (!cli->initialised)
2470 DEBUG(0,("cli_error: client state uninitialised!\n"));
2474 flgs2 = SVAL(cli->inbuf,smb_flg2);
2476 if (eclass) *eclass = 0;
2479 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
2480 /* 32 bit error codes detected */
2481 uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
2482 if (num) *num = nt_err;
2483 DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
2484 if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0;
2486 switch (nt_err & 0xFFFFFF) {
2487 case NT_STATUS_ACCESS_VIOLATION: return EACCES;
2488 case NT_STATUS_NO_SUCH_FILE: return ENOENT;
2489 case NT_STATUS_NO_SUCH_DEVICE: return ENODEV;
2490 case NT_STATUS_INVALID_HANDLE: return EBADF;
2491 case NT_STATUS_NO_MEMORY: return ENOMEM;
2492 case NT_STATUS_ACCESS_DENIED: return EACCES;
2493 case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
2494 case NT_STATUS_SHARING_VIOLATION: return EBUSY;
2495 case NT_STATUS_OBJECT_PATH_INVALID: return ENOTDIR;
2496 case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
2499 /* for all other cases - a default code */
2503 rcls = CVAL(cli->inbuf,smb_rcls);
2504 code = SVAL(cli->inbuf,smb_err);
2505 if (rcls == 0) return 0;
2507 if (eclass) *eclass = rcls;
2508 if (num ) *num = code;
2510 if (rcls == ERRDOS) {
2512 case ERRbadfile: return ENOENT;
2513 case ERRbadpath: return ENOTDIR;
2514 case ERRnoaccess: return EACCES;
2515 case ERRfilexists: return EEXIST;
2516 case ERRrename: return EEXIST;
2517 case ERRbadshare: return EBUSY;
2518 case ERRlock: return EBUSY;
2521 if (rcls == ERRSRV) {
2523 case ERRbadpw: return EPERM;
2524 case ERRaccess: return EACCES;
2525 case ERRnoresource: return ENOMEM;
2526 case ERRinvdevice: return ENODEV;
2527 case ERRinvnetname: return ENODEV;
2530 /* for other cases */
2534 /****************************************************************************
2535 set socket options on a open connection
2536 ****************************************************************************/
2537 void cli_sockopt(struct cli_state *cli, char *options)
2539 set_socket_options(cli->fd, options);
2542 /****************************************************************************
2543 set the PID to use for smb messages. Return the old pid.
2544 ****************************************************************************/
2545 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
2547 uint16 ret = cli->pid;
2552 /****************************************************************************
2553 re-establishes a connection
2554 ****************************************************************************/
2555 BOOL cli_reestablish_connection(struct cli_state *cli)
2557 struct nmb_name calling;
2558 struct nmb_name called;
2562 BOOL do_tcon = False;
2563 int oldfd = cli->fd;
2565 if (!cli->initialised || cli->fd == -1)
2567 DEBUG(3,("cli_reestablish_connection: not connected\n"));
2571 /* copy the parameters necessary to re-establish the connection */
2575 fstrcpy(share, cli->share);
2576 fstrcpy(dev , cli->dev);
2580 memcpy(&called , &(cli->called ), sizeof(called ));
2581 memcpy(&calling, &(cli->calling), sizeof(calling));
2582 fstrcpy(dest_host, cli->full_dest_host_name);
2584 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2585 nmb_namestr(&calling), nmb_namestr(&called),
2586 inet_ntoa(cli->dest_ip),
2587 cli->user_name, cli->domain));
2591 if (cli_establish_connection(cli,
2592 dest_host, &cli->dest_ip,
2594 share, dev, False, do_tcon)) {
2595 if (cli->fd != oldfd) {
2596 if (dup2(cli->fd, oldfd) == oldfd) {
2605 /****************************************************************************
2606 establishes a connection right up to doing tconX, reading in a password.
2607 ****************************************************************************/
2608 BOOL cli_establish_connection(struct cli_state *cli,
2609 char *dest_host, struct in_addr *dest_ip,
2610 struct nmb_name *calling, struct nmb_name *called,
2611 char *service, char *service_type,
2612 BOOL do_shutdown, BOOL do_tcon)
2614 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
2615 nmb_namestr(calling), nmb_namestr(called), inet_ntoa(*dest_ip),
2616 cli->user_name, cli->domain));
2618 /* establish connection */
2620 if ((!cli->initialised))
2627 if (!cli_connect(cli, dest_host, dest_ip))
2629 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
2630 nmb_namestr(calling), inet_ntoa(*dest_ip)));
2635 if (!cli_session_request(cli, calling, called))
2637 DEBUG(1,("failed session request\n"));
2643 if (!cli_negprot(cli))
2645 DEBUG(1,("failed negprot\n"));
2651 if (cli->pwd.cleartext || cli->pwd.null_pwd)
2656 if (cli->pwd.null_pwd)
2658 /* attempt null session */
2664 /* attempt clear-text session */
2665 pwd_get_cleartext(&(cli->pwd), passwd);
2666 pass_len = strlen(passwd);
2669 /* attempt clear-text session */
2670 if (!cli_session_setup(cli, cli->user_name,
2675 DEBUG(1,("failed session setup\n"));
2684 if (!cli_send_tconX(cli, service, service_type,
2685 (char*)passwd, strlen(passwd)))
2687 DEBUG(1,("failed tcon_X\n"));
2698 /* attempt encrypted session */
2699 unsigned char nt_sess_pwd[24];
2700 unsigned char lm_sess_pwd[24];
2702 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
2703 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
2704 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
2706 /* attempt encrypted session */
2707 if (!cli_session_setup(cli, cli->user_name,
2708 (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
2709 (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
2712 DEBUG(1,("failed session setup\n"));
2722 if (!cli_send_tconX(cli, service, service_type,
2723 (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
2725 DEBUG(1,("failed tcon_X\n"));
2744 /****************************************************************************
2745 connect to one of multiple servers: don't care which
2746 ****************************************************************************/
2747 BOOL cli_connect_serverlist(struct cli_state *cli, char *p)
2749 extern pstring global_myname;
2750 extern pstring scope;
2751 fstring remote_machine;
2752 struct in_addr dest_ip;
2753 struct nmb_name calling, called, stupid_smbserver_called;
2754 BOOL connected_ok = False;
2757 * Treat each name in the 'password server =' line as a potential
2758 * PDC/BDC. Contact each in turn and try and authenticate.
2761 while(p && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine)))
2765 if (!cli_initialise(cli))
2767 DEBUG(0,("cli_connect_serverlist: unable to initialize client connection.\n"));
2771 standard_sub_basic(remote_machine);
2772 strupper(remote_machine);
2774 if (!resolve_name( remote_machine, &dest_ip, 0x20))
2776 DEBUG(1,("cli_connect_serverlist: Can't resolve address for %s\n", remote_machine));
2780 if ((lp_security() != SEC_USER) && (ismyip(dest_ip)))
2782 DEBUG(1,("cli_connect_serverlist: Password server loop - not using password server %s\n", remote_machine));
2786 make_nmb_name(&calling, global_myname , 0x0 , scope);
2787 make_nmb_name(&called , remote_machine, 0x20, scope);
2788 /* stupid microsoft destruction of the ability of netbios
2789 * to provide multiple netbios servers on one host.
2791 make_nmb_name(&stupid_smbserver_called , "*SMBSERVER", 0x20, scope);
2793 pwd_set_nullpwd(&cli->pwd);
2795 if (!cli_establish_connection(cli, remote_machine, &dest_ip,
2799 !cli_establish_connection(cli, remote_machine, &dest_ip,
2800 &calling, &stupid_smbserver_called,
2808 if (cli->protocol < PROTOCOL_LANMAN2 ||
2809 !IS_BITS_SET_ALL(cli->sec_mode, 1))
2811 DEBUG(1,("cli_connect_serverlist: machine %s isn't in user level security mode\n",
2818 * We have an anonymous connection to IPC$.
2821 connected_ok = True;
2827 DEBUG(0,("cli_connect_serverlist: Domain password server not available.\n"));
2831 return connected_ok;
2834 /****************************************************************************
2836 ****************************************************************************/
2837 int cli_printjob_del(struct cli_state *cli, int job)
2839 char *rparam = NULL;
2842 int rdrcnt,rprcnt, ret = -1;
2845 bzero(param,sizeof(param));
2848 SSVAL(p,0,81); /* DosPrintJobDel() */
2851 p = skip_string(p,1);
2853 p = skip_string(p,1);
2858 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2859 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2860 &rparam, &rprcnt, /* return params, length */
2861 &rdata, &rdrcnt)) { /* return data, length */
2862 ret = SVAL(rparam,0);
2865 if (rparam) free(rparam);
2866 if (rdata) free(rdata);
2872 /****************************************************************************
2873 call fn() on each entry in a print queue
2874 ****************************************************************************/
2875 int cli_print_queue(struct cli_state *cli,
2876 void (*fn)(struct print_job_info *))
2878 char *rparam = NULL;
2886 bzero(param,sizeof(param));
2889 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2891 pstrcpy(p,"zWrLeh"); /* parameter description? */
2892 p = skip_string(p,1);
2893 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
2894 p = skip_string(p,1);
2895 pstrcpy(p,cli->share); /* name of queue */
2896 p = skip_string(p,1);
2897 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2898 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2900 pstrcpy(p,""); /* subformat */
2901 p = skip_string(p,1);
2903 DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
2906 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2907 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2908 &rparam, &rprcnt, /* return params, length */
2909 &rdata, &rdrcnt)) { /* return data, length */
2911 result_code = SVAL(rparam,0);
2912 converter = SVAL(rparam,2); /* conversion factor */
2914 if (result_code == 0) {
2915 struct print_job_info job;
2919 for (i = 0; i < SVAL(rparam,4); ++i) {
2921 job.priority = SVAL(p,2);
2923 fix_char_ptr(SVAL(p,4), converter,
2925 job.t = make_unix_date3(p + 12);
2926 job.size = IVAL(p,16);
2927 fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
2936 /* If any parameters or data were returned, free the storage. */
2937 if(rparam) free(rparam);
2938 if(rdata) free(rdata);
2943 /****************************************************************************
2944 check for existance of a dir
2945 ****************************************************************************/
2946 BOOL cli_chkpath(struct cli_state *cli, char *path)
2951 fstrcpy(path2,path);
2952 trim_string(path2,NULL,"\\");
2953 if (!*path2) *path2 = '\\';
2955 bzero(cli->outbuf,smb_size);
2956 set_message(cli->outbuf,0,4 + strlen(path2),True);
2957 SCVAL(cli->outbuf,smb_com,SMBchkpth);
2958 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2959 cli_setup_packet(cli);
2961 p = smb_buf(cli->outbuf);
2965 cli_send_smb(cli, True);
2966 if (!cli_receive_smb(cli)) {
2970 if (cli_error(cli, NULL, NULL)) return False;
2976 /****************************************************************************
2977 start a message sequence
2978 ****************************************************************************/
2979 BOOL cli_message_start(struct cli_state *cli, char *host, char *username,
2984 /* send a SMBsendstrt command */
2985 bzero(cli->outbuf,smb_size);
2986 set_message(cli->outbuf,0,0,True);
2987 CVAL(cli->outbuf,smb_com) = SMBsendstrt;
2988 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2989 cli_setup_packet(cli);
2991 p = smb_buf(cli->outbuf);
2993 pstrcpy(p,username);
2994 p = skip_string(p,1);
2997 p = skip_string(p,1);
2999 set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
3001 cli_send_smb(cli, True);
3003 if (!cli_receive_smb(cli)) {
3007 if (cli_error(cli, NULL, NULL)) return False;
3009 *grp = SVAL(cli->inbuf,smb_vwv0);
3015 /****************************************************************************
3017 ****************************************************************************/
3018 BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp)
3022 bzero(cli->outbuf,smb_size);
3023 set_message(cli->outbuf,1,len+3,True);
3024 CVAL(cli->outbuf,smb_com) = SMBsendtxt;
3025 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3026 cli_setup_packet(cli);
3028 SSVAL(cli->outbuf,smb_vwv0,grp);
3030 p = smb_buf(cli->outbuf);
3033 memcpy(p+3,msg,len);
3034 cli_send_smb(cli, True);
3036 if (!cli_receive_smb(cli)) {
3040 if (cli_error(cli, NULL, NULL)) return False;
3045 /****************************************************************************
3047 ****************************************************************************/
3048 BOOL cli_message_end(struct cli_state *cli, int grp)
3050 bzero(cli->outbuf,smb_size);
3051 set_message(cli->outbuf,1,0,True);
3052 CVAL(cli->outbuf,smb_com) = SMBsendend;
3053 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3055 SSVAL(cli->outbuf,smb_vwv0,grp);
3057 cli_setup_packet(cli);
3059 cli_send_smb(cli, True);
3061 if (!cli_receive_smb(cli)) {
3065 if (cli_error(cli, NULL, NULL)) return False;
3071 /****************************************************************************
3073 ****************************************************************************/
3074 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3076 bzero(cli->outbuf,smb_size);
3077 set_message(cli->outbuf,0,0,True);
3078 CVAL(cli->outbuf,smb_com) = SMBdskattr;
3079 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3080 cli_setup_packet(cli);
3082 cli_send_smb(cli, True);
3083 if (!cli_receive_smb(cli)) {
3087 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
3088 *total = SVAL(cli->inbuf,smb_vwv0);
3089 *avail = SVAL(cli->inbuf,smb_vwv3);