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;
30 /*****************************************************
31 RAP error codes - a small start but will be extended.
32 *******************************************************/
40 {5, "User has insufficient privilege" },
41 {86, "The specified password is invalid" },
42 {2226, "Operation only permitted on a Primary Domain Controller" },
43 {2242, "The password of this user has expired." },
44 {2243, "The password of this user cannot change." },
45 {2244, "This password cannot be used now (password history conflict)." },
46 {2245, "The password is shorter than required." },
47 {2246, "The password of this user is too recent to change."},
51 /****************************************************************************
52 return a description of an SMB error
53 ****************************************************************************/
54 static char *cli_smb_errstr(struct cli_state *cli)
56 return smb_errstr(cli->inbuf);
59 /******************************************************
60 Return an error message - either an SMB error or a RAP
62 *******************************************************/
64 char *cli_errstr(struct cli_state *cli)
66 static fstring error_message;
72 * Errors are of three kinds - smb errors,
73 * dealt with by cli_smb_errstr, NT errors,
74 * whose code is in cli.nt_error, and rap
75 * errors, whose error code is in cli.rap_error.
78 cli_error(cli, &errclass, &errnum);
82 return cli_smb_errstr(cli);
86 * Was it an NT error ?
91 char *nt_msg = get_nt_error_msg(cli->nt_error);
95 slprintf(error_message, sizeof(fstring) - 1, "NT code %d", cli->nt_error);
99 fstrcpy(error_message, nt_msg);
102 return error_message;
106 * Must have been a rap error.
109 slprintf(error_message, sizeof(error_message) - 1, "code %d", cli->rap_error);
111 for (i = 0; rap_errmap[i].message != NULL; i++)
113 if (rap_errmap[i].err == cli->rap_error)
115 fstrcpy( error_message, rap_errmap[i].message);
120 return error_message;
123 /****************************************************************************
124 setup basics in a outgoing packet
125 ****************************************************************************/
126 static void cli_setup_packet(struct cli_state *cli)
130 SSVAL(cli->outbuf,smb_pid,cli->pid);
131 SSVAL(cli->outbuf,smb_uid,cli->vuid);
132 SSVAL(cli->outbuf,smb_mid,cli->mid);
133 if (cli->protocol > PROTOCOL_CORE) {
134 SCVAL(cli->outbuf,smb_flg,0x8);
135 SSVAL(cli->outbuf,smb_flg2,0x1);
140 /****************************************************************************
141 send a SMB trans or trans2 request
142 ****************************************************************************/
143 static BOOL cli_send_trans(struct cli_state *cli, int trans,
144 char *name, int pipe_name_len,
146 uint16 *setup, int lsetup, int msetup,
147 char *param, int lparam, int mparam,
148 char *data, int ldata, int mdata)
151 int this_ldata,this_lparam;
152 int tot_data=0,tot_param=0;
153 char *outdata,*outparam;
156 this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
157 this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
159 bzero(cli->outbuf,smb_size);
160 set_message(cli->outbuf,14+lsetup,0,True);
161 CVAL(cli->outbuf,smb_com) = trans;
162 SSVAL(cli->outbuf,smb_tid, cli->cnum);
163 cli_setup_packet(cli);
165 outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len+1 : 3);
166 outdata = outparam+this_lparam;
168 /* primary request */
169 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
170 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
171 SSVAL(cli->outbuf,smb_mprcnt,mparam); /* mprcnt */
172 SSVAL(cli->outbuf,smb_mdrcnt,mdata); /* mdrcnt */
173 SCVAL(cli->outbuf,smb_msrcnt,msetup); /* msrcnt */
174 SSVAL(cli->outbuf,smb_flags,flags); /* flags */
175 SIVAL(cli->outbuf,smb_timeout,0); /* timeout */
176 SSVAL(cli->outbuf,smb_pscnt,this_lparam); /* pscnt */
177 SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
178 SSVAL(cli->outbuf,smb_dscnt,this_ldata); /* dscnt */
179 SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
180 SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */
181 for (i=0;i<lsetup;i++) /* setup[] */
182 SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
183 p = smb_buf(cli->outbuf);
184 if (trans==SMBtrans) {
185 memcpy(p,name, pipe_name_len + 1); /* name[] */
187 *p++ = 0; /* put in a null smb_name */
188 *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */
190 if (this_lparam) /* param[] */
191 memcpy(outparam,param,this_lparam);
192 if (this_ldata) /* data[] */
193 memcpy(outdata,data,this_ldata);
194 set_message(cli->outbuf,14+lsetup, /* wcnt, bcc */
195 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
197 show_msg(cli->outbuf);
198 send_smb(cli->fd,cli->outbuf);
200 if (this_ldata < ldata || this_lparam < lparam) {
201 /* receive interim response */
202 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout) ||
203 CVAL(cli->inbuf,smb_rcls) != 0) {
207 tot_data = this_ldata;
208 tot_param = this_lparam;
210 while (tot_data < ldata || tot_param < lparam) {
211 this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
212 this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
214 set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
215 CVAL(cli->outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
217 outparam = smb_buf(cli->outbuf);
218 outdata = outparam+this_lparam;
220 /* secondary request */
221 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
222 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
223 SSVAL(cli->outbuf,smb_spscnt,this_lparam); /* pscnt */
224 SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
225 SSVAL(cli->outbuf,smb_spsdisp,tot_param); /* psdisp */
226 SSVAL(cli->outbuf,smb_sdscnt,this_ldata); /* dscnt */
227 SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
228 SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */
229 if (trans==SMBtrans2)
230 SSVALS(cli->outbuf,smb_sfid,fid); /* fid */
231 if (this_lparam) /* param[] */
232 memcpy(outparam,param,this_lparam);
233 if (this_ldata) /* data[] */
234 memcpy(outdata,data,this_ldata);
235 set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
236 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
238 show_msg(cli->outbuf);
239 send_smb(cli->fd,cli->outbuf);
241 tot_data += this_ldata;
242 tot_param += this_lparam;
250 /****************************************************************************
251 receive a SMB trans or trans2 response allocating the necessary memory
252 ****************************************************************************/
253 static BOOL cli_receive_trans(struct cli_state *cli,int trans,
254 char **param, int *param_len,
255 char **data, int *data_len)
259 int this_data,this_param;
261 *data_len = *param_len = 0;
263 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
266 show_msg(cli->inbuf);
269 if (CVAL(cli->inbuf,smb_com) != trans) {
270 DEBUG(0,("Expected %s response, got command 0x%02x\n",
271 trans==SMBtrans?"SMBtrans":"SMBtrans2",
272 CVAL(cli->inbuf,smb_com)));
276 if (cli_error(cli, NULL, NULL))
281 /* parse out the lengths */
282 total_data = SVAL(cli->inbuf,smb_tdrcnt);
283 total_param = SVAL(cli->inbuf,smb_tprcnt);
286 *data = Realloc(*data,total_data);
287 *param = Realloc(*param,total_param);
290 this_data = SVAL(cli->inbuf,smb_drcnt);
291 this_param = SVAL(cli->inbuf,smb_prcnt);
293 if (this_data + *data_len > total_data ||
294 this_param + *param_len > total_param) {
295 DEBUG(1,("Data overflow in cli_receive_trans\n"));
300 memcpy(*data + SVAL(cli->inbuf,smb_drdisp),
301 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff),
304 memcpy(*param + SVAL(cli->inbuf,smb_prdisp),
305 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff),
307 *data_len += this_data;
308 *param_len += this_param;
310 /* parse out the total lengths again - they can shrink! */
311 total_data = SVAL(cli->inbuf,smb_tdrcnt);
312 total_param = SVAL(cli->inbuf,smb_tprcnt);
314 if (total_data <= *data_len && total_param <= *param_len)
317 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
320 show_msg(cli->inbuf);
323 if (CVAL(cli->inbuf,smb_com) != trans) {
324 DEBUG(0,("Expected %s response, got command 0x%02x\n",
325 trans==SMBtrans?"SMBtrans":"SMBtrans2",
326 CVAL(cli->inbuf,smb_com)));
329 if (cli_error(cli, NULL, NULL))
338 /****************************************************************************
339 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
340 ****************************************************************************/
341 BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name, int pipe_name_len,
342 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
343 char *params, uint32 param_count, uint32 max_param_count,
344 char *data, uint32 data_count, uint32 max_data_count,
345 char **rparam, uint32 *rparam_count,
346 char **rdata, uint32 *rdata_count)
348 if (pipe_name_len == 0)
349 pipe_name_len = strlen(pipe_name);
351 cli_send_trans(cli, SMBtrans,
352 pipe_name, pipe_name_len,
353 0,0, /* fid, flags */
354 setup, setup_count, max_setup_count,
355 params, param_count, max_param_count,
356 data, data_count, max_data_count);
358 return (cli_receive_trans(cli, SMBtrans,
359 rparam, (int *)rparam_count,
360 rdata, (int *)rdata_count));
363 /****************************************************************************
365 ****************************************************************************/
366 BOOL cli_api(struct cli_state *cli,
367 char *param, int prcnt, int mprcnt,
368 char *data, int drcnt, int mdrcnt,
369 char **rparam, int *rprcnt,
370 char **rdata, int *rdrcnt)
372 cli_send_trans(cli,SMBtrans,
373 PIPE_LANMAN,strlen(PIPE_LANMAN), /* Name, length */
374 0,0, /* fid, flags */
375 NULL,0,0, /* Setup, length, max */
376 param, prcnt, mprcnt, /* Params, length, max */
377 data, drcnt, mdrcnt /* Data, length, max */
380 return (cli_receive_trans(cli,SMBtrans,
386 /****************************************************************************
387 perform a NetWkstaUserLogon
388 ****************************************************************************/
389 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
397 memset(param, 0, sizeof(param));
399 /* send a SMBtrans command with api NetWkstaUserLogon */
401 SSVAL(p,0,132); /* api number */
403 pstrcpy(p,"OOWb54WrLh");
404 p = skip_string(p,1);
405 pstrcpy(p,"WB21BWDWWDDDDDDDzzzD");
406 p = skip_string(p,1);
415 pstrcpy(p, workstation);
418 SSVAL(p, 0, BUFFER_SIZE);
420 SSVAL(p, 0, BUFFER_SIZE);
424 param, PTR_DIFF(p,param),1024, /* param, length, max */
425 NULL, 0, BUFFER_SIZE, /* data, length, max */
426 &rparam, &rprcnt, /* return params, return size */
427 &rdata, &rdrcnt /* return data, return size */
429 cli->rap_error = SVAL(rparam,0);
432 if (cli->rap_error == 0) {
433 DEBUG(4,("NetWkstaUserLogon success\n"));
434 cli->privilages = SVAL(p, 24);
435 fstrcpy(cli->eff_name,p+2);
437 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
445 return (cli->rap_error == 0);
448 /****************************************************************************
449 call a NetShareEnum - try and browse available connections on a host
450 ****************************************************************************/
451 BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, char *))
460 /* now send a SMBtrans command with api RNetShareEnum */
462 SSVAL(p,0,0); /* api number */
465 p = skip_string(p,1);
467 p = skip_string(p,1);
469 SSVAL(p,2,BUFFER_SIZE);
473 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
474 NULL, 0, BUFFER_SIZE, /* data, length, maxlen */
475 &rparam, &rprcnt, /* return params, length */
476 &rdata, &rdrcnt)) /* return data, length */
478 int res = SVAL(rparam,0);
479 int converter=SVAL(rparam,2);
484 count=SVAL(rparam,4);
487 for (i=0;i<count;i++,p+=20)
490 int type = SVAL(p,14);
491 int comment_offset = IVAL(p,16) & 0xFFFF;
492 char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
493 fn(sname, type, cmnt);
507 /****************************************************************************
508 call a NetServerEnum for the specified workgroup and servertype mask.
509 This function then calls the specified callback function for each name returned.
511 The callback function takes 3 arguments: the machine name, the server type and
513 ****************************************************************************/
514 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
515 void (*fn)(char *, uint32, char *))
525 /* send a SMBtrans command with api NetServerEnum */
527 SSVAL(p,0,0x68); /* api number */
529 pstrcpy(p,"WrLehDz");
530 p = skip_string(p,1);
532 pstrcpy(p,"B16BBDz");
534 p = skip_string(p,1);
536 SSVAL(p,2,BUFFER_SIZE);
541 pstrcpy(p, workgroup);
542 p = skip_string(p,1);
545 param, PTR_DIFF(p,param), 8, /* params, length, max */
546 NULL, 0, BUFFER_SIZE, /* data, length, max */
547 &rparam, &rprcnt, /* return params, return size */
548 &rdata, &rdrcnt /* return data, return size */
550 int res = SVAL(rparam,0);
551 int converter=SVAL(rparam,2);
555 count=SVAL(rparam,4);
558 for (i = 0;i < count;i++, p += 26) {
560 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
561 char *cmnt = comment_offset?(rdata+comment_offset):"";
562 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
564 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
566 fn(sname, stype, cmnt);
588 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
589 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
590 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
591 {PROTOCOL_LANMAN1,"LANMAN1.0"},
592 {PROTOCOL_LANMAN2,"LM1.2X002"},
593 {PROTOCOL_LANMAN2,"Samba"},
594 {PROTOCOL_NT1,"NT LM 0.12"},
595 {PROTOCOL_NT1,"NT LANMAN 1.0"},
600 /****************************************************************************
602 ****************************************************************************/
603 BOOL cli_session_setup(struct cli_state *cli,
605 char *pass, int passlen,
606 char *ntpass, int ntpasslen,
610 fstring pword, ntpword;
612 if (cli->protocol < PROTOCOL_LANMAN1)
615 if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
619 if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0')) {
620 /* Null session connect. */
624 if ((cli->sec_mode & 2) && passlen != 24) {
627 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
628 SMBNTencrypt((uchar *)ntpass,(uchar *)cli->cryptkey,(uchar *)ntpword);
630 memcpy(pword, pass, passlen);
631 memcpy(ntpword, ntpass, ntpasslen);
635 /* if in share level security then don't send a password now */
636 if (!(cli->sec_mode & 1)) {
639 fstrcpy(ntpword, "");
643 /* send a session setup command */
644 bzero(cli->outbuf,smb_size);
646 if (cli->protocol < PROTOCOL_NT1)
648 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
649 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
650 cli_setup_packet(cli);
652 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
653 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
654 SSVAL(cli->outbuf,smb_vwv3,2);
655 SSVAL(cli->outbuf,smb_vwv4,1);
656 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
657 SSVAL(cli->outbuf,smb_vwv7,passlen);
658 p = smb_buf(cli->outbuf);
659 memcpy(p,pword,passlen);
666 set_message(cli->outbuf,13,0,True);
667 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
668 cli_setup_packet(cli);
670 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
671 SSVAL(cli->outbuf,smb_vwv2,BUFFER_SIZE);
672 SSVAL(cli->outbuf,smb_vwv3,2);
673 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
674 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
675 SSVAL(cli->outbuf,smb_vwv7,passlen);
676 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
677 SSVAL(cli->outbuf,smb_vwv11,CAP_STATUS32);
678 p = smb_buf(cli->outbuf);
679 memcpy(p,pword,passlen);
680 p += SVAL(cli->outbuf,smb_vwv7);
681 memcpy(p,ntpword,ntpasslen);
682 p += SVAL(cli->outbuf,smb_vwv8);
685 p = skip_string(p,1);
686 pstrcpy(p,workgroup);
688 p = skip_string(p,1);
689 pstrcpy(p,"Unix");p = skip_string(p,1);
690 pstrcpy(p,"Samba");p = skip_string(p,1);
691 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
694 send_smb(cli->fd,cli->outbuf);
695 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
698 show_msg(cli->inbuf);
700 if (CVAL(cli->inbuf,smb_rcls) != 0) {
704 /* use the returned vuid from now on */
705 cli->vuid = SVAL(cli->inbuf,smb_uid);
710 /****************************************************************************
712 *****************************************************************************/
714 BOOL cli_ulogoff(struct cli_state *cli)
716 bzero(cli->outbuf,smb_size);
717 set_message(cli->outbuf,2,0,True);
718 CVAL(cli->outbuf,smb_com) = SMBulogoffX;
719 cli_setup_packet(cli);
720 SSVAL(cli->outbuf,smb_vwv0,0xFF);
721 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
723 send_smb(cli->fd,cli->outbuf);
724 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
727 return CVAL(cli->inbuf,smb_rcls) == 0;
730 /****************************************************************************
732 ****************************************************************************/
733 BOOL cli_send_tconX(struct cli_state *cli,
734 char *share, char *dev, char *pass, int passlen)
736 fstring fullshare, pword;
738 bzero(cli->outbuf,smb_size);
739 bzero(cli->inbuf,smb_size);
741 if (cli->sec_mode & 1) {
746 if ((cli->sec_mode & 2) && *pass && passlen != 24) {
748 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
750 memcpy(pword, pass, passlen);
753 slprintf(fullshare, sizeof(fullshare)-1,
754 "\\\\%s\\%s", cli->desthost, share);
756 set_message(cli->outbuf,4,
757 2 + strlen(fullshare) + passlen + strlen(dev),True);
758 CVAL(cli->outbuf,smb_com) = SMBtconX;
759 cli_setup_packet(cli);
761 SSVAL(cli->outbuf,smb_vwv0,0xFF);
762 SSVAL(cli->outbuf,smb_vwv3,passlen);
764 p = smb_buf(cli->outbuf);
765 memcpy(p,pword,passlen);
767 fstrcpy(p,fullshare);
768 p = skip_string(p,1);
771 SCVAL(cli->inbuf,smb_rcls, 1);
773 send_smb(cli->fd,cli->outbuf);
774 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
777 if (CVAL(cli->inbuf,smb_rcls) != 0) {
781 if (cli->protocol >= PROTOCOL_NT1 &&
782 smb_buflen(cli->inbuf) == 3) {
783 /* almost certainly win95 - enable bug fixes */
787 cli->cnum = SVAL(cli->inbuf,smb_tid);
792 /****************************************************************************
793 send a tree disconnect
794 ****************************************************************************/
795 BOOL cli_tdis(struct cli_state *cli)
797 bzero(cli->outbuf,smb_size);
798 set_message(cli->outbuf,0,0,True);
799 CVAL(cli->outbuf,smb_com) = SMBtdis;
800 SSVAL(cli->outbuf,smb_tid,cli->cnum);
801 cli_setup_packet(cli);
803 send_smb(cli->fd,cli->outbuf);
804 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
807 return CVAL(cli->inbuf,smb_rcls) == 0;
810 /****************************************************************************
812 ****************************************************************************/
813 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
817 bzero(cli->outbuf,smb_size);
818 bzero(cli->inbuf,smb_size);
820 set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
822 CVAL(cli->outbuf,smb_com) = SMBmv;
823 SSVAL(cli->outbuf,smb_tid,cli->cnum);
824 cli_setup_packet(cli);
826 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
828 p = smb_buf(cli->outbuf);
830 pstrcpy(p,fname_src);
831 p = skip_string(p,1);
833 pstrcpy(p,fname_dst);
835 send_smb(cli->fd,cli->outbuf);
836 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
840 if (CVAL(cli->inbuf,smb_rcls) != 0) {
847 /****************************************************************************
849 ****************************************************************************/
850 BOOL cli_unlink(struct cli_state *cli, char *fname)
854 bzero(cli->outbuf,smb_size);
855 bzero(cli->inbuf,smb_size);
857 set_message(cli->outbuf,1, 2 + strlen(fname),True);
859 CVAL(cli->outbuf,smb_com) = SMBunlink;
860 SSVAL(cli->outbuf,smb_tid,cli->cnum);
861 cli_setup_packet(cli);
863 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
865 p = smb_buf(cli->outbuf);
869 send_smb(cli->fd,cli->outbuf);
870 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
874 if (CVAL(cli->inbuf,smb_rcls) != 0) {
881 /****************************************************************************
883 ****************************************************************************/
884 BOOL cli_mkdir(struct cli_state *cli, char *dname)
888 bzero(cli->outbuf,smb_size);
889 bzero(cli->inbuf,smb_size);
891 set_message(cli->outbuf,0, 2 + strlen(dname),True);
893 CVAL(cli->outbuf,smb_com) = SMBmkdir;
894 SSVAL(cli->outbuf,smb_tid,cli->cnum);
895 cli_setup_packet(cli);
897 p = smb_buf(cli->outbuf);
901 send_smb(cli->fd,cli->outbuf);
902 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
906 if (CVAL(cli->inbuf,smb_rcls) != 0) {
913 /****************************************************************************
915 ****************************************************************************/
916 BOOL cli_rmdir(struct cli_state *cli, char *dname)
920 bzero(cli->outbuf,smb_size);
921 bzero(cli->inbuf,smb_size);
923 set_message(cli->outbuf,0, 2 + strlen(dname),True);
925 CVAL(cli->outbuf,smb_com) = SMBrmdir;
926 SSVAL(cli->outbuf,smb_tid,cli->cnum);
927 cli_setup_packet(cli);
929 p = smb_buf(cli->outbuf);
933 send_smb(cli->fd,cli->outbuf);
934 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
938 if (CVAL(cli->inbuf,smb_rcls) != 0) {
947 /****************************************************************************
949 ****************************************************************************/
950 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
954 unsigned accessmode=0;
958 if (!(flags & O_EXCL)) {
965 accessmode = (share_mode<<4);
967 if ((flags & O_RDWR) == O_RDWR) {
969 } else if ((flags & O_WRONLY) == O_WRONLY) {
974 if ((flags & O_SYNC) == O_SYNC) {
975 accessmode |= (1<<14);
979 bzero(cli->outbuf,smb_size);
980 bzero(cli->inbuf,smb_size);
982 set_message(cli->outbuf,15,1 + strlen(fname),True);
984 CVAL(cli->outbuf,smb_com) = SMBopenX;
985 SSVAL(cli->outbuf,smb_tid,cli->cnum);
986 cli_setup_packet(cli);
988 SSVAL(cli->outbuf,smb_vwv0,0xFF);
989 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
990 SSVAL(cli->outbuf,smb_vwv3,accessmode);
991 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
992 SSVAL(cli->outbuf,smb_vwv5,0);
993 SSVAL(cli->outbuf,smb_vwv8,openfn);
995 p = smb_buf(cli->outbuf);
997 p = skip_string(p,1);
999 send_smb(cli->fd,cli->outbuf);
1000 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
1004 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1008 return SVAL(cli->inbuf,smb_vwv2);
1014 /****************************************************************************
1016 ****************************************************************************/
1017 BOOL cli_close(struct cli_state *cli, int fnum)
1019 bzero(cli->outbuf,smb_size);
1020 bzero(cli->inbuf,smb_size);
1022 set_message(cli->outbuf,3,0,True);
1024 CVAL(cli->outbuf,smb_com) = SMBclose;
1025 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1026 cli_setup_packet(cli);
1028 SSVAL(cli->outbuf,smb_vwv0,fnum);
1029 SIVALS(cli->outbuf,smb_vwv1,-1);
1031 send_smb(cli->fd,cli->outbuf);
1032 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
1036 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1044 /****************************************************************************
1046 ****************************************************************************/
1047 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1051 bzero(cli->outbuf,smb_size);
1052 bzero(cli->inbuf,smb_size);
1054 set_message(cli->outbuf,8,10,True);
1056 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1057 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1058 cli_setup_packet(cli);
1060 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1061 SSVAL(cli->outbuf,smb_vwv2,fnum);
1062 CVAL(cli->outbuf,smb_vwv3) = 0;
1063 SIVALS(cli->outbuf, smb_vwv4, timeout);
1064 SSVAL(cli->outbuf,smb_vwv6,0);
1065 SSVAL(cli->outbuf,smb_vwv7,1);
1067 p = smb_buf(cli->outbuf);
1068 SSVAL(p, 0, cli->pid);
1069 SIVAL(p, 2, offset);
1072 send_smb(cli->fd,cli->outbuf);
1073 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
1077 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1084 /****************************************************************************
1086 ****************************************************************************/
1087 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1091 bzero(cli->outbuf,smb_size);
1092 bzero(cli->inbuf,smb_size);
1094 set_message(cli->outbuf,8,10,True);
1096 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1097 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1098 cli_setup_packet(cli);
1100 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1101 SSVAL(cli->outbuf,smb_vwv2,fnum);
1102 CVAL(cli->outbuf,smb_vwv3) = 0;
1103 SIVALS(cli->outbuf, smb_vwv4, timeout);
1104 SSVAL(cli->outbuf,smb_vwv6,1);
1105 SSVAL(cli->outbuf,smb_vwv7,0);
1107 p = smb_buf(cli->outbuf);
1108 SSVAL(p, 0, cli->pid);
1109 SIVAL(p, 2, offset);
1112 send_smb(cli->fd,cli->outbuf);
1113 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
1117 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1125 /****************************************************************************
1127 ****************************************************************************/
1128 int cli_read(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size)
1133 while (total < size) {
1134 int size1 = MIN(size-total, cli->max_xmit - (smb_size+32));
1137 bzero(cli->outbuf,smb_size);
1138 bzero(cli->inbuf,smb_size);
1140 set_message(cli->outbuf,10,0,True);
1142 CVAL(cli->outbuf,smb_com) = SMBreadX;
1143 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1144 cli_setup_packet(cli);
1146 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1147 SSVAL(cli->outbuf,smb_vwv2,fnum);
1148 SIVAL(cli->outbuf,smb_vwv3,offset+total);
1149 SSVAL(cli->outbuf,smb_vwv5,size1);
1150 SSVAL(cli->outbuf,smb_vwv6,size1);
1152 send_smb(cli->fd,cli->outbuf);
1153 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
1154 return total?total:-1;
1157 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1158 return total?total:-1;
1161 size2 = SVAL(cli->inbuf, smb_vwv5);
1162 if (size2 > size1) {
1163 DEBUG(0,("server returned more than we wanted!\n"));
1166 p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
1168 if (size2 <= 0) break;
1170 memcpy(buf+total, p, size2);
1179 /****************************************************************************
1181 ****************************************************************************/
1182 int cli_write(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size)
1187 while (total < size) {
1188 int size1 = MIN(size-total, cli->max_xmit - (smb_size+32));
1191 bzero(cli->outbuf,smb_size);
1192 bzero(cli->inbuf,smb_size);
1194 set_message(cli->outbuf,12,size1,True);
1196 CVAL(cli->outbuf,smb_com) = SMBwriteX;
1197 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1198 cli_setup_packet(cli);
1200 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1201 SSVAL(cli->outbuf,smb_vwv2,fnum);
1202 SIVAL(cli->outbuf,smb_vwv3,offset+total);
1204 SSVAL(cli->outbuf,smb_vwv10,size1);
1205 SSVAL(cli->outbuf,smb_vwv11,
1206 smb_buf(cli->outbuf) - smb_base(cli->outbuf));
1208 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
1209 memcpy(p, buf+total, size1);
1211 send_smb(cli->fd,cli->outbuf);
1212 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
1216 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1220 size2 = SVAL(cli->inbuf, smb_vwv2);
1222 if (size2 <= 0) break;
1231 /****************************************************************************
1232 do a SMBgetattrE call
1233 ****************************************************************************/
1234 BOOL cli_getattrE(struct cli_state *cli, int fd,
1235 int *attr, uint32 *size,
1236 time_t *c_time, time_t *a_time, time_t *m_time)
1238 bzero(cli->outbuf,smb_size);
1239 bzero(cli->inbuf,smb_size);
1241 set_message(cli->outbuf,2,0,True);
1243 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
1244 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1245 cli_setup_packet(cli);
1247 SSVAL(cli->outbuf,smb_vwv0,fd);
1249 send_smb(cli->fd,cli->outbuf);
1250 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
1254 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1259 *size = IVAL(cli->inbuf, smb_vwv6);
1263 *attr = SVAL(cli->inbuf,smb_vwv10);
1267 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
1271 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
1275 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
1282 /****************************************************************************
1284 ****************************************************************************/
1285 BOOL cli_getatr(struct cli_state *cli, char *fname,
1286 uint32 *attr, size_t *size, time_t *t)
1290 bzero(cli->outbuf,smb_size);
1291 bzero(cli->inbuf,smb_size);
1293 set_message(cli->outbuf,0,strlen(fname)+2,True);
1295 CVAL(cli->outbuf,smb_com) = SMBgetatr;
1296 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1297 cli_setup_packet(cli);
1299 p = smb_buf(cli->outbuf);
1301 pstrcpy(p+1, fname);
1303 send_smb(cli->fd,cli->outbuf);
1304 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
1308 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1313 *size = IVAL(cli->inbuf, smb_vwv3);
1317 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1321 *attr = SVAL(cli->inbuf,smb_vwv0);
1329 /****************************************************************************
1331 ****************************************************************************/
1332 BOOL cli_setatr(struct cli_state *cli, char *fname, int attr, time_t t)
1336 bzero(cli->outbuf,smb_size);
1337 bzero(cli->inbuf,smb_size);
1339 set_message(cli->outbuf,8,strlen(fname)+4,True);
1341 CVAL(cli->outbuf,smb_com) = SMBsetatr;
1342 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1343 cli_setup_packet(cli);
1345 SSVAL(cli->outbuf,smb_vwv0, attr);
1346 put_dos_date3(cli->outbuf,smb_vwv1, t);
1348 p = smb_buf(cli->outbuf);
1350 pstrcpy(p+1, fname);
1351 p = skip_string(p,1);
1354 send_smb(cli->fd,cli->outbuf);
1355 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
1359 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1366 /****************************************************************************
1367 send a qpathinfo call
1368 ****************************************************************************/
1369 BOOL cli_qpathinfo(struct cli_state *cli, char *fname,
1370 time_t *c_time, time_t *a_time, time_t *m_time,
1371 size_t *size, uint32 *mode)
1375 uint16 setup = TRANSACT2_QPATHINFO;
1377 char *rparam=NULL, *rdata=NULL;
1380 time_t (*date_fn)(void *);
1382 param_len = strlen(fname) + 7;
1384 memset(param, 0, param_len);
1385 SSVAL(param, 0, SMB_INFO_STANDARD);
1386 pstrcpy(¶m[6], fname);
1389 ret = (cli_send_trans(cli, SMBtrans2,
1390 NULL, 0, /* Name, length */
1391 -1, 0, /* fid, flags */
1392 &setup, 1, 0, /* setup, length, max */
1393 param, param_len, 10, /* param, length, max */
1394 NULL, data_len, cli->max_xmit /* data, length, max */
1396 cli_receive_trans(cli, SMBtrans2,
1397 &rparam, ¶m_len,
1398 &rdata, &data_len));
1400 /* we need to work around a Win95 bug - sometimes
1401 it gives ERRSRV/ERRerror temprarily */
1404 cli_error(cli, &eclass, &ecode);
1405 if (eclass != ERRSRV || ecode != ERRerror) break;
1408 } while (count-- && ret==False);
1410 if (!ret || !rdata || data_len < 22) {
1415 date_fn = make_unix_date;
1417 date_fn = make_unix_date2;
1421 *c_time = date_fn(rdata+0);
1424 *a_time = date_fn(rdata+4);
1427 *m_time = date_fn(rdata+8);
1430 *size = IVAL(rdata, 12);
1433 *mode = SVAL(rdata,l1_attrFile);
1436 if (rdata) free(rdata);
1437 if (rparam) free(rparam);
1441 /****************************************************************************
1442 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1443 ****************************************************************************/
1444 BOOL cli_qpathinfo2(struct cli_state *cli, char *fname,
1445 time_t *c_time, time_t *a_time, time_t *m_time,
1446 time_t *w_time, uint32 *size)
1450 uint16 setup = TRANSACT2_QPATHINFO;
1452 char *rparam=NULL, *rdata=NULL;
1454 param_len = strlen(fname) + 7;
1456 memset(param, 0, param_len);
1457 SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1458 pstrcpy(¶m[6], fname);
1460 if (!cli_send_trans(cli, SMBtrans2,
1461 NULL, 0, /* name, length */
1462 -1, 0, /* fid, flags */
1463 &setup, 1, 0, /* setup, length, max */
1464 param, param_len, 10, /* param, length, max */
1465 NULL, data_len, cli->max_xmit /* data, length, max */
1470 if (!cli_receive_trans(cli, SMBtrans2,
1471 &rparam, ¶m_len,
1472 &rdata, &data_len)) {
1476 if (!rdata || data_len < 22) {
1481 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1484 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1487 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1490 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1493 *size = IVAL(rdata, 40);
1496 if (rdata) free(rdata);
1497 if (rparam) free(rparam);
1502 /****************************************************************************
1503 send a qfileinfo call
1504 ****************************************************************************/
1505 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
1506 time_t *c_time, time_t *a_time, time_t *m_time,
1507 uint32 *size, int *mode)
1511 uint16 setup = TRANSACT2_QFILEINFO;
1513 char *rparam=NULL, *rdata=NULL;
1517 memset(param, 0, param_len);
1518 SSVAL(param, 0, fnum);
1519 SSVAL(param, 2, SMB_INFO_STANDARD);
1521 if (!cli_send_trans(cli, SMBtrans2,
1522 NULL, 0, /* name, length */
1523 -1, 0, /* fid, flags */
1524 &setup, 1, 0, /* setup, length, max */
1525 param, param_len, 2, /* param, length, max */
1526 NULL, data_len, cli->max_xmit /* data, length, max */
1531 if (!cli_receive_trans(cli, SMBtrans2,
1532 &rparam, ¶m_len,
1533 &rdata, &data_len)) {
1537 if (!rdata || data_len < 22) {
1542 *c_time = make_unix_date2(rdata+0);
1545 *a_time = make_unix_date2(rdata+4);
1548 *m_time = make_unix_date2(rdata+8);
1551 *size = IVAL(rdata, 12);
1554 *mode = SVAL(rdata,l1_attrFile);
1557 if (rdata) free(rdata);
1558 if (rparam) free(rparam);
1563 /****************************************************************************
1564 interpret a long filename structure - this is mostly guesses at the moment
1565 The length of the structure is returned
1566 The structure of a long filename depends on the info level. 260 is used
1567 by NT and 2 is used by OS/2
1568 ****************************************************************************/
1569 static int interpret_long_filename(int level,char *p,file_info *finfo)
1571 extern file_info def_finfo;
1574 memcpy(finfo,&def_finfo,sizeof(*finfo));
1578 case 1: /* OS/2 understands this */
1580 /* these dates are converted to GMT by make_unix_date */
1581 finfo->ctime = make_unix_date2(p+4);
1582 finfo->atime = make_unix_date2(p+8);
1583 finfo->mtime = make_unix_date2(p+12);
1584 finfo->size = IVAL(p,16);
1585 finfo->mode = CVAL(p,24);
1586 pstrcpy(finfo->name,p+27);
1588 return(28 + CVAL(p,26));
1590 case 2: /* this is what OS/2 uses mostly */
1592 /* these dates are converted to GMT by make_unix_date */
1593 finfo->ctime = make_unix_date2(p+4);
1594 finfo->atime = make_unix_date2(p+8);
1595 finfo->mtime = make_unix_date2(p+12);
1596 finfo->size = IVAL(p,16);
1597 finfo->mode = CVAL(p,24);
1598 pstrcpy(finfo->name,p+31);
1600 return(32 + CVAL(p,30));
1602 /* levels 3 and 4 are untested */
1605 /* these dates are probably like the other ones */
1606 finfo->ctime = make_unix_date2(p+8);
1607 finfo->atime = make_unix_date2(p+12);
1608 finfo->mtime = make_unix_date2(p+16);
1609 finfo->size = IVAL(p,20);
1610 finfo->mode = CVAL(p,28);
1611 pstrcpy(finfo->name,p+33);
1613 return(SVAL(p,4)+4);
1617 /* these dates are probably like the other ones */
1618 finfo->ctime = make_unix_date2(p+8);
1619 finfo->atime = make_unix_date2(p+12);
1620 finfo->mtime = make_unix_date2(p+16);
1621 finfo->size = IVAL(p,20);
1622 finfo->mode = CVAL(p,28);
1623 pstrcpy(finfo->name,p+37);
1625 return(SVAL(p,4)+4);
1627 case 260: /* NT uses this, but also accepts 2 */
1629 int ret = SVAL(p,0);
1631 p += 4; /* next entry offset */
1632 p += 4; /* fileindex */
1634 /* these dates appear to arrive in a
1635 weird way. It seems to be localtime
1636 plus the serverzone given in the
1637 initial connect. This is GMT when
1638 DST is not in effect and one hour
1639 from GMT otherwise. Can this really
1642 I suppose this could be called
1643 kludge-GMT. Is is the GMT you get
1644 by using the current DST setting on
1645 a different localtime. It will be
1646 cheap to calculate, I suppose, as
1647 no DST tables will be needed */
1649 finfo->ctime = interpret_long_date(p); p += 8;
1650 finfo->atime = interpret_long_date(p); p += 8;
1651 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
1652 finfo->size = IVAL(p,0); p += 8;
1653 p += 8; /* alloc size */
1654 finfo->mode = CVAL(p,0); p += 4;
1655 namelen = IVAL(p,0); p += 4;
1656 p += 4; /* EA size */
1657 p += 2; /* short name len? */
1658 p += 24; /* short name? */
1659 StrnCpy(finfo->name,p,namelen);
1665 DEBUG(1,("Unknown long filename format %d\n",level));
1670 /****************************************************************************
1671 do a directory listing, calling fn on each file found
1672 ****************************************************************************/
1673 int cli_list(struct cli_state *cli,char *Mask,int attribute,void (*fn)(file_info *))
1675 int max_matches = 512;
1676 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1677 int info_level = cli->protocol<PROTOCOL_NT1?1:260;
1682 char *dirlist = NULL;
1683 int dirlist_len = 0;
1684 int total_received = -1;
1686 int ff_resume_key = 0;
1687 int ff_searchcount=0;
1690 int ff_dir_handle=0;
1692 char *rparam=NULL, *rdata=NULL;
1693 int param_len, data_len;
1700 while (ff_eos == 0) {
1702 if (loop_count > 200) {
1703 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
1707 param_len = 12+strlen(mask)+1;
1710 setup = TRANSACT2_FINDFIRST;
1711 SSVAL(param,0,attribute); /* attribute */
1712 SSVAL(param,2,max_matches); /* max count */
1713 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
1714 SSVAL(param,6,info_level);
1716 pstrcpy(param+12,mask);
1718 setup = TRANSACT2_FINDNEXT;
1719 SSVAL(param,0,ff_dir_handle);
1720 SSVAL(param,2,max_matches); /* max count */
1721 SSVAL(param,4,info_level);
1722 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
1723 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
1724 pstrcpy(param+12,mask);
1726 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
1727 ff_dir_handle,ff_resume_key,ff_lastname,mask));
1730 if (!cli_send_trans(cli, SMBtrans2,
1731 NULL, 0, /* Name, length */
1732 -1, 0, /* fid, flags */
1733 &setup, 1, 0, /* setup, length, max */
1734 param, param_len, 10, /* param, length, max */
1736 cli->max_xmit /* data, length, max */
1741 if (!cli_receive_trans(cli, SMBtrans2,
1742 &rparam, ¶m_len,
1743 &rdata, &data_len)) {
1744 /* we need to work around a Win95 bug - sometimes
1745 it gives ERRSRV/ERRerror temprarily */
1748 cli_error(cli, &eclass, &ecode);
1749 if (eclass != ERRSRV || ecode != ERRerror) break;
1754 if (total_received == -1) total_received = 0;
1756 /* parse out some important return info */
1759 ff_dir_handle = SVAL(p,0);
1760 ff_searchcount = SVAL(p,2);
1762 ff_lastname = SVAL(p,8);
1764 ff_searchcount = SVAL(p,0);
1766 ff_lastname = SVAL(p,6);
1769 if (ff_searchcount == 0)
1772 /* point to the data bytes */
1775 /* we might need the lastname for continuations */
1776 if (ff_lastname > 0) {
1781 StrnCpy(mask,p+ff_lastname,
1782 data_len-ff_lastname);
1785 pstrcpy(mask,p + ff_lastname + 1);
1793 /* and add them to the dirlist pool */
1794 dirlist = Realloc(dirlist,dirlist_len + data_len);
1797 DEBUG(0,("Failed to expand dirlist\n"));
1801 /* put in a length for the last entry, to ensure we can chain entries
1802 into the next packet */
1803 for (p2=p,i=0;i<(ff_searchcount-1);i++)
1804 p2 += interpret_long_filename(info_level,p2,NULL);
1805 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
1807 /* grab the data for later use */
1808 memcpy(dirlist+dirlist_len,p,data_len);
1809 dirlist_len += data_len;
1811 total_received += ff_searchcount;
1813 if (rdata) free(rdata); rdata = NULL;
1814 if (rparam) free(rparam); rparam = NULL;
1816 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
1817 ff_searchcount,ff_eos,ff_resume_key));
1822 for (p=dirlist,i=0;i<total_received;i++) {
1823 p += interpret_long_filename(info_level,p,&finfo);
1827 /* free up the dirlist buffer */
1828 if (dirlist) free(dirlist);
1829 return(total_received);
1833 /****************************************************************************
1834 Send a SamOEMChangePassword command
1835 ****************************************************************************/
1837 BOOL cli_oem_change_password(struct cli_state *cli, char *user, char *new_password,
1840 char param[16+sizeof(fstring)];
1843 fstring upper_case_old_pw;
1844 fstring upper_case_new_pw;
1845 unsigned char old_pw_hash[16];
1846 unsigned char new_pw_hash[16];
1849 int new_pw_len = strlen(new_password);
1850 char *rparam = NULL;
1854 if (strlen(user) >= sizeof(fstring)-1) {
1855 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
1859 if (new_pw_len > 512) {
1860 DEBUG(0,("cli_oem_change_password: new password for user %s is too long.\n", user));
1864 SSVAL(p,0,214); /* SamOEMChangePassword command. */
1867 p = skip_string(p,1);
1868 pstrcpy(p, "B516B16");
1869 p = skip_string(p,1);
1871 p = skip_string(p,1);
1875 param_len = PTR_DIFF(p,param);
1878 * Now setup the data area.
1879 * We need to generate a random fill
1880 * for this area to make it harder to
1883 generate_random_buffer((unsigned char *)data, sizeof(data), False);
1884 fstrcpy( &data[512 - new_pw_len], new_password);
1885 SIVAL(data, 512, new_pw_len);
1888 * Get the Lanman hash of the old password, we
1889 * use this as the key to SamOEMHash().
1891 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
1892 fstrcpy(upper_case_old_pw, old_password);
1893 strupper(upper_case_old_pw);
1894 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
1896 SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True);
1899 * Now place the old password hash in the data.
1901 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
1902 fstrcpy(upper_case_new_pw, new_password);
1903 strupper(upper_case_new_pw);
1905 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
1907 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
1911 if (cli_send_trans(cli,SMBtrans,
1912 PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */
1913 0,0, /* fid, flags */
1914 NULL,0,0, /* setup, length, max */
1915 param,param_len,2, /* param, length, max */
1916 data,data_len,0 /* data, length, max */
1918 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
1923 if (cli_receive_trans(cli,SMBtrans,
1927 cli->rap_error = SVAL(rparam,0);
1935 return (cli->rap_error == 0);
1938 /****************************************************************************
1939 send a negprot command
1940 ****************************************************************************/
1941 BOOL cli_negprot(struct cli_state *cli)
1947 bzero(cli->outbuf,smb_size);
1949 /* setup the protocol strings */
1950 for (plength=0,numprots=0;
1951 prots[numprots].name && prots[numprots].prot<=cli->protocol;
1953 plength += strlen(prots[numprots].name)+2;
1955 set_message(cli->outbuf,0,plength,True);
1957 p = smb_buf(cli->outbuf);
1959 prots[numprots].name && prots[numprots].prot<=cli->protocol;
1962 pstrcpy(p,prots[numprots].name);
1966 CVAL(cli->outbuf,smb_com) = SMBnegprot;
1967 cli_setup_packet(cli);
1969 CVAL(smb_buf(cli->outbuf),0) = 2;
1971 send_smb(cli->fd,cli->outbuf);
1972 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
1975 show_msg(cli->inbuf);
1977 if (CVAL(cli->inbuf,smb_rcls) != 0 ||
1978 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
1982 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
1985 if (cli->protocol >= PROTOCOL_NT1) {
1987 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
1988 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1989 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1990 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
1991 /* this time arrives in real GMT */
1992 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
1993 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
1994 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1995 if (cli->capabilities & 1) {
1996 cli->readbraw_supported = True;
1997 cli->writebraw_supported = True;
1999 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2000 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
2001 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
2002 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
2003 cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
2004 /* this time is converted to GMT by make_unix_date */
2005 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
2006 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
2007 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
2008 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2010 /* the old core protocol */
2012 cli->serverzone = TimeDiff(time(NULL));
2019 /****************************************************************************
2020 send a session request. see rfc1002.txt 4.3 and 4.3.2
2021 ****************************************************************************/
2022 BOOL cli_session_request(struct cli_state *cli,
2023 struct nmb_name *calling, struct nmb_name *called)
2027 /* send a session request (RFC 1002) */
2029 memcpy(&(cli->calling), calling, sizeof(*calling));
2030 memcpy(&(cli->called ), called , sizeof(*called ));
2032 /* put in the destination name */
2033 p = cli->outbuf+len;
2034 name_mangle(cli->called .name, p, cli->called .name_type);
2038 p = cli->outbuf+len;
2039 name_mangle(cli->calling.name, p, cli->calling.name_type);
2042 /* setup the packet length */
2043 _smb_setlen(cli->outbuf,len);
2044 CVAL(cli->outbuf,0) = 0x81;
2048 #endif /* WITH_SSL */
2050 send_smb(cli->fd,cli->outbuf);
2051 DEBUG(5,("Sent session request\n"));
2053 if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
2057 if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
2058 if (!sslutil_fd_is_ssl(cli->fd)){
2059 if (sslutil_connect(cli->fd) == 0)
2063 #endif /* WITH_SSL */
2065 if (CVAL(cli->inbuf,0) != 0x82) {
2066 /* This is the wrong place to put the error... JRA. */
2067 cli->rap_error = CVAL(cli->inbuf,0);
2074 /****************************************************************************
2075 open the client sockets
2076 ****************************************************************************/
2077 BOOL cli_connect(struct cli_state *cli, char *host, struct in_addr *ip)
2079 struct in_addr dest_ip;
2080 extern struct in_addr ipzero;
2082 fstrcpy(cli->desthost, host);
2084 if (!ip || ip_equal(*ip, ipzero)) {
2085 if (!resolve_name( cli->desthost, &dest_ip)) {
2093 cli->fd = open_socket_out(SOCK_STREAM, &dest_ip, 139, cli->timeout);
2101 /****************************************************************************
2102 initialise a client structure
2103 ****************************************************************************/
2104 BOOL cli_initialise(struct cli_state *cli)
2106 if (cli->initialised)
2109 memset(cli, 0, sizeof(*cli));
2112 cli->pid = (uint16)getpid();
2114 cli->vuid = UID_FIELD_INVALID;
2115 cli->protocol = PROTOCOL_NT1;
2116 cli->timeout = 20000;
2117 cli->bufsize = 0x10000;
2118 cli->max_xmit = cli->bufsize - 4;
2119 cli->outbuf = (char *)malloc(cli->bufsize);
2120 cli->inbuf = (char *)malloc(cli->bufsize);
2121 if (!cli->outbuf || !cli->inbuf)
2123 cli->initialised = 1;
2127 /****************************************************************************
2128 shutdown a client structure
2129 ****************************************************************************/
2130 void cli_shutdown(struct cli_state *cli)
2138 sslutil_disconnect(cli->fd);
2139 #endif /* WITH_SSL */
2142 memset(cli, 0, sizeof(*cli));
2146 /****************************************************************************
2147 return error codes for the last packet
2148 returns 0 if there was no error and the bext approx of a unix errno
2150 ****************************************************************************/
2151 int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
2153 int flgs2 = SVAL(cli->inbuf,smb_flg2);
2157 if (eclass) *eclass = 0;
2160 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
2161 /* 32 bit error codes detected */
2162 uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
2163 if (num) *num = nt_err;
2164 DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
2165 if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0;
2167 switch (nt_err & 0xFFFFFF) {
2168 case NT_STATUS_ACCESS_VIOLATION: return EACCES;
2169 case NT_STATUS_NO_SUCH_FILE: return ENOENT;
2170 case NT_STATUS_NO_SUCH_DEVICE: return ENODEV;
2171 case NT_STATUS_INVALID_HANDLE: return EBADF;
2172 case NT_STATUS_NO_MEMORY: return ENOMEM;
2173 case NT_STATUS_ACCESS_DENIED: return EACCES;
2174 case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
2177 /* for all other cases - a default code */
2181 rcls = CVAL(cli->inbuf,smb_rcls);
2182 code = SVAL(cli->inbuf,smb_err);
2183 if (rcls == 0) return 0;
2185 if (eclass) *eclass = rcls;
2186 if (num ) *num = code;
2188 if (rcls == ERRDOS) {
2190 case ERRbadfile: return ENOENT;
2191 case ERRnoaccess: return EPERM;
2194 if (rcls == ERRSRV) {
2196 case ERRbadpw: return EPERM;
2199 /* for other cases */
2203 /****************************************************************************
2204 set socket options on a open connection
2205 ****************************************************************************/
2206 void cli_sockopt(struct cli_state *cli, char *options)
2208 set_socket_options(cli->fd, options);
2211 /****************************************************************************
2212 set the PID to use for smb messages. Return the old pid.
2213 ****************************************************************************/
2214 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
2216 uint16 ret = cli->pid;
2221 /****************************************************************************
2222 establishes a connection right up to doing tconX, reading in a password.
2223 ****************************************************************************/
2224 BOOL cli_reestablish_connection(struct cli_state *cli)
2226 struct nmb_name calling;
2227 struct nmb_name called;
2229 struct in_addr dest_ip;
2232 BOOL do_tcon = False;
2234 if (!cli->initialised || cli->fd == -1)
2236 DEBUG(3,("cli_reestablish_connection: not connected\n"));
2240 /* copy the parameters necessary to re-establish the connection */
2244 fstrcpy(share, cli->share);
2245 fstrcpy(dev , cli->dev);
2249 memcpy(&called , &(cli->called ), sizeof(called ));
2250 memcpy(&calling, &(cli->calling), sizeof(calling));
2251 fstrcpy(dest_host, cli->full_dest_host_name);
2252 dest_ip = cli->dest_ip;
2254 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2255 namestr(&calling), namestr(&called), inet_ntoa(dest_ip),
2256 cli->user_name, cli->domain));
2258 return cli_establish_connection(cli,
2259 dest_host, &dest_ip,
2261 share, dev, False, do_tcon);
2264 /****************************************************************************
2265 establishes a connection right up to doing tconX, reading in a password.
2266 ****************************************************************************/
2267 BOOL cli_establish_connection(struct cli_state *cli,
2268 char *dest_host, struct in_addr *dest_ip,
2269 struct nmb_name *calling, struct nmb_name *called,
2270 char *service, char *service_type,
2271 BOOL do_shutdown, BOOL do_tcon)
2273 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
2274 namestr(calling), namestr(called), inet_ntoa(*dest_ip),
2275 cli->user_name, cli->domain));
2277 /* establish connection */
2279 if ((!cli->initialised))
2286 if (!cli_connect(cli, dest_host, dest_ip))
2288 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
2289 namestr(calling), inet_ntoa(*dest_ip)));
2294 if (!cli_session_request(cli, calling, called))
2296 DEBUG(1,("failed session request\n"));
2302 if (!cli_negprot(cli))
2304 DEBUG(1,("failed negprot\n"));
2310 if (cli->pwd.cleartext || cli->pwd.null_pwd)
2312 /* attempt clear-text session */
2316 pwd_get_cleartext(&(cli->pwd), passwd);
2318 /* attempt clear-text session */
2319 if (!cli_session_setup(cli, cli->user_name,
2320 passwd, strlen(passwd),
2324 DEBUG(1,("failed session setup\n"));
2331 if (!cli_send_tconX(cli, service, service_type,
2332 (char*)passwd, strlen(passwd)))
2334 DEBUG(1,("failed tcon_X\n"));
2343 /* attempt encrypted session */
2344 unsigned char nt_sess_pwd[24];
2345 unsigned char lm_sess_pwd[24];
2347 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
2348 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
2349 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
2351 /* attempt encrypted session */
2352 if (!cli_session_setup(cli, cli->user_name,
2353 (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
2354 (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
2357 DEBUG(1,("failed session setup\n"));
2365 if (!cli_send_tconX(cli, service, service_type,
2366 (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
2368 DEBUG(1,("failed tcon_X\n"));