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