2 Unix SMB/Netbios implementation.
4 SMB client generic functions
5 Copyright (C) Andrew Tridgell 1994-1999
6 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 extern int DEBUGLEVEL;
32 * set the port that will be used for connections by the client
35 int cli_set_port(struct cli_state *cli, int port)
41 return cli -> port; /* return it incase caller wants it */
45 /****************************************************************************
47 ****************************************************************************/
48 static BOOL cli_receive_smb(struct cli_state *cli)
50 return client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
53 /****************************************************************************
54 send an smb to a fd and re-establish if necessary
55 ****************************************************************************/
56 static BOOL cli_send_smb(struct cli_state *cli, BOOL show)
61 BOOL reestablished=False;
65 show_msg(cli->outbuf);
68 len = smb_len(cli->outbuf) + 4;
70 while (nwritten < len) {
71 ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
72 if (ret <= 0 && errno == EPIPE && !reestablished)
74 DEBUG(5,("cli_send_smb: write error (%s) - reconnecting\n",
77 if (cli_reestablish_connection(cli)) {
84 DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",
94 /******************************************************
95 Return an error message - either an SMB error or a RAP
97 *******************************************************/
99 char *cli_errstr(struct cli_state *cli)
101 static fstring error_message;
102 cli_safe_errstr(cli, error_message, sizeof(error_message));
103 return error_message;
106 /****************************************************************************
107 return a description of an SMB error
108 ****************************************************************************/
109 void cli_safe_smb_errstr(struct cli_state *cli, char *msg, size_t len)
111 smb_safe_errstr(cli->inbuf, msg, len);
114 /*****************************************************
115 RAP error codes - a small start but will be extended.
116 *******************************************************/
124 {5, "User has insufficient privilege" },
125 {86, "The specified password is invalid" },
126 {2226, "Operation only permitted on a Primary Domain Controller" },
127 {2242, "The password of this user has expired." },
128 {2243, "The password of this user cannot change." },
129 {2244, "This password cannot be used now (password history conflict)." },
130 {2245, "The password is shorter than required." },
131 {2246, "The password of this user is too recent to change."},
135 /****************************************************************************
136 return a description of a RAP error
137 ****************************************************************************/
138 BOOL get_safe_rap_errstr(int rap_error, char *err_msg, size_t msglen)
142 slprintf(err_msg, msglen - 1, "RAP code %d", rap_error);
144 for (i = 0; rap_errmap[i].message != NULL; i++)
146 if (rap_errmap[i].err == rap_error)
148 safe_strcpy( err_msg, rap_errmap[i].message, msglen);
155 /****************************************************************************
156 return a description of an SMB error
157 ****************************************************************************/
158 void cli_safe_errstr(struct cli_state *cli, char *err_msg, size_t msglen)
164 * Errors are of three kinds - smb errors,
165 * dealt with by cli_smb_errstr, NT errors,
166 * whose code is in cli.nt_error, and rap
167 * errors, whose error code is in cli.rap_error.
170 cli_error(cli, &errclass, &errnum);
174 cli_safe_smb_errstr(cli, err_msg, msglen);
176 else if (cli->nt_error)
179 * Was it an NT error ?
182 (void)get_safe_nt_error_msg(cli->nt_error, err_msg, msglen);
187 * Must have been a rap error.
189 (void)get_safe_rap_errstr(cli->rap_error, err_msg, msglen);
192 /****************************************************************************
193 setup basics in a outgoing packet
194 ****************************************************************************/
195 static void cli_setup_packet(struct cli_state *cli)
199 SSVAL(cli->outbuf,smb_pid,cli->pid);
200 SSVAL(cli->outbuf,smb_uid,cli->vuid);
201 SSVAL(cli->outbuf,smb_mid,cli->mid);
202 if (cli->protocol > PROTOCOL_CORE) {
203 SCVAL(cli->outbuf,smb_flg,0x8);
204 SSVAL(cli->outbuf,smb_flg2,0x1);
209 /*****************************************************************************
210 Convert a character pointer in a cli_call_api() response to a form we can use.
211 This function contains code to prevent core dumps if the server returns
213 *****************************************************************************/
214 static char *fix_char_ptr(unsigned int datap, unsigned int converter,
215 char *rdata, int rdrcnt)
217 if (datap == 0) { /* turn NULL pointers into zero length strings */
220 unsigned int offset = datap - converter;
222 if (offset >= rdrcnt) {
223 DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
224 datap, converter, rdrcnt));
227 return &rdata[offset];
232 /****************************************************************************
233 send a SMB trans or trans2 request
234 ****************************************************************************/
235 BOOL cli_send_trans(struct cli_state *cli, int trans,
236 char *name, int pipe_name_len,
238 uint16 *setup, int lsetup, int msetup,
239 char *param, int lparam, int mparam,
240 char *data, int ldata, int mdata)
243 int this_ldata,this_lparam;
244 int tot_data=0,tot_param=0;
245 char *outdata,*outparam;
248 this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
249 this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
251 bzero(cli->outbuf,smb_size);
252 set_message(cli->outbuf,14+lsetup,0,True);
253 CVAL(cli->outbuf,smb_com) = trans;
254 SSVAL(cli->outbuf,smb_tid, cli->cnum);
255 cli_setup_packet(cli);
257 outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len+1 : 3);
258 outdata = outparam+this_lparam;
260 /* primary request */
261 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
262 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
263 SSVAL(cli->outbuf,smb_mprcnt,mparam); /* mprcnt */
264 SSVAL(cli->outbuf,smb_mdrcnt,mdata); /* mdrcnt */
265 SCVAL(cli->outbuf,smb_msrcnt,msetup); /* msrcnt */
266 SSVAL(cli->outbuf,smb_flags,flags); /* flags */
267 SIVAL(cli->outbuf,smb_timeout,0); /* timeout */
268 SSVAL(cli->outbuf,smb_pscnt,this_lparam); /* pscnt */
269 SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
270 SSVAL(cli->outbuf,smb_dscnt,this_ldata); /* dscnt */
271 SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
272 SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */
273 for (i=0;i<lsetup;i++) /* setup[] */
274 SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
275 p = smb_buf(cli->outbuf);
276 if (trans==SMBtrans) {
277 memcpy(p,name, pipe_name_len + 1); /* name[] */
279 *p++ = 0; /* put in a null smb_name */
280 *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */
282 if (this_lparam) /* param[] */
283 memcpy(outparam,param,this_lparam);
284 if (this_ldata) /* data[] */
285 memcpy(outdata,data,this_ldata);
286 set_message(cli->outbuf,14+lsetup, /* wcnt, bcc */
287 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
289 cli_send_smb(cli, True);
291 if (this_ldata < ldata || this_lparam < lparam) {
292 /* receive interim response */
293 if (!cli_receive_smb(cli) ||
294 CVAL(cli->inbuf,smb_rcls) != 0) {
298 tot_data = this_ldata;
299 tot_param = this_lparam;
301 while (tot_data < ldata || tot_param < lparam) {
302 this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
303 this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
305 set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
306 CVAL(cli->outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
308 outparam = smb_buf(cli->outbuf);
309 outdata = outparam+this_lparam;
311 /* secondary request */
312 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
313 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
314 SSVAL(cli->outbuf,smb_spscnt,this_lparam); /* pscnt */
315 SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
316 SSVAL(cli->outbuf,smb_spsdisp,tot_param); /* psdisp */
317 SSVAL(cli->outbuf,smb_sdscnt,this_ldata); /* dscnt */
318 SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
319 SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */
320 if (trans==SMBtrans2)
321 SSVALS(cli->outbuf,smb_sfid,fid); /* fid */
322 if (this_lparam) /* param[] */
323 memcpy(outparam,param,this_lparam);
324 if (this_ldata) /* data[] */
325 memcpy(outdata,data,this_ldata);
326 set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
327 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
329 cli_send_smb(cli, True);
331 tot_data += this_ldata;
332 tot_param += this_lparam;
340 /****************************************************************************
341 receive a SMB trans or trans2 response allocating the necessary memory
342 ****************************************************************************/
343 static BOOL cli_receive_trans(struct cli_state *cli,int trans,
344 char **param, int *param_len,
345 char **data, int *data_len)
349 int this_data,this_param;
351 *data_len = *param_len = 0;
353 if (!cli_receive_smb(cli))
357 if (CVAL(cli->inbuf,smb_com) != trans) {
358 DEBUG(0,("Expected %s response, got command 0x%02x\n",
359 trans==SMBtrans?"SMBtrans":"SMBtrans2",
360 CVAL(cli->inbuf,smb_com)));
364 if (cli_error(cli, NULL, NULL))
369 /* parse out the lengths */
370 total_data = SVAL(cli->inbuf,smb_tdrcnt);
371 total_param = SVAL(cli->inbuf,smb_tprcnt);
374 *data = Realloc(*data,total_data);
375 *param = Realloc(*param,total_param);
378 this_data = SVAL(cli->inbuf,smb_drcnt);
379 this_param = SVAL(cli->inbuf,smb_prcnt);
381 if (this_data + *data_len > total_data ||
382 this_param + *param_len > total_param) {
383 DEBUG(1,("Data overflow in cli_receive_trans\n"));
388 memcpy(*data + SVAL(cli->inbuf,smb_drdisp),
389 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff),
392 memcpy(*param + SVAL(cli->inbuf,smb_prdisp),
393 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff),
395 *data_len += this_data;
396 *param_len += this_param;
398 /* parse out the total lengths again - they can shrink! */
399 total_data = SVAL(cli->inbuf,smb_tdrcnt);
400 total_param = SVAL(cli->inbuf,smb_tprcnt);
402 if (total_data <= *data_len && total_param <= *param_len)
405 if (!cli_receive_smb(cli))
409 if (CVAL(cli->inbuf,smb_com) != trans) {
410 DEBUG(0,("Expected %s response, got command 0x%02x\n",
411 trans==SMBtrans?"SMBtrans":"SMBtrans2",
412 CVAL(cli->inbuf,smb_com)));
416 if (cli_error(cli, NULL, NULL))
425 /****************************************************************************
426 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
427 ****************************************************************************/
428 BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name, int pipe_name_len,
429 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
430 char *params, uint32 param_count, uint32 max_param_count,
431 char *data, uint32 data_count, uint32 max_data_count,
432 char **rparam, uint32 *rparam_count,
433 char **rdata, uint32 *rdata_count)
435 if (pipe_name_len == 0)
436 pipe_name_len = strlen(pipe_name);
438 cli_send_trans(cli, SMBtrans,
439 pipe_name, pipe_name_len,
440 0,0, /* fid, flags */
441 setup, setup_count, max_setup_count,
442 params, param_count, max_param_count,
443 data, data_count, max_data_count);
445 return (cli_receive_trans(cli, SMBtrans,
446 rparam, (int *)rparam_count,
447 rdata, (int *)rdata_count));
450 /****************************************************************************
452 ****************************************************************************/
453 BOOL cli_api(struct cli_state *cli,
454 char *param, int prcnt, int mprcnt,
455 char *data, int drcnt, int mdrcnt,
456 char **rparam, int *rprcnt,
457 char **rdata, int *rdrcnt)
459 cli_send_trans(cli,SMBtrans,
460 PIPE_LANMAN,strlen(PIPE_LANMAN), /* Name, length */
461 0,0, /* fid, flags */
462 NULL,0,0, /* Setup, length, max */
463 param, prcnt, mprcnt, /* Params, length, max */
464 data, drcnt, mdrcnt /* Data, length, max */
467 return (cli_receive_trans(cli,SMBtrans,
473 /****************************************************************************
474 perform a NetWkstaUserLogon
475 ****************************************************************************/
476 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
484 memset(param, 0, sizeof(param));
486 /* send a SMBtrans command with api NetWkstaUserLogon */
488 SSVAL(p,0,132); /* api number */
490 pstrcpy(p,"OOWb54WrLh");
491 p = skip_string(p,1);
492 pstrcpy(p,"WB21BWDWWDDDDDDDzzzD");
493 p = skip_string(p,1);
502 pstrcpy(p, workstation);
505 SSVAL(p, 0, CLI_BUFFER_SIZE);
507 SSVAL(p, 0, CLI_BUFFER_SIZE);
511 param, PTR_DIFF(p,param),1024, /* param, length, max */
512 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
513 &rparam, &rprcnt, /* return params, return size */
514 &rdata, &rdrcnt /* return data, return size */
516 cli->rap_error = SVAL(rparam,0);
519 if (cli->rap_error == 0) {
520 DEBUG(4,("NetWkstaUserLogon success\n"));
521 cli->privilages = SVAL(p, 24);
522 fstrcpy(cli->eff_name,p+2);
524 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
532 return (cli->rap_error == 0);
535 /****************************************************************************
536 call a NetShareEnum - try and browse available connections on a host
537 ****************************************************************************/
538 BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *))
547 /* now send a SMBtrans command with api RNetShareEnum */
549 SSVAL(p,0,0); /* api number */
552 p = skip_string(p,1);
554 p = skip_string(p,1);
560 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
561 NULL, 0, 0xFFFF, /* data, length, maxlen */
562 &rparam, &rprcnt, /* return params, length */
563 &rdata, &rdrcnt)) /* return data, length */
565 int res = SVAL(rparam,0);
566 int converter=SVAL(rparam,2);
569 if (res == 0 || res == ERRmoredata) {
570 count=SVAL(rparam,4);
573 for (i=0;i<count;i++,p+=20) {
575 int type = SVAL(p,14);
576 int comment_offset = IVAL(p,16) & 0xFFFF;
577 char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
578 fn(sname, type, cmnt);
581 DEBUG(4,("NetShareEnum res=%d\n", res));
584 DEBUG(4,("NetShareEnum failed\n"));
596 /****************************************************************************
597 call a NetServerEnum for the specified workgroup and servertype mask.
598 This function then calls the specified callback function for each name returned.
600 The callback function takes 3 arguments: the machine name, the server type and
602 ****************************************************************************/
603 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
604 void (*fn)(const char *, uint32, const char *))
614 /* send a SMBtrans command with api NetServerEnum */
616 SSVAL(p,0,0x68); /* api number */
618 pstrcpy(p,"WrLehDz");
619 p = skip_string(p,1);
621 pstrcpy(p,"B16BBDz");
623 p = skip_string(p,1);
625 SSVAL(p,2,CLI_BUFFER_SIZE);
630 pstrcpy(p, workgroup);
631 p = skip_string(p,1);
634 param, PTR_DIFF(p,param), 8, /* params, length, max */
635 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
636 &rparam, &rprcnt, /* return params, return size */
637 &rdata, &rdrcnt /* return data, return size */
639 int res = SVAL(rparam,0);
640 int converter=SVAL(rparam,2);
643 if (res == 0 || res == ERRmoredata) {
644 count=SVAL(rparam,4);
647 for (i = 0;i < count;i++, p += 26) {
649 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
650 char *cmnt = comment_offset?(rdata+comment_offset):"";
651 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
653 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
655 fn(sname, stype, cmnt);
677 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
678 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
679 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
680 {PROTOCOL_LANMAN1,"LANMAN1.0"},
681 {PROTOCOL_LANMAN2,"LM1.2X002"},
682 {PROTOCOL_LANMAN2,"Samba"},
683 {PROTOCOL_NT1,"NT LANMAN 1.0"},
684 {PROTOCOL_NT1,"NT LM 0.12"},
691 /****************************************************************************
693 ****************************************************************************/
694 BOOL cli_session_setup_x(struct cli_state *cli,
696 char *pass, int passlen,
697 char *ntpass, int ntpasslen,
702 #ifdef DEBUG_PASSWORD
703 DEBUG(100,("cli_session_setup. pass, ntpass\n"));
704 dump_data(100, pass, passlen);
705 dump_data(100, ntpass, ntpasslen);
708 if (cli->protocol < PROTOCOL_LANMAN1)
713 /* send a session setup command */
714 bzero(cli->outbuf,smb_size);
716 if (cli->protocol < PROTOCOL_NT1)
718 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
719 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
720 cli_setup_packet(cli);
722 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
723 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
724 SSVAL(cli->outbuf,smb_vwv3,2);
725 SSVAL(cli->outbuf,smb_vwv4,1);
726 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
727 SSVAL(cli->outbuf,smb_vwv7,passlen);
728 p = smb_buf(cli->outbuf);
729 memcpy(p,pass,passlen);
736 set_message(cli->outbuf,13,0,True);
737 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
738 cli_setup_packet(cli);
740 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
741 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
742 SSVAL(cli->outbuf,smb_vwv3,2);
743 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
744 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
745 SSVAL(cli->outbuf,smb_vwv7,passlen);
746 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
747 SSVAL(cli->outbuf,smb_vwv11,0);
748 p = smb_buf(cli->outbuf);
749 memcpy(p,pass,passlen);
750 p += SVAL(cli->outbuf,smb_vwv7);
751 memcpy(p,ntpass,ntpasslen);
752 p += SVAL(cli->outbuf,smb_vwv8);
755 p = skip_string(p,1);
756 pstrcpy(p,user_domain);
757 p = skip_string(p,1);
758 pstrcpy(p,"Unix");p = skip_string(p,1);
760 pstrcpy(p,"Samba");p = skip_string(p,1);
761 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
764 cli_send_smb(cli, True);
765 if (!cli_receive_smb(cli))
767 DEBUG(10,("cli_session_setup: receive smb failed\n"));
771 if (CVAL(cli->inbuf,smb_rcls) != 0) {
775 /* use the returned vuid from now on */
776 cli->vuid = SVAL(cli->inbuf,smb_uid);
778 if (cli->protocol >= PROTOCOL_NT1) {
780 * Save off some of the connected server
783 char *server_domain,*server_os,*server_type;
784 server_os = smb_buf(cli->inbuf);
785 server_type = skip_string(server_os,1);
786 server_domain = skip_string(server_type,1);
787 fstrcpy(cli->server_os, server_os);
788 fstrcpy(cli->server_type, server_type);
789 fstrcpy(cli->server_domain, server_domain);
795 static BOOL cli_calc_session_pwds(struct cli_state *cli,
796 char *pword, char *ntpword,
797 char *pass, int *passlen,
798 char *ntpass, int *ntpasslen,
801 #ifdef DEBUG_PASSWORD
802 DEBUG(100,("cli_calc_session_pwds. pass, ntpass\n"));
803 dump_data(100, pass, *passlen);
804 dump_data(100, ntpass, *ntpasslen);
806 if (!IS_BITS_SET_ALL(cli->sec_mode, 1))
808 /* if in share level security then don't send a password now */
811 fstrcpy(ntpword, "");
814 else if ((*passlen == 0 || *passlen == 1) && (pass[0] == '\0'))
816 /* Null session connect. */
820 else if (*passlen == 24 && *ntpasslen >= 24)
822 if (IS_BITS_SET_ALL(cli->sec_mode, 2))
824 /* encrypted password, implicit from 24-byte lengths */
825 memcpy(pword , pass , *passlen);
826 memcpy(ntpword, ntpass, *ntpasslen);
830 DEBUG(0,("cli_session_setup: encrypted passwords not supported by server\n"));
834 else if (*ntpasslen == 0 || !IS_BITS_SET_ALL(cli->sec_mode, 2))
836 /* plain-text password: server doesn't support encrypted. */
837 fstrcpy(pword, pass);
838 fstrcpy(ntpword, "");
841 else /* passlen != 0 && ntpasslen != 0 && server supports encryption */
845 /* plain-text password requesting to be encrypted */
846 uchar *srv_key = (uchar *)cli->cryptkey;
850 SMBgenclientchals(cli->lm_cli_chal,
852 &cli->nt_cli_chal_len,
856 nt_owf_gen(pword, nt_owf);
857 ntv2_owf_gen(nt_owf, cli->user_name, cli->domain, kr);
860 memcpy(pword, cli->lm_cli_chal, 8);
861 SMBOWFencrypt_ntv2(kr,
868 memcpy(ntpword, cli->lm_cli_chal, cli->nt_cli_chal_len);
869 SMBOWFencrypt_ntv2(kr,
871 cli->nt_cli_chal, cli->nt_cli_chal_len,
872 &ntpword[cli->nt_cli_chal_len]);
873 *ntpasslen = cli->nt_cli_chal_len + 16;
877 /* plain-text password requesting to be encrypted */
878 uchar *key = (uchar *)cli->cryptkey;
879 SMBencrypt ((uchar *)pass , key,(uchar *)pword );
880 SMBNTencrypt((uchar *)ntpass, key,(uchar *)ntpword);
888 /****************************************************************************
890 ****************************************************************************/
891 BOOL cli_session_setup(struct cli_state *cli,
893 char *pass, int passlen,
894 char *ntpass, int ntpasslen,
897 fstring pword, ntpword;
899 if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1)
904 fstrcpy(cli->user_name, user);
906 return cli_calc_session_pwds(cli, pword, ntpword,
908 ntpass, &ntpasslen, cli->use_ntlmv2) &&
909 cli_session_setup_x(cli, user, pass, passlen, ntpass, ntpasslen,
913 /****************************************************************************
915 *****************************************************************************/
917 BOOL cli_ulogoff(struct cli_state *cli)
919 bzero(cli->outbuf,smb_size);
920 set_message(cli->outbuf,2,0,True);
921 CVAL(cli->outbuf,smb_com) = SMBulogoffX;
922 cli_setup_packet(cli);
923 SSVAL(cli->outbuf,smb_vwv0,0xFF);
924 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
926 cli_send_smb(cli, True);
927 if (!cli_receive_smb(cli))
930 return CVAL(cli->inbuf,smb_rcls) == 0;
933 /****************************************************************************
935 ****************************************************************************/
936 BOOL cli_send_tconX(struct cli_state *cli,
937 char *share, char *dev, char *pass, int passlen)
939 fstring fullshare, pword;
941 bzero(cli->outbuf,smb_size);
942 bzero(cli->inbuf,smb_size);
944 fstrcpy(cli->share, share);
946 /* in user level security don't send a password now */
947 if (cli->sec_mode & 1) {
952 if ((cli->sec_mode & 2) && *pass && passlen != 24) {
954 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
956 memcpy(pword, pass, passlen);
959 slprintf(fullshare, sizeof(fullshare)-1,
960 "\\\\%s\\%s", cli->desthost, share);
963 set_message(cli->outbuf,4,
964 2 + strlen(fullshare) + passlen + strlen(dev),True);
965 CVAL(cli->outbuf,smb_com) = SMBtconX;
966 cli_setup_packet(cli);
968 SSVAL(cli->outbuf,smb_vwv0,0xFF);
969 SSVAL(cli->outbuf,smb_vwv3,passlen);
971 p = smb_buf(cli->outbuf);
972 memcpy(p,pword,passlen);
974 fstrcpy(p,fullshare);
975 p = skip_string(p,1);
978 SCVAL(cli->inbuf,smb_rcls, 1);
980 cli_send_smb(cli, True);
981 if (!cli_receive_smb(cli))
984 if (CVAL(cli->inbuf,smb_rcls) != 0) {
988 fstrcpy(cli->dev, "A:");
990 if (cli->protocol >= PROTOCOL_NT1) {
991 fstrcpy(cli->dev, smb_buf(cli->inbuf));
994 if (strcasecmp(share,"IPC$")==0) {
995 fstrcpy(cli->dev, "IPC");
998 /* only grab the device if we have a recent protocol level */
999 if (cli->protocol >= PROTOCOL_NT1 &&
1000 smb_buflen(cli->inbuf) == 3) {
1001 /* almost certainly win95 - enable bug fixes */
1005 cli->cnum = SVAL(cli->inbuf,smb_tid);
1010 /****************************************************************************
1011 send a tree disconnect
1012 ****************************************************************************/
1013 BOOL cli_tdis(struct cli_state *cli)
1015 bzero(cli->outbuf,smb_size);
1016 set_message(cli->outbuf,0,0,True);
1017 CVAL(cli->outbuf,smb_com) = SMBtdis;
1018 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1019 cli_setup_packet(cli);
1021 cli_send_smb(cli, True);
1022 if (!cli_receive_smb(cli))
1025 return CVAL(cli->inbuf,smb_rcls) == 0;
1028 /****************************************************************************
1030 ****************************************************************************/
1031 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
1035 bzero(cli->outbuf,smb_size);
1036 bzero(cli->inbuf,smb_size);
1038 set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
1040 CVAL(cli->outbuf,smb_com) = SMBmv;
1041 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1042 cli_setup_packet(cli);
1044 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
1046 p = smb_buf(cli->outbuf);
1048 pstrcpy(p,fname_src);
1049 p = skip_string(p,1);
1051 pstrcpy(p,fname_dst);
1053 cli_send_smb(cli, True);
1054 if (!cli_receive_smb(cli)) {
1058 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1065 /****************************************************************************
1067 ****************************************************************************/
1068 BOOL cli_unlink(struct cli_state *cli, char *fname)
1072 bzero(cli->outbuf,smb_size);
1073 bzero(cli->inbuf,smb_size);
1075 set_message(cli->outbuf,1, 2 + strlen(fname),True);
1077 CVAL(cli->outbuf,smb_com) = SMBunlink;
1078 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1079 cli_setup_packet(cli);
1081 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
1083 p = smb_buf(cli->outbuf);
1087 cli_send_smb(cli, True);
1088 if (!cli_receive_smb(cli)) {
1092 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1099 /****************************************************************************
1101 ****************************************************************************/
1102 BOOL cli_mkdir(struct cli_state *cli, char *dname)
1106 bzero(cli->outbuf,smb_size);
1107 bzero(cli->inbuf,smb_size);
1109 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1111 CVAL(cli->outbuf,smb_com) = SMBmkdir;
1112 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1113 cli_setup_packet(cli);
1115 p = smb_buf(cli->outbuf);
1119 cli_send_smb(cli, True);
1120 if (!cli_receive_smb(cli)) {
1124 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1131 /****************************************************************************
1133 ****************************************************************************/
1134 BOOL cli_rmdir(struct cli_state *cli, char *dname)
1138 bzero(cli->outbuf,smb_size);
1139 bzero(cli->inbuf,smb_size);
1141 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1143 CVAL(cli->outbuf,smb_com) = SMBrmdir;
1144 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1145 cli_setup_packet(cli);
1147 p = smb_buf(cli->outbuf);
1151 cli_send_smb(cli, True);
1152 if (!cli_receive_smb(cli)) {
1156 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1165 /****************************************************************************
1167 ****************************************************************************/
1168 int cli_nt_create(struct cli_state *cli, char *fname)
1172 bzero(cli->outbuf,smb_size);
1173 bzero(cli->inbuf,smb_size);
1175 set_message(cli->outbuf,24,1 + strlen(fname),True);
1177 CVAL(cli->outbuf,smb_com) = SMBntcreateX;
1178 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1179 cli_setup_packet(cli);
1181 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1182 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0x06);
1183 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
1184 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, 0x2019f);
1185 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0);
1186 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03);
1187 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01);
1188 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0);
1189 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
1190 SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname));
1192 p = smb_buf(cli->outbuf);
1194 p = skip_string(p,1);
1196 cli_send_smb(cli, True);
1197 if (!cli_receive_smb(cli)) {
1201 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1205 return SVAL(cli->inbuf,smb_vwv2 + 1);
1209 /****************************************************************************
1211 ****************************************************************************/
1212 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
1216 unsigned accessmode=0;
1218 /* you must open for RW not just write - otherwise getattrE doesn't
1220 if ((flags & O_ACCMODE) == O_WRONLY && strncmp(cli->dev, "LPT", 3)) {
1221 flags = (flags & ~O_ACCMODE) | O_RDWR;
1224 if (flags & O_CREAT)
1226 if (!(flags & O_EXCL)) {
1227 if (flags & O_TRUNC)
1233 accessmode = (share_mode<<4);
1235 if ((flags & O_ACCMODE) == O_RDWR) {
1237 } else if ((flags & O_ACCMODE) == O_WRONLY) {
1242 if ((flags & O_SYNC) == O_SYNC) {
1243 accessmode |= (1<<14);
1247 bzero(cli->outbuf,smb_size);
1248 bzero(cli->inbuf,smb_size);
1250 set_message(cli->outbuf,15,1 + strlen(fname),True);
1252 CVAL(cli->outbuf,smb_com) = SMBopenX;
1253 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1254 cli_setup_packet(cli);
1256 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1257 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1258 SSVAL(cli->outbuf,smb_vwv3,accessmode);
1259 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1260 SSVAL(cli->outbuf,smb_vwv5,0);
1261 SSVAL(cli->outbuf,smb_vwv8,openfn);
1263 p = smb_buf(cli->outbuf);
1265 p = skip_string(p,1);
1267 cli_send_smb(cli, True);
1268 if (!cli_receive_smb(cli)) {
1272 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1276 return SVAL(cli->inbuf,smb_vwv2);
1282 /****************************************************************************
1284 ****************************************************************************/
1285 BOOL cli_close(struct cli_state *cli, int fnum)
1287 bzero(cli->outbuf,smb_size);
1288 bzero(cli->inbuf,smb_size);
1290 set_message(cli->outbuf,3,0,True);
1292 CVAL(cli->outbuf,smb_com) = SMBclose;
1293 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1294 cli_setup_packet(cli);
1296 SSVAL(cli->outbuf,smb_vwv0,fnum);
1297 SIVALS(cli->outbuf,smb_vwv1,-1);
1299 cli_send_smb(cli, True);
1300 if (!cli_receive_smb(cli)) {
1304 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1312 /****************************************************************************
1314 ****************************************************************************/
1315 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1318 int saved_timeout = cli->timeout;
1320 bzero(cli->outbuf,smb_size);
1321 bzero(cli->inbuf,smb_size);
1323 set_message(cli->outbuf,8,10,True);
1325 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1326 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1327 cli_setup_packet(cli);
1329 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1330 SSVAL(cli->outbuf,smb_vwv2,fnum);
1331 CVAL(cli->outbuf,smb_vwv3) = 0;
1332 SIVALS(cli->outbuf, smb_vwv4, timeout);
1333 SSVAL(cli->outbuf,smb_vwv6,0);
1334 SSVAL(cli->outbuf,smb_vwv7,1);
1336 p = smb_buf(cli->outbuf);
1337 SSVAL(p, 0, cli->pid);
1338 SIVAL(p, 2, offset);
1340 cli_send_smb(cli, True);
1342 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout;
1344 if (!cli_receive_smb(cli)) {
1345 cli->timeout = saved_timeout;
1349 cli->timeout = saved_timeout;
1351 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1358 /****************************************************************************
1360 ****************************************************************************/
1361 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1365 bzero(cli->outbuf,smb_size);
1366 bzero(cli->inbuf,smb_size);
1368 set_message(cli->outbuf,8,10,True);
1370 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1371 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1372 cli_setup_packet(cli);
1374 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1375 SSVAL(cli->outbuf,smb_vwv2,fnum);
1376 CVAL(cli->outbuf,smb_vwv3) = 0;
1377 SIVALS(cli->outbuf, smb_vwv4, timeout);
1378 SSVAL(cli->outbuf,smb_vwv6,1);
1379 SSVAL(cli->outbuf,smb_vwv7,0);
1381 p = smb_buf(cli->outbuf);
1382 SSVAL(p, 0, cli->pid);
1383 SIVAL(p, 2, offset);
1386 cli_send_smb(cli, True);
1387 if (!cli_receive_smb(cli)) {
1391 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1400 /****************************************************************************
1401 issue a single SMBread and don't wait for a reply
1402 ****************************************************************************/
1403 static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
1406 bzero(cli->outbuf,smb_size);
1407 bzero(cli->inbuf,smb_size);
1409 set_message(cli->outbuf,10,0,True);
1411 CVAL(cli->outbuf,smb_com) = SMBreadX;
1412 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1413 cli_setup_packet(cli);
1415 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1416 SSVAL(cli->outbuf,smb_vwv2,fnum);
1417 SIVAL(cli->outbuf,smb_vwv3,offset);
1418 SSVAL(cli->outbuf,smb_vwv5,size);
1419 SSVAL(cli->outbuf,smb_vwv6,size);
1420 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1422 cli_send_smb(cli, True);
1425 /****************************************************************************
1427 ****************************************************************************/
1428 size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
1434 int mpx = MAX(cli->max_mux-1, 1);
1435 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1437 int blocks = (size + (block-1)) / block;
1439 if (size == 0) return 0;
1441 while (received < blocks) {
1444 while (issued - received < mpx && issued < blocks) {
1445 int size1 = MIN(block, size-issued*block);
1446 cli_issue_read(cli, fnum, offset+issued*block, size1, issued);
1450 if (!cli_receive_smb(cli)) {
1455 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1456 size2 = SVAL(cli->inbuf, smb_vwv5);
1458 if (cli_error(cli, NULL, NULL))
1460 blocks = MIN(blocks, mid-1);
1465 blocks = MIN(blocks, mid-1);
1466 /* this distinguishes EOF from an error */
1467 total = MAX(total, 0);
1471 if (size2 > block) {
1472 DEBUG(0,("server returned more than we wanted!\n"));
1475 if (mid >= issued) {
1476 DEBUG(0,("invalid mid from server!\n"));
1479 p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
1481 memcpy(buf+mid*block, p, size2);
1483 total = MAX(total, mid*block + size2);
1486 while (received < issued) {
1487 cli_receive_smb(cli);
1495 /****************************************************************************
1496 issue a single SMBwrite and don't wait for a reply
1497 ****************************************************************************/
1498 static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf,
1503 bzero(cli->outbuf,smb_size);
1504 bzero(cli->inbuf,smb_size);
1506 set_message(cli->outbuf,12,size,True);
1508 CVAL(cli->outbuf,smb_com) = SMBwriteX;
1509 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1510 cli_setup_packet(cli);
1512 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1513 SSVAL(cli->outbuf,smb_vwv2,fnum);
1515 SIVAL(cli->outbuf,smb_vwv3,offset);
1516 SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0);
1517 SSVAL(cli->outbuf,smb_vwv7,mode);
1519 SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0);
1520 SSVAL(cli->outbuf,smb_vwv10,size);
1521 SSVAL(cli->outbuf,smb_vwv11,
1522 smb_buf(cli->outbuf) - smb_base(cli->outbuf));
1524 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
1525 memcpy(p, buf, size);
1527 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1529 cli_send_smb(cli, True);
1532 /****************************************************************************
1534 write_mode: 0x0001 disallow write cacheing
1535 0x0002 return bytes remaining
1536 0x0004 use raw named pipe protocol
1537 0x0008 start of message mode named pipe protocol
1538 ****************************************************************************/
1539 ssize_t cli_write(struct cli_state *cli,
1540 int fnum, uint16 write_mode,
1541 char *buf, off_t offset, size_t size)
1546 int mpx = MAX(cli->max_mux-1, 1);
1547 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1549 int blocks = (size + (block-1)) / block;
1551 if (size == 0) return 0;
1553 while (received < blocks) {
1556 while (issued - received < mpx && issued < blocks) {
1557 int size1 = MIN(block, size-issued*block);
1558 cli_issue_write(cli, fnum, offset+issued*block,
1565 if (!cli_receive_smb(cli)) {
1570 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1571 size2 = SVAL(cli->inbuf, smb_vwv2);
1573 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1574 blocks = MIN(blocks, mid-1);
1579 blocks = MIN(blocks, mid-1);
1580 /* this distinguishes EOF from an error */
1581 total = MAX(total, 0);
1587 total = MAX(total, mid*block + size2);
1590 while (received < issued) {
1591 cli_receive_smb(cli);
1599 /****************************************************************************
1600 do a SMBgetattrE call
1601 ****************************************************************************/
1602 BOOL cli_getattrE(struct cli_state *cli, int fd,
1603 uint16 *attr, size_t *size,
1604 time_t *c_time, time_t *a_time, time_t *m_time)
1606 bzero(cli->outbuf,smb_size);
1607 bzero(cli->inbuf,smb_size);
1609 set_message(cli->outbuf,2,0,True);
1611 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
1612 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1613 cli_setup_packet(cli);
1615 SSVAL(cli->outbuf,smb_vwv0,fd);
1617 cli_send_smb(cli, True);
1618 if (!cli_receive_smb(cli)) {
1622 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1627 *size = IVAL(cli->inbuf, smb_vwv6);
1631 *attr = SVAL(cli->inbuf,smb_vwv10);
1635 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
1639 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
1643 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
1650 /****************************************************************************
1652 ****************************************************************************/
1653 BOOL cli_getatr(struct cli_state *cli, char *fname,
1654 uint16 *attr, size_t *size, time_t *t)
1658 bzero(cli->outbuf,smb_size);
1659 bzero(cli->inbuf,smb_size);
1661 set_message(cli->outbuf,0,strlen(fname)+2,True);
1663 CVAL(cli->outbuf,smb_com) = SMBgetatr;
1664 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1665 cli_setup_packet(cli);
1667 p = smb_buf(cli->outbuf);
1669 pstrcpy(p+1, fname);
1671 cli_send_smb(cli, True);
1672 if (!cli_receive_smb(cli)) {
1676 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1681 *size = IVAL(cli->inbuf, smb_vwv3);
1685 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1689 *attr = SVAL(cli->inbuf,smb_vwv0);
1697 /****************************************************************************
1699 ****************************************************************************/
1700 BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
1704 bzero(cli->outbuf,smb_size);
1705 bzero(cli->inbuf,smb_size);
1707 set_message(cli->outbuf,8,strlen(fname)+4,True);
1709 CVAL(cli->outbuf,smb_com) = SMBsetatr;
1710 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1711 cli_setup_packet(cli);
1713 SSVAL(cli->outbuf,smb_vwv0, attr);
1714 put_dos_date3(cli->outbuf,smb_vwv1, t);
1716 p = smb_buf(cli->outbuf);
1718 pstrcpy(p+1, fname);
1719 p = skip_string(p,1);
1722 cli_send_smb(cli, True);
1723 if (!cli_receive_smb(cli)) {
1727 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1734 /****************************************************************************
1735 send a qpathinfo call
1736 ****************************************************************************/
1737 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
1738 time_t *c_time, time_t *a_time, time_t *m_time,
1739 size_t *size, uint16 *mode)
1743 uint16 setup = TRANSACT2_QPATHINFO;
1745 char *rparam=NULL, *rdata=NULL;
1748 time_t (*date_fn)(void *);
1750 param_len = strlen(fname) + 7;
1752 memset(param, 0, param_len);
1753 SSVAL(param, 0, SMB_INFO_STANDARD);
1754 pstrcpy(¶m[6], fname);
1757 ret = (cli_send_trans(cli, SMBtrans2,
1758 NULL, 0, /* Name, length */
1759 -1, 0, /* fid, flags */
1760 &setup, 1, 0, /* setup, length, max */
1761 param, param_len, 10, /* param, length, max */
1762 NULL, data_len, cli->max_xmit /* data, length, max */
1764 cli_receive_trans(cli, SMBtrans2,
1765 &rparam, ¶m_len,
1766 &rdata, &data_len));
1768 /* we need to work around a Win95 bug - sometimes
1769 it gives ERRSRV/ERRerror temprarily */
1772 cli_error(cli, &eclass, &ecode);
1773 if (eclass != ERRSRV || ecode != ERRerror) break;
1776 } while (count-- && ret==False);
1778 if (!ret || !rdata || data_len < 22) {
1783 date_fn = make_unix_date;
1785 date_fn = make_unix_date2;
1789 *c_time = date_fn(rdata+0);
1792 *a_time = date_fn(rdata+4);
1795 *m_time = date_fn(rdata+8);
1798 *size = IVAL(rdata, 12);
1801 *mode = SVAL(rdata,l1_attrFile);
1804 if (rdata) free(rdata);
1805 if (rparam) free(rparam);
1809 /****************************************************************************
1810 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1811 ****************************************************************************/
1812 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
1813 time_t *c_time, time_t *a_time, time_t *m_time,
1814 time_t *w_time, size_t *size, uint16 *mode,
1819 uint16 setup = TRANSACT2_QPATHINFO;
1821 char *rparam=NULL, *rdata=NULL;
1823 param_len = strlen(fname) + 7;
1825 memset(param, 0, param_len);
1826 SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1827 pstrcpy(¶m[6], fname);
1829 if (!cli_send_trans(cli, SMBtrans2,
1830 NULL, 0, /* name, length */
1831 -1, 0, /* fid, flags */
1832 &setup, 1, 0, /* setup, length, max */
1833 param, param_len, 10, /* param, length, max */
1834 NULL, data_len, cli->max_xmit /* data, length, max */
1839 if (!cli_receive_trans(cli, SMBtrans2,
1840 &rparam, ¶m_len,
1841 &rdata, &data_len)) {
1845 if (!rdata || data_len < 22) {
1850 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1853 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1856 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1859 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1862 *mode = SVAL(rdata, 32);
1865 *size = IVAL(rdata, 40);
1868 *ino = IVAL(rdata, 64);
1871 if (rdata) free(rdata);
1872 if (rparam) free(rparam);
1877 /****************************************************************************
1878 send a qfileinfo call
1879 ****************************************************************************/
1880 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
1881 uint16 *mode, size_t *size,
1882 time_t *c_time, time_t *a_time, time_t *m_time,
1883 time_t *w_time, SMB_INO_T *ino)
1887 uint16 setup = TRANSACT2_QFILEINFO;
1889 char *rparam=NULL, *rdata=NULL;
1891 /* if its a win95 server then fail this - win95 totally screws it
1893 if (cli->win95) return False;
1897 memset(param, 0, param_len);
1898 SSVAL(param, 0, fnum);
1899 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
1901 if (!cli_send_trans(cli, SMBtrans2,
1902 NULL, 0, /* name, length */
1903 -1, 0, /* fid, flags */
1904 &setup, 1, 0, /* setup, length, max */
1905 param, param_len, 2, /* param, length, max */
1906 NULL, data_len, cli->max_xmit /* data, length, max */
1911 if (!cli_receive_trans(cli, SMBtrans2,
1912 &rparam, ¶m_len,
1913 &rdata, &data_len)) {
1917 if (!rdata || data_len < 68) {
1922 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1925 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1928 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1931 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1934 *mode = SVAL(rdata, 32);
1937 *size = IVAL(rdata, 40);
1940 *ino = IVAL(rdata, 64);
1943 if (rdata) free(rdata);
1944 if (rparam) free(rparam);
1949 /****************************************************************************
1950 interpret a long filename structure - this is mostly guesses at the moment
1951 The length of the structure is returned
1952 The structure of a long filename depends on the info level. 260 is used
1953 by NT and 2 is used by OS/2
1954 ****************************************************************************/
1955 static int interpret_long_filename(int level,char *p,file_info *finfo)
1957 extern file_info def_finfo;
1960 memcpy(finfo,&def_finfo,sizeof(*finfo));
1964 case 1: /* OS/2 understands this */
1966 /* these dates are converted to GMT by make_unix_date */
1967 finfo->ctime = make_unix_date2(p+4);
1968 finfo->atime = make_unix_date2(p+8);
1969 finfo->mtime = make_unix_date2(p+12);
1970 finfo->size = IVAL(p,16);
1971 finfo->mode = CVAL(p,24);
1972 pstrcpy(finfo->name,p+27);
1974 return(28 + CVAL(p,26));
1976 case 2: /* this is what OS/2 uses mostly */
1978 /* these dates are converted to GMT by make_unix_date */
1979 finfo->ctime = make_unix_date2(p+4);
1980 finfo->atime = make_unix_date2(p+8);
1981 finfo->mtime = make_unix_date2(p+12);
1982 finfo->size = IVAL(p,16);
1983 finfo->mode = CVAL(p,24);
1984 pstrcpy(finfo->name,p+31);
1986 return(32 + CVAL(p,30));
1988 /* levels 3 and 4 are untested */
1991 /* these dates are probably like the other ones */
1992 finfo->ctime = make_unix_date2(p+8);
1993 finfo->atime = make_unix_date2(p+12);
1994 finfo->mtime = make_unix_date2(p+16);
1995 finfo->size = IVAL(p,20);
1996 finfo->mode = CVAL(p,28);
1997 pstrcpy(finfo->name,p+33);
1999 return(SVAL(p,4)+4);
2003 /* these dates are probably like the other ones */
2004 finfo->ctime = make_unix_date2(p+8);
2005 finfo->atime = make_unix_date2(p+12);
2006 finfo->mtime = make_unix_date2(p+16);
2007 finfo->size = IVAL(p,20);
2008 finfo->mode = CVAL(p,28);
2009 pstrcpy(finfo->name,p+37);
2011 return(SVAL(p,4)+4);
2013 case 260: /* NT uses this, but also accepts 2 */
2015 int ret = SVAL(p,0);
2017 p += 4; /* next entry offset */
2018 p += 4; /* fileindex */
2020 /* these dates appear to arrive in a
2021 weird way. It seems to be localtime
2022 plus the serverzone given in the
2023 initial connect. This is GMT when
2024 DST is not in effect and one hour
2025 from GMT otherwise. Can this really
2028 I suppose this could be called
2029 kludge-GMT. Is is the GMT you get
2030 by using the current DST setting on
2031 a different localtime. It will be
2032 cheap to calculate, I suppose, as
2033 no DST tables will be needed */
2035 finfo->ctime = interpret_long_date(p); p += 8;
2036 finfo->atime = interpret_long_date(p); p += 8;
2037 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
2038 finfo->size = IVAL(p,0); p += 8;
2039 p += 8; /* alloc size */
2040 finfo->mode = CVAL(p,0); p += 4;
2041 namelen = IVAL(p,0); p += 4;
2042 p += 4; /* EA size */
2043 p += 2; /* short name len? */
2044 p += 24; /* short name? */
2045 StrnCpy(finfo->name,p,namelen);
2051 DEBUG(1,("Unknown long filename format %d\n",level));
2056 /****************************************************************************
2057 do a directory listing, calling fn on each file found
2058 ****************************************************************************/
2059 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
2060 void (*fn)(file_info *, const char *))
2062 int max_matches = 512;
2063 /* NT uses 260, OS/2 uses 2. Both accept 1. */
2064 int info_level = cli->protocol<PROTOCOL_NT1?1:260;
2069 char *dirlist = NULL;
2070 int dirlist_len = 0;
2071 int total_received = -1;
2073 int ff_resume_key = 0;
2074 int ff_searchcount=0;
2077 int ff_dir_handle=0;
2079 char *rparam=NULL, *rdata=NULL;
2080 int param_len, data_len;
2087 while (ff_eos == 0) {
2089 if (loop_count > 200) {
2090 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
2094 param_len = 12+strlen(mask)+1;
2097 setup = TRANSACT2_FINDFIRST;
2098 SSVAL(param,0,attribute); /* attribute */
2099 SSVAL(param,2,max_matches); /* max count */
2100 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
2101 SSVAL(param,6,info_level);
2103 pstrcpy(param+12,mask);
2105 setup = TRANSACT2_FINDNEXT;
2106 SSVAL(param,0,ff_dir_handle);
2107 SSVAL(param,2,max_matches); /* max count */
2108 SSVAL(param,4,info_level);
2109 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
2110 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
2111 pstrcpy(param+12,mask);
2113 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
2114 ff_dir_handle,ff_resume_key,ff_lastname,mask));
2117 if (!cli_send_trans(cli, SMBtrans2,
2118 NULL, 0, /* Name, length */
2119 -1, 0, /* fid, flags */
2120 &setup, 1, 0, /* setup, length, max */
2121 param, param_len, 10, /* param, length, max */
2123 cli->max_xmit /* data, length, max */
2128 if (!cli_receive_trans(cli, SMBtrans2,
2129 &rparam, ¶m_len,
2130 &rdata, &data_len)) {
2131 /* we need to work around a Win95 bug - sometimes
2132 it gives ERRSRV/ERRerror temprarily */
2135 cli_error(cli, &eclass, &ecode);
2136 if (eclass != ERRSRV || ecode != ERRerror) break;
2141 if (total_received == -1) total_received = 0;
2143 /* parse out some important return info */
2146 ff_dir_handle = SVAL(p,0);
2147 ff_searchcount = SVAL(p,2);
2149 ff_lastname = SVAL(p,8);
2151 ff_searchcount = SVAL(p,0);
2153 ff_lastname = SVAL(p,6);
2156 if (ff_searchcount == 0)
2159 /* point to the data bytes */
2162 /* we might need the lastname for continuations */
2163 if (ff_lastname > 0) {
2168 StrnCpy(mask,p+ff_lastname,
2169 data_len-ff_lastname);
2172 pstrcpy(mask,p + ff_lastname + 1);
2180 /* and add them to the dirlist pool */
2181 dirlist = Realloc(dirlist,dirlist_len + data_len);
2184 DEBUG(0,("Failed to expand dirlist\n"));
2188 /* put in a length for the last entry, to ensure we can chain entries
2189 into the next packet */
2190 for (p2=p,i=0;i<(ff_searchcount-1);i++)
2191 p2 += interpret_long_filename(info_level,p2,NULL);
2192 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
2194 /* grab the data for later use */
2195 memcpy(dirlist+dirlist_len,p,data_len);
2196 dirlist_len += data_len;
2198 total_received += ff_searchcount;
2200 if (rdata) free(rdata); rdata = NULL;
2201 if (rparam) free(rparam); rparam = NULL;
2203 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
2204 ff_searchcount,ff_eos,ff_resume_key));
2209 for (p=dirlist,i=0;i<total_received;i++) {
2210 p += interpret_long_filename(info_level,p,&finfo);
2214 /* free up the dirlist buffer */
2215 if (dirlist) free(dirlist);
2216 return(total_received);
2220 /****************************************************************************
2221 Send a SamOEMChangePassword command
2222 ****************************************************************************/
2224 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
2225 const char *old_password)
2227 char param[16+sizeof(fstring)];
2230 fstring upper_case_old_pw;
2231 fstring upper_case_new_pw;
2232 unsigned char old_pw_hash[16];
2233 unsigned char new_pw_hash[16];
2236 char *rparam = NULL;
2240 if (strlen(user) >= sizeof(fstring)-1) {
2241 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
2245 SSVAL(p,0,214); /* SamOEMChangePassword command. */
2248 p = skip_string(p,1);
2249 pstrcpy(p, "B516B16");
2250 p = skip_string(p,1);
2252 p = skip_string(p,1);
2256 param_len = PTR_DIFF(p,param);
2259 * Get the Lanman hash of the old password, we
2260 * use this as the key to make_oem_passwd_hash().
2262 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
2263 fstrcpy(upper_case_old_pw, old_password);
2264 strupper(upper_case_old_pw);
2265 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
2267 if (!make_oem_passwd_hash( data, new_password, old_pw_hash, False))
2273 * Now place the old password hash in the data.
2275 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
2276 fstrcpy(upper_case_new_pw, new_password);
2277 strupper(upper_case_new_pw);
2279 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
2281 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
2285 if (!cli_send_trans(cli,SMBtrans,
2286 PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */
2287 0,0, /* fid, flags */
2288 NULL,0,0, /* setup, length, max */
2289 param,param_len,2, /* param, length, max */
2290 data,data_len,0 /* data, length, max */
2293 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
2298 if (cli_receive_trans(cli,SMBtrans,
2302 cli->rap_error = SVAL(rparam,0);
2310 return (cli->rap_error == 0);
2313 /****************************************************************************
2314 send a negprot command
2315 ****************************************************************************/
2316 BOOL cli_negprot(struct cli_state *cli)
2322 bzero(cli->outbuf,smb_size);
2324 /* setup the protocol strings */
2325 for (plength=0,numprots=0;
2326 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2328 plength += strlen(prots[numprots].name)+2;
2330 set_message(cli->outbuf,0,plength,True);
2332 p = smb_buf(cli->outbuf);
2334 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2337 pstrcpy(p,prots[numprots].name);
2341 CVAL(cli->outbuf,smb_com) = SMBnegprot;
2342 cli_setup_packet(cli);
2344 CVAL(smb_buf(cli->outbuf),0) = 2;
2346 cli_send_smb(cli, True);
2347 if (!cli_receive_smb(cli))
2352 if (CVAL(cli->inbuf,smb_rcls) != 0 ||
2353 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
2357 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
2360 if (cli->protocol >= PROTOCOL_NT1) {
2362 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
2363 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
2364 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
2365 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
2366 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
2367 /* this time arrives in real GMT */
2368 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
2369 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2370 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
2371 if (cli->capabilities & 1) {
2372 cli->readbraw_supported = True;
2373 cli->writebraw_supported = True;
2375 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2376 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
2377 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
2378 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
2379 cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
2380 /* this time is converted to GMT by make_unix_date */
2381 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
2382 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
2383 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
2384 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2386 /* the old core protocol */
2388 cli->serverzone = TimeDiff(time(NULL));
2391 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2397 /****************************************************************************
2398 send a session request. see rfc1002.txt 4.3 and 4.3.2
2399 ****************************************************************************/
2400 BOOL cli_session_request(struct cli_state *cli,
2401 struct nmb_name *calling, struct nmb_name *called)
2405 /* send a session request (RFC 1002) */
2407 memcpy(&(cli->calling), calling, sizeof(*calling));
2408 memcpy(&(cli->called ), called , sizeof(*called ));
2410 /* put in the destination name */
2411 p = cli->outbuf+len;
2412 name_mangle(cli->called .name, p, cli->called .name_type);
2416 p = cli->outbuf+len;
2417 name_mangle(cli->calling.name, p, cli->calling.name_type);
2420 /* setup the packet length */
2421 _smb_setlen(cli->outbuf,len);
2422 CVAL(cli->outbuf,0) = 0x81;
2426 #endif /* WITH_SSL */
2428 cli_send_smb(cli, False);
2429 DEBUG(5,("Sent session request\n"));
2431 if (!cli_receive_smb(cli))
2435 if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
2436 if (!sslutil_fd_is_ssl(cli->fd)){
2437 if (sslutil_connect(cli->fd) == 0)
2441 #endif /* WITH_SSL */
2443 if (CVAL(cli->inbuf,0) != 0x82) {
2444 /* This is the wrong place to put the error... JRA. */
2445 cli->rap_error = CVAL(cli->inbuf,0);
2452 /****************************************************************************
2453 open the client sockets
2454 ****************************************************************************/
2455 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
2457 extern struct in_addr ipzero;
2459 fstrcpy(cli->desthost, host);
2461 if (!ip || ip_equal(*ip, ipzero)) {
2462 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
2465 if (ip) *ip = cli->dest_ip;
2471 if (cli -> port == 0) cli -> port = 139;
2473 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2474 cli -> port, cli->timeout);
2482 /****************************************************************************
2483 initialise a client structure
2484 ****************************************************************************/
2485 struct cli_state *cli_initialise(struct cli_state *cli)
2488 cli = (struct cli_state *)malloc(sizeof(*cli));
2494 if (cli->initialised) {
2503 cli->pid = (uint16)getpid();
2505 cli->vuid = UID_FIELD_INVALID;
2506 cli->protocol = PROTOCOL_NT1;
2507 cli->timeout = 20000;
2508 cli->bufsize = CLI_BUFFER_SIZE+4;
2509 cli->max_xmit = cli->bufsize;
2510 cli->outbuf = (char *)malloc(cli->bufsize);
2511 cli->inbuf = (char *)malloc(cli->bufsize);
2512 if (!cli->outbuf || !cli->inbuf)
2517 cli->initialised = 1;
2522 /****************************************************************************
2523 shutdown a client structure
2524 ****************************************************************************/
2525 void cli_shutdown(struct cli_state *cli)
2527 DEBUG(10,("cli_shutdown\n"));
2538 sslutil_disconnect(cli->fd);
2539 #endif /* WITH_SSL */
2544 memset(cli, 0, sizeof(*cli));
2548 /****************************************************************************
2549 return error codes for the last packet
2550 returns 0 if there was no error and the best approx of a unix errno
2553 for 32 bit "warnings", a return code of 0 is expected.
2555 ****************************************************************************/
2556 int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
2562 if (!cli->initialised)
2564 DEBUG(0,("cli_error: client state uninitialised!\n"));
2568 flgs2 = SVAL(cli->inbuf,smb_flg2);
2570 if (eclass) *eclass = 0;
2573 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
2574 /* 32 bit error codes detected */
2575 uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
2576 if (num) *num = nt_err;
2577 DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
2578 if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0;
2580 switch (nt_err & 0xFFFFFF) {
2581 case NT_STATUS_ACCESS_VIOLATION: return EACCES;
2582 case NT_STATUS_NO_SUCH_FILE: return ENOENT;
2583 case NT_STATUS_NO_SUCH_DEVICE: return ENODEV;
2584 case NT_STATUS_INVALID_HANDLE: return EBADF;
2585 case NT_STATUS_NO_MEMORY: return ENOMEM;
2586 case NT_STATUS_ACCESS_DENIED: return EACCES;
2587 case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
2588 case NT_STATUS_SHARING_VIOLATION: return EBUSY;
2589 case NT_STATUS_OBJECT_PATH_INVALID: return ENOTDIR;
2590 case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
2593 /* for all other cases - a default code */
2597 rcls = CVAL(cli->inbuf,smb_rcls);
2598 code = SVAL(cli->inbuf,smb_err);
2599 if (rcls == 0) return 0;
2601 if (eclass) *eclass = rcls;
2602 if (num ) *num = code;
2604 if (rcls == ERRDOS) {
2606 case ERRbadfile: return ENOENT;
2607 case ERRbadpath: return ENOTDIR;
2608 case ERRnoaccess: return EACCES;
2609 case ERRfilexists: return EEXIST;
2610 case ERRrename: return EEXIST;
2611 case ERRbadshare: return EBUSY;
2612 case ERRlock: return EBUSY;
2613 case ERRmoredata: return 0; /* Informational only */
2616 if (rcls == ERRSRV) {
2618 case ERRbadpw: return EPERM;
2619 case ERRaccess: return EACCES;
2620 case ERRnoresource: return ENOMEM;
2621 case ERRinvdevice: return ENODEV;
2622 case ERRinvnetname: return ENODEV;
2625 /* for other cases */
2629 /****************************************************************************
2630 set socket options on a open connection
2631 ****************************************************************************/
2632 void cli_sockopt(struct cli_state *cli, char *options)
2634 set_socket_options(cli->fd, options);
2637 /****************************************************************************
2638 set the PID to use for smb messages. Return the old pid.
2639 ****************************************************************************/
2640 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
2642 uint16 ret = cli->pid;
2647 /****************************************************************************
2648 re-establishes a connection
2649 ****************************************************************************/
2650 BOOL cli_reestablish_connection(struct cli_state *cli)
2652 struct nmb_name calling;
2653 struct nmb_name called;
2657 BOOL do_tcon = False;
2658 int oldfd = cli->fd;
2660 if (!cli->initialised || cli->fd == -1)
2662 DEBUG(3,("cli_reestablish_connection: not connected\n"));
2666 /* copy the parameters necessary to re-establish the connection */
2670 fstrcpy(share, cli->share);
2671 fstrcpy(dev , cli->dev);
2675 memcpy(&called , &(cli->called ), sizeof(called ));
2676 memcpy(&calling, &(cli->calling), sizeof(calling));
2677 fstrcpy(dest_host, cli->full_dest_host_name);
2679 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2680 nmb_namestr(&calling), nmb_namestr(&called),
2681 inet_ntoa(cli->dest_ip),
2682 cli->user_name, cli->domain));
2686 if (cli_establish_connection(cli,
2687 dest_host, &cli->dest_ip,
2689 share, dev, False, do_tcon))
2691 if (cli->fd != oldfd)
2693 if (dup2(cli->fd, oldfd) == oldfd)
2703 /****************************************************************************
2704 establishes a connection right up to doing tconX, reading in a password.
2705 ****************************************************************************/
2706 BOOL cli_establish_connection(struct cli_state *cli,
2707 char *dest_host, struct in_addr *dest_ip,
2708 struct nmb_name *calling, struct nmb_name *called,
2709 char *service, char *service_type,
2710 BOOL do_shutdown, BOOL do_tcon)
2715 nmb_safe_namestr(calling, callingstr, sizeof(callingstr));
2716 nmb_safe_namestr(called , calledstr , sizeof(calledstr ));
2718 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s] with NTLM%s\n",
2719 callingstr, calledstr, inet_ntoa(*dest_ip),
2720 cli->user_name, cli->domain,
2721 cli->use_ntlmv2 ? "v2" : "v1"));
2723 /* establish connection */
2725 if ((!cli->initialised))
2732 if (!cli_connect(cli, dest_host, dest_ip))
2734 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
2735 callingstr, inet_ntoa(*dest_ip)));
2740 if (!cli_session_request(cli, calling, called))
2742 DEBUG(1,("failed session request\n"));
2750 if (!cli_negprot(cli))
2752 DEBUG(1,("failed negprot\n"));
2760 if (cli->pwd.cleartext || cli->pwd.null_pwd)
2765 if (cli->pwd.null_pwd)
2767 /* attempt null session */
2773 /* attempt clear-text session */
2774 pwd_get_cleartext(&(cli->pwd), passwd);
2775 pass_len = strlen(passwd);
2778 /* attempt clear-text session */
2779 if (!cli_session_setup(cli, cli->user_name,
2784 DEBUG(1,("failed session setup\n"));
2793 if (!cli_send_tconX(cli, service, service_type,
2794 (char*)passwd, strlen(passwd)))
2796 DEBUG(1,("failed tcon_X\n"));
2807 /* attempt encrypted session */
2808 unsigned char lm_sess_pwd[24];
2809 unsigned char nt_sess_pwd[128];
2810 size_t nt_sess_pwd_len;
2811 extern pstring global_myname;
2813 if (cli->use_ntlmv2 != False)
2815 DEBUG(10,("cli_establish_connection: NTLMv2\n"));
2816 pwd_make_lm_nt_owf2(&(cli->pwd), cli->cryptkey,
2817 cli->user_name, global_myname, cli->domain);
2821 DEBUG(10,("cli_establish_connection: NTLMv1\n"));
2822 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
2825 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd,
2828 /* attempt encrypted session */
2829 if (!cli_session_setup_x(cli, cli->user_name,
2830 (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
2831 (char*)nt_sess_pwd, nt_sess_pwd_len,
2834 DEBUG(1,("failed session setup\n"));
2836 if (cli->use_ntlmv2 == Auto)
2838 DEBUG(10,("NTLMv2 failed. Using NTLMv1\n"));
2839 cli->use_ntlmv2 = False;
2840 return cli_establish_connection(cli,
2843 service, service_type,
2844 do_shutdown, do_tcon);
2856 if (!cli_send_tconX(cli, service, service_type,
2857 (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
2859 DEBUG(1,("failed tcon_X\n"));
2877 /****************************************************************************
2878 connect to one of multiple servers: don't care which
2879 ****************************************************************************/
2880 BOOL cli_connect_serverlist(struct cli_state *cli, char *p)
2882 extern pstring global_myname;
2883 extern pstring scope;
2884 fstring remote_machine;
2885 struct in_addr dest_ip;
2886 struct nmb_name calling, called, stupid_smbserver_called;
2887 BOOL connected_ok = False;
2890 * Treat each name in the 'password server =' line as a potential
2891 * PDC/BDC. Contact each in turn and try and authenticate.
2894 while(p && next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine)))
2898 if (!cli_initialise(cli))
2900 DEBUG(0,("cli_connect_serverlist: unable to initialize client connection.\n"));
2904 standard_sub_basic(remote_machine);
2905 strupper(remote_machine);
2907 if (!resolve_name( remote_machine, &dest_ip, 0x20))
2909 DEBUG(1,("cli_connect_serverlist: Can't resolve address for %s\n", remote_machine));
2913 if ((lp_security() != SEC_USER) && (ismyip(dest_ip)))
2915 DEBUG(1,("cli_connect_serverlist: Password server loop - not using password server %s\n", remote_machine));
2919 make_nmb_name(&calling, global_myname , 0x0 , scope);
2920 make_nmb_name(&called , remote_machine, 0x20, scope);
2921 /* stupid microsoft destruction of the ability of netbios
2922 * to provide multiple netbios servers on one host.
2924 make_nmb_name(&stupid_smbserver_called , "*SMBSERVER", 0x20, scope);
2926 pwd_set_nullpwd(&cli->pwd);
2928 if (!cli_establish_connection(cli, remote_machine, &dest_ip,
2932 !cli_establish_connection(cli, remote_machine, &dest_ip,
2933 &calling, &stupid_smbserver_called,
2941 if (cli->protocol < PROTOCOL_LANMAN2 ||
2942 !IS_BITS_SET_ALL(cli->sec_mode, 1))
2944 DEBUG(1,("cli_connect_serverlist: machine %s isn't in user level security mode\n",
2951 * We have an anonymous connection to IPC$.
2954 connected_ok = True;
2960 DEBUG(0,("cli_connect_serverlist: Domain password server not available.\n"));
2964 return connected_ok;
2967 /****************************************************************************
2969 ****************************************************************************/
2970 int cli_printjob_del(struct cli_state *cli, int job)
2972 char *rparam = NULL;
2975 int rdrcnt,rprcnt, ret = -1;
2978 bzero(param,sizeof(param));
2981 SSVAL(p,0,81); /* DosPrintJobDel() */
2984 p = skip_string(p,1);
2986 p = skip_string(p,1);
2991 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2992 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2993 &rparam, &rprcnt, /* return params, length */
2994 &rdata, &rdrcnt)) { /* return data, length */
2995 ret = SVAL(rparam,0);
2998 if (rparam) free(rparam);
2999 if (rdata) free(rdata);
3005 /****************************************************************************
3006 call fn() on each entry in a print queue
3007 ****************************************************************************/
3008 int cli_print_queue(struct cli_state *cli,
3009 void (*fn)(struct print_job_info *))
3011 char *rparam = NULL;
3019 bzero(param,sizeof(param));
3022 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
3024 pstrcpy(p,"zWrLeh"); /* parameter description? */
3025 p = skip_string(p,1);
3026 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
3027 p = skip_string(p,1);
3028 pstrcpy(p,cli->share); /* name of queue */
3029 p = skip_string(p,1);
3030 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
3031 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
3033 pstrcpy(p,""); /* subformat */
3034 p = skip_string(p,1);
3036 DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
3039 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
3040 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
3041 &rparam, &rprcnt, /* return params, length */
3042 &rdata, &rdrcnt)) { /* return data, length */
3044 result_code = SVAL(rparam,0);
3045 converter = SVAL(rparam,2); /* conversion factor */
3047 if (result_code == 0) {
3048 struct print_job_info job;
3052 for (i = 0; i < SVAL(rparam,4); ++i) {
3054 job.priority = SVAL(p,2);
3056 fix_char_ptr(SVAL(p,4), converter,
3058 job.t = make_unix_date3(p + 12);
3059 job.size = IVAL(p,16);
3060 fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
3069 /* If any parameters or data were returned, free the storage. */
3070 if(rparam) free(rparam);
3071 if(rdata) free(rdata);
3076 /****************************************************************************
3077 check for existance of a dir
3078 ****************************************************************************/
3079 BOOL cli_chkpath(struct cli_state *cli, char *path)
3084 fstrcpy(path2,path);
3085 trim_string(path2,NULL,"\\");
3086 if (!*path2) *path2 = '\\';
3088 bzero(cli->outbuf,smb_size);
3089 set_message(cli->outbuf,0,4 + strlen(path2),True);
3090 SCVAL(cli->outbuf,smb_com,SMBchkpth);
3091 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3092 cli_setup_packet(cli);
3094 p = smb_buf(cli->outbuf);
3098 cli_send_smb(cli, True);
3099 if (!cli_receive_smb(cli)) {
3103 if (cli_error(cli, NULL, NULL)) return False;
3109 /****************************************************************************
3110 start a message sequence
3111 ****************************************************************************/
3112 BOOL cli_message_start(struct cli_state *cli, char *host, char *username,
3117 /* send a SMBsendstrt command */
3118 bzero(cli->outbuf,smb_size);
3119 set_message(cli->outbuf,0,0,True);
3120 CVAL(cli->outbuf,smb_com) = SMBsendstrt;
3121 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3122 cli_setup_packet(cli);
3124 p = smb_buf(cli->outbuf);
3126 pstrcpy(p,username);
3127 p = skip_string(p,1);
3130 p = skip_string(p,1);
3132 set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
3134 cli_send_smb(cli, True);
3136 if (!cli_receive_smb(cli)) {
3140 if (cli_error(cli, NULL, NULL)) return False;
3142 *grp = SVAL(cli->inbuf,smb_vwv0);
3148 /****************************************************************************
3150 ****************************************************************************/
3151 BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp)
3155 bzero(cli->outbuf,smb_size);
3156 set_message(cli->outbuf,1,len+3,True);
3157 CVAL(cli->outbuf,smb_com) = SMBsendtxt;
3158 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3159 cli_setup_packet(cli);
3161 SSVAL(cli->outbuf,smb_vwv0,grp);
3163 p = smb_buf(cli->outbuf);
3166 memcpy(p+3,msg,len);
3167 cli_send_smb(cli, True);
3169 if (!cli_receive_smb(cli)) {
3173 if (cli_error(cli, NULL, NULL)) return False;
3178 /****************************************************************************
3180 ****************************************************************************/
3181 BOOL cli_message_end(struct cli_state *cli, int grp)
3183 bzero(cli->outbuf,smb_size);
3184 set_message(cli->outbuf,1,0,True);
3185 CVAL(cli->outbuf,smb_com) = SMBsendend;
3186 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3188 SSVAL(cli->outbuf,smb_vwv0,grp);
3190 cli_setup_packet(cli);
3192 cli_send_smb(cli, True);
3194 if (!cli_receive_smb(cli)) {
3198 if (cli_error(cli, NULL, NULL)) return False;
3204 /****************************************************************************
3206 ****************************************************************************/
3207 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3209 bzero(cli->outbuf,smb_size);
3210 set_message(cli->outbuf,0,0,True);
3211 CVAL(cli->outbuf,smb_com) = SMBdskattr;
3212 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3213 cli_setup_packet(cli);
3215 cli_send_smb(cli, True);
3216 if (!cli_receive_smb(cli)) {
3220 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
3221 *total = SVAL(cli->inbuf,smb_vwv0);
3222 *avail = SVAL(cli->inbuf,smb_vwv3);