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;
29 extern pstring user_socket_options;
31 static void cli_process_oplock(struct cli_state *cli);
34 * Change the port number used to call on
36 int cli_set_port(struct cli_state *cli, int port)
44 /****************************************************************************
46 ****************************************************************************/
47 static BOOL cli_receive_smb(struct cli_state *cli)
51 ret = client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
54 /* it might be an oplock break request */
55 if (CVAL(cli->inbuf,smb_com) == SMBlockingX &&
56 SVAL(cli->inbuf,smb_vwv6) == 0 &&
57 SVAL(cli->inbuf,smb_vwv7) == 0) {
58 if (cli->use_oplocks) cli_process_oplock(cli);
59 /* try to prevent loops */
60 CVAL(cli->inbuf,smb_com) = 0xFF;
68 /****************************************************************************
69 send an smb to a fd and re-establish if necessary
70 ****************************************************************************/
71 static BOOL cli_send_smb(struct cli_state *cli)
76 BOOL reestablished=False;
78 len = smb_len(cli->outbuf) + 4;
80 while (nwritten < len) {
81 ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
82 if (ret <= 0 && errno == EPIPE && !reestablished) {
83 if (cli_reestablish_connection(cli)) {
90 DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",
101 /****************************************************************************
102 setup basics in a outgoing packet
103 ****************************************************************************/
104 static void cli_setup_packet(struct cli_state *cli)
108 SSVAL(cli->outbuf,smb_pid,cli->pid);
109 SSVAL(cli->outbuf,smb_uid,cli->vuid);
110 SSVAL(cli->outbuf,smb_mid,cli->mid);
111 if (cli->protocol > PROTOCOL_CORE) {
112 SCVAL(cli->outbuf,smb_flg,0x8);
113 SSVAL(cli->outbuf,smb_flg2,0x1);
119 /****************************************************************************
120 process an oplock break request from the server
121 ****************************************************************************/
122 static void cli_process_oplock(struct cli_state *cli)
124 char *oldbuf = cli->outbuf;
128 fnum = SVAL(cli->inbuf,smb_vwv2);
130 /* damn, we really need to keep a record of open files so we
131 can detect a oplock break and a close crossing on the
132 wire. for now this swallows the errors */
133 if (fnum == 0) return;
137 memset(buf,'\0',smb_size);
138 set_message(buf,8,0,True);
140 CVAL(buf,smb_com) = SMBlockingX;
141 SSVAL(buf,smb_tid, cli->cnum);
142 cli_setup_packet(cli);
143 SSVAL(buf,smb_vwv0,0xFF);
144 SSVAL(buf,smb_vwv1,0);
145 SSVAL(buf,smb_vwv2,fnum);
146 SSVAL(buf,smb_vwv3,2); /* oplock break ack */
147 SIVAL(buf,smb_vwv4,0); /* timoeut */
148 SSVAL(buf,smb_vwv6,0); /* unlockcount */
149 SSVAL(buf,smb_vwv7,0); /* lockcount */
153 cli->outbuf = oldbuf;
157 /*****************************************************
158 RAP error codes - a small start but will be extended.
159 *******************************************************/
167 {5, "User has insufficient privilege" },
168 {86, "The specified password is invalid" },
169 {2226, "Operation only permitted on a Primary Domain Controller" },
170 {2242, "The password of this user has expired." },
171 {2243, "The password of this user cannot change." },
172 {2244, "This password cannot be used now (password history conflict)." },
173 {2245, "The password is shorter than required." },
174 {2246, "The password of this user is too recent to change."},
176 /* these really shouldn't be here ... */
177 {0x80, "Not listening on called name"},
178 {0x81, "Not listening for calling name"},
179 {0x82, "Called name not present"},
180 {0x83, "Called name present, but insufficient resources"},
185 /****************************************************************************
186 return a description of an SMB error
187 ****************************************************************************/
188 static char *cli_smb_errstr(struct cli_state *cli)
190 return smb_errstr(cli->inbuf);
193 /******************************************************
194 Return an error message - either an SMB error or a RAP
196 *******************************************************/
198 char *cli_errstr(struct cli_state *cli)
200 static fstring error_message;
207 * Errors are of three kinds - smb errors,
208 * dealt with by cli_smb_errstr, NT errors,
209 * whose code is in cli.nt_error, and rap
210 * errors, whose error code is in cli.rap_error.
213 cli_error(cli, &errclass, &errnum, &nt_rpc_error);
217 return cli_smb_errstr(cli);
221 * Was it an NT error ?
226 char *nt_msg = get_nt_error_msg(nt_rpc_error);
230 slprintf(error_message, sizeof(fstring) - 1, "NT code %d", nt_rpc_error);
234 fstrcpy(error_message, nt_msg);
237 return error_message;
241 * Must have been a rap error.
244 slprintf(error_message, sizeof(error_message) - 1, "code %d", cli->rap_error);
246 for (i = 0; rap_errmap[i].message != NULL; i++)
248 if (rap_errmap[i].err == cli->rap_error)
250 fstrcpy( error_message, rap_errmap[i].message);
255 return error_message;
258 /*****************************************************************************
259 Convert a character pointer in a cli_call_api() response to a form we can use.
260 This function contains code to prevent core dumps if the server returns
262 *****************************************************************************/
263 static char *fix_char_ptr(unsigned int datap, unsigned int converter,
264 char *rdata, int rdrcnt)
266 if (datap == 0) { /* turn NULL pointers into zero length strings */
269 unsigned int offset = datap - converter;
271 if (offset >= rdrcnt) {
272 DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
273 datap, converter, rdrcnt));
276 return &rdata[offset];
281 /****************************************************************************
282 send a SMB trans or trans2 request
283 ****************************************************************************/
284 static BOOL cli_send_trans(struct cli_state *cli, int trans,
285 char *name, int pipe_name_len,
287 uint16 *setup, int lsetup, int msetup,
288 char *param, int lparam, int mparam,
289 char *data, int ldata, int mdata)
292 int this_ldata,this_lparam;
293 int tot_data=0,tot_param=0;
294 char *outdata,*outparam;
297 this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
298 this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
300 memset(cli->outbuf,'\0',smb_size);
301 set_message(cli->outbuf,14+lsetup,0,True);
302 CVAL(cli->outbuf,smb_com) = trans;
303 SSVAL(cli->outbuf,smb_tid, cli->cnum);
304 cli_setup_packet(cli);
306 outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len+1 : 3);
307 outdata = outparam+this_lparam;
309 /* primary request */
310 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
311 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
312 SSVAL(cli->outbuf,smb_mprcnt,mparam); /* mprcnt */
313 SSVAL(cli->outbuf,smb_mdrcnt,mdata); /* mdrcnt */
314 SCVAL(cli->outbuf,smb_msrcnt,msetup); /* msrcnt */
315 SSVAL(cli->outbuf,smb_flags,flags); /* flags */
316 SIVAL(cli->outbuf,smb_timeout,0); /* timeout */
317 SSVAL(cli->outbuf,smb_pscnt,this_lparam); /* pscnt */
318 SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
319 SSVAL(cli->outbuf,smb_dscnt,this_ldata); /* dscnt */
320 SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
321 SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */
322 for (i=0;i<lsetup;i++) /* setup[] */
323 SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
324 p = smb_buf(cli->outbuf);
325 if (trans==SMBtrans) {
326 memcpy(p,name, pipe_name_len + 1); /* name[] */
328 *p++ = 0; /* put in a null smb_name */
329 *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */
331 if (this_lparam) /* param[] */
332 memcpy(outparam,param,this_lparam);
333 if (this_ldata) /* data[] */
334 memcpy(outdata,data,this_ldata);
335 set_message(cli->outbuf,14+lsetup, /* wcnt, bcc */
336 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
338 show_msg(cli->outbuf);
341 if (this_ldata < ldata || this_lparam < lparam) {
342 /* receive interim response */
343 if (!cli_receive_smb(cli) ||
344 CVAL(cli->inbuf,smb_rcls) != 0) {
348 tot_data = this_ldata;
349 tot_param = this_lparam;
351 while (tot_data < ldata || tot_param < lparam) {
352 this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
353 this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
355 set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
356 CVAL(cli->outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
358 outparam = smb_buf(cli->outbuf);
359 outdata = outparam+this_lparam;
361 /* secondary request */
362 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
363 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
364 SSVAL(cli->outbuf,smb_spscnt,this_lparam); /* pscnt */
365 SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
366 SSVAL(cli->outbuf,smb_spsdisp,tot_param); /* psdisp */
367 SSVAL(cli->outbuf,smb_sdscnt,this_ldata); /* dscnt */
368 SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
369 SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */
370 if (trans==SMBtrans2)
371 SSVALS(cli->outbuf,smb_sfid,fid); /* fid */
372 if (this_lparam) /* param[] */
373 memcpy(outparam,param+tot_param,this_lparam);
374 if (this_ldata) /* data[] */
375 memcpy(outdata,data+tot_data,this_ldata);
376 set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
377 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
379 show_msg(cli->outbuf);
382 tot_data += this_ldata;
383 tot_param += this_lparam;
391 /****************************************************************************
392 receive a SMB trans or trans2 response allocating the necessary memory
393 ****************************************************************************/
394 static BOOL cli_receive_trans(struct cli_state *cli,int trans,
395 char **param, int *param_len,
396 char **data, int *data_len)
400 int this_data,this_param;
404 *data_len = *param_len = 0;
406 if (!cli_receive_smb(cli))
409 show_msg(cli->inbuf);
412 if (CVAL(cli->inbuf,smb_com) != trans) {
413 DEBUG(0,("Expected %s response, got command 0x%02x\n",
414 trans==SMBtrans?"SMBtrans":"SMBtrans2",
415 CVAL(cli->inbuf,smb_com)));
420 * An NT RPC pipe call can return ERRDOS, ERRmoredata
421 * to a trans call. This is not an error and should not
422 * be treated as such.
425 if (cli_error(cli, &eclass, &ecode, NULL))
427 if(cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata))
431 /* parse out the lengths */
432 total_data = SVAL(cli->inbuf,smb_tdrcnt);
433 total_param = SVAL(cli->inbuf,smb_tprcnt);
436 *data = Realloc(*data,total_data);
437 *param = Realloc(*param,total_param);
440 this_data = SVAL(cli->inbuf,smb_drcnt);
441 this_param = SVAL(cli->inbuf,smb_prcnt);
443 if (this_data + *data_len > total_data ||
444 this_param + *param_len > total_param) {
445 DEBUG(1,("Data overflow in cli_receive_trans\n"));
450 memcpy(*data + SVAL(cli->inbuf,smb_drdisp),
451 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff),
454 memcpy(*param + SVAL(cli->inbuf,smb_prdisp),
455 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff),
457 *data_len += this_data;
458 *param_len += this_param;
460 /* parse out the total lengths again - they can shrink! */
461 total_data = SVAL(cli->inbuf,smb_tdrcnt);
462 total_param = SVAL(cli->inbuf,smb_tprcnt);
464 if (total_data <= *data_len && total_param <= *param_len)
467 if (!cli_receive_smb(cli))
470 show_msg(cli->inbuf);
473 if (CVAL(cli->inbuf,smb_com) != trans) {
474 DEBUG(0,("Expected %s response, got command 0x%02x\n",
475 trans==SMBtrans?"SMBtrans":"SMBtrans2",
476 CVAL(cli->inbuf,smb_com)));
479 if (cli_error(cli, &eclass, &ecode, NULL))
481 if(cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata))
489 /****************************************************************************
490 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
491 ****************************************************************************/
492 BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name, int pipe_name_len,
493 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
494 char *params, uint32 param_count, uint32 max_param_count,
495 char *data, uint32 data_count, uint32 max_data_count,
496 char **rparam, uint32 *rparam_count,
497 char **rdata, uint32 *rdata_count)
499 if (pipe_name_len == 0)
500 pipe_name_len = strlen(pipe_name);
502 cli_send_trans(cli, SMBtrans,
503 pipe_name, pipe_name_len,
504 0,0, /* fid, flags */
505 setup, setup_count, max_setup_count,
506 params, param_count, max_param_count,
507 data, data_count, max_data_count);
509 return (cli_receive_trans(cli, SMBtrans,
510 rparam, (int *)rparam_count,
511 rdata, (int *)rdata_count));
514 /****************************************************************************
516 ****************************************************************************/
517 BOOL cli_api(struct cli_state *cli,
518 char *param, int prcnt, int mprcnt,
519 char *data, int drcnt, int mdrcnt,
520 char **rparam, int *rprcnt,
521 char **rdata, int *rdrcnt)
523 cli_send_trans(cli,SMBtrans,
524 PIPE_LANMAN,strlen(PIPE_LANMAN), /* Name, length */
525 0,0, /* fid, flags */
526 NULL,0,0, /* Setup, length, max */
527 param, prcnt, mprcnt, /* Params, length, max */
528 data, drcnt, mdrcnt /* Data, length, max */
531 return (cli_receive_trans(cli,SMBtrans,
537 /****************************************************************************
538 perform a NetWkstaUserLogon
539 ****************************************************************************/
540 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
548 memset(param, 0, sizeof(param));
550 /* send a SMBtrans command with api NetWkstaUserLogon */
552 SSVAL(p,0,132); /* api number */
554 pstrcpy(p,"OOWb54WrLh");
555 p = skip_string(p,1);
556 pstrcpy(p,"WB21BWDWWDDDDDDDzzzD");
557 p = skip_string(p,1);
566 pstrcpy(p, workstation);
569 SSVAL(p, 0, CLI_BUFFER_SIZE);
571 SSVAL(p, 0, CLI_BUFFER_SIZE);
575 param, PTR_DIFF(p,param),1024, /* param, length, max */
576 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
577 &rparam, &rprcnt, /* return params, return size */
578 &rdata, &rdrcnt /* return data, return size */
580 cli->rap_error = SVAL(rparam,0);
583 if (cli->rap_error == 0) {
584 DEBUG(4,("NetWkstaUserLogon success\n"));
585 cli->privileges = SVAL(p, 24);
586 fstrcpy(cli->eff_name,p+2);
588 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
596 return (cli->rap_error == 0);
599 /****************************************************************************
600 call a NetShareEnum - try and browse available connections on a host
601 ****************************************************************************/
602 BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *))
611 /* now send a SMBtrans command with api RNetShareEnum */
613 SSVAL(p,0,0); /* api number */
616 p = skip_string(p,1);
618 p = skip_string(p,1);
624 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
625 NULL, 0, 0xFFFF, /* data, length, maxlen */
626 &rparam, &rprcnt, /* return params, length */
627 &rdata, &rdrcnt)) /* return data, length */
629 int res = SVAL(rparam,0);
630 int converter=SVAL(rparam,2);
633 if (res == 0 || res == ERRmoredata) {
634 count=SVAL(rparam,4);
637 for (i=0;i<count;i++,p+=20) {
639 int type = SVAL(p,14);
640 int comment_offset = IVAL(p,16) & 0xFFFF;
641 char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
642 dos_to_unix(sname,True);
643 dos_to_unix(cmnt,True);
644 fn(sname, type, cmnt);
647 DEBUG(4,("NetShareEnum res=%d\n", res));
650 DEBUG(4,("NetShareEnum failed\n"));
662 /****************************************************************************
663 call a NetServerEnum for the specified workgroup and servertype mask.
664 This function then calls the specified callback function for each name returned.
666 The callback function takes 3 arguments: the machine name, the server type and
668 ****************************************************************************/
669 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
670 void (*fn)(const char *, uint32, const char *))
680 /* send a SMBtrans command with api NetServerEnum */
682 SSVAL(p,0,0x68); /* api number */
684 pstrcpy(p,"WrLehDz");
685 p = skip_string(p,1);
687 pstrcpy(p,"B16BBDz");
689 p = skip_string(p,1);
691 SSVAL(p,2,CLI_BUFFER_SIZE);
696 pstrcpy(p, workgroup);
697 p = skip_string(p,1);
700 param, PTR_DIFF(p,param), 8, /* params, length, max */
701 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
702 &rparam, &rprcnt, /* return params, return size */
703 &rdata, &rdrcnt /* return data, return size */
705 int res = SVAL(rparam,0);
706 int converter=SVAL(rparam,2);
709 if (res == 0 || res == ERRmoredata) {
710 count=SVAL(rparam,4);
713 for (i = 0;i < count;i++, p += 26) {
715 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
716 char *cmnt = comment_offset?(rdata+comment_offset):"";
717 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
719 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
721 dos_to_unix(sname, True);
722 dos_to_unix(cmnt, True);
723 fn(sname, stype, cmnt);
745 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
746 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
747 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
748 {PROTOCOL_LANMAN1,"LANMAN1.0"},
749 {PROTOCOL_LANMAN2,"LM1.2X002"},
750 {PROTOCOL_LANMAN2,"Samba"},
751 {PROTOCOL_NT1,"NT LANMAN 1.0"},
752 {PROTOCOL_NT1,"NT LM 0.12"},
757 /****************************************************************************
758 Send a session setup. The username is in UNIX character format and must be
759 converted to DOS codepage format before sending. If the password is in
760 plaintext, the same should be done.
761 ****************************************************************************/
763 BOOL cli_session_setup(struct cli_state *cli,
765 char *pass, int passlen,
766 char *ntpass, int ntpasslen,
770 fstring pword, ntpword;
772 if (cli->protocol < PROTOCOL_LANMAN1)
775 if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
779 if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0')) {
780 /* Null session connect. */
784 if ((cli->sec_mode & 2) && passlen != 24) {
786 * Encrypted mode needed, and non encrypted password supplied.
790 fstrcpy(pword, pass);
791 unix_to_dos(pword,True);
792 fstrcpy(ntpword, ntpass);;
793 unix_to_dos(ntpword,True);
794 SMBencrypt((uchar *)pword,(uchar *)cli->cryptkey,(uchar *)pword);
795 SMBNTencrypt((uchar *)ntpword,(uchar *)cli->cryptkey,(uchar *)ntpword);
796 } else if ((cli->sec_mode & 2) && passlen == 24) {
798 * Encrypted mode needed, and encrypted password supplied.
800 memcpy(pword, pass, passlen);
801 if(ntpasslen == 24) {
802 memcpy(ntpword, ntpass, ntpasslen);
804 fstrcpy(ntpword, "");
809 * Plaintext mode needed, assume plaintext supplied.
811 fstrcpy(pword, pass);
812 unix_to_dos(pword,True);
813 fstrcpy(ntpword, "");
818 /* if in share level security then don't send a password now */
819 if (!(cli->sec_mode & 1)) {
822 fstrcpy(ntpword, "");
826 /* send a session setup command */
827 memset(cli->outbuf,'\0',smb_size);
829 if (cli->protocol < PROTOCOL_NT1)
831 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
832 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
833 cli_setup_packet(cli);
835 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
836 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
837 SSVAL(cli->outbuf,smb_vwv3,2);
838 SSVAL(cli->outbuf,smb_vwv4,1);
839 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
840 SSVAL(cli->outbuf,smb_vwv7,passlen);
841 p = smb_buf(cli->outbuf);
842 memcpy(p,pword,passlen);
850 set_message(cli->outbuf,13,0,True);
851 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
852 cli_setup_packet(cli);
854 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
855 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
856 SSVAL(cli->outbuf,smb_vwv3,2);
857 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
858 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
859 SSVAL(cli->outbuf,smb_vwv7,passlen);
860 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
861 SSVAL(cli->outbuf,smb_vwv11,0);
862 p = smb_buf(cli->outbuf);
863 memcpy(p,pword,passlen);
864 p += SVAL(cli->outbuf,smb_vwv7);
865 memcpy(p,ntpword,ntpasslen);
866 p += SVAL(cli->outbuf,smb_vwv8);
870 p = skip_string(p,1);
871 pstrcpy(p,workgroup);
873 p = skip_string(p,1);
874 pstrcpy(p,"Unix");p = skip_string(p,1);
875 pstrcpy(p,"Samba");p = skip_string(p,1);
876 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
880 if (!cli_receive_smb(cli))
883 show_msg(cli->inbuf);
885 if (CVAL(cli->inbuf,smb_rcls) != 0) {
889 /* use the returned vuid from now on */
890 cli->vuid = SVAL(cli->inbuf,smb_uid);
892 if (cli->protocol >= PROTOCOL_NT1) {
894 * Save off some of the connected server
897 char *server_domain,*server_os,*server_type;
898 server_os = smb_buf(cli->inbuf);
899 server_type = skip_string(server_os,1);
900 server_domain = skip_string(server_type,1);
901 fstrcpy(cli->server_os, server_os);
902 dos_to_unix(cli->server_os, True);
903 fstrcpy(cli->server_type, server_type);
904 dos_to_unix(cli->server_type, True);
905 fstrcpy(cli->server_domain, server_domain);
906 dos_to_unix(cli->server_domain, True);
909 fstrcpy(cli->user_name, user);
910 dos_to_unix(cli->user_name, True);
915 /****************************************************************************
917 *****************************************************************************/
919 BOOL cli_ulogoff(struct cli_state *cli)
921 memset(cli->outbuf,'\0',smb_size);
922 set_message(cli->outbuf,2,0,True);
923 CVAL(cli->outbuf,smb_com) = SMBulogoffX;
924 cli_setup_packet(cli);
925 SSVAL(cli->outbuf,smb_vwv0,0xFF);
926 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
929 if (!cli_receive_smb(cli))
932 return CVAL(cli->inbuf,smb_rcls) == 0;
935 /****************************************************************************
937 ****************************************************************************/
938 BOOL cli_send_tconX(struct cli_state *cli,
939 char *share, char *dev, char *pass, int passlen)
941 fstring fullshare, pword, dos_pword;
943 memset(cli->outbuf,'\0',smb_size);
944 memset(cli->inbuf,'\0',smb_size);
946 fstrcpy(cli->share, share);
948 /* in user level security don't send a password now */
949 if (cli->sec_mode & 1) {
954 if ((cli->sec_mode & 2) && *pass && passlen != 24) {
956 * Non-encrypted passwords - convert to DOS codepage before encryption.
959 fstrcpy(dos_pword,pass);
960 unix_to_dos(dos_pword,True);
961 SMBencrypt((uchar *)dos_pword,(uchar *)cli->cryptkey,(uchar *)pword);
963 if(!(cli->sec_mode & 2)) {
965 * Non-encrypted passwords - convert to DOS codepage before using.
968 unix_to_dos(pword,True);
970 memcpy(pword, pass, passlen);
974 slprintf(fullshare, sizeof(fullshare)-1,
975 "\\\\%s\\%s", cli->desthost, share);
976 unix_to_dos(fullshare, True);
979 set_message(cli->outbuf,4,
980 2 + strlen(fullshare) + passlen + strlen(dev),True);
981 CVAL(cli->outbuf,smb_com) = SMBtconX;
982 cli_setup_packet(cli);
984 SSVAL(cli->outbuf,smb_vwv0,0xFF);
985 SSVAL(cli->outbuf,smb_vwv3,passlen);
987 p = smb_buf(cli->outbuf);
988 memcpy(p,pword,passlen);
990 fstrcpy(p,fullshare);
991 p = skip_string(p,1);
995 SCVAL(cli->inbuf,smb_rcls, 1);
998 if (!cli_receive_smb(cli))
1001 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1005 fstrcpy(cli->dev, "A:");
1007 if (cli->protocol >= PROTOCOL_NT1) {
1008 fstrcpy(cli->dev, smb_buf(cli->inbuf));
1011 if (strcasecmp(share,"IPC$")==0) {
1012 fstrcpy(cli->dev, "IPC");
1015 /* only grab the device if we have a recent protocol level */
1016 if (cli->protocol >= PROTOCOL_NT1 &&
1017 smb_buflen(cli->inbuf) == 3) {
1018 /* almost certainly win95 - enable bug fixes */
1022 cli->cnum = SVAL(cli->inbuf,smb_tid);
1027 /****************************************************************************
1028 send a tree disconnect
1029 ****************************************************************************/
1030 BOOL cli_tdis(struct cli_state *cli)
1032 memset(cli->outbuf,'\0',smb_size);
1033 set_message(cli->outbuf,0,0,True);
1034 CVAL(cli->outbuf,smb_com) = SMBtdis;
1035 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1036 cli_setup_packet(cli);
1039 if (!cli_receive_smb(cli))
1042 return CVAL(cli->inbuf,smb_rcls) == 0;
1045 /****************************************************************************
1047 ****************************************************************************/
1048 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
1052 memset(cli->outbuf,'\0',smb_size);
1053 memset(cli->inbuf,'\0',smb_size);
1055 set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
1057 CVAL(cli->outbuf,smb_com) = SMBmv;
1058 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1059 cli_setup_packet(cli);
1061 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
1063 p = smb_buf(cli->outbuf);
1065 pstrcpy(p,fname_src);
1066 unix_to_dos(p,True);
1067 p = skip_string(p,1);
1069 pstrcpy(p,fname_dst);
1070 unix_to_dos(p,True);
1073 if (!cli_receive_smb(cli)) {
1077 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1084 /****************************************************************************
1086 ****************************************************************************/
1087 BOOL cli_unlink(struct cli_state *cli, char *fname)
1091 memset(cli->outbuf,'\0',smb_size);
1092 memset(cli->inbuf,'\0',smb_size);
1094 set_message(cli->outbuf,1, 2 + strlen(fname),True);
1096 CVAL(cli->outbuf,smb_com) = SMBunlink;
1097 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1098 cli_setup_packet(cli);
1100 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
1102 p = smb_buf(cli->outbuf);
1105 unix_to_dos(p,True);
1108 if (!cli_receive_smb(cli)) {
1112 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1119 /****************************************************************************
1121 ****************************************************************************/
1122 BOOL cli_mkdir(struct cli_state *cli, char *dname)
1126 memset(cli->outbuf,'\0',smb_size);
1127 memset(cli->inbuf,'\0',smb_size);
1129 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1131 CVAL(cli->outbuf,smb_com) = SMBmkdir;
1132 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1133 cli_setup_packet(cli);
1135 p = smb_buf(cli->outbuf);
1138 unix_to_dos(p,True);
1141 if (!cli_receive_smb(cli)) {
1145 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1152 /****************************************************************************
1154 ****************************************************************************/
1155 BOOL cli_rmdir(struct cli_state *cli, char *dname)
1159 memset(cli->outbuf,'\0',smb_size);
1160 memset(cli->inbuf,'\0',smb_size);
1162 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1164 CVAL(cli->outbuf,smb_com) = SMBrmdir;
1165 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1166 cli_setup_packet(cli);
1168 p = smb_buf(cli->outbuf);
1171 unix_to_dos(p,True);
1174 if (!cli_receive_smb(cli)) {
1178 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1187 /****************************************************************************
1189 ****************************************************************************/
1190 int cli_nt_create(struct cli_state *cli, char *fname)
1194 memset(cli->outbuf,'\0',smb_size);
1195 memset(cli->inbuf,'\0',smb_size);
1197 set_message(cli->outbuf,24,1 + strlen(fname),True);
1199 CVAL(cli->outbuf,smb_com) = SMBntcreateX;
1200 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1201 cli_setup_packet(cli);
1203 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1204 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0x06);
1205 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
1206 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, 0x2019f);
1207 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0);
1208 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03);
1209 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01);
1210 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0);
1211 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
1212 SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname));
1214 p = smb_buf(cli->outbuf);
1216 unix_to_dos(p,True);
1217 p = skip_string(p,1);
1220 if (!cli_receive_smb(cli)) {
1224 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1228 return SVAL(cli->inbuf,smb_vwv2 + 1);
1232 /****************************************************************************
1234 WARNING: if you open with O_WRONLY then getattrE won't work!
1235 ****************************************************************************/
1236 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
1240 unsigned accessmode=0;
1242 if (flags & O_CREAT)
1244 if (!(flags & O_EXCL)) {
1245 if (flags & O_TRUNC)
1251 accessmode = (share_mode<<4);
1253 if ((flags & O_ACCMODE) == O_RDWR) {
1255 } else if ((flags & O_ACCMODE) == O_WRONLY) {
1260 if ((flags & O_SYNC) == O_SYNC) {
1261 accessmode |= (1<<14);
1265 if (share_mode == DENY_FCB) {
1269 memset(cli->outbuf,'\0',smb_size);
1270 memset(cli->inbuf,'\0',smb_size);
1272 set_message(cli->outbuf,15,1 + strlen(fname),True);
1274 CVAL(cli->outbuf,smb_com) = SMBopenX;
1275 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1276 cli_setup_packet(cli);
1278 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1279 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1280 SSVAL(cli->outbuf,smb_vwv3,accessmode);
1281 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1282 SSVAL(cli->outbuf,smb_vwv5,0);
1283 SSVAL(cli->outbuf,smb_vwv8,openfn);
1285 if (cli->use_oplocks) {
1286 /* if using oplocks then ask for a batch oplock via
1287 core and extended methods */
1288 CVAL(cli->outbuf,smb_flg) |=
1289 FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
1290 SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
1293 p = smb_buf(cli->outbuf);
1295 unix_to_dos(p,True);
1296 p = skip_string(p,1);
1299 if (!cli_receive_smb(cli)) {
1303 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1307 return SVAL(cli->inbuf,smb_vwv2);
1313 /****************************************************************************
1315 ****************************************************************************/
1316 BOOL cli_close(struct cli_state *cli, int fnum)
1318 memset(cli->outbuf,'\0',smb_size);
1319 memset(cli->inbuf,'\0',smb_size);
1321 set_message(cli->outbuf,3,0,True);
1323 CVAL(cli->outbuf,smb_com) = SMBclose;
1324 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1325 cli_setup_packet(cli);
1327 SSVAL(cli->outbuf,smb_vwv0,fnum);
1328 SIVALS(cli->outbuf,smb_vwv1,-1);
1331 if (!cli_receive_smb(cli)) {
1335 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1343 /****************************************************************************
1345 ****************************************************************************/
1346 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1349 int saved_timeout = cli->timeout;
1351 memset(cli->outbuf,'\0',smb_size);
1352 memset(cli->inbuf,'\0', smb_size);
1354 set_message(cli->outbuf,8,10,True);
1356 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1357 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1358 cli_setup_packet(cli);
1360 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1361 SSVAL(cli->outbuf,smb_vwv2,fnum);
1362 CVAL(cli->outbuf,smb_vwv3) = 0;
1363 SIVALS(cli->outbuf, smb_vwv4, timeout);
1364 SSVAL(cli->outbuf,smb_vwv6,0);
1365 SSVAL(cli->outbuf,smb_vwv7,1);
1367 p = smb_buf(cli->outbuf);
1368 SSVAL(p, 0, cli->pid);
1369 SIVAL(p, 2, offset);
1373 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout;
1375 if (!cli_receive_smb(cli)) {
1376 cli->timeout = saved_timeout;
1380 cli->timeout = saved_timeout;
1382 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1389 /****************************************************************************
1391 ****************************************************************************/
1392 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1396 memset(cli->outbuf,'\0',smb_size);
1397 memset(cli->inbuf,'\0',smb_size);
1399 set_message(cli->outbuf,8,10,True);
1401 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1402 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1403 cli_setup_packet(cli);
1405 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1406 SSVAL(cli->outbuf,smb_vwv2,fnum);
1407 CVAL(cli->outbuf,smb_vwv3) = 0;
1408 SIVALS(cli->outbuf, smb_vwv4, timeout);
1409 SSVAL(cli->outbuf,smb_vwv6,1);
1410 SSVAL(cli->outbuf,smb_vwv7,0);
1412 p = smb_buf(cli->outbuf);
1413 SSVAL(p, 0, cli->pid);
1414 SIVAL(p, 2, offset);
1418 if (!cli_receive_smb(cli)) {
1422 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1431 /****************************************************************************
1432 issue a single SMBread and don't wait for a reply
1433 ****************************************************************************/
1434 static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
1437 memset(cli->outbuf,'\0',smb_size);
1438 memset(cli->inbuf,'\0',smb_size);
1440 set_message(cli->outbuf,10,0,True);
1442 CVAL(cli->outbuf,smb_com) = SMBreadX;
1443 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1444 cli_setup_packet(cli);
1446 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1447 SSVAL(cli->outbuf,smb_vwv2,fnum);
1448 SIVAL(cli->outbuf,smb_vwv3,offset);
1449 SSVAL(cli->outbuf,smb_vwv5,size);
1450 SSVAL(cli->outbuf,smb_vwv6,size);
1451 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1456 /****************************************************************************
1458 ****************************************************************************/
1459 size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
1466 * There is a problem in this code when mpx is more than one.
1467 * for some reason files can get corrupted when being read.
1468 * Until we understand this fully I am serializing reads (one
1469 * read/one reply) for now. JRA.
1472 int mpx = MAX(cli->max_mux-1, 1);
1476 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1478 int blocks = (size + (block-1)) / block;
1480 if (size == 0) return 0;
1482 while (received < blocks) {
1485 while (issued - received < mpx && issued < blocks) {
1486 int size1 = MIN(block, size-issued*block);
1487 cli_issue_read(cli, fnum, offset+issued*block, size1, issued);
1491 if (!cli_receive_smb(cli)) {
1496 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1497 size2 = SVAL(cli->inbuf, smb_vwv5);
1499 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1500 blocks = MIN(blocks, mid-1);
1505 blocks = MIN(blocks, mid-1);
1506 /* this distinguishes EOF from an error */
1507 total = MAX(total, 0);
1511 if (size2 > block) {
1512 DEBUG(0,("server returned more than we wanted!\n"));
1515 if (mid >= issued) {
1516 DEBUG(0,("invalid mid from server!\n"));
1519 p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
1521 memcpy(buf+mid*block, p, size2);
1523 total = MAX(total, mid*block + size2);
1526 while (received < issued) {
1527 cli_receive_smb(cli);
1535 /****************************************************************************
1536 issue a single SMBwrite and don't wait for a reply
1537 ****************************************************************************/
1538 static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf,
1543 memset(cli->outbuf,'\0',smb_size);
1544 memset(cli->inbuf,'\0',smb_size);
1546 set_message(cli->outbuf,12,size,True);
1548 CVAL(cli->outbuf,smb_com) = SMBwriteX;
1549 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1550 cli_setup_packet(cli);
1552 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1553 SSVAL(cli->outbuf,smb_vwv2,fnum);
1555 SIVAL(cli->outbuf,smb_vwv3,offset);
1556 SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0);
1557 SSVAL(cli->outbuf,smb_vwv7,mode);
1559 SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0);
1560 SSVAL(cli->outbuf,smb_vwv10,size);
1561 SSVAL(cli->outbuf,smb_vwv11,
1562 smb_buf(cli->outbuf) - smb_base(cli->outbuf));
1564 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
1565 memcpy(p, buf, size);
1567 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1569 show_msg(cli->outbuf);
1573 /****************************************************************************
1575 write_mode: 0x0001 disallow write cacheing
1576 0x0002 return bytes remaining
1577 0x0004 use raw named pipe protocol
1578 0x0008 start of message mode named pipe protocol
1579 ****************************************************************************/
1580 ssize_t cli_write(struct cli_state *cli,
1581 int fnum, uint16 write_mode,
1582 char *buf, off_t offset, size_t size)
1587 int mpx = MAX(cli->max_mux-1, 1);
1588 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1589 int blocks = (size + (block-1)) / block;
1591 while (received < blocks) {
1593 while ((issued - received < mpx) && (issued < blocks))
1595 int bsent = issued * block;
1596 int size1 = MIN(block, size - bsent);
1598 cli_issue_write(cli, fnum, offset + bsent,
1605 if (!cli_receive_smb(cli))
1612 if (CVAL(cli->inbuf,smb_rcls) != 0)
1617 bwritten += SVAL(cli->inbuf, smb_vwv2);
1620 while (received < issued && cli_receive_smb(cli))
1629 /****************************************************************************
1630 write to a file using a SMBwrite and not bypassing 0 byte writes
1631 ****************************************************************************/
1632 ssize_t cli_smbwrite(struct cli_state *cli,
1633 int fnum, char *buf, off_t offset, size_t size1)
1639 size_t size = MIN(size1, cli->max_xmit - 48);
1641 memset(cli->outbuf,'\0',smb_size);
1642 memset(cli->inbuf,'\0',smb_size);
1644 set_message(cli->outbuf,5, 3 + size,True);
1646 CVAL(cli->outbuf,smb_com) = SMBwrite;
1647 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1648 cli_setup_packet(cli);
1650 SSVAL(cli->outbuf,smb_vwv0,fnum);
1651 SSVAL(cli->outbuf,smb_vwv1,size);
1652 SIVAL(cli->outbuf,smb_vwv2,offset);
1653 SSVAL(cli->outbuf,smb_vwv4,0);
1655 p = smb_buf(cli->outbuf);
1658 memcpy(p+2, buf, size);
1661 if (!cli_receive_smb(cli)) {
1665 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1669 size = SVAL(cli->inbuf,smb_vwv0);
1670 if (size == 0) break;
1680 /****************************************************************************
1681 do a SMBgetattrE call
1682 ****************************************************************************/
1683 BOOL cli_getattrE(struct cli_state *cli, int fd,
1684 uint16 *attr, size_t *size,
1685 time_t *c_time, time_t *a_time, time_t *m_time)
1687 memset(cli->outbuf,'\0',smb_size);
1688 memset(cli->inbuf,'\0',smb_size);
1690 set_message(cli->outbuf,1,0,True);
1692 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
1693 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1694 cli_setup_packet(cli);
1696 SSVAL(cli->outbuf,smb_vwv0,fd);
1699 if (!cli_receive_smb(cli)) {
1703 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1708 *size = IVAL(cli->inbuf, smb_vwv6);
1712 *attr = SVAL(cli->inbuf,smb_vwv10);
1716 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
1720 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
1724 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
1731 /****************************************************************************
1733 ****************************************************************************/
1734 BOOL cli_getatr(struct cli_state *cli, char *fname,
1735 uint16 *attr, size_t *size, time_t *t)
1739 memset(cli->outbuf,'\0',smb_size);
1740 memset(cli->inbuf,'\0',smb_size);
1742 set_message(cli->outbuf,0,strlen(fname)+2,True);
1744 CVAL(cli->outbuf,smb_com) = SMBgetatr;
1745 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1746 cli_setup_packet(cli);
1748 p = smb_buf(cli->outbuf);
1750 pstrcpy(p+1, fname);
1751 unix_to_dos(p+1,True);
1754 if (!cli_receive_smb(cli)) {
1758 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1763 *size = IVAL(cli->inbuf, smb_vwv3);
1767 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1771 *attr = SVAL(cli->inbuf,smb_vwv0);
1779 /****************************************************************************
1781 ****************************************************************************/
1782 BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
1786 memset(cli->outbuf,'\0',smb_size);
1787 memset(cli->inbuf,'\0',smb_size);
1789 set_message(cli->outbuf,8,strlen(fname)+4,True);
1791 CVAL(cli->outbuf,smb_com) = SMBsetatr;
1792 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1793 cli_setup_packet(cli);
1795 SSVAL(cli->outbuf,smb_vwv0, attr);
1796 put_dos_date3(cli->outbuf,smb_vwv1, t);
1798 p = smb_buf(cli->outbuf);
1800 pstrcpy(p+1, fname);
1801 unix_to_dos(p+1,True);
1802 p = skip_string(p,1);
1806 if (!cli_receive_smb(cli)) {
1810 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1817 /****************************************************************************
1818 send a qpathinfo call
1819 ****************************************************************************/
1820 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
1821 time_t *c_time, time_t *a_time, time_t *m_time,
1822 size_t *size, uint16 *mode)
1826 uint16 setup = TRANSACT2_QPATHINFO;
1828 char *rparam=NULL, *rdata=NULL;
1831 time_t (*date_fn)(void *);
1833 param_len = strlen(fname) + 7;
1835 memset(param, 0, param_len);
1836 SSVAL(param, 0, SMB_INFO_STANDARD);
1837 pstrcpy(¶m[6], fname);
1838 unix_to_dos(¶m[6],True);
1841 ret = (cli_send_trans(cli, SMBtrans2,
1842 NULL, 0, /* Name, length */
1843 -1, 0, /* fid, flags */
1844 &setup, 1, 0, /* setup, length, max */
1845 param, param_len, 10, /* param, length, max */
1846 NULL, data_len, cli->max_xmit /* data, length, max */
1848 cli_receive_trans(cli, SMBtrans2,
1849 &rparam, ¶m_len,
1850 &rdata, &data_len));
1852 /* we need to work around a Win95 bug - sometimes
1853 it gives ERRSRV/ERRerror temprarily */
1856 cli_error(cli, &eclass, &ecode, NULL);
1857 if (eclass != ERRSRV || ecode != ERRerror) break;
1860 } while (count-- && ret==False);
1862 if (!ret || !rdata || data_len < 22) {
1867 date_fn = make_unix_date;
1869 date_fn = make_unix_date2;
1873 *c_time = date_fn(rdata+0);
1876 *a_time = date_fn(rdata+4);
1879 *m_time = date_fn(rdata+8);
1882 *size = IVAL(rdata, 12);
1885 *mode = SVAL(rdata,l1_attrFile);
1888 if (rdata) free(rdata);
1889 if (rparam) free(rparam);
1893 /****************************************************************************
1894 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1895 ****************************************************************************/
1896 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
1897 time_t *c_time, time_t *a_time, time_t *m_time,
1898 time_t *w_time, size_t *size, uint16 *mode,
1903 uint16 setup = TRANSACT2_QPATHINFO;
1905 char *rparam=NULL, *rdata=NULL;
1907 param_len = strlen(fname) + 7;
1909 memset(param, 0, param_len);
1910 SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1911 pstrcpy(¶m[6], fname);
1912 unix_to_dos(¶m[6],True);
1914 if (!cli_send_trans(cli, SMBtrans2,
1915 NULL, 0, /* name, length */
1916 -1, 0, /* fid, flags */
1917 &setup, 1, 0, /* setup, length, max */
1918 param, param_len, 10, /* param, length, max */
1919 NULL, data_len, cli->max_xmit /* data, length, max */
1924 if (!cli_receive_trans(cli, SMBtrans2,
1925 &rparam, ¶m_len,
1926 &rdata, &data_len)) {
1930 if (!rdata || data_len < 22) {
1935 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1938 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1941 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1944 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1947 *mode = SVAL(rdata, 32);
1950 *size = IVAL(rdata, 48);
1953 *ino = IVAL(rdata, 64);
1956 if (rdata) free(rdata);
1957 if (rparam) free(rparam);
1962 /****************************************************************************
1963 send a qfileinfo call
1964 ****************************************************************************/
1965 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
1966 uint16 *mode, size_t *size,
1967 time_t *c_time, time_t *a_time, time_t *m_time,
1968 time_t *w_time, SMB_INO_T *ino)
1972 uint16 setup = TRANSACT2_QFILEINFO;
1974 char *rparam=NULL, *rdata=NULL;
1976 /* if its a win95 server then fail this - win95 totally screws it
1978 if (cli->win95) return False;
1982 memset(param, 0, param_len);
1983 SSVAL(param, 0, fnum);
1984 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
1986 if (!cli_send_trans(cli, SMBtrans2,
1987 NULL, 0, /* name, length */
1988 -1, 0, /* fid, flags */
1989 &setup, 1, 0, /* setup, length, max */
1990 param, param_len, 2, /* param, length, max */
1991 NULL, data_len, cli->max_xmit /* data, length, max */
1996 if (!cli_receive_trans(cli, SMBtrans2,
1997 &rparam, ¶m_len,
1998 &rdata, &data_len)) {
2002 if (!rdata || data_len < 68) {
2007 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
2010 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
2013 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
2016 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
2019 *mode = SVAL(rdata, 32);
2022 *size = IVAL(rdata, 48);
2025 *ino = IVAL(rdata, 64);
2028 if (rdata) free(rdata);
2029 if (rparam) free(rparam);
2034 /****************************************************************************
2035 interpret a long filename structure - this is mostly guesses at the moment
2036 The length of the structure is returned
2037 The structure of a long filename depends on the info level. 260 is used
2038 by NT and 2 is used by OS/2
2039 ****************************************************************************/
2040 static int interpret_long_filename(int level,char *p,file_info *finfo)
2042 extern file_info def_finfo;
2045 memcpy(finfo,&def_finfo,sizeof(*finfo));
2049 case 1: /* OS/2 understands this */
2051 /* these dates are converted to GMT by make_unix_date */
2052 finfo->ctime = make_unix_date2(p+4);
2053 finfo->atime = make_unix_date2(p+8);
2054 finfo->mtime = make_unix_date2(p+12);
2055 finfo->size = IVAL(p,16);
2056 finfo->mode = CVAL(p,24);
2057 pstrcpy(finfo->name,p+27);
2058 dos_to_unix(finfo->name,True);
2060 return(28 + CVAL(p,26));
2062 case 2: /* this is what OS/2 uses mostly */
2064 /* these dates are converted to GMT by make_unix_date */
2065 finfo->ctime = make_unix_date2(p+4);
2066 finfo->atime = make_unix_date2(p+8);
2067 finfo->mtime = make_unix_date2(p+12);
2068 finfo->size = IVAL(p,16);
2069 finfo->mode = CVAL(p,24);
2070 pstrcpy(finfo->name,p+31);
2071 dos_to_unix(finfo->name,True);
2073 return(32 + CVAL(p,30));
2075 /* levels 3 and 4 are untested */
2078 /* these dates are probably like the other ones */
2079 finfo->ctime = make_unix_date2(p+8);
2080 finfo->atime = make_unix_date2(p+12);
2081 finfo->mtime = make_unix_date2(p+16);
2082 finfo->size = IVAL(p,20);
2083 finfo->mode = CVAL(p,28);
2084 pstrcpy(finfo->name,p+33);
2085 dos_to_unix(finfo->name,True);
2087 return(SVAL(p,4)+4);
2091 /* these dates are probably like the other ones */
2092 finfo->ctime = make_unix_date2(p+8);
2093 finfo->atime = make_unix_date2(p+12);
2094 finfo->mtime = make_unix_date2(p+16);
2095 finfo->size = IVAL(p,20);
2096 finfo->mode = CVAL(p,28);
2097 pstrcpy(finfo->name,p+37);
2098 dos_to_unix(finfo->name,True);
2100 return(SVAL(p,4)+4);
2102 case 260: /* NT uses this, but also accepts 2 */
2104 int ret = SVAL(p,0);
2106 p += 4; /* next entry offset */
2107 p += 4; /* fileindex */
2109 /* these dates appear to arrive in a
2110 weird way. It seems to be localtime
2111 plus the serverzone given in the
2112 initial connect. This is GMT when
2113 DST is not in effect and one hour
2114 from GMT otherwise. Can this really
2117 I suppose this could be called
2118 kludge-GMT. Is is the GMT you get
2119 by using the current DST setting on
2120 a different localtime. It will be
2121 cheap to calculate, I suppose, as
2122 no DST tables will be needed */
2124 finfo->ctime = interpret_long_date(p); p += 8;
2125 finfo->atime = interpret_long_date(p); p += 8;
2126 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
2127 finfo->size = IVAL(p,0); p += 8;
2128 p += 8; /* alloc size */
2129 finfo->mode = CVAL(p,0); p += 4;
2130 namelen = IVAL(p,0); p += 4;
2131 p += 4; /* EA size */
2132 p += 2; /* short name len? */
2133 p += 24; /* short name? */
2134 StrnCpy(finfo->name,p,MIN(sizeof(finfo->name)-1,namelen));
2135 dos_to_unix(finfo->name,True);
2141 DEBUG(1,("Unknown long filename format %d\n",level));
2146 /****************************************************************************
2147 do a directory listing, calling fn on each file found
2148 ****************************************************************************/
2149 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
2150 void (*fn)(file_info *, const char *))
2152 int max_matches = 512;
2153 /* NT uses 260, OS/2 uses 2. Both accept 1. */
2154 int info_level = cli->protocol<PROTOCOL_NT1?1:260;
2159 char *dirlist = NULL;
2160 int dirlist_len = 0;
2161 int total_received = -1;
2163 int ff_searchcount=0;
2166 int ff_dir_handle=0;
2168 char *rparam=NULL, *rdata=NULL;
2169 int param_len, data_len;
2175 unix_to_dos(mask,True);
2177 while (ff_eos == 0) {
2179 if (loop_count > 200) {
2180 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
2184 param_len = 12+strlen(mask)+1;
2187 setup = TRANSACT2_FINDFIRST;
2188 SSVAL(param,0,attribute); /* attribute */
2189 SSVAL(param,2,max_matches); /* max count */
2190 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
2191 SSVAL(param,6,info_level);
2193 pstrcpy(param+12,mask);
2195 setup = TRANSACT2_FINDNEXT;
2196 SSVAL(param,0,ff_dir_handle);
2197 SSVAL(param,2,max_matches); /* max count */
2198 SSVAL(param,4,info_level);
2199 SIVAL(param,6,0); /* ff_resume_key */
2200 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
2201 pstrcpy(param+12,mask);
2203 DEBUG(5,("hand=0x%X ff_lastname=%d mask=%s\n",
2204 ff_dir_handle,ff_lastname,mask));
2207 if (!cli_send_trans(cli, SMBtrans2,
2208 NULL, 0, /* Name, length */
2209 -1, 0, /* fid, flags */
2210 &setup, 1, 0, /* setup, length, max */
2211 param, param_len, 10, /* param, length, max */
2213 cli->max_xmit /* data, length, max */
2218 if (!cli_receive_trans(cli, SMBtrans2,
2219 &rparam, ¶m_len,
2220 &rdata, &data_len)) {
2221 /* we need to work around a Win95 bug - sometimes
2222 it gives ERRSRV/ERRerror temprarily */
2225 cli_error(cli, &eclass, &ecode, NULL);
2226 if (eclass != ERRSRV || ecode != ERRerror) break;
2231 if (total_received == -1) total_received = 0;
2233 /* parse out some important return info */
2236 ff_dir_handle = SVAL(p,0);
2237 ff_searchcount = SVAL(p,2);
2239 ff_lastname = SVAL(p,8);
2241 ff_searchcount = SVAL(p,0);
2243 ff_lastname = SVAL(p,6);
2246 if (ff_searchcount == 0)
2249 /* point to the data bytes */
2252 /* we might need the lastname for continuations */
2253 if (ff_lastname > 0) {
2257 StrnCpy(mask,p+ff_lastname,
2258 MIN(sizeof(mask)-1,data_len-ff_lastname));
2261 pstrcpy(mask,p + ff_lastname + 1);
2268 dos_to_unix(mask, True);
2270 /* and add them to the dirlist pool */
2271 dirlist = Realloc(dirlist,dirlist_len + data_len);
2274 DEBUG(0,("Failed to expand dirlist\n"));
2278 /* put in a length for the last entry, to ensure we can chain entries
2279 into the next packet */
2280 for (p2=p,i=0;i<(ff_searchcount-1);i++)
2281 p2 += interpret_long_filename(info_level,p2,NULL);
2282 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
2284 /* grab the data for later use */
2285 memcpy(dirlist+dirlist_len,p,data_len);
2286 dirlist_len += data_len;
2288 total_received += ff_searchcount;
2290 if (rdata) free(rdata); rdata = NULL;
2291 if (rparam) free(rparam); rparam = NULL;
2293 DEBUG(3,("received %d entries (eos=%d)\n",
2294 ff_searchcount,ff_eos));
2296 if (ff_searchcount > 0) loop_count = 0;
2301 for (p=dirlist,i=0;i<total_received;i++) {
2302 p += interpret_long_filename(info_level,p,&finfo);
2306 /* free up the dirlist buffer */
2307 if (dirlist) free(dirlist);
2308 return(total_received);
2312 /****************************************************************************
2313 Send a SamOEMChangePassword command
2314 ****************************************************************************/
2316 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
2317 const char *old_password)
2319 char param[16+sizeof(fstring)];
2322 fstring upper_case_old_pw;
2323 fstring upper_case_new_pw;
2324 unsigned char old_pw_hash[16];
2325 unsigned char new_pw_hash[16];
2328 char *rparam = NULL;
2331 pstring dos_new_password;
2333 if (strlen(user) >= sizeof(fstring)-1) {
2334 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
2338 SSVAL(p,0,214); /* SamOEMChangePassword command. */
2341 p = skip_string(p,1);
2342 pstrcpy(p, "B516B16");
2343 p = skip_string(p,1);
2345 p = skip_string(p,1);
2349 param_len = PTR_DIFF(p,param);
2352 * Get the Lanman hash of the old password, we
2353 * use this as the key to make_oem_passwd_hash().
2355 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
2356 fstrcpy(upper_case_old_pw, old_password);
2357 unix_to_dos(upper_case_old_pw,True);
2358 strupper(upper_case_old_pw);
2359 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
2361 pstrcpy(dos_new_password, new_password);
2362 unix_to_dos(dos_new_password, True);
2364 if (!make_oem_passwd_hash( data, dos_new_password, old_pw_hash, False))
2368 * Now place the old password hash in the data.
2370 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
2371 fstrcpy(upper_case_new_pw, new_password);
2372 unix_to_dos(upper_case_new_pw,True);
2373 strupper(upper_case_new_pw);
2375 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
2377 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
2381 if (cli_send_trans(cli,SMBtrans,
2382 PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */
2383 0,0, /* fid, flags */
2384 NULL,0,0, /* setup, length, max */
2385 param,param_len,2, /* param, length, max */
2386 data,data_len,0 /* data, length, max */
2388 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
2393 if (cli_receive_trans(cli,SMBtrans,
2397 cli->rap_error = SVAL(rparam,0);
2405 return (cli->rap_error == 0);
2408 /****************************************************************************
2409 send a negprot command
2410 ****************************************************************************/
2411 BOOL cli_negprot(struct cli_state *cli)
2417 memset(cli->outbuf,'\0',smb_size);
2419 /* setup the protocol strings */
2420 for (plength=0,numprots=0;
2421 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2423 plength += strlen(prots[numprots].name)+2;
2425 set_message(cli->outbuf,0,plength,True);
2427 p = smb_buf(cli->outbuf);
2429 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2432 pstrcpy(p,prots[numprots].name);
2433 unix_to_dos(p,True);
2437 CVAL(cli->outbuf,smb_com) = SMBnegprot;
2438 cli_setup_packet(cli);
2440 CVAL(smb_buf(cli->outbuf),0) = 2;
2443 if (!cli_receive_smb(cli))
2446 show_msg(cli->inbuf);
2448 if (CVAL(cli->inbuf,smb_rcls) != 0 ||
2449 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
2453 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
2456 if (cli->protocol >= PROTOCOL_NT1) {
2458 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
2459 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
2460 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
2461 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
2462 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
2463 cli->serverzone *= 60;
2464 /* this time arrives in real GMT */
2465 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
2466 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2467 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
2468 if (cli->capabilities & 1) {
2469 cli->readbraw_supported = True;
2470 cli->writebraw_supported = True;
2472 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2473 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
2474 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
2475 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
2476 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
2477 cli->serverzone *= 60;
2478 /* this time is converted to GMT by make_unix_date */
2479 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
2480 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
2481 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
2482 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2484 /* the old core protocol */
2486 cli->serverzone = TimeDiff(time(NULL));
2489 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2495 /****************************************************************************
2496 send a session request. see rfc1002.txt 4.3 and 4.3.2
2497 ****************************************************************************/
2498 BOOL cli_session_request(struct cli_state *cli,
2499 struct nmb_name *calling, struct nmb_name *called)
2503 /* send a session request (RFC 1002) */
2505 memcpy(&(cli->calling), calling, sizeof(*calling));
2506 memcpy(&(cli->called ), called , sizeof(*called ));
2508 /* put in the destination name */
2509 p = cli->outbuf+len;
2510 name_mangle(cli->called .name, p, cli->called .name_type);
2514 p = cli->outbuf+len;
2515 name_mangle(cli->calling.name, p, cli->calling.name_type);
2518 /* setup the packet length */
2519 _smb_setlen(cli->outbuf,len);
2520 CVAL(cli->outbuf,0) = 0x81;
2524 #endif /* WITH_SSL */
2527 DEBUG(5,("Sent session request\n"));
2529 if (!cli_receive_smb(cli))
2532 if (CVAL(cli->inbuf,0) == 0x84) {
2533 /* C. Hoch 9/14/95 Start */
2534 /* For information, here is the response structure.
2535 * We do the byte-twiddling to for portability.
2536 struct RetargetResponse{
2538 unsigned char flags;
2544 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2545 /* SESSION RETARGET */
2546 putip((char *)&cli->dest_ip,cli->inbuf+4);
2549 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
2553 DEBUG(3,("Retargeted\n"));
2555 set_socket_options(cli->fd,user_socket_options);
2558 return cli_session_request(cli, calling, called);
2559 } /* C. Hoch 9/14/95 End */
2562 if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
2563 if (!sslutil_fd_is_ssl(cli->fd)){
2564 if (sslutil_connect(cli->fd) == 0)
2568 #endif /* WITH_SSL */
2570 if (CVAL(cli->inbuf,0) != 0x82) {
2571 /* This is the wrong place to put the error... JRA. */
2572 cli->rap_error = CVAL(cli->inbuf,4);
2579 /****************************************************************************
2580 open the client sockets
2581 ****************************************************************************/
2582 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
2584 extern struct in_addr ipzero;
2586 fstrcpy(cli->desthost, host);
2588 if (!ip || ip_equal(*ip, ipzero)) {
2589 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
2592 if (ip) *ip = cli->dest_ip;
2597 if (cli->port == 0) cli->port = 139; /* Set to default */
2599 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2600 cli->port, cli->timeout);
2604 set_socket_options(cli->fd,user_socket_options);
2610 /****************************************************************************
2611 initialise a client structure
2612 ****************************************************************************/
2613 struct cli_state *cli_initialise(struct cli_state *cli)
2616 cli = (struct cli_state *)malloc(sizeof(*cli));
2622 if (cli->initialised) {
2631 cli->pid = (uint16)getpid();
2633 cli->vuid = UID_FIELD_INVALID;
2634 cli->protocol = PROTOCOL_NT1;
2635 cli->timeout = 20000; /* Timeout is in milliseconds. */
2636 cli->bufsize = CLI_BUFFER_SIZE+4;
2637 cli->max_xmit = cli->bufsize;
2638 cli->outbuf = (char *)malloc(cli->bufsize);
2639 cli->inbuf = (char *)malloc(cli->bufsize);
2640 if (!cli->outbuf || !cli->inbuf)
2645 memset(cli->outbuf, '\0', cli->bufsize);
2646 memset(cli->inbuf, '\0', cli->bufsize);
2648 cli->initialised = 1;
2653 /****************************************************************************
2654 shutdown a client structure
2655 ****************************************************************************/
2656 void cli_shutdown(struct cli_state *cli)
2668 sslutil_disconnect(cli->fd);
2669 #endif /* WITH_SSL */
2672 memset(cli, 0, sizeof(*cli));
2676 /****************************************************************************
2677 return error codes for the last packet
2678 returns 0 if there was no error and the best approx of a unix errno
2681 for 32 bit "warnings", a return code of 0 is expected.
2683 ****************************************************************************/
2684 int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num, uint32 *nt_rpc_error)
2686 int flgs2 = SVAL(cli->inbuf,smb_flg2);
2690 if (eclass) *eclass = 0;
2692 if (nt_rpc_error) *nt_rpc_error = cli->nt_error;
2694 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
2695 /* 32 bit error codes detected */
2696 uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
2697 if (num) *num = nt_err;
2698 DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
2699 if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0;
2701 switch (nt_err & 0xFFFFFF) {
2702 case NT_STATUS_ACCESS_VIOLATION: return EACCES;
2703 case NT_STATUS_NO_SUCH_FILE: return ENOENT;
2704 case NT_STATUS_NO_SUCH_DEVICE: return ENODEV;
2705 case NT_STATUS_INVALID_HANDLE: return EBADF;
2706 case NT_STATUS_NO_MEMORY: return ENOMEM;
2707 case NT_STATUS_ACCESS_DENIED: return EACCES;
2708 case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
2709 case NT_STATUS_SHARING_VIOLATION: return EBUSY;
2710 case NT_STATUS_OBJECT_PATH_INVALID: return ENOTDIR;
2711 case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
2714 /* for all other cases - a default code */
2718 rcls = CVAL(cli->inbuf,smb_rcls);
2719 code = SVAL(cli->inbuf,smb_err);
2720 if (rcls == 0) return 0;
2722 if (eclass) *eclass = rcls;
2723 if (num ) *num = code;
2725 if (rcls == ERRDOS) {
2727 case ERRbadfile: return ENOENT;
2728 case ERRbadpath: return ENOTDIR;
2729 case ERRnoaccess: return EACCES;
2730 case ERRfilexists: return EEXIST;
2731 case ERRrename: return EEXIST;
2732 case ERRbadshare: return EBUSY;
2733 case ERRlock: return EBUSY;
2736 if (rcls == ERRSRV) {
2738 case ERRbadpw: return EPERM;
2739 case ERRaccess: return EACCES;
2740 case ERRnoresource: return ENOMEM;
2741 case ERRinvdevice: return ENODEV;
2742 case ERRinvnetname: return ENODEV;
2745 /* for other cases */
2749 /****************************************************************************
2750 set socket options on a open connection
2751 ****************************************************************************/
2752 void cli_sockopt(struct cli_state *cli, char *options)
2754 set_socket_options(cli->fd, options);
2757 /****************************************************************************
2758 set the PID to use for smb messages. Return the old pid.
2759 ****************************************************************************/
2760 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
2762 uint16 ret = cli->pid;
2767 /****************************************************************************
2768 re-establishes a connection
2769 ****************************************************************************/
2770 BOOL cli_reestablish_connection(struct cli_state *cli)
2772 struct nmb_name calling;
2773 struct nmb_name called;
2777 BOOL do_tcon = False;
2778 int oldfd = cli->fd;
2780 if (!cli->initialised || cli->fd == -1)
2782 DEBUG(3,("cli_reestablish_connection: not connected\n"));
2786 /* copy the parameters necessary to re-establish the connection */
2790 fstrcpy(share, cli->share);
2791 fstrcpy(dev , cli->dev);
2795 memcpy(&called , &(cli->called ), sizeof(called ));
2796 memcpy(&calling, &(cli->calling), sizeof(calling));
2797 fstrcpy(dest_host, cli->full_dest_host_name);
2799 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2800 nmb_namestr(&calling), nmb_namestr(&called),
2801 inet_ntoa(cli->dest_ip),
2802 cli->user_name, cli->domain));
2806 if (cli_establish_connection(cli,
2807 dest_host, &cli->dest_ip,
2809 share, dev, False, do_tcon)) {
2810 if (cli->fd != oldfd) {
2811 if (dup2(cli->fd, oldfd) == oldfd) {
2820 /****************************************************************************
2821 establishes a connection right up to doing tconX, reading in a password.
2822 ****************************************************************************/
2823 BOOL cli_establish_connection(struct cli_state *cli,
2824 char *dest_host, struct in_addr *dest_ip,
2825 struct nmb_name *calling, struct nmb_name *called,
2826 char *service, char *service_type,
2827 BOOL do_shutdown, BOOL do_tcon)
2829 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
2830 nmb_namestr(calling), nmb_namestr(called), inet_ntoa(*dest_ip),
2831 cli->user_name, cli->domain));
2833 /* establish connection */
2835 if ((!cli->initialised))
2842 if (!cli_connect(cli, dest_host, dest_ip))
2844 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
2845 nmb_namestr(calling), inet_ntoa(*dest_ip)));
2850 if (!cli_session_request(cli, calling, called))
2852 DEBUG(1,("failed session request\n"));
2858 if (!cli_negprot(cli))
2860 DEBUG(1,("failed negprot\n"));
2866 if (cli->pwd.cleartext || cli->pwd.null_pwd)
2871 if (cli->pwd.null_pwd)
2873 /* attempt null session */
2879 /* attempt clear-text session */
2880 pwd_get_cleartext(&(cli->pwd), passwd);
2881 pass_len = strlen(passwd);
2884 /* attempt clear-text session */
2885 if (!cli_session_setup(cli, cli->user_name,
2890 DEBUG(1,("failed session setup\n"));
2899 if (!cli_send_tconX(cli, service, service_type,
2900 (char*)passwd, strlen(passwd)))
2902 DEBUG(1,("failed tcon_X\n"));
2913 /* attempt encrypted session */
2914 unsigned char nt_sess_pwd[24];
2915 unsigned char lm_sess_pwd[24];
2917 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
2918 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
2919 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
2921 /* attempt encrypted session */
2922 if (!cli_session_setup(cli, cli->user_name,
2923 (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
2924 (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
2927 DEBUG(1,("failed session setup\n"));
2935 if (!cli_send_tconX(cli, service, service_type,
2936 (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
2938 DEBUG(1,("failed tcon_X\n"));
2953 /****************************************************************************
2955 ****************************************************************************/
2956 int cli_printjob_del(struct cli_state *cli, int job)
2958 char *rparam = NULL;
2961 int rdrcnt,rprcnt, ret = -1;
2964 memset(param,'\0',sizeof(param));
2967 SSVAL(p,0,81); /* DosPrintJobDel() */
2970 p = skip_string(p,1);
2972 p = skip_string(p,1);
2977 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2978 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2979 &rparam, &rprcnt, /* return params, length */
2980 &rdata, &rdrcnt)) { /* return data, length */
2981 ret = SVAL(rparam,0);
2984 if (rparam) free(rparam);
2985 if (rdata) free(rdata);
2991 /****************************************************************************
2992 call fn() on each entry in a print queue
2993 ****************************************************************************/
2994 int cli_print_queue(struct cli_state *cli,
2995 void (*fn)(struct print_job_info *))
2997 char *rparam = NULL;
3005 memset(param,'\0',sizeof(param));
3008 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
3010 pstrcpy(p,"zWrLeh"); /* parameter description? */
3011 p = skip_string(p,1);
3012 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
3013 p = skip_string(p,1);
3014 pstrcpy(p,cli->share); /* name of queue */
3015 p = skip_string(p,1);
3016 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
3017 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
3019 pstrcpy(p,""); /* subformat */
3020 p = skip_string(p,1);
3022 DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
3025 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
3026 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
3027 &rparam, &rprcnt, /* return params, length */
3028 &rdata, &rdrcnt)) { /* return data, length */
3030 result_code = SVAL(rparam,0);
3031 converter = SVAL(rparam,2); /* conversion factor */
3033 if (result_code == 0) {
3034 struct print_job_info job;
3038 for (i = 0; i < SVAL(rparam,4); ++i) {
3040 job.priority = SVAL(p,2);
3042 fix_char_ptr(SVAL(p,4), converter,
3044 job.t = make_unix_date3(p + 12);
3045 job.size = IVAL(p,16);
3046 fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
3055 /* If any parameters or data were returned, free the storage. */
3056 if(rparam) free(rparam);
3057 if(rdata) free(rdata);
3062 /****************************************************************************
3063 check for existance of a dir
3064 ****************************************************************************/
3065 BOOL cli_chkpath(struct cli_state *cli, char *path)
3070 safe_strcpy(path2,path,sizeof(pstring));
3071 trim_string(path2,NULL,"\\");
3072 if (!*path2) *path2 = '\\';
3074 memset(cli->outbuf,'\0',smb_size);
3075 set_message(cli->outbuf,0,4 + strlen(path2),True);
3076 SCVAL(cli->outbuf,smb_com,SMBchkpth);
3077 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3078 cli_setup_packet(cli);
3079 p = smb_buf(cli->outbuf);
3081 safe_strcpy(p,path2,strlen(path2));
3082 unix_to_dos(p,True);
3085 if (!cli_receive_smb(cli)) {
3089 if (cli_error(cli, NULL, NULL, NULL)) return False;
3095 /****************************************************************************
3096 start a message sequence
3097 ****************************************************************************/
3098 BOOL cli_message_start(struct cli_state *cli, char *host, char *username,
3103 /* send a SMBsendstrt command */
3104 memset(cli->outbuf,'\0',smb_size);
3105 set_message(cli->outbuf,0,0,True);
3106 CVAL(cli->outbuf,smb_com) = SMBsendstrt;
3107 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3108 cli_setup_packet(cli);
3110 p = smb_buf(cli->outbuf);
3112 pstrcpy(p,username);
3113 unix_to_dos(p,True);
3114 p = skip_string(p,1);
3117 unix_to_dos(p,True);
3118 p = skip_string(p,1);
3120 set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
3124 if (!cli_receive_smb(cli)) {
3128 if (cli_error(cli, NULL, NULL, NULL)) return False;
3130 *grp = SVAL(cli->inbuf,smb_vwv0);
3136 /****************************************************************************
3138 ****************************************************************************/
3139 BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp)
3143 memset(cli->outbuf,'\0',smb_size);
3144 set_message(cli->outbuf,1,len+3,True);
3145 CVAL(cli->outbuf,smb_com) = SMBsendtxt;
3146 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3147 cli_setup_packet(cli);
3149 SSVAL(cli->outbuf,smb_vwv0,grp);
3151 p = smb_buf(cli->outbuf);
3154 memcpy(p+3,msg,len);
3157 if (!cli_receive_smb(cli)) {
3161 if (cli_error(cli, NULL, NULL, NULL)) return False;
3166 /****************************************************************************
3168 ****************************************************************************/
3169 BOOL cli_message_end(struct cli_state *cli, int grp)
3171 memset(cli->outbuf,'\0',smb_size);
3172 set_message(cli->outbuf,1,0,True);
3173 CVAL(cli->outbuf,smb_com) = SMBsendend;
3174 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3176 SSVAL(cli->outbuf,smb_vwv0,grp);
3178 cli_setup_packet(cli);
3182 if (!cli_receive_smb(cli)) {
3186 if (cli_error(cli, NULL, NULL, NULL)) return False;
3192 /****************************************************************************
3194 ****************************************************************************/
3195 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3197 memset(cli->outbuf,'\0',smb_size);
3198 set_message(cli->outbuf,0,0,True);
3199 CVAL(cli->outbuf,smb_com) = SMBdskattr;
3200 SSVAL(cli->outbuf,smb_tid,cli->cnum);
3201 cli_setup_packet(cli);
3204 if (!cli_receive_smb(cli)) {
3208 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
3209 *total = SVAL(cli->inbuf,smb_vwv0);
3210 *avail = SVAL(cli->inbuf,smb_vwv3);
3215 /****************************************************************************
3216 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
3217 ****************************************************************************/
3219 BOOL attempt_netbios_session_request(struct cli_state *cli, char *srchost, char *desthost,
3220 struct in_addr *pdest_ip)
3222 struct nmb_name calling, called;
3224 make_nmb_name(&calling, srchost, 0x0);
3227 * If the called name is an IP address
3228 * then use *SMBSERVER immediately.
3231 if(is_ipaddress(desthost))
3232 make_nmb_name(&called, "*SMBSERVER", 0x20);
3234 make_nmb_name(&called, desthost, 0x20);
3236 if (!cli_session_request(cli, &calling, &called)) {
3237 struct nmb_name smbservername;
3240 * If the name wasn't *SMBSERVER then
3241 * try with *SMBSERVER if the first name fails.
3246 make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
3248 if (!nmb_name_equal(&called, &smbservername) ||
3249 !cli_initialise(cli) ||
3250 !cli_connect(cli, desthost, pdest_ip) ||
3251 !cli_session_request(cli, &calling, &smbservername)) {
3252 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER.\n",