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
);
80 return cli_smb_errstr(cli
);
83 * Was it an NT error ?
87 char *nt_msg
= get_nt_error_msg(cli
->nt_error
);
90 slprintf(error_message
, sizeof(fstring
) - 1, "NT code %d", cli
->nt_error
);
92 fstrcpy(error_message
, nt_msg
);
98 * Must have been a rap error.
101 slprintf(error_message
, sizeof(error_message
) - 1, "code %d", cli
->rap_error
);
103 for(i
= 0; rap_errmap
[i
].message
!= NULL
; i
++) {
104 if (rap_errmap
[i
].err
== cli
->rap_error
) {
105 fstrcpy( error_message
, rap_errmap
[i
].message
);
110 return error_message
;
113 /****************************************************************************
114 setup basics in a outgoing packet
115 ****************************************************************************/
116 static void cli_setup_packet(struct cli_state
*cli
)
120 SSVAL(cli
->outbuf
,smb_pid
,cli
->pid
);
121 SSVAL(cli
->outbuf
,smb_uid
,cli
->vuid
);
122 SSVAL(cli
->outbuf
,smb_mid
,cli
->mid
);
123 if (cli
->protocol
> PROTOCOL_CORE
) {
124 SCVAL(cli
->outbuf
,smb_flg
,0x8);
125 SSVAL(cli
->outbuf
,smb_flg2
,0x1);
130 /****************************************************************************
131 send a SMB trans or trans2 request
132 ****************************************************************************/
133 static BOOL
cli_send_trans(struct cli_state
*cli
, int trans
,
134 char *name
, int pipe_name_len
,
136 uint16
*setup
, int lsetup
, int msetup
,
137 char *param
, int lparam
, int mparam
,
138 char *data
, int ldata
, int mdata
)
141 int this_ldata
,this_lparam
;
142 int tot_data
=0,tot_param
=0;
143 char *outdata
,*outparam
;
146 this_lparam
= MIN(lparam
,cli
->max_xmit
- (500+lsetup
*2)); /* hack */
147 this_ldata
= MIN(ldata
,cli
->max_xmit
- (500+lsetup
*2+this_lparam
));
149 bzero(cli
->outbuf
,smb_size
);
150 set_message(cli
->outbuf
,14+lsetup
,0,True
);
151 CVAL(cli
->outbuf
,smb_com
) = trans
;
152 SSVAL(cli
->outbuf
,smb_tid
, cli
->cnum
);
153 cli_setup_packet(cli
);
155 outparam
= smb_buf(cli
->outbuf
)+(trans
==SMBtrans
? pipe_name_len
+1 : 3);
156 outdata
= outparam
+this_lparam
;
158 /* primary request */
159 SSVAL(cli
->outbuf
,smb_tpscnt
,lparam
); /* tpscnt */
160 SSVAL(cli
->outbuf
,smb_tdscnt
,ldata
); /* tdscnt */
161 SSVAL(cli
->outbuf
,smb_mprcnt
,mparam
); /* mprcnt */
162 SSVAL(cli
->outbuf
,smb_mdrcnt
,mdata
); /* mdrcnt */
163 SCVAL(cli
->outbuf
,smb_msrcnt
,msetup
); /* msrcnt */
164 SSVAL(cli
->outbuf
,smb_flags
,flags
); /* flags */
165 SIVAL(cli
->outbuf
,smb_timeout
,0); /* timeout */
166 SSVAL(cli
->outbuf
,smb_pscnt
,this_lparam
); /* pscnt */
167 SSVAL(cli
->outbuf
,smb_psoff
,smb_offset(outparam
,cli
->outbuf
)); /* psoff */
168 SSVAL(cli
->outbuf
,smb_dscnt
,this_ldata
); /* dscnt */
169 SSVAL(cli
->outbuf
,smb_dsoff
,smb_offset(outdata
,cli
->outbuf
)); /* dsoff */
170 SCVAL(cli
->outbuf
,smb_suwcnt
,lsetup
); /* suwcnt */
171 for (i
=0;i
<lsetup
;i
++) /* setup[] */
172 SSVAL(cli
->outbuf
,smb_setup
+i
*2,setup
[i
]);
173 p
= smb_buf(cli
->outbuf
);
174 if (trans
==SMBtrans
) {
175 memcpy(p
,name
, pipe_name_len
+ 1); /* name[] */
177 *p
++ = 0; /* put in a null smb_name */
178 *p
++ = 'D'; *p
++ = ' '; /* observed in OS/2 */
180 if (this_lparam
) /* param[] */
181 memcpy(outparam
,param
,this_lparam
);
182 if (this_ldata
) /* data[] */
183 memcpy(outdata
,data
,this_ldata
);
184 set_message(cli
->outbuf
,14+lsetup
, /* wcnt, bcc */
185 PTR_DIFF(outdata
+this_ldata
,smb_buf(cli
->outbuf
)),False
);
187 show_msg(cli
->outbuf
);
188 send_smb(cli
->fd
,cli
->outbuf
);
190 if (this_ldata
< ldata
|| this_lparam
< lparam
) {
191 /* receive interim response */
192 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
) ||
193 CVAL(cli
->inbuf
,smb_rcls
) != 0) {
197 tot_data
= this_ldata
;
198 tot_param
= this_lparam
;
200 while (tot_data
< ldata
|| tot_param
< lparam
) {
201 this_lparam
= MIN(lparam
-tot_param
,cli
->max_xmit
- 500); /* hack */
202 this_ldata
= MIN(ldata
-tot_data
,cli
->max_xmit
- (500+this_lparam
));
204 set_message(cli
->outbuf
,trans
==SMBtrans
?8:9,0,True
);
205 CVAL(cli
->outbuf
,smb_com
) = trans
==SMBtrans
? SMBtranss
: SMBtranss2
;
207 outparam
= smb_buf(cli
->outbuf
);
208 outdata
= outparam
+this_lparam
;
210 /* secondary request */
211 SSVAL(cli
->outbuf
,smb_tpscnt
,lparam
); /* tpscnt */
212 SSVAL(cli
->outbuf
,smb_tdscnt
,ldata
); /* tdscnt */
213 SSVAL(cli
->outbuf
,smb_spscnt
,this_lparam
); /* pscnt */
214 SSVAL(cli
->outbuf
,smb_spsoff
,smb_offset(outparam
,cli
->outbuf
)); /* psoff */
215 SSVAL(cli
->outbuf
,smb_spsdisp
,tot_param
); /* psdisp */
216 SSVAL(cli
->outbuf
,smb_sdscnt
,this_ldata
); /* dscnt */
217 SSVAL(cli
->outbuf
,smb_sdsoff
,smb_offset(outdata
,cli
->outbuf
)); /* dsoff */
218 SSVAL(cli
->outbuf
,smb_sdsdisp
,tot_data
); /* dsdisp */
219 if (trans
==SMBtrans2
)
220 SSVALS(cli
->outbuf
,smb_sfid
,fid
); /* fid */
221 if (this_lparam
) /* param[] */
222 memcpy(outparam
,param
,this_lparam
);
223 if (this_ldata
) /* data[] */
224 memcpy(outdata
,data
,this_ldata
);
225 set_message(cli
->outbuf
,trans
==SMBtrans
?8:9, /* wcnt, bcc */
226 PTR_DIFF(outdata
+this_ldata
,smb_buf(cli
->outbuf
)),False
);
228 show_msg(cli
->outbuf
);
229 send_smb(cli
->fd
,cli
->outbuf
);
231 tot_data
+= this_ldata
;
232 tot_param
+= this_lparam
;
240 /****************************************************************************
241 receive a SMB trans or trans2 response allocating the necessary memory
242 ****************************************************************************/
243 static BOOL
cli_receive_trans(struct cli_state
*cli
,int trans
,
244 char **param
, int *param_len
,
245 char **data
, int *data_len
)
249 int this_data
,this_param
;
251 *data_len
= *param_len
= 0;
253 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
))
256 show_msg(cli
->inbuf
);
259 if (CVAL(cli
->inbuf
,smb_com
) != trans
) {
260 DEBUG(0,("Expected %s response, got command 0x%02x\n",
261 trans
==SMBtrans
?"SMBtrans":"SMBtrans2",
262 CVAL(cli
->inbuf
,smb_com
)));
265 if (CVAL(cli
->inbuf
,smb_rcls
) != 0)
268 /* parse out the lengths */
269 total_data
= SVAL(cli
->inbuf
,smb_tdrcnt
);
270 total_param
= SVAL(cli
->inbuf
,smb_tprcnt
);
273 *data
= Realloc(*data
,total_data
);
274 *param
= Realloc(*param
,total_param
);
277 this_data
= SVAL(cli
->inbuf
,smb_drcnt
);
278 this_param
= SVAL(cli
->inbuf
,smb_prcnt
);
280 if (this_data
+ *data_len
> total_data
||
281 this_param
+ *param_len
> total_param
) {
282 DEBUG(1,("Data overflow in cli_receive_trans\n"));
287 memcpy(*data
+ SVAL(cli
->inbuf
,smb_drdisp
),
288 smb_base(cli
->inbuf
) + SVAL(cli
->inbuf
,smb_droff
),
291 memcpy(*param
+ SVAL(cli
->inbuf
,smb_prdisp
),
292 smb_base(cli
->inbuf
) + SVAL(cli
->inbuf
,smb_proff
),
294 *data_len
+= this_data
;
295 *param_len
+= this_param
;
297 /* parse out the total lengths again - they can shrink! */
298 total_data
= SVAL(cli
->inbuf
,smb_tdrcnt
);
299 total_param
= SVAL(cli
->inbuf
,smb_tprcnt
);
301 if (total_data
<= *data_len
&& total_param
<= *param_len
)
304 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
))
307 show_msg(cli
->inbuf
);
310 if (CVAL(cli
->inbuf
,smb_com
) != trans
) {
311 DEBUG(0,("Expected %s response, got command 0x%02x\n",
312 trans
==SMBtrans
?"SMBtrans":"SMBtrans2",
313 CVAL(cli
->inbuf
,smb_com
)));
316 if (CVAL(cli
->inbuf
,smb_rcls
) != 0)
323 /****************************************************************************
324 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
325 ****************************************************************************/
326 BOOL
cli_api_pipe(struct cli_state
*cli
, char *pipe_name
, int pipe_name_len
,
327 uint16
*setup
, uint32 setup_count
, uint32 max_setup_count
,
328 char *params
, uint32 param_count
, uint32 max_param_count
,
329 char *data
, uint32 data_count
, uint32 max_data_count
,
330 char **rparam
, uint32
*rparam_count
,
331 char **rdata
, uint32
*rdata_count
)
333 if(pipe_name_len
== 0)
334 pipe_name_len
= strlen(pipe_name
);
336 cli_send_trans(cli
, SMBtrans
,
337 pipe_name
, pipe_name_len
,
338 0,0, /* fid, flags */
339 setup
, setup_count
, max_setup_count
,
340 params
, param_count
, max_param_count
,
341 data
, data_count
, max_data_count
);
343 return (cli_receive_trans(cli
, SMBtrans
,
344 rparam
, (int *)rparam_count
,
345 rdata
, (int *)rdata_count
));
348 /****************************************************************************
350 ****************************************************************************/
351 BOOL
cli_api(struct cli_state
*cli
,
352 char *param
, int prcnt
, int mprcnt
,
353 char *data
, int drcnt
, int mdrcnt
,
354 char **rparam
, int *rprcnt
,
355 char **rdata
, int *rdrcnt
)
357 cli_send_trans(cli
,SMBtrans
,
358 PIPE_LANMAN
,strlen(PIPE_LANMAN
), /* Name, length */
359 0,0, /* fid, flags */
360 NULL
,0,0, /* Setup, length, max */
361 param
, prcnt
, mprcnt
, /* Params, length, max */
362 data
, drcnt
, mdrcnt
/* Data, length, max */
365 return (cli_receive_trans(cli
,SMBtrans
,
371 /****************************************************************************
372 perform a NetWkstaUserLogon
373 ****************************************************************************/
374 BOOL
cli_NetWkstaUserLogon(struct cli_state
*cli
,char *user
, char *workstation
)
382 memset(param
, 0, sizeof(param
));
384 /* send a SMBtrans command with api NetWkstaUserLogon */
386 SSVAL(p
,0,132); /* api number */
388 pstrcpy(p
,"OOWb54WrLh");
389 p
= skip_string(p
,1);
390 pstrcpy(p
,"WB21BWDWWDDDDDDDzzzD");
391 p
= skip_string(p
,1);
400 pstrcpy(p
, workstation
);
403 SSVAL(p
, 0, BUFFER_SIZE
);
405 SSVAL(p
, 0, BUFFER_SIZE
);
409 param
, PTR_DIFF(p
,param
),1024, /* param, length, max */
410 NULL
, 0, BUFFER_SIZE
, /* data, length, max */
411 &rparam
, &rprcnt
, /* return params, return size */
412 &rdata
, &rdrcnt
/* return data, return size */
414 cli
->rap_error
= SVAL(rparam
,0);
417 if (cli
->rap_error
== 0) {
418 DEBUG(4,("NetWkstaUserLogon success\n"));
419 cli
->privilages
= SVAL(p
, 24);
420 fstrcpy(cli
->eff_name
,p
+2);
422 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli
->rap_error
));
430 return (cli
->rap_error
== 0);
434 /****************************************************************************
435 call a NetShareEnum - try and browse available connections on a host
436 ****************************************************************************/
437 BOOL
cli_RNetShareEnum(struct cli_state
*cli
, void (*fn
)(char *, uint32
, char *))
446 /* now send a SMBtrans command with api RNetShareEnum */
448 SSVAL(p
,0,0); /* api number */
451 p
= skip_string(p
,1);
453 p
= skip_string(p
,1);
455 SSVAL(p
,2,BUFFER_SIZE
);
459 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
460 NULL
, 0, BUFFER_SIZE
, /* data, length, maxlen */
461 &rparam
, &rprcnt
, /* return params, length */
462 &rdata
, &rdrcnt
)) /* return data, length */
464 int res
= SVAL(rparam
,0);
465 int converter
=SVAL(rparam
,2);
470 count
=SVAL(rparam
,4);
473 for (i
=0;i
<count
;i
++,p
+=20)
476 int type
= SVAL(p
,14);
477 int comment_offset
= IVAL(p
,16) & 0xFFFF;
478 char *cmnt
= comment_offset
?(rdata
+comment_offset
-converter
):"";
479 fn(sname
, type
, cmnt
);
493 /****************************************************************************
494 call a NetServerEnum for the specified workgroup and servertype mask.
495 This function then calls the specified callback function for each name returned.
497 The callback function takes 3 arguments: the machine name, the server type and
499 ****************************************************************************/
500 BOOL
cli_NetServerEnum(struct cli_state
*cli
, char *workgroup
, uint32 stype
,
501 void (*fn
)(char *, uint32
, char *))
511 /* send a SMBtrans command with api NetServerEnum */
513 SSVAL(p
,0,0x68); /* api number */
515 pstrcpy(p
,"WrLehDz");
516 p
= skip_string(p
,1);
518 pstrcpy(p
,"B16BBDz");
520 p
= skip_string(p
,1);
522 SSVAL(p
,2,BUFFER_SIZE
);
527 pstrcpy(p
, workgroup
);
528 p
= skip_string(p
,1);
531 param
, PTR_DIFF(p
,param
), 8, /* params, length, max */
532 NULL
, 0, BUFFER_SIZE
, /* data, length, max */
533 &rparam
, &rprcnt
, /* return params, return size */
534 &rdata
, &rdrcnt
/* return data, return size */
536 int res
= SVAL(rparam
,0);
537 int converter
=SVAL(rparam
,2);
541 count
=SVAL(rparam
,4);
544 for (i
= 0;i
< count
;i
++, p
+= 26) {
546 int comment_offset
= (IVAL(p
,22) & 0xFFFF)-converter
;
547 char *cmnt
= comment_offset
?(rdata
+comment_offset
):"";
548 if (comment_offset
< 0 || comment_offset
> rdrcnt
) continue;
550 stype
= IVAL(p
,18) & ~SV_TYPE_LOCAL_LIST_ONLY
;
552 fn(sname
, stype
, cmnt
);
574 {PROTOCOL_CORE
,"PC NETWORK PROGRAM 1.0"},
575 {PROTOCOL_COREPLUS
,"MICROSOFT NETWORKS 1.03"},
576 {PROTOCOL_LANMAN1
,"MICROSOFT NETWORKS 3.0"},
577 {PROTOCOL_LANMAN1
,"LANMAN1.0"},
578 {PROTOCOL_LANMAN2
,"LM1.2X002"},
579 {PROTOCOL_LANMAN2
,"Samba"},
580 {PROTOCOL_NT1
,"NT LM 0.12"},
581 {PROTOCOL_NT1
,"NT LANMAN 1.0"},
586 /****************************************************************************
588 ****************************************************************************/
589 BOOL
cli_session_setup(struct cli_state
*cli
,
591 char *pass
, int passlen
,
592 char *ntpass
, int ntpasslen
,
598 if (cli
->protocol
< PROTOCOL_LANMAN1
)
601 if (passlen
> sizeof(pword
)-1) {
605 if(((passlen
== 0) || (passlen
== 1)) && (pass
[0] == '\0')) {
606 /* Null session connect. */
609 if ((cli
->sec_mode
& 2) && passlen
!= 24) {
611 SMBencrypt((uchar
*)pass
,(uchar
*)cli
->cryptkey
,(uchar
*)pword
);
613 memcpy(pword
, pass
, passlen
);
617 /* if in share level security then don't send a password now */
618 if (!(cli
->sec_mode
& 1)) {fstrcpy(pword
, "");passlen
=1;}
620 /* send a session setup command */
621 bzero(cli
->outbuf
,smb_size
);
623 if (cli
->protocol
< PROTOCOL_NT1
) {
624 set_message(cli
->outbuf
,10,1 + strlen(user
) + passlen
,True
);
625 CVAL(cli
->outbuf
,smb_com
) = SMBsesssetupX
;
626 cli_setup_packet(cli
);
628 CVAL(cli
->outbuf
,smb_vwv0
) = 0xFF;
629 SSVAL(cli
->outbuf
,smb_vwv2
,cli
->max_xmit
);
630 SSVAL(cli
->outbuf
,smb_vwv3
,2);
631 SSVAL(cli
->outbuf
,smb_vwv4
,1);
632 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
633 SSVAL(cli
->outbuf
,smb_vwv7
,passlen
);
634 p
= smb_buf(cli
->outbuf
);
635 memcpy(p
,pword
,passlen
);
640 set_message(cli
->outbuf
,13,0,True
);
641 CVAL(cli
->outbuf
,smb_com
) = SMBsesssetupX
;
642 cli_setup_packet(cli
);
644 CVAL(cli
->outbuf
,smb_vwv0
) = 0xFF;
645 SSVAL(cli
->outbuf
,smb_vwv2
,BUFFER_SIZE
);
646 SSVAL(cli
->outbuf
,smb_vwv3
,2);
647 SSVAL(cli
->outbuf
,smb_vwv4
,cli
->pid
);
648 SIVAL(cli
->outbuf
,smb_vwv5
,cli
->sesskey
);
649 SSVAL(cli
->outbuf
,smb_vwv7
,passlen
);
650 SSVAL(cli
->outbuf
,smb_vwv8
,ntpasslen
);
651 p
= smb_buf(cli
->outbuf
);
652 memcpy(p
,pword
,passlen
);
653 p
+= SVAL(cli
->outbuf
,smb_vwv7
);
654 memcpy(p
,ntpass
,ntpasslen
);
655 p
+= SVAL(cli
->outbuf
,smb_vwv8
);
658 p
= skip_string(p
,1);
659 pstrcpy(p
,workgroup
);
661 p
= skip_string(p
,1);
662 pstrcpy(p
,"Unix");p
= skip_string(p
,1);
663 pstrcpy(p
,"Samba");p
= skip_string(p
,1);
664 set_message(cli
->outbuf
,13,PTR_DIFF(p
,smb_buf(cli
->outbuf
)),False
);
667 send_smb(cli
->fd
,cli
->outbuf
);
668 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
))
671 show_msg(cli
->inbuf
);
673 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
677 /* use the returned vuid from now on */
678 cli
->vuid
= SVAL(cli
->inbuf
,smb_uid
);
683 /****************************************************************************
685 *****************************************************************************/
687 BOOL
cli_ulogoff(struct cli_state
*cli
)
689 bzero(cli
->outbuf
,smb_size
);
690 set_message(cli
->outbuf
,2,0,True
);
691 CVAL(cli
->outbuf
,smb_com
) = SMBulogoffX
;
692 cli_setup_packet(cli
);
693 SSVAL(cli
->outbuf
,smb_vwv0
,0xFF);
694 SSVAL(cli
->outbuf
,smb_vwv2
,0); /* no additional info */
696 send_smb(cli
->fd
,cli
->outbuf
);
697 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
))
700 return CVAL(cli
->inbuf
,smb_rcls
) == 0;
703 /****************************************************************************
705 ****************************************************************************/
706 BOOL
cli_send_tconX(struct cli_state
*cli
,
707 char *share
, char *dev
, char *pass
, int passlen
)
709 fstring fullshare
, pword
;
711 bzero(cli
->outbuf
,smb_size
);
712 bzero(cli
->inbuf
,smb_size
);
714 if (cli
->sec_mode
& 1) {
719 if ((cli
->sec_mode
& 2) && *pass
&& passlen
!= 24) {
721 SMBencrypt((uchar
*)pass
,(uchar
*)cli
->cryptkey
,(uchar
*)pword
);
723 memcpy(pword
, pass
, passlen
);
726 slprintf(fullshare
, sizeof(fullshare
)-1,
727 "\\\\%s\\%s", cli
->desthost
, share
);
729 set_message(cli
->outbuf
,4,
730 2 + strlen(fullshare
) + passlen
+ strlen(dev
),True
);
731 CVAL(cli
->outbuf
,smb_com
) = SMBtconX
;
732 cli_setup_packet(cli
);
734 SSVAL(cli
->outbuf
,smb_vwv0
,0xFF);
735 SSVAL(cli
->outbuf
,smb_vwv3
,passlen
);
737 p
= smb_buf(cli
->outbuf
);
738 memcpy(p
,pword
,passlen
);
740 fstrcpy(p
,fullshare
);
741 p
= skip_string(p
,1);
744 SCVAL(cli
->inbuf
,smb_rcls
, 1);
746 send_smb(cli
->fd
,cli
->outbuf
);
747 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
))
750 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
754 cli
->cnum
= SVAL(cli
->inbuf
,smb_tid
);
759 /****************************************************************************
760 send a tree disconnect
761 ****************************************************************************/
762 BOOL
cli_tdis(struct cli_state
*cli
)
764 bzero(cli
->outbuf
,smb_size
);
765 set_message(cli
->outbuf
,0,0,True
);
766 CVAL(cli
->outbuf
,smb_com
) = SMBtdis
;
767 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
768 cli_setup_packet(cli
);
770 send_smb(cli
->fd
,cli
->outbuf
);
771 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
))
774 return CVAL(cli
->inbuf
,smb_rcls
) == 0;
778 /****************************************************************************
780 ****************************************************************************/
781 BOOL
cli_mv(struct cli_state
*cli
, char *fname_src
, char *fname_dst
)
785 bzero(cli
->outbuf
,smb_size
);
786 bzero(cli
->inbuf
,smb_size
);
788 set_message(cli
->outbuf
,1, 4 + strlen(fname_src
) + strlen(fname_dst
), True
);
790 CVAL(cli
->outbuf
,smb_com
) = SMBmv
;
791 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
792 cli_setup_packet(cli
);
794 SSVAL(cli
->outbuf
,smb_vwv0
,aSYSTEM
| aHIDDEN
);
796 p
= smb_buf(cli
->outbuf
);
798 pstrcpy(p
,fname_src
);
799 p
= skip_string(p
,1);
801 pstrcpy(p
,fname_dst
);
803 send_smb(cli
->fd
,cli
->outbuf
);
804 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
808 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
816 /****************************************************************************
818 ****************************************************************************/
819 BOOL
cli_unlink(struct cli_state
*cli
, char *fname
)
823 bzero(cli
->outbuf
,smb_size
);
824 bzero(cli
->inbuf
,smb_size
);
826 set_message(cli
->outbuf
,1, 2 + strlen(fname
),True
);
828 CVAL(cli
->outbuf
,smb_com
) = SMBunlink
;
829 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
830 cli_setup_packet(cli
);
832 SSVAL(cli
->outbuf
,smb_vwv0
,aSYSTEM
| aHIDDEN
);
834 p
= smb_buf(cli
->outbuf
);
838 send_smb(cli
->fd
,cli
->outbuf
);
839 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
843 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
851 /****************************************************************************
853 ****************************************************************************/
854 BOOL
cli_mkdir(struct cli_state
*cli
, char *dname
)
858 bzero(cli
->outbuf
,smb_size
);
859 bzero(cli
->inbuf
,smb_size
);
861 set_message(cli
->outbuf
,0, 2 + strlen(dname
),True
);
863 CVAL(cli
->outbuf
,smb_com
) = SMBmkdir
;
864 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
865 cli_setup_packet(cli
);
867 p
= smb_buf(cli
->outbuf
);
871 send_smb(cli
->fd
,cli
->outbuf
);
872 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
876 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
883 /****************************************************************************
885 ****************************************************************************/
886 BOOL
cli_rmdir(struct cli_state
*cli
, char *dname
)
890 bzero(cli
->outbuf
,smb_size
);
891 bzero(cli
->inbuf
,smb_size
);
893 set_message(cli
->outbuf
,0, 2 + strlen(dname
),True
);
895 CVAL(cli
->outbuf
,smb_com
) = SMBrmdir
;
896 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
897 cli_setup_packet(cli
);
899 p
= smb_buf(cli
->outbuf
);
903 send_smb(cli
->fd
,cli
->outbuf
);
904 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
908 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
917 /****************************************************************************
919 ****************************************************************************/
920 int cli_open(struct cli_state
*cli
, char *fname
, int flags
, int share_mode
)
924 unsigned accessmode
=0;
928 if (!(flags
& O_EXCL
)) {
935 accessmode
= (share_mode
<<4);
937 if ((flags
& O_RDWR
) == O_RDWR
) {
939 } else if ((flags
& O_WRONLY
) == O_WRONLY
) {
944 if ((flags
& O_SYNC
) == O_SYNC
) {
945 accessmode
|= (1<<14);
949 bzero(cli
->outbuf
,smb_size
);
950 bzero(cli
->inbuf
,smb_size
);
952 set_message(cli
->outbuf
,15,1 + strlen(fname
),True
);
954 CVAL(cli
->outbuf
,smb_com
) = SMBopenX
;
955 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
956 cli_setup_packet(cli
);
958 SSVAL(cli
->outbuf
,smb_vwv0
,0xFF);
959 SSVAL(cli
->outbuf
,smb_vwv2
,0); /* no additional info */
960 SSVAL(cli
->outbuf
,smb_vwv3
,accessmode
);
961 SSVAL(cli
->outbuf
,smb_vwv4
,aSYSTEM
| aHIDDEN
);
962 SSVAL(cli
->outbuf
,smb_vwv5
,0);
963 SSVAL(cli
->outbuf
,smb_vwv8
,openfn
);
965 p
= smb_buf(cli
->outbuf
);
967 p
= skip_string(p
,1);
969 send_smb(cli
->fd
,cli
->outbuf
);
970 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
974 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
978 return SVAL(cli
->inbuf
,smb_vwv2
);
984 /****************************************************************************
986 ****************************************************************************/
987 BOOL
cli_close(struct cli_state
*cli
, int fnum
)
989 bzero(cli
->outbuf
,smb_size
);
990 bzero(cli
->inbuf
,smb_size
);
992 set_message(cli
->outbuf
,3,0,True
);
994 CVAL(cli
->outbuf
,smb_com
) = SMBclose
;
995 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
996 cli_setup_packet(cli
);
998 SSVAL(cli
->outbuf
,smb_vwv0
,fnum
);
999 SIVALS(cli
->outbuf
,smb_vwv1
,-1);
1001 send_smb(cli
->fd
,cli
->outbuf
);
1002 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
1006 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
1014 /****************************************************************************
1016 ****************************************************************************/
1017 BOOL
cli_lock(struct cli_state
*cli
, int fnum
, uint32 offset
, uint32 len
, int timeout
)
1021 bzero(cli
->outbuf
,smb_size
);
1022 bzero(cli
->inbuf
,smb_size
);
1024 set_message(cli
->outbuf
,8,10,True
);
1026 CVAL(cli
->outbuf
,smb_com
) = SMBlockingX
;
1027 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1028 cli_setup_packet(cli
);
1030 CVAL(cli
->outbuf
,smb_vwv0
) = 0xFF;
1031 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
1032 CVAL(cli
->outbuf
,smb_vwv3
) = 0;
1033 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
1034 SSVAL(cli
->outbuf
,smb_vwv6
,0);
1035 SSVAL(cli
->outbuf
,smb_vwv7
,1);
1037 p
= smb_buf(cli
->outbuf
);
1038 SSVAL(p
, 0, cli
->pid
);
1039 SIVAL(p
, 2, offset
);
1042 send_smb(cli
->fd
,cli
->outbuf
);
1043 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
1047 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
1054 /****************************************************************************
1056 ****************************************************************************/
1057 BOOL
cli_unlock(struct cli_state
*cli
, int fnum
, uint32 offset
, uint32 len
, int timeout
)
1061 bzero(cli
->outbuf
,smb_size
);
1062 bzero(cli
->inbuf
,smb_size
);
1064 set_message(cli
->outbuf
,8,10,True
);
1066 CVAL(cli
->outbuf
,smb_com
) = SMBlockingX
;
1067 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1068 cli_setup_packet(cli
);
1070 CVAL(cli
->outbuf
,smb_vwv0
) = 0xFF;
1071 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
1072 CVAL(cli
->outbuf
,smb_vwv3
) = 0;
1073 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
1074 SSVAL(cli
->outbuf
,smb_vwv6
,1);
1075 SSVAL(cli
->outbuf
,smb_vwv7
,0);
1077 p
= smb_buf(cli
->outbuf
);
1078 SSVAL(p
, 0, cli
->pid
);
1079 SIVAL(p
, 2, offset
);
1082 send_smb(cli
->fd
,cli
->outbuf
);
1083 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
1087 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
1095 /****************************************************************************
1097 ****************************************************************************/
1098 int cli_read(struct cli_state
*cli
, int fnum
, char *buf
, uint32 offset
, uint16 size
)
1102 bzero(cli
->outbuf
,smb_size
);
1103 bzero(cli
->inbuf
,smb_size
);
1105 set_message(cli
->outbuf
,10,0,True
);
1107 CVAL(cli
->outbuf
,smb_com
) = SMBreadX
;
1108 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1109 cli_setup_packet(cli
);
1111 CVAL(cli
->outbuf
,smb_vwv0
) = 0xFF;
1112 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
1113 SIVAL(cli
->outbuf
,smb_vwv3
,offset
);
1114 SSVAL(cli
->outbuf
,smb_vwv5
,size
);
1115 SSVAL(cli
->outbuf
,smb_vwv6
,size
);
1117 send_smb(cli
->fd
,cli
->outbuf
);
1118 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
1122 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
1126 size
= SVAL(cli
->inbuf
, smb_vwv5
);
1127 p
= smb_base(cli
->inbuf
) + SVAL(cli
->inbuf
,smb_vwv6
);
1129 memcpy(buf
, p
, size
);
1135 /****************************************************************************
1137 ****************************************************************************/
1138 int cli_write(struct cli_state
*cli
, int fnum
, char *buf
, uint32 offset
, uint16 size
)
1142 bzero(cli
->outbuf
,smb_size
);
1143 bzero(cli
->inbuf
,smb_size
);
1145 set_message(cli
->outbuf
,12,size
,True
);
1147 CVAL(cli
->outbuf
,smb_com
) = SMBwriteX
;
1148 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1149 cli_setup_packet(cli
);
1151 CVAL(cli
->outbuf
,smb_vwv0
) = 0xFF;
1152 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
1153 SIVAL(cli
->outbuf
,smb_vwv3
,offset
);
1155 SSVAL(cli
->outbuf
,smb_vwv10
,size
);
1156 SSVAL(cli
->outbuf
,smb_vwv11
,smb_buf(cli
->outbuf
) - smb_base(cli
->outbuf
));
1158 p
= smb_base(cli
->outbuf
) + SVAL(cli
->outbuf
,smb_vwv11
);
1159 memcpy(p
, buf
, size
);
1161 send_smb(cli
->fd
,cli
->outbuf
);
1162 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
1166 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
1170 return SVAL(cli
->inbuf
, smb_vwv2
);
1174 /****************************************************************************
1176 ****************************************************************************/
1177 BOOL
cli_getatr(struct cli_state
*cli
, char *fname
,
1178 int *attr
, uint32
*size
, time_t *t
)
1182 bzero(cli
->outbuf
,smb_size
);
1183 bzero(cli
->inbuf
,smb_size
);
1185 set_message(cli
->outbuf
,0,strlen(fname
)+2,True
);
1187 CVAL(cli
->outbuf
,smb_com
) = SMBgetatr
;
1188 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1189 cli_setup_packet(cli
);
1191 p
= smb_buf(cli
->outbuf
);
1193 pstrcpy(p
+1, fname
);
1195 send_smb(cli
->fd
,cli
->outbuf
);
1196 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
1200 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
1205 *size
= IVAL(cli
->inbuf
, smb_vwv3
);
1209 *t
= make_unix_date3(cli
->inbuf
+smb_vwv1
);
1213 *attr
= SVAL(cli
->inbuf
,smb_vwv0
);
1221 /****************************************************************************
1223 ****************************************************************************/
1224 BOOL
cli_setatr(struct cli_state
*cli
, char *fname
, int attr
, time_t t
)
1228 bzero(cli
->outbuf
,smb_size
);
1229 bzero(cli
->inbuf
,smb_size
);
1231 set_message(cli
->outbuf
,8,strlen(fname
)+4,True
);
1233 CVAL(cli
->outbuf
,smb_com
) = SMBsetatr
;
1234 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1235 cli_setup_packet(cli
);
1237 SSVAL(cli
->outbuf
,smb_vwv0
, attr
);
1238 put_dos_date3(cli
->outbuf
,smb_vwv1
, t
);
1240 p
= smb_buf(cli
->outbuf
);
1242 pstrcpy(p
+1, fname
);
1243 p
= skip_string(p
,1);
1246 send_smb(cli
->fd
,cli
->outbuf
);
1247 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
)) {
1251 if (CVAL(cli
->inbuf
,smb_rcls
) != 0) {
1258 /****************************************************************************
1259 send a qpathinfo call
1260 ****************************************************************************/
1261 BOOL
cli_qpathinfo(struct cli_state
*cli
, char *fname
,
1262 time_t *c_time
, time_t *a_time
, time_t *m_time
, uint32
*size
)
1266 uint16 setup
= TRANSACT2_QPATHINFO
;
1268 char *rparam
=NULL
, *rdata
=NULL
;
1270 param_len
= strlen(fname
) + 7;
1272 memset(param
, 0, param_len
);
1273 SSVAL(param
, 0, SMB_INFO_STANDARD
);
1274 pstrcpy(¶m
[6], fname
);
1276 if (!cli_send_trans(cli
, SMBtrans2
,
1277 NULL
, 0, /* Name, length */
1278 -1, 0, /* fid, flags */
1279 &setup
, 1, 0, /* setup, length, max */
1280 param
, param_len
, 10, /* param, length, max */
1281 NULL
, data_len
, cli
->max_xmit
/* data, length, max */
1286 if (!cli_receive_trans(cli
, SMBtrans2
,
1287 &rparam
, ¶m_len
,
1288 &rdata
, &data_len
)) {
1292 if (!rdata
|| data_len
< 22) {
1297 *c_time
= make_unix_date2(rdata
+0);
1300 *a_time
= make_unix_date2(rdata
+4);
1303 *m_time
= make_unix_date2(rdata
+8);
1306 *size
= IVAL(rdata
, 12);
1309 if (rdata
) free(rdata
);
1310 if (rparam
) free(rparam
);
1314 /****************************************************************************
1315 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1316 ****************************************************************************/
1317 BOOL
cli_qpathinfo2(struct cli_state
*cli
, char *fname
,
1318 time_t *c_time
, time_t *a_time
, time_t *m_time
,
1319 time_t *w_time
, uint32
*size
)
1323 uint16 setup
= TRANSACT2_QPATHINFO
;
1325 char *rparam
=NULL
, *rdata
=NULL
;
1327 param_len
= strlen(fname
) + 7;
1329 memset(param
, 0, param_len
);
1330 SSVAL(param
, 0, SMB_QUERY_FILE_ALL_INFO
);
1331 pstrcpy(¶m
[6], fname
);
1333 if (!cli_send_trans(cli
, SMBtrans2
,
1334 NULL
, 0, /* name, length */
1335 -1, 0, /* fid, flags */
1336 &setup
, 1, 0, /* setup, length, max */
1337 param
, param_len
, 10, /* param, length, max */
1338 NULL
, data_len
, cli
->max_xmit
/* data, length, max */
1343 if (!cli_receive_trans(cli
, SMBtrans2
,
1344 &rparam
, ¶m_len
,
1345 &rdata
, &data_len
)) {
1349 if (!rdata
|| data_len
< 22) {
1354 *c_time
= interpret_long_date(rdata
+0) - cli
->serverzone
;
1357 *a_time
= interpret_long_date(rdata
+8) - cli
->serverzone
;
1360 *m_time
= interpret_long_date(rdata
+16) - cli
->serverzone
;
1363 *w_time
= interpret_long_date(rdata
+24) - cli
->serverzone
;
1366 *size
= IVAL(rdata
, 40);
1369 if (rdata
) free(rdata
);
1370 if (rparam
) free(rparam
);
1375 /****************************************************************************
1376 send a qfileinfo call
1377 ****************************************************************************/
1378 BOOL
cli_qfileinfo(struct cli_state
*cli
, int fnum
,
1379 time_t *c_time
, time_t *a_time
, time_t *m_time
, uint32
*size
)
1383 uint16 setup
= TRANSACT2_QFILEINFO
;
1385 char *rparam
=NULL
, *rdata
=NULL
;
1389 memset(param
, 0, param_len
);
1390 SSVAL(param
, 0, fnum
);
1391 SSVAL(param
, 2, SMB_INFO_STANDARD
);
1393 if (!cli_send_trans(cli
, SMBtrans2
,
1394 NULL
, 0, /* name, length */
1395 -1, 0, /* fid, flags */
1396 &setup
, 1, 0, /* setup, length, max */
1397 param
, param_len
, 2, /* param, length, max */
1398 NULL
, data_len
, cli
->max_xmit
/* data, length, max */
1403 if (!cli_receive_trans(cli
, SMBtrans2
,
1404 &rparam
, ¶m_len
,
1405 &rdata
, &data_len
)) {
1409 if (!rdata
|| data_len
< 22) {
1414 *c_time
= make_unix_date2(rdata
+0);
1417 *a_time
= make_unix_date2(rdata
+4);
1420 *m_time
= make_unix_date2(rdata
+8);
1423 *size
= IVAL(rdata
, 12);
1426 if (rdata
) free(rdata
);
1427 if (rparam
) free(rparam
);
1431 /****************************************************************************
1432 Send a SamOEMChangePassword command
1433 ****************************************************************************/
1435 BOOL
cli_oem_change_password(struct cli_state
*cli
, char *user
, char *new_password
,
1438 char param
[16+sizeof(fstring
)];
1441 fstring upper_case_old_pw
;
1442 fstring upper_case_new_pw
;
1443 unsigned char old_pw_hash
[16];
1444 unsigned char new_pw_hash
[16];
1447 int new_pw_len
= strlen(new_password
);
1448 char *rparam
= NULL
;
1452 if(strlen(user
) >= sizeof(fstring
)-1) {
1453 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user
));
1457 if(new_pw_len
> 512) {
1458 DEBUG(0,("cli_oem_change_password: new password for user %s is too long.\n", user
));
1462 SSVAL(p
,0,214); /* SamOEMChangePassword command. */
1465 p
= skip_string(p
,1);
1466 pstrcpy(p
, "B516B16");
1467 p
= skip_string(p
,1);
1469 p
= skip_string(p
,1);
1473 param_len
= PTR_DIFF(p
,param
);
1476 * Now setup the data area.
1477 * We need to generate a random fill
1478 * for this area to make it harder to
1481 generate_random_buffer((unsigned char *)data
, sizeof(data
), False
);
1482 fstrcpy( &data
[512 - new_pw_len
], new_password
);
1483 SIVAL(data
, 512, new_pw_len
);
1486 * Get the Lanman hash of the old password, we
1487 * use this as the key to SamOEMHash().
1489 memset(upper_case_old_pw
, '\0', sizeof(upper_case_old_pw
));
1490 fstrcpy(upper_case_old_pw
, old_password
);
1491 strupper(upper_case_old_pw
);
1492 E_P16((uchar
*)upper_case_old_pw
, old_pw_hash
);
1494 SamOEMhash( (unsigned char *)data
, (unsigned char *)old_pw_hash
, True
);
1497 * Now place the old password hash in the data.
1499 memset(upper_case_new_pw
, '\0', sizeof(upper_case_new_pw
));
1500 fstrcpy(upper_case_new_pw
, new_password
);
1501 strupper(upper_case_new_pw
);
1503 E_P16((uchar
*)upper_case_new_pw
, new_pw_hash
);
1505 E_old_pw_hash( new_pw_hash
, old_pw_hash
, (uchar
*)&data
[516]);
1509 if(cli_send_trans(cli
,SMBtrans
,
1510 PIPE_LANMAN
,strlen(PIPE_LANMAN
), /* name, length */
1511 0,0, /* fid, flags */
1512 NULL
,0,0, /* setup, length, max */
1513 param
,param_len
,2, /* param, length, max */
1514 data
,data_len
,0 /* data, length, max */
1516 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
1521 if(cli_receive_trans(cli
,SMBtrans
,
1525 cli
->rap_error
= SVAL(rparam
,0);
1533 return (cli
->rap_error
== 0);
1536 /****************************************************************************
1537 send a negprot command
1538 ****************************************************************************/
1539 BOOL
cli_negprot(struct cli_state
*cli
)
1545 bzero(cli
->outbuf
,smb_size
);
1547 /* setup the protocol strings */
1548 for (plength
=0,numprots
=0;
1549 prots
[numprots
].name
&& prots
[numprots
].prot
<=cli
->protocol
;
1551 plength
+= strlen(prots
[numprots
].name
)+2;
1553 set_message(cli
->outbuf
,0,plength
,True
);
1555 p
= smb_buf(cli
->outbuf
);
1557 prots
[numprots
].name
&& prots
[numprots
].prot
<=cli
->protocol
;
1560 pstrcpy(p
,prots
[numprots
].name
);
1564 CVAL(cli
->outbuf
,smb_com
) = SMBnegprot
;
1565 cli_setup_packet(cli
);
1567 CVAL(smb_buf(cli
->outbuf
),0) = 2;
1569 send_smb(cli
->fd
,cli
->outbuf
);
1570 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
))
1573 show_msg(cli
->inbuf
);
1575 if (CVAL(cli
->inbuf
,smb_rcls
) != 0 ||
1576 ((int)SVAL(cli
->inbuf
,smb_vwv0
) >= numprots
)) {
1580 cli
->protocol
= prots
[SVAL(cli
->inbuf
,smb_vwv0
)].prot
;
1583 if (cli
->protocol
>= PROTOCOL_NT1
) {
1585 cli
->sec_mode
= CVAL(cli
->inbuf
,smb_vwv1
);
1586 cli
->max_xmit
= IVAL(cli
->inbuf
,smb_vwv3
+1);
1587 cli
->sesskey
= IVAL(cli
->inbuf
,smb_vwv7
+1);
1588 cli
->serverzone
= SVALS(cli
->inbuf
,smb_vwv15
+1)*60;
1589 /* this time arrives in real GMT */
1590 cli
->servertime
= interpret_long_date(cli
->inbuf
+smb_vwv11
+1);
1591 memcpy(cli
->cryptkey
,smb_buf(cli
->inbuf
),8);
1592 if (IVAL(cli
->inbuf
,smb_vwv9
+1) & 1)
1593 cli
->readbraw_supported
=
1594 cli
->writebraw_supported
= True
;
1595 } else if (cli
->protocol
>= PROTOCOL_LANMAN1
) {
1596 cli
->sec_mode
= SVAL(cli
->inbuf
,smb_vwv1
);
1597 cli
->max_xmit
= SVAL(cli
->inbuf
,smb_vwv2
);
1598 cli
->sesskey
= IVAL(cli
->inbuf
,smb_vwv6
);
1599 cli
->serverzone
= SVALS(cli
->inbuf
,smb_vwv10
)*60;
1600 /* this time is converted to GMT by make_unix_date */
1601 cli
->servertime
= make_unix_date(cli
->inbuf
+smb_vwv8
);
1602 cli
->readbraw_supported
= ((SVAL(cli
->inbuf
,smb_vwv5
) & 0x1) != 0);
1603 cli
->writebraw_supported
= ((SVAL(cli
->inbuf
,smb_vwv5
) & 0x2) != 0);
1604 memcpy(cli
->cryptkey
,smb_buf(cli
->inbuf
),8);
1606 /* the old core protocol */
1608 cli
->serverzone
= TimeDiff(time(NULL
));
1615 /****************************************************************************
1616 send a session request. see rfc1002.txt 4.3 and 4.3.2
1617 ****************************************************************************/
1618 BOOL
cli_session_request(struct cli_state
*cli
,
1619 struct nmb_name
*calling
, struct nmb_name
*called
)
1623 /* send a session request (RFC 1002) */
1625 memcpy(&(cli
->calling
), calling
, sizeof(*calling
));
1626 memcpy(&(cli
->called
), called
, sizeof(*called
));
1628 /* put in the destination name */
1629 p
= cli
->outbuf
+len
;
1630 name_mangle(cli
->called
.name
, p
, cli
->called
.name_type
);
1634 p
= cli
->outbuf
+len
;
1635 name_mangle(cli
->calling
.name
, p
, cli
->calling
.name_type
);
1638 /* setup the packet length */
1639 _smb_setlen(cli
->outbuf
,len
);
1640 CVAL(cli
->outbuf
,0) = 0x81;
1644 #endif /* WITH_SSL */
1646 send_smb(cli
->fd
,cli
->outbuf
);
1647 DEBUG(5,("Sent session request\n"));
1649 if (!client_receive_smb(cli
->fd
,cli
->inbuf
,cli
->timeout
))
1653 if(CVAL(cli
->inbuf
,0) == 0x83 && CVAL(cli
->inbuf
,4) == 0x8e){ /* use ssl */
1654 if(!sslutil_fd_is_ssl(cli
->fd
)){
1655 if(sslutil_connect(cli
->fd
) == 0)
1659 #endif /* WITH_SSL */
1661 if (CVAL(cli
->inbuf
,0) != 0x82) {
1662 /* This is the wrong place to put the error... JRA. */
1663 cli
->rap_error
= CVAL(cli
->inbuf
,0);
1670 /****************************************************************************
1671 open the client sockets
1672 ****************************************************************************/
1673 BOOL
cli_connect(struct cli_state
*cli
, char *host
, struct in_addr
*ip
)
1675 struct in_addr dest_ip
;
1676 extern struct in_addr ipzero
;
1678 fstrcpy(cli
->desthost
, host
);
1680 if (!ip
|| ip_equal(*ip
, ipzero
)) {
1681 if(!resolve_name( cli
->desthost
, &dest_ip
)) {
1689 cli
->fd
= open_socket_out(SOCK_STREAM
, &dest_ip
, 139, cli
->timeout
);
1697 /****************************************************************************
1698 initialise a client structure
1699 ****************************************************************************/
1700 BOOL
cli_initialise(struct cli_state
*cli
)
1702 if (cli
->initialised
)
1705 memset(cli
, 0, sizeof(*cli
));
1708 cli
->pid
= (uint16
)getpid();
1710 cli
->vuid
= UID_FIELD_INVALID
;
1711 cli
->protocol
= PROTOCOL_NT1
;
1712 cli
->timeout
= 20000;
1713 cli
->bufsize
= 0x10000;
1714 cli
->max_xmit
= cli
->bufsize
- 4;
1715 cli
->outbuf
= (char *)malloc(cli
->bufsize
);
1716 cli
->inbuf
= (char *)malloc(cli
->bufsize
);
1717 if (!cli
->outbuf
|| !cli
->inbuf
)
1719 cli
->initialised
= 1;
1723 /****************************************************************************
1724 shutdown a client structure
1725 ****************************************************************************/
1726 void cli_shutdown(struct cli_state
*cli
)
1734 sslutil_disconnect(cli
->fd
);
1735 #endif /* WITH_SSL */
1738 memset(cli
, 0, sizeof(*cli
));
1741 /****************************************************************************
1742 return error codes for the last packet
1743 ****************************************************************************/
1744 void cli_error(struct cli_state
*cli
, int *eclass
, int *num
)
1746 *eclass
= CVAL(cli
->inbuf
,smb_rcls
);
1747 *num
= SVAL(cli
->inbuf
,smb_err
);
1750 /****************************************************************************
1751 set socket options on a open connection
1752 ****************************************************************************/
1753 void cli_sockopt(struct cli_state
*cli
, char *options
)
1755 set_socket_options(cli
->fd
, options
);
1758 /****************************************************************************
1759 set the PID to use for smb messages. Return the old pid.
1760 ****************************************************************************/
1761 uint16
cli_setpid(struct cli_state
*cli
, uint16 pid
)
1763 uint16 ret
= cli
->pid
;
1768 /****************************************************************************
1769 establishes a connection right up to doing tconX, reading in a password.
1770 ****************************************************************************/
1771 BOOL
cli_reestablish_connection(struct cli_state
*cli
)
1773 struct nmb_name calling
;
1774 struct nmb_name called
;
1776 struct in_addr dest_ip
;
1779 BOOL do_tcon
= False
;
1781 if (!cli
->initialised
|| cli
->fd
== -1)
1783 DEBUG(3,("cli_reestablish_connection: not connected\n"));
1787 /* copy the parameters necessary to re-establish the connection */
1791 fstrcpy(share
, cli
->share
);
1792 fstrcpy(dev
, cli
->dev
);
1796 memcpy(&called
, &(cli
->called
), sizeof(called
));
1797 memcpy(&calling
, &(cli
->calling
), sizeof(calling
));
1798 fstrcpy(dest_host
, cli
->full_dest_host_name
);
1799 dest_ip
= cli
->dest_ip
;
1801 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
1802 namestr(&calling
), namestr(&called
), inet_ntoa(dest_ip
),
1803 cli
->user_name
, cli
->domain
));
1805 return cli_establish_connection(cli
,
1806 dest_host
, &dest_ip
,
1808 share
, dev
, False
, do_tcon
);
1811 /****************************************************************************
1812 establishes a connection right up to doing tconX, reading in a password.
1813 ****************************************************************************/
1814 BOOL
cli_establish_connection(struct cli_state
*cli
,
1815 char *dest_host
, struct in_addr
*dest_ip
,
1816 struct nmb_name
*calling
, struct nmb_name
*called
,
1817 char *service
, char *service_type
,
1818 BOOL do_shutdown
, BOOL do_tcon
)
1820 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
1821 namestr(calling
), namestr(called
), inet_ntoa(*dest_ip
),
1822 cli
->user_name
, cli
->domain
));
1824 /* establish connection */
1826 if ((!cli
->initialised
))
1833 if (!cli_connect(cli
, dest_host
, dest_ip
))
1835 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
1836 namestr(calling
), inet_ntoa(*dest_ip
)));
1841 if (!cli_session_request(cli
, calling
, called
))
1843 DEBUG(1,("failed session request\n"));
1849 if (!cli_negprot(cli
))
1851 DEBUG(1,("failed negprot\n"));
1857 if (cli
->pwd
.cleartext
|| cli
->pwd
.null_pwd
)
1859 /* attempt clear-text session */
1863 pwd_get_cleartext(&(cli
->pwd
), passwd
);
1865 /* attempt clear-text session */
1866 if (!cli_session_setup(cli
, cli
->user_name
,
1867 passwd
, strlen(passwd
),
1871 DEBUG(1,("failed session setup\n"));
1878 if (!cli_send_tconX(cli
, service
, service_type
,
1879 (char*)passwd
, strlen(passwd
)))
1881 DEBUG(1,("failed tcon_X\n"));
1890 /* attempt encrypted session */
1891 char nt_sess_pwd
[24];
1892 char lm_sess_pwd
[24];
1894 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
1895 pwd_make_lm_nt_owf(&(cli
->pwd
), cli
->cryptkey
);
1896 pwd_get_lm_nt_owf(&(cli
->pwd
), lm_sess_pwd
, nt_sess_pwd
);
1898 /* attempt encrypted session */
1899 if (!cli_session_setup(cli
, cli
->user_name
,
1900 (char*)lm_sess_pwd
, sizeof(lm_sess_pwd
),
1901 (char*)nt_sess_pwd
, sizeof(nt_sess_pwd
),
1904 DEBUG(1,("failed session setup\n"));
1912 if (!cli_send_tconX(cli
, service
, service_type
,
1913 (char*)nt_sess_pwd
, sizeof(nt_sess_pwd
)))
1915 DEBUG(1,("failed tcon_X\n"));