2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1997
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.
34 extern pstring myname
;
35 pstring password
= "";
37 pstring workgroup
=WORKGROUP
;
38 BOOL got_pass
= False
;
39 BOOL connect_as_printer
= False
;
40 BOOL connect_as_ipc
= False
;
45 extern pstring user_socket_options
;
47 /* 30 second timeout on most commands */
48 #define CLIENT_TIMEOUT (30*1000)
49 #define SHORT_TIMEOUT (5*1000)
53 int max_protocol
= PROTOCOL_NT1
;
55 BOOL readbraw_supported
= False
;
56 BOOL writebraw_supported
= False
;
58 extern int DEBUGLEVEL
;
66 int max_xmit
= BUFFER_SIZE
;
70 extern struct in_addr dest_ip
;
77 /****************************************************************************
78 setup basics in a outgoing packet
79 ****************************************************************************/
80 void cli_setup_pkt(char *outbuf
)
82 SSVAL(outbuf
,smb_pid
,pid
);
83 SSVAL(outbuf
,smb_uid
,uid
);
84 SSVAL(outbuf
,smb_mid
,mid
);
85 if (Protocol
> PROTOCOL_COREPLUS
)
87 SCVAL(outbuf
,smb_flg
,0x8);
88 SSVAL(outbuf
,smb_flg2
,0x1);
92 /****************************************************************************
94 ****************************************************************************/
95 BOOL
cli_call_api(char *pipe_name
, int prcnt
,int drcnt
, int srcnt
,
96 int mprcnt
,int mdrcnt
,
97 int *rprcnt
,int *rdrcnt
,
98 char *param
,char *data
, uint16
*setup
,
99 char **rparam
,char **rdata
)
101 static char *inbuf
=NULL
;
102 static char *outbuf
=NULL
;
104 if (!inbuf
) inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
105 if (!outbuf
) outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
107 cli_send_trans_request(outbuf
,SMBtrans
,pipe_name
, 0,0,
112 return (cli_receive_trans_response(inbuf
,SMBtrans
,
118 /****************************************************************************
119 receive a SMB trans or trans2 response allocating the necessary memory
120 ****************************************************************************/
121 BOOL
cli_receive_trans_response(char *inbuf
,int trans
,
122 int *data_len
,int *param_len
,
123 char **data
,char **param
)
127 int this_data
,this_param
;
129 *data_len
= *param_len
= 0;
131 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
135 if (CVAL(inbuf
,smb_com
) != trans
)
137 DEBUG(0,("Expected %s response, got command 0x%02x\n",
138 trans
==SMBtrans
?"SMBtrans":"SMBtrans2", CVAL(inbuf
,smb_com
)));
141 if (CVAL(inbuf
,smb_rcls
) != 0)
144 /* parse out the lengths */
145 total_data
= SVAL(inbuf
,smb_tdrcnt
);
146 total_param
= SVAL(inbuf
,smb_tprcnt
);
149 *data
= Realloc(*data
,total_data
);
150 *param
= Realloc(*param
,total_param
);
154 this_data
= SVAL(inbuf
,smb_drcnt
);
155 this_param
= SVAL(inbuf
,smb_prcnt
);
157 memcpy(*data
+ SVAL(inbuf
,smb_drdisp
),
158 smb_base(inbuf
) + SVAL(inbuf
,smb_droff
),
161 memcpy(*param
+ SVAL(inbuf
,smb_prdisp
),
162 smb_base(inbuf
) + SVAL(inbuf
,smb_proff
),
164 *data_len
+= this_data
;
165 *param_len
+= this_param
;
167 /* parse out the total lengths again - they can shrink! */
168 total_data
= SVAL(inbuf
,smb_tdrcnt
);
169 total_param
= SVAL(inbuf
,smb_tprcnt
);
171 if (total_data
<= *data_len
&& total_param
<= *param_len
)
174 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
178 if (CVAL(inbuf
,smb_com
) != trans
)
180 DEBUG(0,("Expected %s response, got command 0x%02x\n",
181 trans
==SMBtrans
?"SMBtrans":"SMBtrans2", CVAL(inbuf
,smb_com
)));
184 if (CVAL(inbuf
,smb_rcls
) != 0)
193 /****************************************************************************
194 send a SMB trans or trans2 request
195 ****************************************************************************/
196 BOOL
cli_send_trans_request(char *outbuf
,int trans
,
197 char *name
,int fid
,int flags
,
198 char *data
,char *param
,uint16
*setup
,
199 int ldata
,int lparam
,int lsetup
,
200 int mdata
,int mparam
,int msetup
)
203 int this_ldata
,this_lparam
;
204 int tot_data
=0,tot_param
=0;
205 char *outdata
,*outparam
;
209 this_lparam
= MIN(lparam
,max_xmit
- (500+lsetup
*SIZEOFWORD
)); /* hack */
210 this_ldata
= MIN(ldata
,max_xmit
- (500+lsetup
*SIZEOFWORD
+this_lparam
));
212 bzero(outbuf
,smb_size
);
213 set_message(outbuf
,14+lsetup
,0,True
);
214 CVAL(outbuf
,smb_com
) = trans
;
215 SSVAL(outbuf
,smb_tid
,cnum
);
216 cli_setup_pkt(outbuf
);
218 outparam
= smb_buf(outbuf
)+(trans
==SMBtrans
? strlen(name
)+1 : 3);
219 outdata
= outparam
+this_lparam
;
221 /* primary request */
222 SSVAL(outbuf
,smb_tpscnt
,lparam
); /* tpscnt */
223 SSVAL(outbuf
,smb_tdscnt
,ldata
); /* tdscnt */
224 SSVAL(outbuf
,smb_mprcnt
,mparam
); /* mprcnt */
225 SSVAL(outbuf
,smb_mdrcnt
,mdata
); /* mdrcnt */
226 SCVAL(outbuf
,smb_msrcnt
,msetup
); /* msrcnt */
227 SSVAL(outbuf
,smb_flags
,flags
); /* flags */
228 SIVAL(outbuf
,smb_timeout
,0); /* timeout */
229 SSVAL(outbuf
,smb_pscnt
,this_lparam
); /* pscnt */
230 SSVAL(outbuf
,smb_psoff
,smb_offset(outparam
,outbuf
)); /* psoff */
231 SSVAL(outbuf
,smb_dscnt
,this_ldata
); /* dscnt */
232 SSVAL(outbuf
,smb_dsoff
,smb_offset(outdata
,outbuf
)); /* dsoff */
233 SCVAL(outbuf
,smb_suwcnt
,lsetup
); /* suwcnt */
234 for (i
=0;i
<lsetup
;i
++) /* setup[] */
235 SSVAL(outbuf
,smb_setup
+i
*SIZEOFWORD
,setup
[i
]);
238 strcpy(p
,name
); /* name[] */
241 *p
++ = 0; /* put in a null smb_name */
242 *p
++ = 'D'; *p
++ = ' '; /* this was added because OS/2 does it */
244 if (this_lparam
) /* param[] */
245 memcpy(outparam
,param
,this_lparam
);
246 if (this_ldata
) /* data[] */
247 memcpy(outdata
,data
,this_ldata
);
248 set_message(outbuf
,14+lsetup
, /* wcnt, bcc */
249 PTR_DIFF(outdata
+this_ldata
,smb_buf(outbuf
)),False
);
252 send_smb(Client
,outbuf
);
254 if (this_ldata
< ldata
|| this_lparam
< lparam
)
256 /* receive interim response */
257 if (!receive_smb(Client
,inbuf
,SHORT_TIMEOUT
) || CVAL(inbuf
,smb_rcls
) != 0)
259 DEBUG(0,("%s request failed (%s)\n",
260 trans
==SMBtrans
?"SMBtrans":"SMBtrans2", smb_errstr(inbuf
)));
264 tot_data
= this_ldata
;
265 tot_param
= this_lparam
;
267 while (tot_data
< ldata
|| tot_param
< lparam
)
269 this_lparam
= MIN(lparam
-tot_param
,max_xmit
- 500); /* hack */
270 this_ldata
= MIN(ldata
-tot_data
,max_xmit
- (500+this_lparam
));
272 set_message(outbuf
,trans
==SMBtrans
?8:9,0,True
);
273 CVAL(outbuf
,smb_com
) = trans
==SMBtrans
? SMBtranss
: SMBtranss2
;
275 outparam
= smb_buf(outbuf
);
276 outdata
= outparam
+this_lparam
;
278 /* secondary request */
279 SSVAL(outbuf
,smb_tpscnt
,lparam
); /* tpscnt */
280 SSVAL(outbuf
,smb_tdscnt
,ldata
); /* tdscnt */
281 SSVAL(outbuf
,smb_spscnt
,this_lparam
); /* pscnt */
282 SSVAL(outbuf
,smb_spsoff
,smb_offset(outparam
,outbuf
)); /* psoff */
283 SSVAL(outbuf
,smb_spsdisp
,tot_param
); /* psdisp */
284 SSVAL(outbuf
,smb_sdscnt
,this_ldata
); /* dscnt */
285 SSVAL(outbuf
,smb_sdsoff
,smb_offset(outdata
,outbuf
)); /* dsoff */
286 SSVAL(outbuf
,smb_sdsdisp
,tot_data
); /* dsdisp */
287 if (trans
==SMBtrans2
)
288 SSVAL(outbuf
,smb_sfid
,fid
); /* fid */
289 if (this_lparam
) /* param[] */
290 memcpy(outparam
,param
,this_lparam
);
291 if (this_ldata
) /* data[] */
292 memcpy(outdata
,data
,this_ldata
);
293 set_message(outbuf
,trans
==SMBtrans
?8:9, /* wcnt, bcc */
294 PTR_DIFF(outdata
+this_ldata
,smb_buf(outbuf
)),False
);
297 send_smb(Client
,outbuf
);
299 tot_data
+= this_ldata
;
300 tot_param
+= this_lparam
;
308 /****************************************************************************
309 send a session request
310 ****************************************************************************/
311 BOOL
cli_send_session_request(char *inbuf
,char *outbuf
)
316 /* send a session request (RFC 8002) */
318 strcpy(dest
,desthost
);
319 p
= strchr(dest
,'.');
322 /* put in the destination name */
324 name_mangle(dest
,p
,name_type
); /* 0x20 is the SMB server NetBIOS type. */
329 name_mangle(myname
,p
,0);
332 /* setup the packet length */
333 _smb_setlen(outbuf
,len
);
334 CVAL(outbuf
,0) = 0x81;
336 send_smb(Client
,outbuf
);
337 DEBUG(5,("Sent session request\n"));
339 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
341 if (CVAL(inbuf
,0) == 0x84) /* C. Hoch 9/14/95 Start */
343 /* For information, here is the response structure.
344 * We do the byte-twiddling to for portability.
345 struct RetargetResponse{
354 int port
= (CVAL(inbuf
,8)<<8)+CVAL(inbuf
,9);
355 /* SESSION RETARGET */
356 putip((char *)&dest_ip
,inbuf
+4);
359 Client
= open_socket_out(SOCK_STREAM
, &dest_ip
, port
, LONG_CONNECT_TIMEOUT
);
363 DEBUG(3,("Retargeted\n"));
365 set_socket_options(Client
,user_socket_options
);
368 return cli_send_session_request(inbuf
,outbuf
);
369 } /* C. Hoch 9/14/95 End */
372 if (CVAL(inbuf
,0) != 0x82)
374 int ecode
= CVAL(inbuf
,4);
375 DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
376 CVAL(inbuf
,0),ecode
,myname
,desthost
));
380 DEBUG(0,("Not listening on called name\n"));
381 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost
));
382 DEBUG(0,("You may find the -I option useful for this\n"));
385 DEBUG(0,("Not listening for calling name\n"));
386 DEBUG(0,("Try to connect as another name (instead of %s)\n",myname
));
387 DEBUG(0,("You may find the -n option useful for this\n"));
390 DEBUG(0,("Called name not present\n"));
391 DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost
));
392 DEBUG(0,("You may find the -I option useful for this\n"));
395 DEBUG(0,("Called name present, but insufficient resources\n"));
396 DEBUG(0,("Perhaps you should try again later?\n"));
399 DEBUG(0,("Unspecified error 0x%X\n",ecode
));
400 DEBUG(0,("Your server software is being unfriendly\n"));
412 {PROTOCOL_CORE
,"PC NETWORK PROGRAM 1.0"},
413 {PROTOCOL_COREPLUS
,"MICROSOFT NETWORKS 1.03"},
414 {PROTOCOL_LANMAN1
,"MICROSOFT NETWORKS 3.0"},
415 {PROTOCOL_LANMAN1
,"LANMAN1.0"},
416 {PROTOCOL_LANMAN2
,"LM1.2X002"},
417 {PROTOCOL_LANMAN2
,"Samba"},
418 {PROTOCOL_NT1
,"NT LM 0.12"},
419 {PROTOCOL_NT1
,"NT LANMAN 1.0"},
424 /****************************************************************************
426 ****************************************************************************/
427 BOOL
cli_send_login(char *inbuf
,char *outbuf
,BOOL start_session
,BOOL use_setup
)
429 BOOL was_null
= (!inbuf
&& !outbuf
);
431 time_t servertime
= 0;
432 extern int serverzone
;
444 inbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
445 outbuf
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
449 if (strstr(service
,"IPC$")) connect_as_ipc
= True
;
453 if (connect_as_printer
)
459 if (start_session
&& !cli_send_session_request(inbuf
,outbuf
))
469 bzero(outbuf
,smb_size
);
471 /* setup the protocol strings */
475 for (plength
=0,numprots
=0;
476 prots
[numprots
].name
&& prots
[numprots
].prot
<=max_protocol
;
478 plength
+= strlen(prots
[numprots
].name
)+2;
480 set_message(outbuf
,0,plength
,True
);
484 prots
[numprots
].name
&& prots
[numprots
].prot
<=max_protocol
;
488 strcpy(p
,prots
[numprots
].name
);
493 CVAL(outbuf
,smb_com
) = SMBnegprot
;
494 cli_setup_pkt(outbuf
);
496 CVAL(smb_buf(outbuf
),0) = 2;
498 send_smb(Client
,outbuf
);
499 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
503 if (CVAL(inbuf
,smb_rcls
) != 0 || ((int)SVAL(inbuf
,smb_vwv0
) >= numprots
))
505 DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
506 myname
,desthost
,smb_errstr(inbuf
)));
515 Protocol
= prots
[SVAL(inbuf
,smb_vwv0
)].prot
;
518 if (Protocol
< PROTOCOL_NT1
) {
519 sec_mode
= SVAL(inbuf
,smb_vwv1
);
520 max_xmit
= SVAL(inbuf
,smb_vwv2
);
521 sesskey
= IVAL(inbuf
,smb_vwv6
);
522 serverzone
= SVALS(inbuf
,smb_vwv10
)*60;
523 /* this time is converted to GMT by make_unix_date */
524 servertime
= make_unix_date(inbuf
+smb_vwv8
);
525 if (Protocol
>= PROTOCOL_COREPLUS
) {
526 readbraw_supported
= ((SVAL(inbuf
,smb_vwv5
) & 0x1) != 0);
527 writebraw_supported
= ((SVAL(inbuf
,smb_vwv5
) & 0x2) != 0);
529 crypt_len
= smb_buflen(inbuf
);
530 memcpy(cryptkey
,smb_buf(inbuf
),8);
531 DEBUG(3,("max mux %d\n",SVAL(inbuf
,smb_vwv3
)));
532 max_vcs
= SVAL(inbuf
,smb_vwv4
);
533 DEBUG(3,("max vcs %d\n",max_vcs
));
534 DEBUG(3,("max blk %d\n",SVAL(inbuf
,smb_vwv5
)));
537 sec_mode
= CVAL(inbuf
,smb_vwv1
);
538 max_xmit
= IVAL(inbuf
,smb_vwv3
+1);
539 sesskey
= IVAL(inbuf
,smb_vwv7
+1);
540 serverzone
= SVALS(inbuf
,smb_vwv15
+1)*60;
541 /* this time arrives in real GMT */
542 servertime
= interpret_long_date(inbuf
+smb_vwv11
+1);
543 crypt_len
= CVAL(inbuf
,smb_vwv16
+1);
544 memcpy(cryptkey
,smb_buf(inbuf
),8);
545 if (IVAL(inbuf
,smb_vwv9
+1) & 1)
546 readbraw_supported
= writebraw_supported
= True
;
547 DEBUG(3,("max mux %d\n",SVAL(inbuf
,smb_vwv1
+1)));
548 max_vcs
= SVAL(inbuf
,smb_vwv2
+1);
549 DEBUG(3,("max vcs %d\n",max_vcs
));
550 DEBUG(3,("max raw %d\n",IVAL(inbuf
,smb_vwv5
+1)));
551 DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf
,smb_vwv9
+1)));
554 DEBUG(3,("Sec mode %d\n",SVAL(inbuf
,smb_vwv1
)));
555 DEBUG(3,("max xmt %d\n",max_xmit
));
556 DEBUG(3,("Got %d byte crypt key\n",crypt_len
));
557 DEBUG(3,("Chose protocol [%s]\n",prots
[SVAL(inbuf
,smb_vwv0
)].name
));
559 doencrypt
= ((sec_mode
& 2) != 0);
562 static BOOL done_time
= False
;
564 DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
565 asctime(LocalTime(&servertime
)),
566 -(double)(serverzone
/3600.0)));
576 pass
= (char *)getpass("Password: ");
578 /* use a blank username for the 2nd try with a blank password */
579 if (tries
++ && !*pass
)
582 if (Protocol
>= PROTOCOL_LANMAN1
&& use_setup
)
585 int passlen
= strlen(pass
)+1;
588 if (doencrypt
&& *pass
) {
589 DEBUG(3,("Using encrypted passwords\n"));
591 SMBencrypt((uchar
*)pass
,(uchar
*)cryptkey
,(uchar
*)pword
);
594 /* if in share level security then don't send a password now */
595 if (!(sec_mode
& 1)) {strcpy(pword
, "");passlen
=1;}
597 /* send a session setup command */
598 bzero(outbuf
,smb_size
);
600 if (Protocol
< PROTOCOL_NT1
) {
601 set_message(outbuf
,10,1 + strlen(username
) + passlen
,True
);
602 CVAL(outbuf
,smb_com
) = SMBsesssetupX
;
603 cli_setup_pkt(outbuf
);
605 CVAL(outbuf
,smb_vwv0
) = 0xFF;
606 SSVAL(outbuf
,smb_vwv2
,max_xmit
);
607 SSVAL(outbuf
,smb_vwv3
,2);
608 SSVAL(outbuf
,smb_vwv4
,max_vcs
-1);
609 SIVAL(outbuf
,smb_vwv5
,sesskey
);
610 SSVAL(outbuf
,smb_vwv7
,passlen
);
612 memcpy(p
,pword
,passlen
);
616 if (!doencrypt
) passlen
--;
618 set_message(outbuf
,13,0,True
);
619 CVAL(outbuf
,smb_com
) = SMBsesssetupX
;
620 cli_setup_pkt(outbuf
);
622 CVAL(outbuf
,smb_vwv0
) = 0xFF;
623 SSVAL(outbuf
,smb_vwv2
,BUFFER_SIZE
);
624 SSVAL(outbuf
,smb_vwv3
,2);
625 SSVAL(outbuf
,smb_vwv4
,getpid());
626 SIVAL(outbuf
,smb_vwv5
,sesskey
);
627 SSVAL(outbuf
,smb_vwv7
,passlen
);
628 SSVAL(outbuf
,smb_vwv8
,0);
630 memcpy(p
,pword
,passlen
); p
+= SVAL(outbuf
,smb_vwv7
);
631 strcpy(p
,username
);p
= skip_string(p
,1);
632 strcpy(p
,workgroup
);p
= skip_string(p
,1);
633 strcpy(p
,"Unix");p
= skip_string(p
,1);
634 strcpy(p
,"Samba");p
= skip_string(p
,1);
635 set_message(outbuf
,13,PTR_DIFF(p
,smb_buf(outbuf
)),False
);
638 send_smb(Client
,outbuf
);
639 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
643 if (CVAL(inbuf
,smb_rcls
) != 0)
646 ((CVAL(inbuf
,smb_rcls
) == ERRDOS
&&
647 SVAL(inbuf
,smb_err
) == ERRnoaccess
) ||
648 (CVAL(inbuf
,smb_rcls
) == ERRSRV
&&
649 SVAL(inbuf
,smb_err
) == ERRbadpw
)))
652 DEBUG(3,("resending login\n"));
656 DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n",
657 username
,myname
,desthost
,smb_errstr(inbuf
)));
658 DEBUG(0,("You might find the -U, -W or -n options useful\n"));
659 DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
660 DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
669 if (Protocol
>= PROTOCOL_NT1
) {
670 char *domain
,*os
,*lanman
;
673 lanman
= skip_string(os
,1);
674 domain
= skip_string(lanman
,1);
675 if (*domain
|| *os
|| *lanman
)
676 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain
,os
,lanman
));
679 /* use the returned uid from now on */
680 if (SVAL(inbuf
,smb_uid
) != uid
)
681 DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
682 SVAL(inbuf
,smb_uid
),uid
));
683 uid
= SVAL(inbuf
,smb_uid
);
687 if (SVAL(inbuf
, smb_vwv2
) & 1)
688 DEBUG(1,("connected as guest "));
689 DEBUG(1,("security=user\n"));
691 DEBUG(1,("security=share\n"));
694 /* now we've got a connection - send a tcon message */
695 bzero(outbuf
,smb_size
);
697 if (strncmp(service
,"\\\\",2) != 0)
699 DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
700 DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
707 int passlen
= strlen(pass
)+1;
711 if (doencrypt
&& *pass
) {
713 SMBencrypt((uchar
*)pass
,(uchar
*)cryptkey
,(uchar
*)pword
);
716 /* if in user level security then don't send a password now */
717 if ((sec_mode
& 1)) {
718 strcpy(pword
, ""); passlen
=1;
721 if (Protocol
<= PROTOCOL_COREPLUS
) {
722 set_message(outbuf
,0,6 + strlen(service
) + passlen
+ strlen(dev
),True
);
723 CVAL(outbuf
,smb_com
) = SMBtcon
;
724 cli_setup_pkt(outbuf
);
729 p
= skip_string(p
,1);
731 memcpy(p
,pword
,passlen
);
737 set_message(outbuf
,4,2 + strlen(service
) + passlen
+ strlen(dev
),True
);
738 CVAL(outbuf
,smb_com
) = SMBtconX
;
739 cli_setup_pkt(outbuf
);
741 SSVAL(outbuf
,smb_vwv0
,0xFF);
742 SSVAL(outbuf
,smb_vwv3
,passlen
);
745 memcpy(p
,pword
,passlen
);
748 p
= skip_string(p
,1);
753 send_smb(Client
,outbuf
);
754 receive_smb(Client
,inbuf
,CLIENT_TIMEOUT
);
756 /* trying again with a blank password */
757 if (CVAL(inbuf
,smb_rcls
) != 0 &&
758 (int)strlen(pass
) > 0 &&
760 Protocol
>= PROTOCOL_LANMAN1
)
762 DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf
)));
767 if (CVAL(inbuf
,smb_rcls
) != 0)
769 DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf
)));
770 DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
771 DEBUG(0,("Some servers insist that these be in uppercase\n"));
781 if (Protocol
<= PROTOCOL_COREPLUS
) {
782 max_xmit
= SVAL(inbuf
,smb_vwv0
);
784 cnum
= SVAL(inbuf
,smb_vwv1
);
787 max_xmit
= MIN(max_xmit
,BUFFER_SIZE
-4);
789 max_xmit
= BUFFER_SIZE
- 4;
791 cnum
= SVAL(inbuf
,smb_tid
);
794 DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum
,max_xmit
));
806 /****************************************************************************
807 send a logout command
808 ****************************************************************************/
809 void cli_send_logout(void )
811 pstring inbuf
,outbuf
;
813 DEBUG(5,("cli_send_logout\n"));
815 bzero(outbuf
,smb_size
);
816 set_message(outbuf
,0,0,True
);
817 CVAL(outbuf
,smb_com
) = SMBtdis
;
818 SSVAL(outbuf
,smb_tid
,cnum
);
819 cli_setup_pkt(outbuf
);
821 send_smb(Client
,outbuf
);
822 receive_smb(Client
,inbuf
,SHORT_TIMEOUT
);
824 if (CVAL(inbuf
,smb_rcls
) != 0)
826 DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf
)));
837 /****************************************************************************
838 open the client sockets
839 ****************************************************************************/
840 BOOL
cli_open_sockets(int port
)
842 static int last_port
;
848 if (port
== 0) port
=last_port
;
859 strcpy(service2
,service
);
860 host
= strtok(service2
,"\\/");
862 DEBUG(0,("Badly formed host name\n"));
865 strcpy(desthost
,host
);
869 get_myname(myname
,NULL
);
873 DEBUG(3,("Opening sockets\n"));
879 if ((hp
= Get_Hostbyname(host
)))
881 putip((char *)&dest_ip
,(char *)hp
->h_addr
);
887 /* Try and resolve the name with the netbios server */
890 if ((bcast
= open_socket_in(SOCK_DGRAM
, 0, 3,
891 interpret_addr(lp_socket_address()))) != -1) {
892 set_socket_options(bcast
, "SO_BROADCAST");
894 if (name_query(bcast
, host
, name_type
, True
, True
, *iface_bcast(dest_ip
),
902 DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host
));
908 Client
= open_socket_out(SOCK_STREAM
, &dest_ip
, port
, LONG_CONNECT_TIMEOUT
);
912 DEBUG(3,("Connected\n"));
914 set_socket_options(Client
,user_socket_options
);
919 /****************************************************************************
920 close and open the connection again
921 ****************************************************************************/
922 BOOL
cli_reopen_connection(char *inbuf
,char *outbuf
)
924 static int open_count
=0;
928 if (open_count
>5) return(False
);
930 DEBUG(1,("Trying to re-open connection\n"));
932 set_message(outbuf
,0,0,True
);
933 SCVAL(outbuf
,smb_com
,SMBtdis
);
934 SSVAL(outbuf
,smb_tid
,cnum
);
935 cli_setup_pkt(outbuf
);
937 send_smb(Client
,outbuf
);
938 receive_smb(Client
,inbuf
,SHORT_TIMEOUT
);
941 if (!cli_open_sockets(0)) return(False
);
943 return(cli_send_login(inbuf
,outbuf
,True
,True
));
946 /* error code stuff - put together by Merik Karman
947 merik@blackadder.dsh.oz.au */
956 /* Dos Error Messages */
957 err_code_struct dos_msgs
[] = {
958 {"ERRbadfunc",1,"Invalid function."},
959 {"ERRbadfile",2,"File not found."},
960 {"ERRbadpath",3,"Directory invalid."},
961 {"ERRnofids",4,"No file descriptors available"},
962 {"ERRnoaccess",5,"Access denied."},
963 {"ERRbadfid",6,"Invalid file handle."},
964 {"ERRbadmcb",7,"Memory control blocks destroyed."},
965 {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
966 {"ERRbadmem",9,"Invalid memory block address."},
967 {"ERRbadenv",10,"Invalid environment."},
968 {"ERRbadformat",11,"Invalid format."},
969 {"ERRbadaccess",12,"Invalid open mode."},
970 {"ERRbaddata",13,"Invalid data."},
971 {"ERR",14,"reserved."},
972 {"ERRbaddrive",15,"Invalid drive specified."},
973 {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
974 {"ERRdiffdevice",17,"Not same device."},
975 {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
976 {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
977 {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
978 {"ERRnosuchshare", 67, "You specified an invalid share name"},
979 {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
980 {"ERRbadpipe",230,"Pipe invalid."},
981 {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
982 {"ERRpipeclosing",232,"Pipe close in progress."},
983 {"ERRnotconnected",233,"No process on other end of pipe."},
984 {"ERRmoredata",234,"There is more data to be returned."},
985 {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
988 /* Server Error Messages */
989 err_code_struct server_msgs
[] = {
990 {"ERRerror",1,"Non-specific error code."},
991 {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
992 {"ERRbadtype",3,"reserved."},
993 {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
994 {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
995 {"ERRinvnetname",6,"Invalid network name in tree connect."},
996 {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
997 {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
998 {"ERRqtoobig",50,"Print queue full -- no space."},
999 {"ERRqeof",51,"EOF on print queue dump."},
1000 {"ERRinvpfid",52,"Invalid print file FID."},
1001 {"ERRsmbcmd",64,"The server did not recognize the command received."},
1002 {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
1003 {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
1004 {"ERRreserved",68,"reserved."},
1005 {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
1006 {"ERRreserved",70,"reserved."},
1007 {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
1008 {"ERRpaused",81,"Server is paused."},
1009 {"ERRmsgoff",82,"Not receiving messages."},
1010 {"ERRnoroom",83,"No room to buffer message."},
1011 {"ERRrmuns",87,"Too many remote user names."},
1012 {"ERRtimeout",88,"Operation timed out."},
1013 {"ERRnoresource",89,"No resources currently available for request."},
1014 {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
1015 {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
1016 {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
1017 {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
1018 {"ERRcontmpx",252,"Continue in MPX mode."},
1019 {"ERRreserved",253,"reserved."},
1020 {"ERRreserved",254,"reserved."},
1021 {"ERRnosupport",0xFFFF,"Function not supported."},
1024 /* Hard Error Messages */
1025 err_code_struct hard_msgs
[] = {
1026 {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
1027 {"ERRbadunit",20,"Unknown unit."},
1028 {"ERRnotready",21,"Drive not ready."},
1029 {"ERRbadcmd",22,"Unknown command."},
1030 {"ERRdata",23,"Data error (CRC)."},
1031 {"ERRbadreq",24,"Bad request structure length."},
1032 {"ERRseek",25 ,"Seek error."},
1033 {"ERRbadmedia",26,"Unknown media type."},
1034 {"ERRbadsector",27,"Sector not found."},
1035 {"ERRnopaper",28,"Printer out of paper."},
1036 {"ERRwrite",29,"Write fault."},
1037 {"ERRread",30,"Read fault."},
1038 {"ERRgeneral",31,"General failure."},
1039 {"ERRbadshare",32,"An open conflicts with an existing open."},
1040 {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
1041 {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
1042 {"ERRFCBUnavail",35,"No FCBs are available to process request."},
1043 {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
1051 err_code_struct
*err_msgs
;
1054 {0x01,"ERRDOS",dos_msgs
},
1055 {0x02,"ERRSRV",server_msgs
},
1056 {0x03,"ERRHRD",hard_msgs
},
1057 {0x04,"ERRXOS",NULL
},
1058 {0xE1,"ERRRMX1",NULL
},
1059 {0xE2,"ERRRMX2",NULL
},
1060 {0xE3,"ERRRMX3",NULL
},
1061 {0xFF,"ERRCMD",NULL
},
1065 /****************************************************************************
1066 return a SMB error string from a SMB buffer
1067 ****************************************************************************/
1068 char *smb_errstr(char *inbuf
)
1071 int class = CVAL(inbuf
,smb_rcls
);
1072 int num
= SVAL(inbuf
,smb_err
);
1075 for (i
=0;err_classes
[i
].class;i
++)
1076 if (err_classes
[i
].code
== class)
1078 if (err_classes
[i
].err_msgs
)
1080 err_code_struct
*err
= err_classes
[i
].err_msgs
;
1081 for (j
=0;err
[j
].name
;j
++)
1082 if (num
== err
[j
].code
)
1085 sprintf(ret
,"%s - %s (%s)",err_classes
[i
].class,
1086 err
[j
].name
,err
[j
].message
);
1088 sprintf(ret
,"%s - %s",err_classes
[i
].class,err
[j
].name
);
1093 sprintf(ret
,"%s - %d",err_classes
[i
].class,num
);
1097 sprintf(ret
,"Error: Unknown error (%d,%d)",class,num
);