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