Split up async_req into a generic and a NTSTATUS specific part
[samba.git] / source3 / libsmb / cliconnect.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client connect/disconnect routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Andrew Bartlett 2001-2003
6    
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 3 of the License, or
10    (at your option) any later version.
11    
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.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22
23 static const struct {
24         int prot;
25         const char name[24];
26 } prots[10] = {
27         {PROTOCOL_CORE,         "PC NETWORK PROGRAM 1.0"},
28         {PROTOCOL_COREPLUS,     "MICROSOFT NETWORKS 1.03"},
29         {PROTOCOL_LANMAN1,      "MICROSOFT NETWORKS 3.0"},
30         {PROTOCOL_LANMAN1,      "LANMAN1.0"},
31         {PROTOCOL_LANMAN2,      "LM1.2X002"},
32         {PROTOCOL_LANMAN2,      "DOS LANMAN2.1"},
33         {PROTOCOL_LANMAN2,      "LANMAN2.1"},
34         {PROTOCOL_LANMAN2,      "Samba"},
35         {PROTOCOL_NT1,          "NT LANMAN 1.0"},
36         {PROTOCOL_NT1,          "NT LM 0.12"},
37 };
38
39 #define STAR_SMBSERVER "*SMBSERVER"
40
41 /**
42  * Set the user session key for a connection
43  * @param cli The cli structure to add it too
44  * @param session_key The session key used.  (A copy of this is taken for the cli struct)
45  *
46  */
47
48 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key) 
49 {
50         cli->user_session_key = data_blob(session_key.data, session_key.length);
51 }
52
53 /****************************************************************************
54  Do an old lanman2 style session setup.
55 ****************************************************************************/
56
57 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
58                                           const char *user, 
59                                           const char *pass, size_t passlen,
60                                           const char *workgroup)
61 {
62         DATA_BLOB session_key = data_blob_null;
63         DATA_BLOB lm_response = data_blob_null;
64         fstring pword;
65         char *p;
66
67         if (passlen > sizeof(pword)-1) {
68                 return NT_STATUS_INVALID_PARAMETER;
69         }
70
71         /* LANMAN servers predate NT status codes and Unicode and ignore those 
72            smb flags so we must disable the corresponding default capabilities  
73            that would otherwise cause the Unicode and NT Status flags to be
74            set (and even returned by the server) */
75
76         cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
77
78         /* if in share level security then don't send a password now */
79         if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
80                 passlen = 0;
81
82         if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
83                 /* Encrypted mode needed, and non encrypted password supplied. */
84                 lm_response = data_blob(NULL, 24);
85                 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
86                         DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
87                         return NT_STATUS_ACCESS_DENIED;
88                 }
89         } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
90                 /* Encrypted mode needed, and encrypted password supplied. */
91                 lm_response = data_blob(pass, passlen);
92         } else if (passlen > 0) {
93                 /* Plaintext mode needed, assume plaintext supplied. */
94                 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
95                 lm_response = data_blob(pass, passlen);
96         }
97
98         /* send a session setup command */
99         memset(cli->outbuf,'\0',smb_size);
100         cli_set_message(cli->outbuf,10, 0, True);
101         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
102         cli_setup_packet(cli);
103         
104         SCVAL(cli->outbuf,smb_vwv0,0xFF);
105         SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
106         SSVAL(cli->outbuf,smb_vwv3,2);
107         SSVAL(cli->outbuf,smb_vwv4,1);
108         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
109         SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
110
111         p = smb_buf(cli->outbuf);
112         memcpy(p,lm_response.data,lm_response.length);
113         p += lm_response.length;
114         p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
115         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
116         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
117         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
118         cli_setup_bcc(cli, p);
119
120         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
121                 return cli_nt_error(cli);
122         }
123
124         show_msg(cli->inbuf);
125
126         if (cli_is_error(cli)) {
127                 return cli_nt_error(cli);
128         }
129         
130         /* use the returned vuid from now on */
131         cli->vuid = SVAL(cli->inbuf,smb_uid);   
132         fstrcpy(cli->user_name, user);
133
134         if (session_key.data) {
135                 /* Have plaintext orginal */
136                 cli_set_session_key(cli, session_key);
137         }
138
139         return NT_STATUS_OK;
140 }
141
142 /****************************************************************************
143  Work out suitable capabilities to offer the server.
144 ****************************************************************************/
145
146 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
147 {
148         uint32 capabilities = CAP_NT_SMBS;
149
150         if (!cli->force_dos_errors)
151                 capabilities |= CAP_STATUS32;
152
153         if (cli->use_level_II_oplocks)
154                 capabilities |= CAP_LEVEL_II_OPLOCKS;
155
156         capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
157         return capabilities;
158 }
159
160 /****************************************************************************
161  Do a NT1 guest session setup.
162 ****************************************************************************/
163
164 struct async_req *cli_session_setup_guest_send(TALLOC_CTX *mem_ctx,
165                                                struct event_context *ev,
166                                                struct cli_state *cli)
167 {
168         struct async_req *result;
169         uint16_t vwv[13];
170         uint8_t *bytes;
171
172         SCVAL(vwv+0, 0, 0xFF);
173         SCVAL(vwv+0, 1, 0);
174         SSVAL(vwv+1, 0, 0);
175         SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
176         SSVAL(vwv+3, 0, 2);
177         SSVAL(vwv+4, 0, cli->pid);
178         SIVAL(vwv+5, 0, cli->sesskey);
179         SSVAL(vwv+7, 0, 0);
180         SSVAL(vwv+8, 0, 0);
181         SSVAL(vwv+9, 0, 0);
182         SSVAL(vwv+10, 0, 0);
183         SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
184
185         bytes = talloc_array(talloc_tos(), uint8_t, 0);
186
187         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "",  1, /* username */
188                                    NULL);
189         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, /* workgroup */
190                                    NULL);
191         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix",
192                                    strlen("Unix")+1, NULL);
193         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba",
194                                    strlen("Samba")+1, NULL);
195
196         if (bytes == NULL) {
197                 return NULL;
198         }
199
200         result = cli_request_send(mem_ctx, ev, cli, SMBsesssetupX, 0,
201                                   13, vwv, 0, talloc_get_size(bytes), bytes);
202         TALLOC_FREE(bytes);
203         return result;
204 }
205
206 NTSTATUS cli_session_setup_guest_recv(struct async_req *req)
207 {
208         struct cli_request *cli_req = talloc_get_type_abort(
209                 req->private_data, struct cli_request);
210         struct cli_state *cli = cli_req->cli;
211         uint8_t wct;
212         uint16_t *vwv;
213         uint16_t num_bytes;
214         uint8_t *bytes;
215         uint8_t *p;
216         NTSTATUS status;
217
218         if (async_req_is_nterror(req, &status)) {
219                 return status;
220         }
221
222         status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
223         if (!NT_STATUS_IS_OK(status)) {
224                 return status;
225         }
226
227         p = bytes;
228
229         cli->vuid = SVAL(cli_req->inbuf, smb_uid);
230
231         p += clistr_pull(cli_req->inbuf, cli->server_os, (char *)p,
232                          sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
233         p += clistr_pull(cli_req->inbuf, cli->server_type, (char *)p,
234                          sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
235         p += clistr_pull(cli_req->inbuf, cli->server_domain, (char *)p,
236                          sizeof(fstring), bytes+num_bytes-p, STR_TERMINATE);
237
238         if (strstr(cli->server_type, "Samba")) {
239                 cli->is_samba = True;
240         }
241
242         fstrcpy(cli->user_name, "");
243
244         return NT_STATUS_OK;
245 }
246
247 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
248 {
249         TALLOC_CTX *frame = talloc_stackframe();
250         struct event_context *ev;
251         struct async_req *req;
252         NTSTATUS status;
253
254         if (cli->fd_event != NULL) {
255                 /*
256                  * Can't use sync call while an async call is in flight
257                  */
258                 status = NT_STATUS_INVALID_PARAMETER;
259                 goto fail;
260         }
261
262         ev = event_context_init(frame);
263         if (ev == NULL) {
264                 status = NT_STATUS_NO_MEMORY;
265                 goto fail;
266         }
267
268         req = cli_session_setup_guest_send(frame, ev, cli);
269         if (req == NULL) {
270                 status = NT_STATUS_NO_MEMORY;
271                 goto fail;
272         }
273
274         while (req->state < ASYNC_REQ_DONE) {
275                 event_loop_once(ev);
276         }
277
278         status = cli_session_setup_guest_recv(req);
279  fail:
280         TALLOC_FREE(frame);
281         return status;
282 }
283
284 /****************************************************************************
285  Do a NT1 plaintext session setup.
286 ****************************************************************************/
287
288 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
289                                             const char *user, const char *pass,
290                                             const char *workgroup)
291 {
292         uint32 capabilities = cli_session_setup_capabilities(cli);
293         char *p;
294         fstring lanman;
295         
296         fstr_sprintf( lanman, "Samba %s", samba_version_string());
297
298         memset(cli->outbuf, '\0', smb_size);
299         cli_set_message(cli->outbuf,13,0,True);
300         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
301         cli_setup_packet(cli);
302                         
303         SCVAL(cli->outbuf,smb_vwv0,0xFF);
304         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
305         SSVAL(cli->outbuf,smb_vwv3,2);
306         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
307         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
308         SSVAL(cli->outbuf,smb_vwv8,0);
309         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
310         p = smb_buf(cli->outbuf);
311         
312         /* check wether to send the ASCII or UNICODE version of the password */
313         
314         if ( (capabilities & CAP_UNICODE) == 0 ) {
315                 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
316                 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
317         }
318         else {
319                 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
320                  * the space taken by the unicode password to be one byte too
321                  * long (as we're on an odd byte boundary here). Reduce the
322                  * count by 1 to cope with this. Fixes smbclient against NetApp
323                  * servers which can't cope. Fix from
324                  * bryan.kolodziej@allenlund.com in bug #3840.
325                  */
326                 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
327                 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);        
328         }
329         
330         p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
331         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
332         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
333         p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
334         cli_setup_bcc(cli, p);
335
336         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
337                 return cli_nt_error(cli);
338         }
339         
340         show_msg(cli->inbuf);
341         
342         if (cli_is_error(cli)) {
343                 return cli_nt_error(cli);
344         }
345
346         cli->vuid = SVAL(cli->inbuf,smb_uid);
347         p = smb_buf(cli->inbuf);
348         p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
349                          -1, STR_TERMINATE);
350         p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
351                          -1, STR_TERMINATE);
352         p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
353                          -1, STR_TERMINATE);
354         fstrcpy(cli->user_name, user);
355
356         if (strstr(cli->server_type, "Samba")) {
357                 cli->is_samba = True;
358         }
359
360         return NT_STATUS_OK;
361 }
362
363 /****************************************************************************
364    do a NT1 NTLM/LM encrypted session setup - for when extended security
365    is not negotiated.
366    @param cli client state to create do session setup on
367    @param user username
368    @param pass *either* cleartext password (passlen !=24) or LM response.
369    @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
370    @param workgroup The user's domain.
371 ****************************************************************************/
372
373 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user, 
374                                       const char *pass, size_t passlen,
375                                       const char *ntpass, size_t ntpasslen,
376                                       const char *workgroup)
377 {
378         uint32 capabilities = cli_session_setup_capabilities(cli);
379         DATA_BLOB lm_response = data_blob_null;
380         DATA_BLOB nt_response = data_blob_null;
381         DATA_BLOB session_key = data_blob_null;
382         NTSTATUS result;
383         char *p;
384
385         if (passlen == 0) {
386                 /* do nothing - guest login */
387         } else if (passlen != 24) {
388                 if (lp_client_ntlmv2_auth()) {
389                         DATA_BLOB server_chal;
390                         DATA_BLOB names_blob;
391                         server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8)); 
392
393                         /* note that the 'workgroup' here is a best guess - we don't know
394                            the server's domain at this point.  The 'server name' is also
395                            dodgy... 
396                         */
397                         names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
398
399                         if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal, 
400                                               &names_blob,
401                                               &lm_response, &nt_response, &session_key)) {
402                                 data_blob_free(&names_blob);
403                                 data_blob_free(&server_chal);
404                                 return NT_STATUS_ACCESS_DENIED;
405                         }
406                         data_blob_free(&names_blob);
407                         data_blob_free(&server_chal);
408
409                 } else {
410                         uchar nt_hash[16];
411                         E_md4hash(pass, nt_hash);
412
413 #ifdef LANMAN_ONLY
414                         nt_response = data_blob_null;
415 #else
416                         nt_response = data_blob(NULL, 24);
417                         SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
418 #endif
419                         /* non encrypted password supplied. Ignore ntpass. */
420                         if (lp_client_lanman_auth()) {
421                                 lm_response = data_blob(NULL, 24);
422                                 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
423                                         /* Oops, the LM response is invalid, just put 
424                                            the NT response there instead */
425                                         data_blob_free(&lm_response);
426                                         lm_response = data_blob(nt_response.data, nt_response.length);
427                                 }
428                         } else {
429                                 /* LM disabled, place NT# in LM field instead */
430                                 lm_response = data_blob(nt_response.data, nt_response.length);
431                         }
432
433                         session_key = data_blob(NULL, 16);
434 #ifdef LANMAN_ONLY
435                         E_deshash(pass, session_key.data);
436                         memset(&session_key.data[8], '\0', 8);
437 #else
438                         SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
439 #endif
440                 }
441 #ifdef LANMAN_ONLY
442                 cli_simple_set_signing(cli, session_key, lm_response); 
443 #else
444                 cli_simple_set_signing(cli, session_key, nt_response); 
445 #endif
446         } else {
447                 /* pre-encrypted password supplied.  Only used for 
448                    security=server, can't do
449                    signing because we don't have original key */
450
451                 lm_response = data_blob(pass, passlen);
452                 nt_response = data_blob(ntpass, ntpasslen);
453         }
454
455         /* send a session setup command */
456         memset(cli->outbuf,'\0',smb_size);
457
458         cli_set_message(cli->outbuf,13,0,True);
459         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
460         cli_setup_packet(cli);
461                         
462         SCVAL(cli->outbuf,smb_vwv0,0xFF);
463         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
464         SSVAL(cli->outbuf,smb_vwv3,2);
465         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
466         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
467         SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
468         SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
469         SIVAL(cli->outbuf,smb_vwv11,capabilities); 
470         p = smb_buf(cli->outbuf);
471         if (lm_response.length) {
472                 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
473         }
474         if (nt_response.length) {
475                 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
476         }
477         p += clistr_push(cli, p, user, -1, STR_TERMINATE);
478
479         /* Upper case here might help some NTLMv2 implementations */
480         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
481         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
482         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
483         cli_setup_bcc(cli, p);
484
485         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
486                 result = cli_nt_error(cli);
487                 goto end;
488         }
489
490         /* show_msg(cli->inbuf); */
491
492         if (cli_is_error(cli)) {
493                 result = cli_nt_error(cli);
494                 goto end;
495         }
496
497         /* use the returned vuid from now on */
498         cli->vuid = SVAL(cli->inbuf,smb_uid);
499         
500         p = smb_buf(cli->inbuf);
501         p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
502                          -1, STR_TERMINATE);
503         p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
504                          -1, STR_TERMINATE);
505         p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
506                          -1, STR_TERMINATE);
507
508         if (strstr(cli->server_type, "Samba")) {
509                 cli->is_samba = True;
510         }
511
512         fstrcpy(cli->user_name, user);
513
514         if (session_key.data) {
515                 /* Have plaintext orginal */
516                 cli_set_session_key(cli, session_key);
517         }
518
519         result = NT_STATUS_OK;
520 end:    
521         data_blob_free(&lm_response);
522         data_blob_free(&nt_response);
523         data_blob_free(&session_key);
524         return result;
525 }
526
527 /****************************************************************************
528  Send a extended security session setup blob
529 ****************************************************************************/
530
531 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
532 {
533         uint32 capabilities = cli_session_setup_capabilities(cli);
534         char *p;
535
536         capabilities |= CAP_EXTENDED_SECURITY;
537
538         /* send a session setup command */
539         memset(cli->outbuf,'\0',smb_size);
540
541         cli_set_message(cli->outbuf,12,0,True);
542         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
543
544         cli_setup_packet(cli);
545
546         SCVAL(cli->outbuf,smb_vwv0,0xFF);
547         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
548         SSVAL(cli->outbuf,smb_vwv3,2);
549         SSVAL(cli->outbuf,smb_vwv4,1);
550         SIVAL(cli->outbuf,smb_vwv5,0);
551         SSVAL(cli->outbuf,smb_vwv7,blob.length);
552         SIVAL(cli->outbuf,smb_vwv10,capabilities); 
553         p = smb_buf(cli->outbuf);
554         memcpy(p, blob.data, blob.length);
555         p += blob.length;
556         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
557         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
558         cli_setup_bcc(cli, p);
559         return cli_send_smb(cli);
560 }
561
562 /****************************************************************************
563  Send a extended security session setup blob, returning a reply blob.
564 ****************************************************************************/
565
566 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
567 {
568         DATA_BLOB blob2 = data_blob_null;
569         char *p;
570         size_t len;
571
572         if (!cli_receive_smb(cli))
573                 return blob2;
574
575         show_msg(cli->inbuf);
576
577         if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
578                                                   NT_STATUS_MORE_PROCESSING_REQUIRED)) {
579                 return blob2;
580         }
581
582         /* use the returned vuid from now on */
583         cli->vuid = SVAL(cli->inbuf,smb_uid);
584
585         p = smb_buf(cli->inbuf);
586
587         blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
588
589         p += blob2.length;
590         p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
591                          -1, STR_TERMINATE);
592
593         /* w2k with kerberos doesn't properly null terminate this field */
594         len = smb_bufrem(cli->inbuf, p);
595         p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
596                          len, 0);
597
598         return blob2;
599 }
600
601 #ifdef HAVE_KRB5
602 /****************************************************************************
603  Send a extended security session setup blob, returning a reply blob.
604 ****************************************************************************/
605
606 /* The following is calculated from :
607  * (smb_size-4) = 35
608  * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
609  * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
610  * end of packet.
611  */
612
613 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
614
615 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
616 {
617         int32 remaining = blob.length;
618         int32 cur = 0;
619         DATA_BLOB send_blob = data_blob_null;
620         int32 max_blob_size = 0;
621         DATA_BLOB receive_blob = data_blob_null;
622
623         if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
624                 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
625                         "(was %u, need minimum %u)\n",
626                         (unsigned int)cli->max_xmit,
627                         BASE_SESSSETUP_BLOB_PACKET_SIZE));
628                 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
629                 return False;
630         }
631
632         max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
633
634         while ( remaining > 0) {
635                 if (remaining >= max_blob_size) {
636                         send_blob.length = max_blob_size;
637                         remaining -= max_blob_size;
638                 } else {
639                         send_blob.length = remaining; 
640                         remaining = 0;
641                 }
642
643                 send_blob.data =  &blob.data[cur];
644                 cur += send_blob.length;
645
646                 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n", 
647                         (unsigned int)remaining,
648                         (unsigned int)send_blob.length,
649                         (unsigned int)cur ));
650
651                 if (!cli_session_setup_blob_send(cli, send_blob)) {
652                         DEBUG(0, ("cli_session_setup_blob: send failed\n"));
653                         return False;
654                 }
655
656                 receive_blob = cli_session_setup_blob_receive(cli);
657                 data_blob_free(&receive_blob);
658
659                 if (cli_is_error(cli) &&
660                                 !NT_STATUS_EQUAL( cli_get_nt_error(cli), 
661                                         NT_STATUS_MORE_PROCESSING_REQUIRED)) {
662                         DEBUG(0, ("cli_session_setup_blob: receive failed "
663                                   "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
664                         cli->vuid = 0;
665                         return False;
666                 }
667         }
668
669         return True;
670 }
671
672 /****************************************************************************
673  Use in-memory credentials cache
674 ****************************************************************************/
675
676 static void use_in_memory_ccache(void) {
677         setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
678 }
679
680 /****************************************************************************
681  Do a spnego/kerberos encrypted session setup.
682 ****************************************************************************/
683
684 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
685 {
686         DATA_BLOB negTokenTarg;
687         DATA_BLOB session_key_krb5;
688         NTSTATUS nt_status;
689         int rc;
690
691         cli_temp_set_signing(cli);
692
693         DEBUG(2,("Doing kerberos session setup\n"));
694
695         /* generate the encapsulated kerberos5 ticket */
696         rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
697
698         if (rc) {
699                 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
700                         error_message(rc)));
701                 return ADS_ERROR_KRB5(rc);
702         }
703
704 #if 0
705         file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
706 #endif
707
708         if (!cli_session_setup_blob(cli, negTokenTarg)) {
709                 nt_status = cli_nt_error(cli);
710                 goto nt_error;
711         }
712
713         if (cli_is_error(cli)) {
714                 nt_status = cli_nt_error(cli);
715                 if (NT_STATUS_IS_OK(nt_status)) {
716                         nt_status = NT_STATUS_UNSUCCESSFUL;
717                 }
718                 goto nt_error;
719         }
720
721         cli_set_session_key(cli, session_key_krb5);
722
723         if (cli_simple_set_signing(
724                     cli, session_key_krb5, data_blob_null)) {
725
726                 /* 'resign' the last message, so we get the right sequence numbers
727                    for checking the first reply from the server */
728                 cli_calculate_sign_mac(cli, cli->outbuf);
729
730                 if (!cli_check_sign_mac(cli, cli->inbuf)) {
731                         nt_status = NT_STATUS_ACCESS_DENIED;
732                         goto nt_error;
733                 }
734         }
735
736         data_blob_free(&negTokenTarg);
737         data_blob_free(&session_key_krb5);
738
739         return ADS_ERROR_NT(NT_STATUS_OK);
740
741 nt_error:
742         data_blob_free(&negTokenTarg);
743         data_blob_free(&session_key_krb5);
744         cli->vuid = 0;
745         return ADS_ERROR_NT(nt_status);
746 }
747 #endif  /* HAVE_KRB5 */
748
749
750 /****************************************************************************
751  Do a spnego/NTLMSSP encrypted session setup.
752 ****************************************************************************/
753
754 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, 
755                                           const char *pass, const char *domain)
756 {
757         struct ntlmssp_state *ntlmssp_state;
758         NTSTATUS nt_status;
759         int turn = 1;
760         DATA_BLOB msg1;
761         DATA_BLOB blob = data_blob_null;
762         DATA_BLOB blob_in = data_blob_null;
763         DATA_BLOB blob_out = data_blob_null;
764
765         cli_temp_set_signing(cli);
766
767         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
768                 return nt_status;
769         }
770         ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
771
772         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
773                 return nt_status;
774         }
775         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
776                 return nt_status;
777         }
778         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
779                 return nt_status;
780         }
781
782         do {
783                 nt_status = ntlmssp_update(ntlmssp_state, 
784                                                   blob_in, &blob_out);
785                 data_blob_free(&blob_in);
786                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
787                         if (turn == 1) {
788                                 /* and wrap it in a SPNEGO wrapper */
789                                 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
790                         } else {
791                                 /* wrap it in SPNEGO */
792                                 msg1 = spnego_gen_auth(blob_out);
793                         }
794
795                         /* now send that blob on its way */
796                         if (!cli_session_setup_blob_send(cli, msg1)) {
797                                 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
798                                 nt_status = NT_STATUS_UNSUCCESSFUL;
799                         } else {
800                                 blob = cli_session_setup_blob_receive(cli);
801
802                                 nt_status = cli_nt_error(cli);
803                                 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
804                                         if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
805                                                 nt_status = NT_STATUS_ACCESS_DENIED;
806                                         } else {
807                                                 nt_status = NT_STATUS_UNSUCCESSFUL;
808                                         }
809                                 }
810                         }
811                         data_blob_free(&msg1);
812                 }
813
814                 if (!blob.length) {
815                         if (NT_STATUS_IS_OK(nt_status)) {
816                                 nt_status = NT_STATUS_UNSUCCESSFUL;
817                         }
818                 } else if ((turn == 1) && 
819                            NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
820                         DATA_BLOB tmp_blob = data_blob_null;
821                         /* the server might give us back two challenges */
822                         if (!spnego_parse_challenge(blob, &blob_in, 
823                                                     &tmp_blob)) {
824                                 DEBUG(3,("Failed to parse challenges\n"));
825                                 nt_status = NT_STATUS_INVALID_PARAMETER;
826                         }
827                         data_blob_free(&tmp_blob);
828                 } else {
829                         if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP, 
830                                                         &blob_in)) {
831                                 DEBUG(3,("Failed to parse auth response\n"));
832                                 if (NT_STATUS_IS_OK(nt_status) 
833                                     || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) 
834                                         nt_status = NT_STATUS_INVALID_PARAMETER;
835                         }
836                 }
837                 data_blob_free(&blob);
838                 data_blob_free(&blob_out);
839                 turn++;
840         } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
841
842         data_blob_free(&blob_in);
843
844         if (NT_STATUS_IS_OK(nt_status)) {
845
846                 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
847                 cli_set_session_key(cli, ntlmssp_state->session_key);
848
849                 if (cli_simple_set_signing(
850                             cli, ntlmssp_state->session_key, data_blob_null)) {
851
852                         /* 'resign' the last message, so we get the right sequence numbers
853                            for checking the first reply from the server */
854                         cli_calculate_sign_mac(cli, cli->outbuf);
855
856                         if (!cli_check_sign_mac(cli, cli->inbuf)) {
857                                 nt_status = NT_STATUS_ACCESS_DENIED;
858                         }
859                 }
860         }
861
862         /* we have a reference conter on ntlmssp_state, if we are signing
863            then the state will be kept by the signing engine */
864
865         ntlmssp_end(&ntlmssp_state);
866
867         if (!NT_STATUS_IS_OK(nt_status)) {
868                 cli->vuid = 0;
869         }
870         return nt_status;
871 }
872
873 /****************************************************************************
874  Do a spnego encrypted session setup.
875
876  user_domain: The shortname of the domain the user/machine is a member of.
877  dest_realm: The realm we're connecting to, if NULL we use our default realm.
878 ****************************************************************************/
879
880 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 
881                               const char *pass, const char *user_domain,
882                               const char * dest_realm)
883 {
884         char *principal = NULL;
885         char *OIDs[ASN1_MAX_OIDS];
886         int i;
887         DATA_BLOB blob;
888         const char *p = NULL;
889         char *account = NULL;
890
891         DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
892
893         /* the server might not even do spnego */
894         if (cli->secblob.length <= 16) {
895                 DEBUG(3,("server didn't supply a full spnego negprot\n"));
896                 goto ntlmssp;
897         }
898
899 #if 0
900         file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
901 #endif
902
903         /* there is 16 bytes of GUID before the real spnego packet starts */
904         blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
905
906         /* The server sent us the first part of the SPNEGO exchange in the
907          * negprot reply. It is WRONG to depend on the principal sent in the
908          * negprot reply, but right now we do it. If we don't receive one,
909          * we try to best guess, then fall back to NTLM.  */
910         if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
911                 data_blob_free(&blob);
912                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
913         }
914         data_blob_free(&blob);
915
916         /* make sure the server understands kerberos */
917         for (i=0;OIDs[i];i++) {
918                 DEBUG(3,("got OID=%s\n", OIDs[i]));
919                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
920                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
921                         cli->got_kerberos_mechanism = True;
922                 }
923                 talloc_free(OIDs[i]);
924         }
925
926         DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
927
928         fstrcpy(cli->user_name, user);
929
930 #ifdef HAVE_KRB5
931         /* If password is set we reauthenticate to kerberos server
932          * and do not store results */
933
934         if (cli->got_kerberos_mechanism && cli->use_kerberos) {
935                 ADS_STATUS rc;
936
937                 if (pass && *pass) {
938                         int ret;
939
940                         use_in_memory_ccache();
941                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
942
943                         if (ret){
944                                 TALLOC_FREE(principal);
945                                 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
946                                 if (cli->fallback_after_kerberos)
947                                         goto ntlmssp;
948                                 return ADS_ERROR_KRB5(ret);
949                         }
950                 }
951
952                 /* If we get a bad principal, try to guess it if
953                    we have a valid host NetBIOS name.
954                  */
955                 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
956                         TALLOC_FREE(principal);
957                 }
958
959                 if (principal == NULL &&
960                         !is_ipaddress(cli->desthost) &&
961                         !strequal(STAR_SMBSERVER,
962                                 cli->desthost)) {
963                         char *realm = NULL;
964                         char *machine = NULL;
965                         char *host = NULL;
966                         DEBUG(3,("cli_session_setup_spnego: got a "
967                                 "bad server principal, trying to guess ...\n"));
968
969                         host = strchr_m(cli->desthost, '.');
970                         if (host) {
971                                 machine = SMB_STRNDUP(cli->desthost,
972                                         host - cli->desthost);
973                         } else {
974                                 machine = SMB_STRDUP(cli->desthost);
975                         }
976                         if (machine == NULL) {
977                                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
978                         }
979
980                         if (dest_realm) {
981                                 realm = SMB_STRDUP(dest_realm);
982                                 strupper_m(realm);
983                         } else {
984                                 realm = kerberos_get_default_realm_from_ccache();
985                         }
986                         if (realm && *realm) {
987                                 principal = talloc_asprintf(NULL, "%s$@%s",
988                                                         machine, realm);
989                                 if (!principal) {
990                                         SAFE_FREE(machine);
991                                         SAFE_FREE(realm);
992                                         return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
993                                 }
994                                 DEBUG(3,("cli_session_setup_spnego: guessed "
995                                         "server principal=%s\n",
996                                         principal ? principal : "<null>"));
997                         }
998                         SAFE_FREE(machine);
999                         SAFE_FREE(realm);
1000                 }
1001
1002                 if (principal) {
1003                         rc = cli_session_setup_kerberos(cli, principal,
1004                                 dest_realm);
1005                         if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1006                                 TALLOC_FREE(principal);
1007                                 return rc;
1008                         }
1009                 }
1010         }
1011 #endif
1012
1013         TALLOC_FREE(principal);
1014
1015 ntlmssp:
1016
1017         account = talloc_strdup(talloc_tos(), user);
1018         if (!account) {
1019                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1020         }
1021
1022         /* when falling back to ntlmssp while authenticating with a machine
1023          * account strip off the realm - gd */
1024
1025         if ((p = strchr_m(user, '@')) != NULL) {
1026                 account[PTR_DIFF(p,user)] = '\0';
1027         }
1028
1029         return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1030 }
1031
1032 /****************************************************************************
1033  Send a session setup. The username and workgroup is in UNIX character
1034  format and must be converted to DOS codepage format before sending. If the
1035  password is in plaintext, the same should be done.
1036 ****************************************************************************/
1037
1038 NTSTATUS cli_session_setup(struct cli_state *cli,
1039                            const char *user,
1040                            const char *pass, int passlen,
1041                            const char *ntpass, int ntpasslen,
1042                            const char *workgroup)
1043 {
1044         char *p;
1045         fstring user2;
1046
1047         if (user) {
1048                 fstrcpy(user2, user);
1049         } else {
1050                 user2[0] ='\0';
1051         }
1052
1053         if (!workgroup) {
1054                 workgroup = "";
1055         }
1056
1057         /* allow for workgroups as part of the username */
1058         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1059             (p=strchr_m(user2,*lp_winbind_separator()))) {
1060                 *p = 0;
1061                 user = p+1;
1062                 workgroup = user2;
1063         }
1064
1065         if (cli->protocol < PROTOCOL_LANMAN1) {
1066                 return NT_STATUS_OK;
1067         }
1068
1069         /* now work out what sort of session setup we are going to
1070            do. I have split this into separate functions to make the
1071            flow a bit easier to understand (tridge) */
1072
1073         /* if its an older server then we have to use the older request format */
1074
1075         if (cli->protocol < PROTOCOL_NT1) {
1076                 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1077                         DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1078                                   " is disabled\n"));
1079                         return NT_STATUS_ACCESS_DENIED;
1080                 }
1081
1082                 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1083                     !lp_client_plaintext_auth() && (*pass)) {
1084                         DEBUG(1, ("Server requested plaintext password but "
1085                                   "'client plaintext auth' is disabled\n"));
1086                         return NT_STATUS_ACCESS_DENIED;
1087                 }
1088
1089                 return cli_session_setup_lanman2(cli, user, pass, passlen,
1090                                                  workgroup);
1091         }
1092
1093         /* if no user is supplied then we have to do an anonymous connection.
1094            passwords are ignored */
1095
1096         if (!user || !*user)
1097                 return cli_session_setup_guest(cli);
1098
1099         /* if the server is share level then send a plaintext null
1100            password at this point. The password is sent in the tree
1101            connect */
1102
1103         if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 
1104                 return cli_session_setup_plaintext(cli, user, "", workgroup);
1105
1106         /* if the server doesn't support encryption then we have to use 
1107            plaintext. The second password is ignored */
1108
1109         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1110                 if (!lp_client_plaintext_auth() && (*pass)) {
1111                         DEBUG(1, ("Server requested plaintext password but "
1112                                   "'client plaintext auth' is disabled\n"));
1113                         return NT_STATUS_ACCESS_DENIED;
1114                 }
1115                 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1116         }
1117
1118         /* if the server supports extended security then use SPNEGO */
1119
1120         if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1121                 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1122                                                              workgroup, NULL);
1123                 if (!ADS_ERR_OK(status)) {
1124                         DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1125                         return ads_ntstatus(status);
1126                 }
1127         } else {
1128                 NTSTATUS status;
1129
1130                 /* otherwise do a NT1 style session setup */
1131                 status = cli_session_setup_nt1(cli, user, pass, passlen,
1132                                                ntpass, ntpasslen, workgroup);
1133                 if (!NT_STATUS_IS_OK(status)) {
1134                         DEBUG(3,("cli_session_setup: NT1 session setup "
1135                                  "failed: %s\n", nt_errstr(status)));
1136                         return status;
1137                 }
1138         }
1139
1140         if (strstr(cli->server_type, "Samba")) {
1141                 cli->is_samba = True;
1142         }
1143
1144         return NT_STATUS_OK;
1145 }
1146
1147 /****************************************************************************
1148  Send a uloggoff.
1149 *****************************************************************************/
1150
1151 bool cli_ulogoff(struct cli_state *cli)
1152 {
1153         memset(cli->outbuf,'\0',smb_size);
1154         cli_set_message(cli->outbuf,2,0,True);
1155         SCVAL(cli->outbuf,smb_com,SMBulogoffX);
1156         cli_setup_packet(cli);
1157         SSVAL(cli->outbuf,smb_vwv0,0xFF);
1158         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
1159
1160         cli_send_smb(cli);
1161         if (!cli_receive_smb(cli))
1162                 return False;
1163
1164         if (cli_is_error(cli)) {
1165                 return False;
1166         }
1167
1168         cli->cnum = -1;
1169         return True;
1170 }
1171
1172 /****************************************************************************
1173  Send a tconX.
1174 ****************************************************************************/
1175
1176 struct async_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1177                                      struct event_context *ev,
1178                                      struct cli_state *cli,
1179                                      const char *share, const char *dev,
1180                                      const char *pass, int passlen)
1181 {
1182         fstring pword;
1183         char *tmp = NULL;
1184         struct async_req *result;
1185         uint16_t vwv[4];
1186         uint8_t *bytes;
1187
1188         fstrcpy(cli->share, share);
1189
1190         /* in user level security don't send a password now */
1191         if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1192                 passlen = 1;
1193                 pass = "";
1194         } else if (pass == NULL) {
1195                 DEBUG(1, ("Server not using user level security and no "
1196                           "password supplied.\n"));
1197                 goto access_denied;
1198         }
1199
1200         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1201             *pass && passlen != 24) {
1202                 if (!lp_client_lanman_auth()) {
1203                         DEBUG(1, ("Server requested LANMAN password "
1204                                   "(share-level security) but "
1205                                   "'client lanman auth' is disabled\n"));
1206                         goto access_denied;
1207                 }
1208
1209                 /*
1210                  * Non-encrypted passwords - convert to DOS codepage before
1211                  * encryption.
1212                  */
1213                 passlen = 24;
1214                 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1215         } else {
1216                 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1217                                      |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1218                    == 0) {
1219                         if (!lp_client_plaintext_auth() && (*pass)) {
1220                                 DEBUG(1, ("Server requested plaintext "
1221                                           "password but 'client plaintext "
1222                                           "auth' is disabled\n"));
1223                                 goto access_denied;
1224                         }
1225
1226                         /*
1227                          * Non-encrypted passwords - convert to DOS codepage
1228                          * before using.
1229                          */
1230                         passlen = clistr_push(cli, pword, pass, sizeof(pword),
1231                                               STR_TERMINATE);
1232                 } else {
1233                         if (passlen) {
1234                                 memcpy(pword, pass, passlen);
1235                         }
1236                 }
1237         }
1238
1239         SCVAL(vwv+0, 0, 0xFF);
1240         SCVAL(vwv+0, 1, 0);
1241         SSVAL(vwv+1, 0, 0);
1242         SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1243         SSVAL(vwv+3, 0, passlen);
1244
1245         if (passlen) {
1246                 bytes = (uint8_t *)talloc_memdup(talloc_tos(), pword, passlen);
1247         } else {
1248                 bytes = talloc_array(talloc_tos(), uint8_t, 0);
1249         }
1250
1251         /*
1252          * Add the sharename
1253          */
1254         tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1255                                          cli->desthost, share);
1256         if (tmp == NULL) {
1257                 TALLOC_FREE(bytes);
1258                 return NULL;
1259         }
1260         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1261                                    NULL);
1262         TALLOC_FREE(tmp);
1263
1264         /*
1265          * Add the devicetype
1266          */
1267         tmp = talloc_strdup_upper(talloc_tos(), dev);
1268         if (tmp == NULL) {
1269                 TALLOC_FREE(bytes);
1270                 return NULL;
1271         }
1272         bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1273         TALLOC_FREE(tmp);
1274
1275         if (bytes == NULL) {
1276                 return NULL;
1277         }
1278
1279         result = cli_request_send(mem_ctx, ev, cli, SMBtconX, 0,
1280                                   4, vwv, 0, talloc_get_size(bytes), bytes);
1281         TALLOC_FREE(bytes);
1282         return result;
1283
1284  access_denied:
1285         result = async_req_new(mem_ctx);
1286         if (async_post_ntstatus(result, ev, NT_STATUS_ACCESS_DENIED)) {
1287                 return result;
1288         }
1289         TALLOC_FREE(result);
1290         return NULL;
1291 }
1292
1293 NTSTATUS cli_tcon_andx_recv(struct async_req *req)
1294 {
1295         struct cli_request *cli_req = talloc_get_type_abort(
1296                 req->private_data, struct cli_request);
1297         struct cli_state *cli = cli_req->cli;
1298         uint8_t wct;
1299         uint16_t *vwv;
1300         uint16_t num_bytes;
1301         uint8_t *bytes;
1302         NTSTATUS status;
1303
1304         if (async_req_is_nterror(req, &status)) {
1305                 return status;
1306         }
1307
1308         status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1309         if (!NT_STATUS_IS_OK(status)) {
1310                 return status;
1311         }
1312
1313         clistr_pull(cli_req->inbuf, cli->dev, bytes, sizeof(fstring),
1314                     num_bytes, STR_TERMINATE|STR_ASCII);
1315
1316         if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1317                 /* almost certainly win95 - enable bug fixes */
1318                 cli->win95 = True;
1319         }
1320
1321         /*
1322          * Make sure that we have the optional support 16-bit field. WCT > 2.
1323          * Avoids issues when connecting to Win9x boxes sharing files
1324          */
1325
1326         cli->dfsroot = false;
1327
1328         if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1329                 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1330         }
1331
1332         cli->cnum = SVAL(cli_req->inbuf,smb_tid);
1333         return NT_STATUS_OK;
1334 }
1335
1336 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1337                        const char *dev, const char *pass, int passlen)
1338 {
1339         TALLOC_CTX *frame = talloc_stackframe();
1340         struct event_context *ev;
1341         struct async_req *req;
1342         NTSTATUS status;
1343
1344         if (cli->fd_event != NULL) {
1345                 /*
1346                  * Can't use sync call while an async call is in flight
1347                  */
1348                 status = NT_STATUS_INVALID_PARAMETER;
1349                 goto fail;
1350         }
1351
1352         ev = event_context_init(frame);
1353         if (ev == NULL) {
1354                 status = NT_STATUS_NO_MEMORY;
1355                 goto fail;
1356         }
1357
1358         req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1359         if (req == NULL) {
1360                 status = NT_STATUS_NO_MEMORY;
1361                 goto fail;
1362         }
1363
1364         while (req->state < ASYNC_REQ_DONE) {
1365                 event_loop_once(ev);
1366         }
1367
1368         status = cli_tcon_andx_recv(req);
1369  fail:
1370         TALLOC_FREE(frame);
1371         return status;
1372 }
1373
1374 /****************************************************************************
1375  Send a tree disconnect.
1376 ****************************************************************************/
1377
1378 bool cli_tdis(struct cli_state *cli)
1379 {
1380         memset(cli->outbuf,'\0',smb_size);
1381         cli_set_message(cli->outbuf,0,0,True);
1382         SCVAL(cli->outbuf,smb_com,SMBtdis);
1383         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1384         cli_setup_packet(cli);
1385
1386         cli_send_smb(cli);
1387         if (!cli_receive_smb(cli))
1388                 return False;
1389
1390         if (cli_is_error(cli)) {
1391                 return False;
1392         }
1393
1394         cli->cnum = -1;
1395         return True;
1396 }
1397
1398 /****************************************************************************
1399  Send a negprot command.
1400 ****************************************************************************/
1401
1402 void cli_negprot_sendsync(struct cli_state *cli)
1403 {
1404         char *p;
1405         int numprots;
1406
1407         if (cli->protocol < PROTOCOL_NT1)
1408                 cli->use_spnego = False;
1409
1410         memset(cli->outbuf,'\0',smb_size);
1411
1412         /* setup the protocol strings */
1413         cli_set_message(cli->outbuf,0,0,True);
1414
1415         p = smb_buf(cli->outbuf);
1416         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1417                 if (prots[numprots].prot > cli->protocol) {
1418                         break;
1419                 }
1420                 *p++ = 2;
1421                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1422         }
1423
1424         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1425         cli_setup_bcc(cli, p);
1426         cli_setup_packet(cli);
1427
1428         SCVAL(smb_buf(cli->outbuf),0,2);
1429
1430         cli_send_smb(cli);
1431 }
1432
1433 /****************************************************************************
1434  Send a negprot command.
1435 ****************************************************************************/
1436
1437 struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1438                                    struct event_context *ev,
1439                                    struct cli_state *cli)
1440 {
1441         struct async_req *result;
1442         uint8_t *bytes = NULL;
1443         int numprots;
1444
1445         if (cli->protocol < PROTOCOL_NT1)
1446                 cli->use_spnego = False;
1447
1448         /* setup the protocol strings */
1449         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1450                 uint8_t c = 2;
1451                 if (prots[numprots].prot > cli->protocol) {
1452                         break;
1453                 }
1454                 bytes = (uint8_t *)talloc_append_blob(
1455                         talloc_tos(), bytes, data_blob_const(&c, sizeof(c)));
1456                 if (bytes == NULL) {
1457                         return NULL;
1458                 }
1459                 bytes = smb_bytes_push_str(bytes, false,
1460                                            prots[numprots].name,
1461                                            strlen(prots[numprots].name)+1,
1462                                            NULL);
1463                 if (bytes == NULL) {
1464                         return NULL;
1465                 }
1466         }
1467
1468         result = cli_request_send(mem_ctx, ev, cli, SMBnegprot, 0, 0, NULL, 0,
1469                                   talloc_get_size(bytes), bytes);
1470         TALLOC_FREE(bytes);
1471         return result;
1472 }
1473
1474 NTSTATUS cli_negprot_recv(struct async_req *req)
1475 {
1476         struct cli_request *cli_req = talloc_get_type_abort(
1477                 req->private_data, struct cli_request);
1478         struct cli_state *cli = cli_req->cli;
1479         uint8_t wct;
1480         uint16_t *vwv;
1481         uint16_t num_bytes;
1482         uint8_t *bytes;
1483         NTSTATUS status;
1484         uint16_t protnum;
1485
1486         if (async_req_is_nterror(req, &status)) {
1487                 return status;
1488         }
1489
1490         status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1491         if (!NT_STATUS_IS_OK(status)) {
1492                 return status;
1493         }
1494
1495         protnum = SVAL(vwv, 0);
1496
1497         if ((protnum >= ARRAY_SIZE(prots))
1498             || (prots[protnum].prot > cli_req->cli->protocol)) {
1499                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1500         }
1501
1502         cli->protocol = prots[protnum].prot;
1503
1504         if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1505                 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1506                 return NT_STATUS_ACCESS_DENIED;
1507         }
1508
1509         if (cli->protocol >= PROTOCOL_NT1) {    
1510                 struct timespec ts;
1511                 /* NT protocol */
1512                 cli->sec_mode = CVAL(vwv + 1, 0);
1513                 cli->max_mux = SVAL(vwv + 1, 1);
1514                 cli->max_xmit = IVAL(vwv + 3, 1);
1515                 cli->sesskey = IVAL(vwv + 7, 1);
1516                 cli->serverzone = SVALS(vwv + 15, 1);
1517                 cli->serverzone *= 60;
1518                 /* this time arrives in real GMT */
1519                 ts = interpret_long_date(((char *)(vwv+11))+1);
1520                 cli->servertime = ts.tv_sec;
1521                 cli->secblob = data_blob(bytes, num_bytes);
1522                 cli->capabilities = IVAL(vwv + 9, 1);
1523                 if (cli->capabilities & CAP_RAW_MODE) {
1524                         cli->readbraw_supported = True;
1525                         cli->writebraw_supported = True;      
1526                 }
1527                 /* work out if they sent us a workgroup */
1528                 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1529                     smb_buflen(cli->inbuf) > 8) {
1530                         clistr_pull(cli->inbuf, cli->server_domain,
1531                                     bytes+8, sizeof(cli->server_domain),
1532                                     num_bytes-8,
1533                                     STR_UNICODE|STR_NOALIGN);
1534                 }
1535
1536                 /*
1537                  * As signing is slow we only turn it on if either the client or
1538                  * the server require it. JRA.
1539                  */
1540
1541                 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1542                         /* Fail if server says signing is mandatory and we don't want to support it. */
1543                         if (!cli->sign_info.allow_smb_signing) {
1544                                 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1545                                 return NT_STATUS_ACCESS_DENIED;
1546                         }
1547                         cli->sign_info.negotiated_smb_signing = True;
1548                         cli->sign_info.mandatory_signing = True;
1549                 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1550                         /* Fail if client says signing is mandatory and the server doesn't support it. */
1551                         if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1552                                 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1553                                 return NT_STATUS_ACCESS_DENIED;
1554                         }
1555                         cli->sign_info.negotiated_smb_signing = True;
1556                         cli->sign_info.mandatory_signing = True;
1557                 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1558                         cli->sign_info.negotiated_smb_signing = True;
1559                 }
1560
1561                 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1562                         SAFE_FREE(cli->outbuf);
1563                         SAFE_FREE(cli->inbuf);
1564                         cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1565                         cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1566                         cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1567                 }
1568
1569         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1570                 cli->use_spnego = False;
1571                 cli->sec_mode = SVAL(vwv + 1, 0);
1572                 cli->max_xmit = SVAL(vwv + 2, 0);
1573                 cli->max_mux = SVAL(vwv + 3, 0);
1574                 cli->sesskey = IVAL(vwv + 6, 0);
1575                 cli->serverzone = SVALS(vwv + 10, 0);
1576                 cli->serverzone *= 60;
1577                 /* this time is converted to GMT by make_unix_date */
1578                 cli->servertime = cli_make_unix_date(
1579                         cli, (char *)(vwv + 8));
1580                 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1581                 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1582                 cli->secblob = data_blob(bytes, num_bytes);
1583         } else {
1584                 /* the old core protocol */
1585                 cli->use_spnego = False;
1586                 cli->sec_mode = 0;
1587                 cli->serverzone = get_time_zone(time(NULL));
1588         }
1589
1590         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1591
1592         /* a way to force ascii SMB */
1593         if (getenv("CLI_FORCE_ASCII"))
1594                 cli->capabilities &= ~CAP_UNICODE;
1595
1596         return NT_STATUS_OK;
1597 }
1598
1599 NTSTATUS cli_negprot(struct cli_state *cli)
1600 {
1601         TALLOC_CTX *frame = talloc_stackframe();
1602         struct event_context *ev;
1603         struct async_req *req;
1604         NTSTATUS status = NT_STATUS_NO_MEMORY;
1605
1606         if (cli->fd_event != NULL) {
1607                 /*
1608                  * Can't use sync call while an async call is in flight
1609                  */
1610                 cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
1611                 goto fail;
1612         }
1613
1614         ev = event_context_init(frame);
1615         if (ev == NULL) {
1616                 goto fail;
1617         }
1618
1619         req = cli_negprot_send(frame, ev, cli);
1620         if (req == NULL) {
1621                 goto fail;
1622         }
1623
1624         while (req->state < ASYNC_REQ_DONE) {
1625                 event_loop_once(ev);
1626         }
1627
1628         status = cli_negprot_recv(req);
1629  fail:
1630         TALLOC_FREE(frame);
1631         return status;
1632 }
1633
1634 /****************************************************************************
1635  Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1636 ****************************************************************************/
1637
1638 bool cli_session_request(struct cli_state *cli,
1639                          struct nmb_name *calling, struct nmb_name *called)
1640 {
1641         char *p;
1642         int len = 4;
1643
1644         /* 445 doesn't have session request */
1645         if (cli->port == 445)
1646                 return True;
1647
1648         memcpy(&(cli->calling), calling, sizeof(*calling));
1649         memcpy(&(cli->called ), called , sizeof(*called ));
1650
1651         /* put in the destination name */
1652         p = cli->outbuf+len;
1653         name_mangle(cli->called .name, p, cli->called .name_type);
1654         len += name_len(p);
1655
1656         /* and my name */
1657         p = cli->outbuf+len;
1658         name_mangle(cli->calling.name, p, cli->calling.name_type);
1659         len += name_len(p);
1660
1661         /* send a session request (RFC 1002) */
1662         /* setup the packet length
1663          * Remove four bytes from the length count, since the length
1664          * field in the NBT Session Service header counts the number
1665          * of bytes which follow.  The cli_send_smb() function knows
1666          * about this and accounts for those four bytes.
1667          * CRH.
1668          */
1669         len -= 4;
1670         _smb_setlen(cli->outbuf,len);
1671         SCVAL(cli->outbuf,0,0x81);
1672
1673         cli_send_smb(cli);
1674         DEBUG(5,("Sent session request\n"));
1675
1676         if (!cli_receive_smb(cli))
1677                 return False;
1678
1679         if (CVAL(cli->inbuf,0) == 0x84) {
1680                 /* C. Hoch  9/14/95 Start */
1681                 /* For information, here is the response structure.
1682                  * We do the byte-twiddling to for portability.
1683                 struct RetargetResponse{
1684                 unsigned char type;
1685                 unsigned char flags;
1686                 int16 length;
1687                 int32 ip_addr;
1688                 int16 port;
1689                 };
1690                 */
1691                 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1692                 struct in_addr dest_ip;
1693                 NTSTATUS status;
1694
1695                 /* SESSION RETARGET */
1696                 putip((char *)&dest_ip,cli->inbuf+4);
1697                 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1698
1699                 status = open_socket_out(&cli->dest_ss, port,
1700                                          LONG_CONNECT_TIMEOUT, &cli->fd);
1701                 if (!NT_STATUS_IS_OK(status)) {
1702                         return False;
1703                 }
1704
1705                 DEBUG(3,("Retargeted\n"));
1706
1707                 set_socket_options(cli->fd, lp_socket_options());
1708
1709                 /* Try again */
1710                 {
1711                         static int depth;
1712                         bool ret;
1713                         if (depth > 4) {
1714                                 DEBUG(0,("Retarget recursion - failing\n"));
1715                                 return False;
1716                         }
1717                         depth++;
1718                         ret = cli_session_request(cli, calling, called);
1719                         depth--;
1720                         return ret;
1721                 }
1722         } /* C. Hoch 9/14/95 End */
1723
1724         if (CVAL(cli->inbuf,0) != 0x82) {
1725                 /* This is the wrong place to put the error... JRA. */
1726                 cli->rap_error = CVAL(cli->inbuf,4);
1727                 return False;
1728         }
1729         return(True);
1730 }
1731
1732 static void smb_sock_connected(struct async_req *req)
1733 {
1734         int *pfd = (int *)req->async.priv;
1735         int fd;
1736         NTSTATUS status;
1737
1738         status = open_socket_out_defer_recv(req, &fd);
1739         if (NT_STATUS_IS_OK(status)) {
1740                 *pfd = fd;
1741         }
1742 }
1743
1744 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1745                                 uint16_t *port, int timeout, int *pfd)
1746 {
1747         struct event_context *ev;
1748         struct async_req *r139, *r445;
1749         int fd139 = -1;
1750         int fd445 = -1;
1751         NTSTATUS status;
1752
1753         if (*port != 0) {
1754                 return open_socket_out(pss, *port, timeout, pfd);
1755         }
1756
1757         ev = event_context_init(talloc_tos());
1758         if (ev == NULL) {
1759                 return NT_STATUS_NO_MEMORY;
1760         }
1761
1762         r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1763                                           pss, 445, timeout);
1764         r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
1765                                           pss, 139, timeout);
1766         if ((r445 == NULL) || (r139 == NULL)) {
1767                 status = NT_STATUS_NO_MEMORY;
1768                 goto done;
1769         }
1770         r445->async.fn = smb_sock_connected;
1771         r445->async.priv = &fd445;
1772         r139->async.fn = smb_sock_connected;
1773         r139->async.priv = &fd139;
1774
1775         while ((fd139 == -1) && (r139->state < ASYNC_REQ_DONE)
1776                && (fd445 == -1) && (r445->state < ASYNC_REQ_DONE)) {
1777                 event_loop_once(ev);
1778         }
1779
1780         if ((fd139 != -1) && (fd445 != -1)) {
1781                 close(fd139);
1782                 fd139 = -1;
1783         }
1784
1785         if (fd445 != -1) {
1786                 *port = 445;
1787                 *pfd = fd445;
1788                 status = NT_STATUS_OK;
1789                 goto done;
1790         }
1791         if (fd139 != -1) {
1792                 *port = 139;
1793                 *pfd = fd139;
1794                 status = NT_STATUS_OK;
1795                 goto done;
1796         }
1797
1798         status = open_socket_out_defer_recv(r445, &fd445);
1799  done:
1800         TALLOC_FREE(ev);
1801         return status;
1802 }
1803
1804 /****************************************************************************
1805  Open the client sockets.
1806 ****************************************************************************/
1807
1808 NTSTATUS cli_connect(struct cli_state *cli,
1809                 const char *host,
1810                 struct sockaddr_storage *dest_ss)
1811
1812 {
1813         int name_type = 0x20;
1814         TALLOC_CTX *frame = talloc_stackframe();
1815         unsigned int num_addrs = 0;
1816         unsigned int i = 0;
1817         struct sockaddr_storage *ss_arr = NULL;
1818         char *p = NULL;
1819
1820         /* reasonable default hostname */
1821         if (!host) {
1822                 host = STAR_SMBSERVER;
1823         }
1824
1825         fstrcpy(cli->desthost, host);
1826
1827         /* allow hostnames of the form NAME#xx and do a netbios lookup */
1828         if ((p = strchr(cli->desthost, '#'))) {
1829                 name_type = strtol(p+1, NULL, 16);
1830                 *p = 0;
1831         }
1832
1833         if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
1834                 NTSTATUS status =resolve_name_list(frame,
1835                                         cli->desthost,
1836                                         name_type,
1837                                         &ss_arr,
1838                                         &num_addrs);
1839                 if (!NT_STATUS_IS_OK(status)) {
1840                         TALLOC_FREE(frame);
1841                         return NT_STATUS_BAD_NETWORK_NAME;
1842                 }
1843         } else {
1844                 num_addrs = 1;
1845                 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
1846                 if (!ss_arr) {
1847                         TALLOC_FREE(frame);
1848                         return NT_STATUS_NO_MEMORY;
1849                 }
1850                 *ss_arr = *dest_ss;
1851         }
1852
1853         for (i = 0; i < num_addrs; i++) {
1854                 cli->dest_ss = ss_arr[i];
1855                 if (getenv("LIBSMB_PROG")) {
1856                         cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1857                 } else {
1858                         uint16_t port = cli->port;
1859                         NTSTATUS status;
1860                         status = open_smb_socket(&cli->dest_ss, &port,
1861                                                  cli->timeout, &cli->fd);
1862                         if (NT_STATUS_IS_OK(status)) {
1863                                 cli->port = port;
1864                         }
1865                 }
1866                 if (cli->fd == -1) {
1867                         char addr[INET6_ADDRSTRLEN];
1868                         print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
1869                         DEBUG(2,("Error connecting to %s (%s)\n",
1870                                  dest_ss?addr:host,strerror(errno)));
1871                 } else {
1872                         /* Exit from loop on first connection. */
1873                         break;
1874                 }
1875         }
1876
1877         if (cli->fd == -1) {
1878                 TALLOC_FREE(frame);
1879                 return map_nt_error_from_unix(errno);
1880         }
1881
1882         if (dest_ss) {
1883                 *dest_ss = cli->dest_ss;
1884         }
1885
1886         set_socket_options(cli->fd, lp_socket_options());
1887
1888         TALLOC_FREE(frame);
1889         return NT_STATUS_OK;
1890 }
1891
1892 /**
1893    establishes a connection to after the negprot. 
1894    @param output_cli A fully initialised cli structure, non-null only on success
1895    @param dest_host The netbios name of the remote host
1896    @param dest_ss (optional) The the destination IP, NULL for name based lookup
1897    @param port (optional) The destination port (0 for default)
1898    @param retry bool. Did this connection fail with a retryable error ?
1899
1900 */
1901 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
1902                               const char *my_name, 
1903                               const char *dest_host, 
1904                               struct sockaddr_storage *dest_ss, int port,
1905                               int signing_state, int flags,
1906                               bool *retry) 
1907 {
1908         NTSTATUS nt_status;
1909         struct nmb_name calling;
1910         struct nmb_name called;
1911         struct cli_state *cli;
1912         struct sockaddr_storage ss;
1913
1914         if (retry)
1915                 *retry = False;
1916
1917         if (!my_name) 
1918                 my_name = global_myname();
1919
1920         if (!(cli = cli_initialise())) {
1921                 return NT_STATUS_NO_MEMORY;
1922         }
1923
1924         make_nmb_name(&calling, my_name, 0x0);
1925         make_nmb_name(&called , dest_host, 0x20);
1926
1927         cli_set_port(cli, port);
1928         cli_set_timeout(cli, 10000); /* 10 seconds. */
1929
1930         if (dest_ss) {
1931                 ss = *dest_ss;
1932         } else {
1933                 zero_sockaddr(&ss);
1934         }
1935
1936 again:
1937
1938         DEBUG(3,("Connecting to host=%s\n", dest_host));
1939
1940         nt_status = cli_connect(cli, dest_host, &ss);
1941         if (!NT_STATUS_IS_OK(nt_status)) {
1942                 char addr[INET6_ADDRSTRLEN];
1943                 print_sockaddr(addr, sizeof(addr), &ss);
1944                 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
1945                          nmb_namestr(&called), addr, nt_errstr(nt_status) ));
1946                 cli_shutdown(cli);
1947                 return nt_status;
1948         }
1949
1950         if (retry)
1951                 *retry = True;
1952
1953         if (!cli_session_request(cli, &calling, &called)) {
1954                 char *p;
1955                 DEBUG(1,("session request to %s failed (%s)\n",
1956                          called.name, cli_errstr(cli)));
1957                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1958                         *p = 0;
1959                         goto again;
1960                 }
1961                 if (strcmp(called.name, STAR_SMBSERVER)) {
1962                         make_nmb_name(&called , STAR_SMBSERVER, 0x20);
1963                         goto again;
1964                 }
1965                 return NT_STATUS_BAD_NETWORK_NAME;
1966         }
1967
1968         cli_setup_signing_state(cli, signing_state);
1969
1970         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1971                 cli->use_spnego = False;
1972         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1973                 cli->use_kerberos = True;
1974
1975         if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
1976              cli->use_kerberos) {
1977                 cli->fallback_after_kerberos = true;
1978         }
1979
1980         nt_status = cli_negprot(cli);
1981         if (!NT_STATUS_IS_OK(nt_status)) {
1982                 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
1983                 cli_shutdown(cli);
1984                 return nt_status;
1985         }
1986
1987         *output_cli = cli;
1988         return NT_STATUS_OK;
1989 }
1990
1991
1992 /**
1993    establishes a connection right up to doing tconX, password specified.
1994    @param output_cli A fully initialised cli structure, non-null only on success
1995    @param dest_host The netbios name of the remote host
1996    @param dest_ip (optional) The the destination IP, NULL for name based lookup
1997    @param port (optional) The destination port (0 for default)
1998    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
1999    @param service_type The 'type' of serivice. 
2000    @param user Username, unix string
2001    @param domain User's domain
2002    @param password User's password, unencrypted unix string.
2003    @param retry bool. Did this connection fail with a retryable error ?
2004 */
2005
2006 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
2007                              const char *my_name, 
2008                              const char *dest_host, 
2009                              struct sockaddr_storage *dest_ss, int port,
2010                              const char *service, const char *service_type,
2011                              const char *user, const char *domain, 
2012                              const char *password, int flags,
2013                              int signing_state,
2014                              bool *retry) 
2015 {
2016         NTSTATUS nt_status;
2017         struct cli_state *cli = NULL;
2018         int pw_len = password ? strlen(password)+1 : 0;
2019
2020         *output_cli = NULL;
2021
2022         if (password == NULL) {
2023                 password = "";
2024         }
2025
2026         nt_status = cli_start_connection(&cli, my_name, dest_host,
2027                                          dest_ss, port, signing_state,
2028                                          flags, retry);
2029
2030         if (!NT_STATUS_IS_OK(nt_status)) {
2031                 return nt_status;
2032         }
2033
2034         nt_status = cli_session_setup(cli, user, password, pw_len, password,
2035                                       pw_len, domain);
2036         if (!NT_STATUS_IS_OK(nt_status)) {
2037
2038                 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2039                         DEBUG(1,("failed session setup with %s\n",
2040                                  nt_errstr(nt_status)));
2041                         cli_shutdown(cli);
2042                         return nt_status;
2043                 }
2044
2045                 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2046                 if (!NT_STATUS_IS_OK(nt_status)) {
2047                         DEBUG(1,("anonymous failed session setup with %s\n",
2048                                  nt_errstr(nt_status)));
2049                         cli_shutdown(cli);
2050                         return nt_status;
2051                 }
2052         }
2053
2054         if (service) {
2055                 nt_status = cli_tcon_andx(cli, service, service_type, password,
2056                                           pw_len);
2057                 if (!NT_STATUS_IS_OK(nt_status)) {
2058                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2059                         cli_shutdown(cli);
2060                         if (NT_STATUS_IS_OK(nt_status)) {
2061                                 nt_status = NT_STATUS_UNSUCCESSFUL;
2062                         }
2063                         return nt_status;
2064                 }
2065         }
2066
2067         cli_init_creds(cli, user, domain, password);
2068
2069         *output_cli = cli;
2070         return NT_STATUS_OK;
2071 }
2072
2073 /****************************************************************************
2074  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2075 ****************************************************************************/
2076
2077 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2078                                      struct sockaddr_storage *pdest_ss)
2079 {
2080         struct nmb_name calling, called;
2081
2082         make_nmb_name(&calling, srchost, 0x0);
2083
2084         /*
2085          * If the called name is an IP address
2086          * then use *SMBSERVER immediately.
2087          */
2088
2089         if(is_ipaddress(desthost)) {
2090                 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2091         } else {
2092                 make_nmb_name(&called, desthost, 0x20);
2093         }
2094
2095         if (!cli_session_request(*ppcli, &calling, &called)) {
2096                 NTSTATUS status;
2097                 struct nmb_name smbservername;
2098
2099                 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2100
2101                 /*
2102                  * If the name wasn't *SMBSERVER then
2103                  * try with *SMBSERVER if the first name fails.
2104                  */
2105
2106                 if (nmb_name_equal(&called, &smbservername)) {
2107
2108                         /*
2109                          * The name used was *SMBSERVER, don't bother with another name.
2110                          */
2111
2112                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2113 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2114                         return False;
2115                 }
2116
2117                 /* Try again... */
2118                 cli_shutdown(*ppcli);
2119
2120                 *ppcli = cli_initialise();
2121                 if (!*ppcli) {
2122                         /* Out of memory... */
2123                         return False;
2124                 }
2125
2126                 status = cli_connect(*ppcli, desthost, pdest_ss);
2127                 if (!NT_STATUS_IS_OK(status) ||
2128                                 !cli_session_request(*ppcli, &calling, &smbservername)) {
2129                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2130 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2131                         return False;
2132                 }
2133         }
2134
2135         return True;
2136 }
2137
2138 /****************************************************************************
2139  Send an old style tcon.
2140 ****************************************************************************/
2141 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
2142                       const char *service, const char *pass, const char *dev,
2143                       uint16 *max_xmit, uint16 *tid)
2144 {
2145         char *p;
2146
2147         if (!lp_client_plaintext_auth() && (*pass)) {
2148                 DEBUG(1, ("Server requested plaintext password but 'client "
2149                           "plaintext auth' is disabled\n"));
2150                 return NT_STATUS_ACCESS_DENIED;
2151         }
2152
2153         memset(cli->outbuf,'\0',smb_size);
2154         memset(cli->inbuf,'\0',smb_size);
2155
2156         cli_set_message(cli->outbuf, 0, 0, True);
2157         SCVAL(cli->outbuf,smb_com,SMBtcon);
2158         cli_setup_packet(cli);
2159
2160         p = smb_buf(cli->outbuf);
2161         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2162         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2163         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2164
2165         cli_setup_bcc(cli, p);
2166
2167         cli_send_smb(cli);
2168         if (!cli_receive_smb(cli)) {
2169                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2170         }
2171
2172         if (cli_is_error(cli)) {
2173                 return cli_nt_error(cli);
2174         }
2175
2176         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2177         *tid = SVAL(cli->inbuf, smb_vwv1);
2178
2179         return NT_STATUS_OK;
2180 }
2181
2182 /* Return a cli_state pointing at the IPC$ share for the given server */
2183
2184 struct cli_state *get_ipc_connect(char *server,
2185                                 struct sockaddr_storage *server_ss,
2186                                 const struct user_auth_info *user_info)
2187 {
2188         struct cli_state *cli;
2189         NTSTATUS nt_status;
2190         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2191
2192         if (user_info->use_kerberos) {
2193                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2194         }
2195
2196         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
2197                                         user_info->username ? user_info->username : "",
2198                                         lp_workgroup(),
2199                                         user_info->password ? user_info->password : "",
2200                                         flags,
2201                                         Undefined, NULL);
2202
2203         if (NT_STATUS_IS_OK(nt_status)) {
2204                 return cli;
2205         } else if (is_ipaddress(server)) {
2206             /* windows 9* needs a correct NMB name for connections */
2207             fstring remote_name;
2208
2209             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2210                 cli = get_ipc_connect(remote_name, server_ss, user_info);
2211                 if (cli)
2212                     return cli;
2213             }
2214         }
2215         return NULL;
2216 }
2217
2218 /*
2219  * Given the IP address of a master browser on the network, return its
2220  * workgroup and connect to it.
2221  *
2222  * This function is provided to allow additional processing beyond what
2223  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2224  * browsers and obtain each master browsers' list of domains (in case the
2225  * first master browser is recently on the network and has not yet
2226  * synchronized with other master browsers and therefore does not yet have the
2227  * entire network browse list)
2228  */
2229
2230 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2231                                 struct ip_service *mb_ip,
2232                                 const struct user_auth_info *user_info,
2233                                 char **pp_workgroup_out)
2234 {
2235         char addr[INET6_ADDRSTRLEN];
2236         fstring name;
2237         struct cli_state *cli;
2238         struct sockaddr_storage server_ss;
2239
2240         *pp_workgroup_out = NULL;
2241
2242         print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2243         DEBUG(99, ("Looking up name of master browser %s\n",
2244                    addr));
2245
2246         /*
2247          * Do a name status query to find out the name of the master browser.
2248          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2249          * master browser will not respond to a wildcard query (or, at least,
2250          * an NT4 server acting as the domain master browser will not).
2251          *
2252          * We might be able to use ONLY the query on MSBROWSE, but that's not
2253          * yet been tested with all Windows versions, so until it is, leave
2254          * the original wildcard query as the first choice and fall back to
2255          * MSBROWSE if the wildcard query fails.
2256          */
2257         if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2258             !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2259
2260                 DEBUG(99, ("Could not retrieve name status for %s\n",
2261                            addr));
2262                 return NULL;
2263         }
2264
2265         if (!find_master_ip(name, &server_ss)) {
2266                 DEBUG(99, ("Could not find master ip for %s\n", name));
2267                 return NULL;
2268         }
2269
2270         *pp_workgroup_out = talloc_strdup(ctx, name);
2271
2272         DEBUG(4, ("found master browser %s, %s\n", name, addr));
2273
2274         print_sockaddr(addr, sizeof(addr), &server_ss);
2275         cli = get_ipc_connect(addr, &server_ss, user_info);
2276
2277         return cli;
2278 }
2279
2280 /*
2281  * Return the IP address and workgroup of a master browser on the network, and
2282  * connect to it.
2283  */
2284
2285 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2286                                         const struct user_auth_info *user_info,
2287                                         char **pp_workgroup_out)
2288 {
2289         struct ip_service *ip_list;
2290         struct cli_state *cli;
2291         int i, count;
2292
2293         *pp_workgroup_out = NULL;
2294
2295         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2296
2297         /* Go looking for workgroups by broadcasting on the local network */
2298
2299         if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2300                                                 &count))) {
2301                 DEBUG(99, ("No master browsers responded\n"));
2302                 return False;
2303         }
2304
2305         for (i = 0; i < count; i++) {
2306                 char addr[INET6_ADDRSTRLEN];
2307                 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2308                 DEBUG(99, ("Found master browser %s\n", addr));
2309
2310                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2311                                 user_info, pp_workgroup_out);
2312                 if (cli)
2313                         return(cli);
2314         }
2315
2316         return NULL;
2317 }