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