Merge branch 'master' of ssh://git.samba.org/data/git/samba
[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 cheated: spnego_gen_negTokenTarg can block if
858          * we have to acquire a ticket. To be fixed later :-)
859          */
860         rc = spnego_gen_negTokenTarg(principal, 0, &state->negTokenTarg,
861                                      &state->session_key_krb5, 0, NULL);
862         if (rc) {
863                 DEBUG(1, ("cli_session_setup_kerberos: "
864                           "spnego_gen_negTokenTarg 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
988         req = tevent_req_create(mem_ctx, &state,
989                                 struct cli_session_setup_ntlmssp_state);
990         if (req == NULL) {
991                 return NULL;
992         }
993         state->ev = ev;
994         state->cli = cli;
995         state->turn = 1;
996
997         state->ntlmssp_state = NULL;
998         talloc_set_destructor(
999                 state, cli_session_setup_ntlmssp_state_destructor);
1000
1001         cli_temp_set_signing(cli);
1002
1003         status = ntlmssp_client_start(state,
1004                                       global_myname(),
1005                                       lp_workgroup(),
1006                                       lp_client_ntlmv2_auth(),
1007                                       &state->ntlmssp_state);
1008         if (!NT_STATUS_IS_OK(status)) {
1009                 goto fail;
1010         }
1011         ntlmssp_want_feature(state->ntlmssp_state,
1012                              NTLMSSP_FEATURE_SESSION_KEY);
1013         if (cli->use_ccache) {
1014                 ntlmssp_want_feature(state->ntlmssp_state,
1015                                      NTLMSSP_FEATURE_CCACHE);
1016         }
1017         status = ntlmssp_set_username(state->ntlmssp_state, user);
1018         if (!NT_STATUS_IS_OK(status)) {
1019                 goto fail;
1020         }
1021         status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1022         if (!NT_STATUS_IS_OK(status)) {
1023                 goto fail;
1024         }
1025         status = ntlmssp_set_password(state->ntlmssp_state, pass);
1026         if (!NT_STATUS_IS_OK(status)) {
1027                 goto fail;
1028         }
1029         status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1030                                 &blob_out);
1031         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1032                 goto fail;
1033         }
1034
1035         state->blob_out = gen_negTokenInit(OID_NTLMSSP, blob_out);
1036         data_blob_free(&blob_out);
1037
1038         subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1039         if (tevent_req_nomem(subreq, req)) {
1040                 return tevent_req_post(req, ev);
1041         }
1042         tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1043         return req;
1044 fail:
1045         tevent_req_nterror(req, status);
1046         return tevent_req_post(req, ev);
1047 }
1048
1049 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1050 {
1051         struct tevent_req *req = tevent_req_callback_data(
1052                 subreq, struct tevent_req);
1053         struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1054                 req, struct cli_session_setup_ntlmssp_state);
1055         DATA_BLOB blob_in, msg_in, blob_out;
1056         char *inbuf = NULL;
1057         bool parse_ret;
1058         NTSTATUS status;
1059
1060         status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1061                                          &inbuf);
1062         TALLOC_FREE(subreq);
1063         data_blob_free(&state->blob_out);
1064
1065         if (NT_STATUS_IS_OK(status)) {
1066                 if (state->cli->server_domain[0] == '\0') {
1067                         fstrcpy(state->cli->server_domain,
1068                                 state->ntlmssp_state->server.netbios_domain);
1069                 }
1070                 cli_set_session_key(
1071                         state->cli, state->ntlmssp_state->session_key);
1072
1073                 if (cli_simple_set_signing(
1074                             state->cli, state->ntlmssp_state->session_key,
1075                             data_blob_null)
1076                     && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1077                         TALLOC_FREE(subreq);
1078                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1079                         return;
1080                 }
1081                 TALLOC_FREE(subreq);
1082                 TALLOC_FREE(state->ntlmssp_state);
1083                 tevent_req_done(req);
1084                 return;
1085         }
1086         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1087                 tevent_req_nterror(req, status);
1088                 return;
1089         }
1090
1091         if (blob_in.length == 0) {
1092                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1093                 return;
1094         }
1095
1096         if ((state->turn == 1)
1097             && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1098                 DATA_BLOB tmp_blob = data_blob_null;
1099                 /* the server might give us back two challenges */
1100                 parse_ret = spnego_parse_challenge(blob_in, &msg_in,
1101                                                    &tmp_blob);
1102                 data_blob_free(&tmp_blob);
1103         } else {
1104                 parse_ret = spnego_parse_auth_response(blob_in, status,
1105                                                        OID_NTLMSSP, &msg_in);
1106         }
1107         state->turn += 1;
1108
1109         if (!parse_ret) {
1110                 DEBUG(3,("Failed to parse auth response\n"));
1111                 if (NT_STATUS_IS_OK(status)
1112                     || NT_STATUS_EQUAL(status,
1113                                        NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1114                         tevent_req_nterror(
1115                                 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1116                         return;
1117                 }
1118         }
1119
1120         status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1121
1122         if (!NT_STATUS_IS_OK(status)
1123             && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1124                 TALLOC_FREE(subreq);
1125                 TALLOC_FREE(state->ntlmssp_state);
1126                 tevent_req_nterror(req, status);
1127                 return;
1128         }
1129
1130         state->blob_out = spnego_gen_auth(blob_out);
1131         TALLOC_FREE(subreq);
1132         if (tevent_req_nomem(state->blob_out.data, req)) {
1133                 return;
1134         }
1135
1136         subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1137                                          state->blob_out);
1138         if (tevent_req_nomem(subreq, req)) {
1139                 return;
1140         }
1141         tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1142 }
1143
1144 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1145 {
1146         struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1147                 req, struct cli_session_setup_ntlmssp_state);
1148         NTSTATUS status;
1149
1150         if (tevent_req_is_nterror(req, &status)) {
1151                 state->cli->vuid = 0;
1152                 return status;
1153         }
1154         return NT_STATUS_OK;
1155 }
1156
1157 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1158                                           const char *user,
1159                                           const char *pass,
1160                                           const char *domain)
1161 {
1162         struct tevent_context *ev;
1163         struct tevent_req *req;
1164         NTSTATUS status = NT_STATUS_NO_MEMORY;
1165
1166         if (cli_has_async_calls(cli)) {
1167                 return NT_STATUS_INVALID_PARAMETER;
1168         }
1169         ev = tevent_context_init(talloc_tos());
1170         if (ev == NULL) {
1171                 goto fail;
1172         }
1173         req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1174         if (req == NULL) {
1175                 goto fail;
1176         }
1177         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1178                 goto fail;
1179         }
1180         status = cli_session_setup_ntlmssp_recv(req);
1181 fail:
1182         TALLOC_FREE(ev);
1183         if (!NT_STATUS_IS_OK(status)) {
1184                 cli_set_error(cli, status);
1185         }
1186         return status;
1187 }
1188
1189 /****************************************************************************
1190  Do a spnego encrypted session setup.
1191
1192  user_domain: The shortname of the domain the user/machine is a member of.
1193  dest_realm: The realm we're connecting to, if NULL we use our default realm.
1194 ****************************************************************************/
1195
1196 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 
1197                               const char *pass, const char *user_domain,
1198                               const char * dest_realm)
1199 {
1200         char *principal = NULL;
1201         char *OIDs[ASN1_MAX_OIDS];
1202         int i;
1203         DATA_BLOB blob;
1204         const char *p = NULL;
1205         char *account = NULL;
1206         NTSTATUS status;
1207
1208         DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1209
1210         /* the server might not even do spnego */
1211         if (cli->secblob.length <= 16) {
1212                 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1213                 goto ntlmssp;
1214         }
1215
1216 #if 0
1217         file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1218 #endif
1219
1220         /* there is 16 bytes of GUID before the real spnego packet starts */
1221         blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1222
1223         /* The server sent us the first part of the SPNEGO exchange in the
1224          * negprot reply. It is WRONG to depend on the principal sent in the
1225          * negprot reply, but right now we do it. If we don't receive one,
1226          * we try to best guess, then fall back to NTLM.  */
1227         if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
1228                 data_blob_free(&blob);
1229                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1230         }
1231         data_blob_free(&blob);
1232
1233         /* make sure the server understands kerberos */
1234         for (i=0;OIDs[i];i++) {
1235                 if (i == 0)
1236                         DEBUG(3,("got OID=%s\n", OIDs[i]));
1237                 else
1238                         DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1239                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1240                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1241                         cli->got_kerberos_mechanism = True;
1242                 }
1243                 talloc_free(OIDs[i]);
1244         }
1245
1246         DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1247
1248         status = cli_set_username(cli, user);
1249         if (!NT_STATUS_IS_OK(status)) {
1250                 return ADS_ERROR_NT(status);
1251         }
1252
1253 #ifdef HAVE_KRB5
1254         /* If password is set we reauthenticate to kerberos server
1255          * and do not store results */
1256
1257         if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1258                 ADS_STATUS rc;
1259
1260                 if (pass && *pass) {
1261                         int ret;
1262
1263                         use_in_memory_ccache();
1264                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1265
1266                         if (ret){
1267                                 TALLOC_FREE(principal);
1268                                 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1269                                 if (cli->fallback_after_kerberos)
1270                                         goto ntlmssp;
1271                                 return ADS_ERROR_KRB5(ret);
1272                         }
1273                 }
1274
1275                 /* If we get a bad principal, try to guess it if
1276                    we have a valid host NetBIOS name.
1277                  */
1278                 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1279                         TALLOC_FREE(principal);
1280                 }
1281
1282                 if (principal == NULL &&
1283                         !is_ipaddress(cli->desthost) &&
1284                         !strequal(STAR_SMBSERVER,
1285                                 cli->desthost)) {
1286                         char *realm = NULL;
1287                         char *machine = NULL;
1288                         char *host = NULL;
1289                         DEBUG(3,("cli_session_setup_spnego: got a "
1290                                 "bad server principal, trying to guess ...\n"));
1291
1292                         host = strchr_m(cli->desthost, '.');
1293                         if (host) {
1294                                 /* We had a '.' in the name. */
1295                                 machine = SMB_STRNDUP(cli->desthost,
1296                                         host - cli->desthost);
1297                         } else {
1298                                 machine = SMB_STRDUP(cli->desthost);
1299                         }
1300                         if (machine == NULL) {
1301                                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1302                         }
1303
1304                         if (dest_realm) {
1305                                 realm = SMB_STRDUP(dest_realm);
1306                                 strupper_m(realm);
1307                         } else {
1308                                 if (host) {
1309                                         /* DNS name. */
1310                                         realm = kerberos_get_realm_from_hostname(cli->desthost);
1311                                 } else {
1312                                         /* NetBIOS name - use our realm. */
1313                                         realm = kerberos_get_default_realm_from_ccache();
1314                                 }
1315                         }
1316
1317                         if (realm && *realm) {
1318                                 if (host) {
1319                                         /* DNS name. */
1320                                         principal = talloc_asprintf(talloc_tos(),
1321                                                         "cifs/%s@%s",
1322                                                         cli->desthost,
1323                                                         realm);
1324                                 } else {
1325                                         /* NetBIOS name, use machine account. */
1326                                         principal = talloc_asprintf(talloc_tos(),
1327                                                         "%s$@%s",
1328                                                         machine,
1329                                                         realm);
1330                                 }
1331                                 if (!principal) {
1332                                         SAFE_FREE(machine);
1333                                         SAFE_FREE(realm);
1334                                         return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1335                                 }
1336                                 DEBUG(3,("cli_session_setup_spnego: guessed "
1337                                         "server principal=%s\n",
1338                                         principal ? principal : "<null>"));
1339                         }
1340                         SAFE_FREE(machine);
1341                         SAFE_FREE(realm);
1342                 }
1343
1344                 if (principal) {
1345                         rc = cli_session_setup_kerberos(cli, principal,
1346                                 dest_realm);
1347                         if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1348                                 TALLOC_FREE(principal);
1349                                 return rc;
1350                         }
1351                 }
1352         }
1353 #endif
1354
1355         TALLOC_FREE(principal);
1356
1357 ntlmssp:
1358
1359         account = talloc_strdup(talloc_tos(), user);
1360         if (!account) {
1361                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1362         }
1363
1364         /* when falling back to ntlmssp while authenticating with a machine
1365          * account strip off the realm - gd */
1366
1367         if ((p = strchr_m(user, '@')) != NULL) {
1368                 account[PTR_DIFF(p,user)] = '\0';
1369         }
1370
1371         return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1372 }
1373
1374 /****************************************************************************
1375  Send a session setup. The username and workgroup is in UNIX character
1376  format and must be converted to DOS codepage format before sending. If the
1377  password is in plaintext, the same should be done.
1378 ****************************************************************************/
1379
1380 NTSTATUS cli_session_setup(struct cli_state *cli,
1381                            const char *user,
1382                            const char *pass, int passlen,
1383                            const char *ntpass, int ntpasslen,
1384                            const char *workgroup)
1385 {
1386         char *p;
1387         fstring user2;
1388
1389         if (user) {
1390                 fstrcpy(user2, user);
1391         } else {
1392                 user2[0] ='\0';
1393         }
1394
1395         if (!workgroup) {
1396                 workgroup = "";
1397         }
1398
1399         /* allow for workgroups as part of the username */
1400         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1401             (p=strchr_m(user2,*lp_winbind_separator()))) {
1402                 *p = 0;
1403                 user = p+1;
1404                 workgroup = user2;
1405         }
1406
1407         if (cli->protocol < PROTOCOL_LANMAN1) {
1408                 return NT_STATUS_OK;
1409         }
1410
1411         /* now work out what sort of session setup we are going to
1412            do. I have split this into separate functions to make the
1413            flow a bit easier to understand (tridge) */
1414
1415         /* if its an older server then we have to use the older request format */
1416
1417         if (cli->protocol < PROTOCOL_NT1) {
1418                 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1419                         DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1420                                   " is disabled\n"));
1421                         return NT_STATUS_ACCESS_DENIED;
1422                 }
1423
1424                 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1425                     !lp_client_plaintext_auth() && (*pass)) {
1426                         DEBUG(1, ("Server requested plaintext password but "
1427                                   "'client plaintext auth' is disabled\n"));
1428                         return NT_STATUS_ACCESS_DENIED;
1429                 }
1430
1431                 return cli_session_setup_lanman2(cli, user, pass, passlen,
1432                                                  workgroup);
1433         }
1434
1435         /* if no user is supplied then we have to do an anonymous connection.
1436            passwords are ignored */
1437
1438         if (!user || !*user)
1439                 return cli_session_setup_guest(cli);
1440
1441         /* if the server is share level then send a plaintext null
1442            password at this point. The password is sent in the tree
1443            connect */
1444
1445         if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 
1446                 return cli_session_setup_plaintext(cli, user, "", workgroup);
1447
1448         /* if the server doesn't support encryption then we have to use 
1449            plaintext. The second password is ignored */
1450
1451         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1452                 if (!lp_client_plaintext_auth() && (*pass)) {
1453                         DEBUG(1, ("Server requested plaintext password but "
1454                                   "'client plaintext auth' is disabled\n"));
1455                         return NT_STATUS_ACCESS_DENIED;
1456                 }
1457                 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1458         }
1459
1460         /* if the server supports extended security then use SPNEGO */
1461
1462         if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1463                 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1464                                                              workgroup, NULL);
1465                 if (!ADS_ERR_OK(status)) {
1466                         DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1467                         return ads_ntstatus(status);
1468                 }
1469         } else {
1470                 NTSTATUS status;
1471
1472                 /* otherwise do a NT1 style session setup */
1473                 status = cli_session_setup_nt1(cli, user, pass, passlen,
1474                                                ntpass, ntpasslen, workgroup);
1475                 if (!NT_STATUS_IS_OK(status)) {
1476                         DEBUG(3,("cli_session_setup: NT1 session setup "
1477                                  "failed: %s\n", nt_errstr(status)));
1478                         return status;
1479                 }
1480         }
1481
1482         if (strstr(cli->server_type, "Samba")) {
1483                 cli->is_samba = True;
1484         }
1485
1486         return NT_STATUS_OK;
1487 }
1488
1489 /****************************************************************************
1490  Send a uloggoff.
1491 *****************************************************************************/
1492
1493 struct cli_ulogoff_state {
1494         struct cli_state *cli;
1495         uint16_t vwv[2];
1496 };
1497
1498 static void cli_ulogoff_done(struct tevent_req *subreq);
1499
1500 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1501                                     struct tevent_context *ev,
1502                                     struct cli_state *cli)
1503 {
1504         struct tevent_req *req, *subreq;
1505         struct cli_ulogoff_state *state;
1506
1507         req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1508         if (req == NULL) {
1509                 return NULL;
1510         }
1511         state->cli = cli;
1512
1513         SCVAL(state->vwv+0, 0, 0xFF);
1514         SCVAL(state->vwv+1, 0, 0);
1515         SSVAL(state->vwv+2, 0, 0);
1516
1517         subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
1518                               0, NULL);
1519         if (tevent_req_nomem(subreq, req)) {
1520                 return tevent_req_post(req, ev);
1521         }
1522         tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1523         return req;
1524 }
1525
1526 static void cli_ulogoff_done(struct tevent_req *subreq)
1527 {
1528         struct tevent_req *req = tevent_req_callback_data(
1529                 subreq, struct tevent_req);
1530         struct cli_ulogoff_state *state = tevent_req_data(
1531                 req, struct cli_ulogoff_state);
1532         NTSTATUS status;
1533
1534         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1535         if (!NT_STATUS_IS_OK(status)) {
1536                 tevent_req_nterror(req, status);
1537                 return;
1538         }
1539         state->cli->vuid = -1;
1540         tevent_req_done(req);
1541 }
1542
1543 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1544 {
1545         return tevent_req_simple_recv_ntstatus(req);
1546 }
1547
1548 NTSTATUS cli_ulogoff(struct cli_state *cli)
1549 {
1550         struct tevent_context *ev;
1551         struct tevent_req *req;
1552         NTSTATUS status = NT_STATUS_NO_MEMORY;
1553
1554         if (cli_has_async_calls(cli)) {
1555                 return NT_STATUS_INVALID_PARAMETER;
1556         }
1557         ev = tevent_context_init(talloc_tos());
1558         if (ev == NULL) {
1559                 goto fail;
1560         }
1561         req = cli_ulogoff_send(ev, ev, cli);
1562         if (req == NULL) {
1563                 goto fail;
1564         }
1565         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1566                 goto fail;
1567         }
1568         status = cli_ulogoff_recv(req);
1569 fail:
1570         TALLOC_FREE(ev);
1571         if (!NT_STATUS_IS_OK(status)) {
1572                 cli_set_error(cli, status);
1573         }
1574         return status;
1575 }
1576
1577 /****************************************************************************
1578  Send a tconX.
1579 ****************************************************************************/
1580
1581 struct cli_tcon_andx_state {
1582         struct cli_state *cli;
1583         uint16_t vwv[4];
1584         struct iovec bytes;
1585 };
1586
1587 static void cli_tcon_andx_done(struct tevent_req *subreq);
1588
1589 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1590                                         struct event_context *ev,
1591                                         struct cli_state *cli,
1592                                         const char *share, const char *dev,
1593                                         const char *pass, int passlen,
1594                                         struct tevent_req **psmbreq)
1595 {
1596         struct tevent_req *req, *subreq;
1597         struct cli_tcon_andx_state *state;
1598         fstring pword;
1599         uint16_t *vwv;
1600         char *tmp = NULL;
1601         uint8_t *bytes;
1602
1603         *psmbreq = NULL;
1604
1605         req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1606         if (req == NULL) {
1607                 return NULL;
1608         }
1609         state->cli = cli;
1610         vwv = state->vwv;
1611
1612         fstrcpy(cli->share, share);
1613
1614         /* in user level security don't send a password now */
1615         if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1616                 passlen = 1;
1617                 pass = "";
1618         } else if (pass == NULL) {
1619                 DEBUG(1, ("Server not using user level security and no "
1620                           "password supplied.\n"));
1621                 goto access_denied;
1622         }
1623
1624         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1625             *pass && passlen != 24) {
1626                 if (!lp_client_lanman_auth()) {
1627                         DEBUG(1, ("Server requested LANMAN password "
1628                                   "(share-level security) but "
1629                                   "'client lanman auth' is disabled\n"));
1630                         goto access_denied;
1631                 }
1632
1633                 /*
1634                  * Non-encrypted passwords - convert to DOS codepage before
1635                  * encryption.
1636                  */
1637                 passlen = 24;
1638                 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1639         } else {
1640                 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1641                                      |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1642                    == 0) {
1643                         if (!lp_client_plaintext_auth() && (*pass)) {
1644                                 DEBUG(1, ("Server requested plaintext "
1645                                           "password but 'client plaintext "
1646                                           "auth' is disabled\n"));
1647                                 goto access_denied;
1648                         }
1649
1650                         /*
1651                          * Non-encrypted passwords - convert to DOS codepage
1652                          * before using.
1653                          */
1654                         passlen = clistr_push(cli, pword, pass, sizeof(pword),
1655                                               STR_TERMINATE);
1656                         if (passlen == -1) {
1657                                 DEBUG(1, ("clistr_push(pword) failed\n"));
1658                                 goto access_denied;
1659                         }
1660                 } else {
1661                         if (passlen) {
1662                                 memcpy(pword, pass, passlen);
1663                         }
1664                 }
1665         }
1666
1667         SCVAL(vwv+0, 0, 0xFF);
1668         SCVAL(vwv+0, 1, 0);
1669         SSVAL(vwv+1, 0, 0);
1670         SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1671         SSVAL(vwv+3, 0, passlen);
1672
1673         if (passlen) {
1674                 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1675         } else {
1676                 bytes = talloc_array(state, uint8_t, 0);
1677         }
1678
1679         /*
1680          * Add the sharename
1681          */
1682         tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1683                                          cli->desthost, share);
1684         if (tmp == NULL) {
1685                 TALLOC_FREE(req);
1686                 return NULL;
1687         }
1688         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1689                                    NULL);
1690         TALLOC_FREE(tmp);
1691
1692         /*
1693          * Add the devicetype
1694          */
1695         tmp = talloc_strdup_upper(talloc_tos(), dev);
1696         if (tmp == NULL) {
1697                 TALLOC_FREE(req);
1698                 return NULL;
1699         }
1700         bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1701         TALLOC_FREE(tmp);
1702
1703         if (bytes == NULL) {
1704                 TALLOC_FREE(req);
1705                 return NULL;
1706         }
1707
1708         state->bytes.iov_base = (void *)bytes;
1709         state->bytes.iov_len = talloc_get_size(bytes);
1710
1711         subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1712                                     1, &state->bytes);
1713         if (subreq == NULL) {
1714                 TALLOC_FREE(req);
1715                 return NULL;
1716         }
1717         tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1718         *psmbreq = subreq;
1719         return req;
1720
1721  access_denied:
1722         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1723         return tevent_req_post(req, ev);
1724 }
1725
1726 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1727                                       struct event_context *ev,
1728                                       struct cli_state *cli,
1729                                       const char *share, const char *dev,
1730                                       const char *pass, int passlen)
1731 {
1732         struct tevent_req *req, *subreq;
1733         NTSTATUS status;
1734
1735         req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1736                                    &subreq);
1737         if (req == NULL) {
1738                 return NULL;
1739         }
1740         if (subreq == NULL) {
1741                 return req;
1742         }
1743         status = cli_smb_req_send(subreq);
1744         if (!NT_STATUS_IS_OK(status)) {
1745                 tevent_req_nterror(req, status);
1746                 return tevent_req_post(req, ev);
1747         }
1748         return req;
1749 }
1750
1751 static void cli_tcon_andx_done(struct tevent_req *subreq)
1752 {
1753         struct tevent_req *req = tevent_req_callback_data(
1754                 subreq, struct tevent_req);
1755         struct cli_tcon_andx_state *state = tevent_req_data(
1756                 req, struct cli_tcon_andx_state);
1757         struct cli_state *cli = state->cli;
1758         uint8_t *in;
1759         char *inbuf;
1760         uint8_t wct;
1761         uint16_t *vwv;
1762         uint32_t num_bytes;
1763         uint8_t *bytes;
1764         NTSTATUS status;
1765
1766         status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
1767                               &num_bytes, &bytes);
1768         TALLOC_FREE(subreq);
1769         if (!NT_STATUS_IS_OK(status)) {
1770                 tevent_req_nterror(req, status);
1771                 return;
1772         }
1773
1774         inbuf = (char *)in;
1775
1776         clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1777                     STR_TERMINATE|STR_ASCII);
1778
1779         if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1780                 /* almost certainly win95 - enable bug fixes */
1781                 cli->win95 = True;
1782         }
1783
1784         /*
1785          * Make sure that we have the optional support 16-bit field. WCT > 2.
1786          * Avoids issues when connecting to Win9x boxes sharing files
1787          */
1788
1789         cli->dfsroot = false;
1790
1791         if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1792                 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1793         }
1794
1795         cli->cnum = SVAL(inbuf,smb_tid);
1796         tevent_req_done(req);
1797 }
1798
1799 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1800 {
1801         return tevent_req_simple_recv_ntstatus(req);
1802 }
1803
1804 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1805                        const char *dev, const char *pass, int passlen)
1806 {
1807         TALLOC_CTX *frame = talloc_stackframe();
1808         struct event_context *ev;
1809         struct tevent_req *req;
1810         NTSTATUS status = NT_STATUS_OK;
1811
1812         if (cli_has_async_calls(cli)) {
1813                 /*
1814                  * Can't use sync call while an async call is in flight
1815                  */
1816                 status = NT_STATUS_INVALID_PARAMETER;
1817                 goto fail;
1818         }
1819
1820         ev = event_context_init(frame);
1821         if (ev == NULL) {
1822                 status = NT_STATUS_NO_MEMORY;
1823                 goto fail;
1824         }
1825
1826         req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1827         if (req == NULL) {
1828                 status = NT_STATUS_NO_MEMORY;
1829                 goto fail;
1830         }
1831
1832         if (!tevent_req_poll(req, ev)) {
1833                 status = map_nt_error_from_unix(errno);
1834                 goto fail;
1835         }
1836
1837         status = cli_tcon_andx_recv(req);
1838  fail:
1839         TALLOC_FREE(frame);
1840         if (!NT_STATUS_IS_OK(status)) {
1841                 cli_set_error(cli, status);
1842         }
1843         return status;
1844 }
1845
1846 /****************************************************************************
1847  Send a tree disconnect.
1848 ****************************************************************************/
1849
1850 struct cli_tdis_state {
1851         struct cli_state *cli;
1852 };
1853
1854 static void cli_tdis_done(struct tevent_req *subreq);
1855
1856 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
1857                                  struct tevent_context *ev,
1858                                  struct cli_state *cli)
1859 {
1860         struct tevent_req *req, *subreq;
1861         struct cli_tdis_state *state;
1862
1863         req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
1864         if (req == NULL) {
1865                 return NULL;
1866         }
1867         state->cli = cli;
1868
1869         subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
1870         if (tevent_req_nomem(subreq, req)) {
1871                 return tevent_req_post(req, ev);
1872         }
1873         tevent_req_set_callback(subreq, cli_tdis_done, req);
1874         return req;
1875 }
1876
1877 static void cli_tdis_done(struct tevent_req *subreq)
1878 {
1879         struct tevent_req *req = tevent_req_callback_data(
1880                 subreq, struct tevent_req);
1881         struct cli_tdis_state *state = tevent_req_data(
1882                 req, struct cli_tdis_state);
1883         NTSTATUS status;
1884
1885         status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1886         TALLOC_FREE(subreq);
1887         if (!NT_STATUS_IS_OK(status)) {
1888                 tevent_req_nterror(req, status);
1889                 return;
1890         }
1891         state->cli->cnum = -1;
1892         tevent_req_done(req);
1893 }
1894
1895 NTSTATUS cli_tdis_recv(struct tevent_req *req)
1896 {
1897         return tevent_req_simple_recv_ntstatus(req);
1898 }
1899
1900 NTSTATUS cli_tdis(struct cli_state *cli)
1901 {
1902         struct tevent_context *ev;
1903         struct tevent_req *req;
1904         NTSTATUS status = NT_STATUS_NO_MEMORY;
1905
1906         if (cli_has_async_calls(cli)) {
1907                 return NT_STATUS_INVALID_PARAMETER;
1908         }
1909         ev = tevent_context_init(talloc_tos());
1910         if (ev == NULL) {
1911                 goto fail;
1912         }
1913         req = cli_tdis_send(ev, ev, cli);
1914         if (req == NULL) {
1915                 goto fail;
1916         }
1917         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1918                 goto fail;
1919         }
1920         status = cli_tdis_recv(req);
1921 fail:
1922         TALLOC_FREE(ev);
1923         if (!NT_STATUS_IS_OK(status)) {
1924                 cli_set_error(cli, status);
1925         }
1926         return status;
1927 }
1928
1929 /****************************************************************************
1930  Send a negprot command.
1931 ****************************************************************************/
1932
1933 void cli_negprot_sendsync(struct cli_state *cli)
1934 {
1935         char *p;
1936         int numprots;
1937
1938         if (cli->protocol < PROTOCOL_NT1)
1939                 cli->use_spnego = False;
1940
1941         memset(cli->outbuf,'\0',smb_size);
1942
1943         /* setup the protocol strings */
1944         cli_set_message(cli->outbuf,0,0,True);
1945
1946         p = smb_buf(cli->outbuf);
1947         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1948                 if (prots[numprots].prot > cli->protocol) {
1949                         break;
1950                 }
1951                 *p++ = 2;
1952                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1953         }
1954
1955         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1956         cli_setup_bcc(cli, p);
1957         cli_setup_packet(cli);
1958
1959         SCVAL(smb_buf(cli->outbuf),0,2);
1960
1961         cli_send_smb(cli);
1962 }
1963
1964 /****************************************************************************
1965  Send a negprot command.
1966 ****************************************************************************/
1967
1968 struct cli_negprot_state {
1969         struct cli_state *cli;
1970 };
1971
1972 static void cli_negprot_done(struct tevent_req *subreq);
1973
1974 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1975                                     struct event_context *ev,
1976                                     struct cli_state *cli)
1977 {
1978         struct tevent_req *req, *subreq;
1979         struct cli_negprot_state *state;
1980         uint8_t *bytes = NULL;
1981         int numprots;
1982         uint16_t cnum;
1983
1984         req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1985         if (req == NULL) {
1986                 return NULL;
1987         }
1988         state->cli = cli;
1989
1990         if (cli->protocol < PROTOCOL_NT1)
1991                 cli->use_spnego = False;
1992
1993         /* setup the protocol strings */
1994         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1995                 uint8_t c = 2;
1996                 if (prots[numprots].prot > cli->protocol) {
1997                         break;
1998                 }
1999                 bytes = (uint8_t *)talloc_append_blob(
2000                         state, bytes, data_blob_const(&c, sizeof(c)));
2001                 if (tevent_req_nomem(bytes, req)) {
2002                         return tevent_req_post(req, ev);
2003                 }
2004                 bytes = smb_bytes_push_str(bytes, false,
2005                                            prots[numprots].name,
2006                                            strlen(prots[numprots].name)+1,
2007                                            NULL);
2008                 if (tevent_req_nomem(bytes, req)) {
2009                         return tevent_req_post(req, ev);
2010                 }
2011         }
2012
2013         cnum = cli->cnum;
2014
2015         cli->cnum = 0;
2016         subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
2017                               talloc_get_size(bytes), bytes);
2018         cli->cnum = cnum;
2019
2020         if (tevent_req_nomem(subreq, req)) {
2021                 return tevent_req_post(req, ev);
2022         }
2023         tevent_req_set_callback(subreq, cli_negprot_done, req);
2024         return req;
2025 }
2026
2027 static void cli_negprot_done(struct tevent_req *subreq)
2028 {
2029         struct tevent_req *req = tevent_req_callback_data(
2030                 subreq, struct tevent_req);
2031         struct cli_negprot_state *state = tevent_req_data(
2032                 req, struct cli_negprot_state);
2033         struct cli_state *cli = state->cli;
2034         uint8_t wct;
2035         uint16_t *vwv;
2036         uint32_t num_bytes;
2037         uint8_t *bytes;
2038         NTSTATUS status;
2039         uint16_t protnum;
2040         uint8_t *inbuf;
2041
2042         status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
2043                               &num_bytes, &bytes);
2044         TALLOC_FREE(subreq);
2045         if (!NT_STATUS_IS_OK(status)) {
2046                 tevent_req_nterror(req, status);
2047                 return;
2048         }
2049
2050         protnum = SVAL(vwv, 0);
2051
2052         if ((protnum >= ARRAY_SIZE(prots))
2053             || (prots[protnum].prot > cli->protocol)) {
2054                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2055                 return;
2056         }
2057
2058         cli->protocol = prots[protnum].prot;
2059
2060         if ((cli->protocol < PROTOCOL_NT1) &&
2061             client_is_signing_mandatory(cli)) {
2062                 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2063                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2064                 return;
2065         }
2066
2067         if (cli->protocol >= PROTOCOL_NT1) {    
2068                 struct timespec ts;
2069                 bool negotiated_smb_signing = false;
2070
2071                 /* NT protocol */
2072                 cli->sec_mode = CVAL(vwv + 1, 0);
2073                 cli->max_mux = SVAL(vwv + 1, 1);
2074                 cli->max_xmit = IVAL(vwv + 3, 1);
2075                 cli->sesskey = IVAL(vwv + 7, 1);
2076                 cli->serverzone = SVALS(vwv + 15, 1);
2077                 cli->serverzone *= 60;
2078                 /* this time arrives in real GMT */
2079                 ts = interpret_long_date(((char *)(vwv+11))+1);
2080                 cli->servertime = ts.tv_sec;
2081                 cli->secblob = data_blob(bytes, num_bytes);
2082                 cli->capabilities = IVAL(vwv + 9, 1);
2083                 if (cli->capabilities & CAP_RAW_MODE) {
2084                         cli->readbraw_supported = True;
2085                         cli->writebraw_supported = True;      
2086                 }
2087                 /* work out if they sent us a workgroup */
2088                 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2089                     smb_buflen(cli->inbuf) > 8) {
2090                         clistr_pull(cli->inbuf, cli->server_domain,
2091                                     bytes+8, sizeof(cli->server_domain),
2092                                     num_bytes-8,
2093                                     STR_UNICODE|STR_NOALIGN);
2094                 }
2095
2096                 /*
2097                  * As signing is slow we only turn it on if either the client or
2098                  * the server require it. JRA.
2099                  */
2100
2101                 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2102                         /* Fail if server says signing is mandatory and we don't want to support it. */
2103                         if (!client_is_signing_allowed(cli)) {
2104                                 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2105                                 tevent_req_nterror(req,
2106                                                    NT_STATUS_ACCESS_DENIED);
2107                                 return;
2108                         }
2109                         negotiated_smb_signing = true;
2110                 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2111                         /* Fail if client says signing is mandatory and the server doesn't support it. */
2112                         if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2113                                 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2114                                 tevent_req_nterror(req,
2115                                                    NT_STATUS_ACCESS_DENIED);
2116                                 return;
2117                         }
2118                         negotiated_smb_signing = true;
2119                 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2120                         negotiated_smb_signing = true;
2121                 }
2122
2123                 if (negotiated_smb_signing) {
2124                         cli_set_signing_negotiated(cli);
2125                 }
2126
2127                 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2128                         SAFE_FREE(cli->outbuf);
2129                         SAFE_FREE(cli->inbuf);
2130                         cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2131                         cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2132                         cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2133                 }
2134
2135         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2136                 cli->use_spnego = False;
2137                 cli->sec_mode = SVAL(vwv + 1, 0);
2138                 cli->max_xmit = SVAL(vwv + 2, 0);
2139                 cli->max_mux = SVAL(vwv + 3, 0);
2140                 cli->sesskey = IVAL(vwv + 6, 0);
2141                 cli->serverzone = SVALS(vwv + 10, 0);
2142                 cli->serverzone *= 60;
2143                 /* this time is converted to GMT by make_unix_date */
2144                 cli->servertime = cli_make_unix_date(
2145                         cli, (char *)(vwv + 8));
2146                 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2147                 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2148                 cli->secblob = data_blob(bytes, num_bytes);
2149         } else {
2150                 /* the old core protocol */
2151                 cli->use_spnego = False;
2152                 cli->sec_mode = 0;
2153                 cli->serverzone = get_time_zone(time(NULL));
2154         }
2155
2156         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2157
2158         /* a way to force ascii SMB */
2159         if (getenv("CLI_FORCE_ASCII"))
2160                 cli->capabilities &= ~CAP_UNICODE;
2161
2162         tevent_req_done(req);
2163 }
2164
2165 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2166 {
2167         return tevent_req_simple_recv_ntstatus(req);
2168 }
2169
2170 NTSTATUS cli_negprot(struct cli_state *cli)
2171 {
2172         TALLOC_CTX *frame = talloc_stackframe();
2173         struct event_context *ev;
2174         struct tevent_req *req;
2175         NTSTATUS status = NT_STATUS_OK;
2176
2177         if (cli_has_async_calls(cli)) {
2178                 /*
2179                  * Can't use sync call while an async call is in flight
2180                  */
2181                 status = NT_STATUS_INVALID_PARAMETER;
2182                 goto fail;
2183         }
2184
2185         ev = event_context_init(frame);
2186         if (ev == NULL) {
2187                 status = NT_STATUS_NO_MEMORY;
2188                 goto fail;
2189         }
2190
2191         req = cli_negprot_send(frame, ev, cli);
2192         if (req == NULL) {
2193                 status = NT_STATUS_NO_MEMORY;
2194                 goto fail;
2195         }
2196
2197         if (!tevent_req_poll(req, ev)) {
2198                 status = map_nt_error_from_unix(errno);
2199                 goto fail;
2200         }
2201
2202         status = cli_negprot_recv(req);
2203  fail:
2204         TALLOC_FREE(frame);
2205         if (!NT_STATUS_IS_OK(status)) {
2206                 cli_set_error(cli, status);
2207         }
2208         return status;
2209 }
2210
2211 /****************************************************************************
2212  Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2213 ****************************************************************************/
2214
2215 bool cli_session_request(struct cli_state *cli,
2216                          struct nmb_name *calling, struct nmb_name *called)
2217 {
2218         char *p;
2219         int len = 4;
2220         char *tmp;
2221
2222         /* 445 doesn't have session request */
2223         if (cli->port == 445)
2224                 return True;
2225
2226         memcpy(&(cli->calling), calling, sizeof(*calling));
2227         memcpy(&(cli->called ), called , sizeof(*called ));
2228
2229         /* put in the destination name */
2230
2231         tmp = name_mangle(talloc_tos(), cli->called.name,
2232                           cli->called.name_type);
2233         if (tmp == NULL) {
2234                 return false;
2235         }
2236
2237         p = cli->outbuf+len;
2238         memcpy(p, tmp, name_len(tmp));
2239         len += name_len(tmp);
2240         TALLOC_FREE(tmp);
2241
2242         /* and my name */
2243
2244         tmp = name_mangle(talloc_tos(), cli->calling.name,
2245                           cli->calling.name_type);
2246         if (tmp == NULL) {
2247                 return false;
2248         }
2249
2250         p = cli->outbuf+len;
2251         memcpy(p, tmp, name_len(tmp));
2252         len += name_len(tmp);
2253         TALLOC_FREE(tmp);
2254
2255         /* send a session request (RFC 1002) */
2256         /* setup the packet length
2257          * Remove four bytes from the length count, since the length
2258          * field in the NBT Session Service header counts the number
2259          * of bytes which follow.  The cli_send_smb() function knows
2260          * about this and accounts for those four bytes.
2261          * CRH.
2262          */
2263         len -= 4;
2264         _smb_setlen(cli->outbuf,len);
2265         SCVAL(cli->outbuf,0,0x81);
2266
2267         cli_send_smb(cli);
2268         DEBUG(5,("Sent session request\n"));
2269
2270         if (!cli_receive_smb(cli))
2271                 return False;
2272
2273         if (CVAL(cli->inbuf,0) == 0x84) {
2274                 /* C. Hoch  9/14/95 Start */
2275                 /* For information, here is the response structure.
2276                  * We do the byte-twiddling to for portability.
2277                 struct RetargetResponse{
2278                 unsigned char type;
2279                 unsigned char flags;
2280                 int16 length;
2281                 int32 ip_addr;
2282                 int16 port;
2283                 };
2284                 */
2285                 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2286                 struct in_addr dest_ip;
2287                 NTSTATUS status;
2288
2289                 /* SESSION RETARGET */
2290                 putip((char *)&dest_ip,cli->inbuf+4);
2291                 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2292
2293                 status = open_socket_out(&cli->dest_ss, port,
2294                                          LONG_CONNECT_TIMEOUT, &cli->fd);
2295                 if (!NT_STATUS_IS_OK(status)) {
2296                         return False;
2297                 }
2298
2299                 DEBUG(3,("Retargeted\n"));
2300
2301                 set_socket_options(cli->fd, lp_socket_options());
2302
2303                 /* Try again */
2304                 {
2305                         static int depth;
2306                         bool ret;
2307                         if (depth > 4) {
2308                                 DEBUG(0,("Retarget recursion - failing\n"));
2309                                 return False;
2310                         }
2311                         depth++;
2312                         ret = cli_session_request(cli, calling, called);
2313                         depth--;
2314                         return ret;
2315                 }
2316         } /* C. Hoch 9/14/95 End */
2317
2318         if (CVAL(cli->inbuf,0) != 0x82) {
2319                 /* This is the wrong place to put the error... JRA. */
2320                 cli->rap_error = CVAL(cli->inbuf,4);
2321                 return False;
2322         }
2323         return(True);
2324 }
2325
2326 struct fd_struct {
2327         int fd;
2328 };
2329
2330 static void smb_sock_connected(struct tevent_req *req)
2331 {
2332         struct fd_struct *pfd = tevent_req_callback_data(
2333                 req, struct fd_struct);
2334         int fd;
2335         NTSTATUS status;
2336
2337         status = open_socket_out_defer_recv(req, &fd);
2338         if (NT_STATUS_IS_OK(status)) {
2339                 pfd->fd = fd;
2340         }
2341 }
2342
2343 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2344                                 uint16_t *port, int timeout, int *pfd)
2345 {
2346         struct event_context *ev;
2347         struct tevent_req *r139, *r445;
2348         struct fd_struct *fd139, *fd445;
2349         NTSTATUS status = NT_STATUS_NO_MEMORY;
2350
2351         if (*port != 0) {
2352                 return open_socket_out(pss, *port, timeout, pfd);
2353         }
2354
2355         ev = event_context_init(talloc_tos());
2356         if (ev == NULL) {
2357                 return NT_STATUS_NO_MEMORY;
2358         }
2359
2360         fd139 = talloc(ev, struct fd_struct);
2361         if (fd139 == NULL) {
2362                 goto done;
2363         }
2364         fd139->fd = -1;
2365
2366         fd445 = talloc(ev, struct fd_struct);
2367         if (fd445 == NULL) {
2368                 goto done;
2369         }
2370         fd445->fd = -1;
2371
2372         r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2373                                           pss, 445, timeout);
2374         r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2375                                           pss, 139, timeout);
2376         if ((r445 == NULL) || (r139 == NULL)) {
2377                 goto done;
2378         }
2379         tevent_req_set_callback(r445, smb_sock_connected, fd445);
2380         tevent_req_set_callback(r139, smb_sock_connected, fd139);
2381
2382         while ((fd445->fd == -1) && (fd139->fd == -1)
2383                && (tevent_req_is_in_progress(r139)
2384                    || tevent_req_is_in_progress(r445))) {
2385                 event_loop_once(ev);
2386         }
2387
2388         if ((fd139->fd != -1) && (fd445->fd != -1)) {
2389                 close(fd139->fd);
2390                 fd139->fd = -1;
2391         }
2392
2393         if (fd445->fd != -1) {
2394                 *port = 445;
2395                 *pfd = fd445->fd;
2396                 status = NT_STATUS_OK;
2397                 goto done;
2398         }
2399         if (fd139->fd != -1) {
2400                 *port = 139;
2401                 *pfd = fd139->fd;
2402                 status = NT_STATUS_OK;
2403                 goto done;
2404         }
2405
2406         status = open_socket_out_defer_recv(r445, &fd445->fd);
2407  done:
2408         TALLOC_FREE(ev);
2409         return status;
2410 }
2411
2412 /****************************************************************************
2413  Open the client sockets.
2414 ****************************************************************************/
2415
2416 NTSTATUS cli_connect(struct cli_state *cli,
2417                 const char *host,
2418                 struct sockaddr_storage *dest_ss)
2419
2420 {
2421         int name_type = 0x20;
2422         TALLOC_CTX *frame = talloc_stackframe();
2423         unsigned int num_addrs = 0;
2424         unsigned int i = 0;
2425         struct sockaddr_storage *ss_arr = NULL;
2426         char *p = NULL;
2427
2428         /* reasonable default hostname */
2429         if (!host) {
2430                 host = STAR_SMBSERVER;
2431         }
2432
2433         fstrcpy(cli->desthost, host);
2434
2435         /* allow hostnames of the form NAME#xx and do a netbios lookup */
2436         if ((p = strchr(cli->desthost, '#'))) {
2437                 name_type = strtol(p+1, NULL, 16);
2438                 *p = 0;
2439         }
2440
2441         if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2442                 NTSTATUS status =resolve_name_list(frame,
2443                                         cli->desthost,
2444                                         name_type,
2445                                         &ss_arr,
2446                                         &num_addrs);
2447                 if (!NT_STATUS_IS_OK(status)) {
2448                         TALLOC_FREE(frame);
2449                         return NT_STATUS_BAD_NETWORK_NAME;
2450                 }
2451         } else {
2452                 num_addrs = 1;
2453                 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2454                 if (!ss_arr) {
2455                         TALLOC_FREE(frame);
2456                         return NT_STATUS_NO_MEMORY;
2457                 }
2458                 *ss_arr = *dest_ss;
2459         }
2460
2461         for (i = 0; i < num_addrs; i++) {
2462                 cli->dest_ss = ss_arr[i];
2463                 if (getenv("LIBSMB_PROG")) {
2464                         cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2465                 } else {
2466                         uint16_t port = cli->port;
2467                         NTSTATUS status;
2468                         status = open_smb_socket(&cli->dest_ss, &port,
2469                                                  cli->timeout, &cli->fd);
2470                         if (NT_STATUS_IS_OK(status)) {
2471                                 cli->port = port;
2472                         }
2473                 }
2474                 if (cli->fd == -1) {
2475                         char addr[INET6_ADDRSTRLEN];
2476                         print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2477                         DEBUG(2,("Error connecting to %s (%s)\n",
2478                                  dest_ss?addr:host,strerror(errno)));
2479                 } else {
2480                         /* Exit from loop on first connection. */
2481                         break;
2482                 }
2483         }
2484
2485         if (cli->fd == -1) {
2486                 TALLOC_FREE(frame);
2487                 return map_nt_error_from_unix(errno);
2488         }
2489
2490         if (dest_ss) {
2491                 *dest_ss = cli->dest_ss;
2492         }
2493
2494         set_socket_options(cli->fd, lp_socket_options());
2495
2496         TALLOC_FREE(frame);
2497         return NT_STATUS_OK;
2498 }
2499
2500 /**
2501    establishes a connection to after the negprot. 
2502    @param output_cli A fully initialised cli structure, non-null only on success
2503    @param dest_host The netbios name of the remote host
2504    @param dest_ss (optional) The the destination IP, NULL for name based lookup
2505    @param port (optional) The destination port (0 for default)
2506    @param retry bool. Did this connection fail with a retryable error ?
2507
2508 */
2509 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
2510                               const char *my_name, 
2511                               const char *dest_host, 
2512                               struct sockaddr_storage *dest_ss, int port,
2513                               int signing_state, int flags,
2514                               bool *retry) 
2515 {
2516         NTSTATUS nt_status;
2517         struct nmb_name calling;
2518         struct nmb_name called;
2519         struct cli_state *cli;
2520         struct sockaddr_storage ss;
2521
2522         if (retry)
2523                 *retry = False;
2524
2525         if (!my_name) 
2526                 my_name = global_myname();
2527
2528         if (!(cli = cli_initialise_ex(signing_state))) {
2529                 return NT_STATUS_NO_MEMORY;
2530         }
2531
2532         make_nmb_name(&calling, my_name, 0x0);
2533         make_nmb_name(&called , dest_host, 0x20);
2534
2535         cli_set_port(cli, port);
2536         cli_set_timeout(cli, 10000); /* 10 seconds. */
2537
2538         if (dest_ss) {
2539                 ss = *dest_ss;
2540         } else {
2541                 zero_sockaddr(&ss);
2542         }
2543
2544 again:
2545
2546         DEBUG(3,("Connecting to host=%s\n", dest_host));
2547
2548         nt_status = cli_connect(cli, dest_host, &ss);
2549         if (!NT_STATUS_IS_OK(nt_status)) {
2550                 char addr[INET6_ADDRSTRLEN];
2551                 print_sockaddr(addr, sizeof(addr), &ss);
2552                 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2553                          nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2554                 cli_shutdown(cli);
2555                 return nt_status;
2556         }
2557
2558         if (retry)
2559                 *retry = True;
2560
2561         if (!cli_session_request(cli, &calling, &called)) {
2562                 char *p;
2563                 DEBUG(1,("session request to %s failed (%s)\n",
2564                          called.name, cli_errstr(cli)));
2565                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2566                         *p = 0;
2567                         goto again;
2568                 }
2569                 if (strcmp(called.name, STAR_SMBSERVER)) {
2570                         make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2571                         goto again;
2572                 }
2573                 return NT_STATUS_BAD_NETWORK_NAME;
2574         }
2575
2576         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2577                 cli->use_spnego = False;
2578         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2579                 cli->use_kerberos = True;
2580
2581         if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2582              cli->use_kerberos) {
2583                 cli->fallback_after_kerberos = true;
2584         }
2585         if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2586                 cli->use_ccache = true;
2587         }
2588
2589         nt_status = cli_negprot(cli);
2590         if (!NT_STATUS_IS_OK(nt_status)) {
2591                 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2592                 cli_shutdown(cli);
2593                 return nt_status;
2594         }
2595
2596         *output_cli = cli;
2597         return NT_STATUS_OK;
2598 }
2599
2600
2601 /**
2602    establishes a connection right up to doing tconX, password specified.
2603    @param output_cli A fully initialised cli structure, non-null only on success
2604    @param dest_host The netbios name of the remote host
2605    @param dest_ip (optional) The the destination IP, NULL for name based lookup
2606    @param port (optional) The destination port (0 for default)
2607    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
2608    @param service_type The 'type' of serivice. 
2609    @param user Username, unix string
2610    @param domain User's domain
2611    @param password User's password, unencrypted unix string.
2612    @param retry bool. Did this connection fail with a retryable error ?
2613 */
2614
2615 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
2616                              const char *my_name, 
2617                              const char *dest_host, 
2618                              struct sockaddr_storage *dest_ss, int port,
2619                              const char *service, const char *service_type,
2620                              const char *user, const char *domain, 
2621                              const char *password, int flags,
2622                              int signing_state,
2623                              bool *retry) 
2624 {
2625         NTSTATUS nt_status;
2626         struct cli_state *cli = NULL;
2627         int pw_len = password ? strlen(password)+1 : 0;
2628
2629         *output_cli = NULL;
2630
2631         if (password == NULL) {
2632                 password = "";
2633         }
2634
2635         nt_status = cli_start_connection(&cli, my_name, dest_host,
2636                                          dest_ss, port, signing_state,
2637                                          flags, retry);
2638
2639         if (!NT_STATUS_IS_OK(nt_status)) {
2640                 return nt_status;
2641         }
2642
2643         cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2644         cli->use_level_II_oplocks =
2645                 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2646
2647         nt_status = cli_session_setup(cli, user, password, pw_len, password,
2648                                       pw_len, domain);
2649         if (!NT_STATUS_IS_OK(nt_status)) {
2650
2651                 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2652                         DEBUG(1,("failed session setup with %s\n",
2653                                  nt_errstr(nt_status)));
2654                         cli_shutdown(cli);
2655                         return nt_status;
2656                 }
2657
2658                 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2659                 if (!NT_STATUS_IS_OK(nt_status)) {
2660                         DEBUG(1,("anonymous failed session setup with %s\n",
2661                                  nt_errstr(nt_status)));
2662                         cli_shutdown(cli);
2663                         return nt_status;
2664                 }
2665         }
2666
2667         if (service) {
2668                 nt_status = cli_tcon_andx(cli, service, service_type, password,
2669                                           pw_len);
2670                 if (!NT_STATUS_IS_OK(nt_status)) {
2671                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2672                         cli_shutdown(cli);
2673                         if (NT_STATUS_IS_OK(nt_status)) {
2674                                 nt_status = NT_STATUS_UNSUCCESSFUL;
2675                         }
2676                         return nt_status;
2677                 }
2678         }
2679
2680         nt_status = cli_init_creds(cli, user, domain, password);
2681         if (!NT_STATUS_IS_OK(nt_status)) {
2682                 cli_shutdown(cli);
2683                 return nt_status;
2684         }
2685
2686         *output_cli = cli;
2687         return NT_STATUS_OK;
2688 }
2689
2690 /****************************************************************************
2691  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2692 ****************************************************************************/
2693
2694 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2695                                      struct sockaddr_storage *pdest_ss)
2696 {
2697         struct nmb_name calling, called;
2698
2699         make_nmb_name(&calling, srchost, 0x0);
2700
2701         /*
2702          * If the called name is an IP address
2703          * then use *SMBSERVER immediately.
2704          */
2705
2706         if(is_ipaddress(desthost)) {
2707                 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2708         } else {
2709                 make_nmb_name(&called, desthost, 0x20);
2710         }
2711
2712         if (!cli_session_request(*ppcli, &calling, &called)) {
2713                 NTSTATUS status;
2714                 struct nmb_name smbservername;
2715
2716                 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2717
2718                 /*
2719                  * If the name wasn't *SMBSERVER then
2720                  * try with *SMBSERVER if the first name fails.
2721                  */
2722
2723                 if (nmb_name_equal(&called, &smbservername)) {
2724
2725                         /*
2726                          * The name used was *SMBSERVER, don't bother with another name.
2727                          */
2728
2729                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2730 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2731                         return False;
2732                 }
2733
2734                 /* Try again... */
2735                 cli_shutdown(*ppcli);
2736
2737                 *ppcli = cli_initialise();
2738                 if (!*ppcli) {
2739                         /* Out of memory... */
2740                         return False;
2741                 }
2742
2743                 status = cli_connect(*ppcli, desthost, pdest_ss);
2744                 if (!NT_STATUS_IS_OK(status) ||
2745                                 !cli_session_request(*ppcli, &calling, &smbservername)) {
2746                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2747 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2748                         return False;
2749                 }
2750         }
2751
2752         return True;
2753 }
2754
2755 /****************************************************************************
2756  Send an old style tcon.
2757 ****************************************************************************/
2758 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
2759                       const char *service, const char *pass, const char *dev,
2760                       uint16 *max_xmit, uint16 *tid)
2761 {
2762         char *p;
2763
2764         if (!lp_client_plaintext_auth() && (*pass)) {
2765                 DEBUG(1, ("Server requested plaintext password but 'client "
2766                           "plaintext auth' is disabled\n"));
2767                 return NT_STATUS_ACCESS_DENIED;
2768         }
2769
2770         memset(cli->outbuf,'\0',smb_size);
2771         memset(cli->inbuf,'\0',smb_size);
2772
2773         cli_set_message(cli->outbuf, 0, 0, True);
2774         SCVAL(cli->outbuf,smb_com,SMBtcon);
2775         cli_setup_packet(cli);
2776
2777         p = smb_buf(cli->outbuf);
2778         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2779         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2780         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2781
2782         cli_setup_bcc(cli, p);
2783
2784         cli_send_smb(cli);
2785         if (!cli_receive_smb(cli)) {
2786                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2787         }
2788
2789         if (cli_is_error(cli)) {
2790                 return cli_nt_error(cli);
2791         }
2792
2793         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2794         *tid = SVAL(cli->inbuf, smb_vwv1);
2795
2796         return NT_STATUS_OK;
2797 }
2798
2799 /* Return a cli_state pointing at the IPC$ share for the given server */
2800
2801 struct cli_state *get_ipc_connect(char *server,
2802                                 struct sockaddr_storage *server_ss,
2803                                 const struct user_auth_info *user_info)
2804 {
2805         struct cli_state *cli;
2806         NTSTATUS nt_status;
2807         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2808
2809         if (user_info->use_kerberos) {
2810                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2811         }
2812
2813         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
2814                                         user_info->username ? user_info->username : "",
2815                                         lp_workgroup(),
2816                                         user_info->password ? user_info->password : "",
2817                                         flags,
2818                                         Undefined, NULL);
2819
2820         if (NT_STATUS_IS_OK(nt_status)) {
2821                 return cli;
2822         } else if (is_ipaddress(server)) {
2823             /* windows 9* needs a correct NMB name for connections */
2824             fstring remote_name;
2825
2826             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2827                 cli = get_ipc_connect(remote_name, server_ss, user_info);
2828                 if (cli)
2829                     return cli;
2830             }
2831         }
2832         return NULL;
2833 }
2834
2835 /*
2836  * Given the IP address of a master browser on the network, return its
2837  * workgroup and connect to it.
2838  *
2839  * This function is provided to allow additional processing beyond what
2840  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2841  * browsers and obtain each master browsers' list of domains (in case the
2842  * first master browser is recently on the network and has not yet
2843  * synchronized with other master browsers and therefore does not yet have the
2844  * entire network browse list)
2845  */
2846
2847 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2848                                 struct ip_service *mb_ip,
2849                                 const struct user_auth_info *user_info,
2850                                 char **pp_workgroup_out)
2851 {
2852         char addr[INET6_ADDRSTRLEN];
2853         fstring name;
2854         struct cli_state *cli;
2855         struct sockaddr_storage server_ss;
2856
2857         *pp_workgroup_out = NULL;
2858
2859         print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2860         DEBUG(99, ("Looking up name of master browser %s\n",
2861                    addr));
2862
2863         /*
2864          * Do a name status query to find out the name of the master browser.
2865          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2866          * master browser will not respond to a wildcard query (or, at least,
2867          * an NT4 server acting as the domain master browser will not).
2868          *
2869          * We might be able to use ONLY the query on MSBROWSE, but that's not
2870          * yet been tested with all Windows versions, so until it is, leave
2871          * the original wildcard query as the first choice and fall back to
2872          * MSBROWSE if the wildcard query fails.
2873          */
2874         if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2875             !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2876
2877                 DEBUG(99, ("Could not retrieve name status for %s\n",
2878                            addr));
2879                 return NULL;
2880         }
2881
2882         if (!find_master_ip(name, &server_ss)) {
2883                 DEBUG(99, ("Could not find master ip for %s\n", name));
2884                 return NULL;
2885         }
2886
2887         *pp_workgroup_out = talloc_strdup(ctx, name);
2888
2889         DEBUG(4, ("found master browser %s, %s\n", name, addr));
2890
2891         print_sockaddr(addr, sizeof(addr), &server_ss);
2892         cli = get_ipc_connect(addr, &server_ss, user_info);
2893
2894         return cli;
2895 }
2896
2897 /*
2898  * Return the IP address and workgroup of a master browser on the network, and
2899  * connect to it.
2900  */
2901
2902 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2903                                         const struct user_auth_info *user_info,
2904                                         char **pp_workgroup_out)
2905 {
2906         struct ip_service *ip_list;
2907         struct cli_state *cli;
2908         int i, count;
2909
2910         *pp_workgroup_out = NULL;
2911
2912         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2913
2914         /* Go looking for workgroups by broadcasting on the local network */
2915
2916         if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2917                                                 &count))) {
2918                 DEBUG(99, ("No master browsers responded\n"));
2919                 return False;
2920         }
2921
2922         for (i = 0; i < count; i++) {
2923                 char addr[INET6_ADDRSTRLEN];
2924                 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2925                 DEBUG(99, ("Found master browser %s\n", addr));
2926
2927                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2928                                 user_info, pp_workgroup_out);
2929                 if (cli)
2930                         return(cli);
2931         }
2932
2933         return NULL;
2934 }