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