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