s3-libads Default to NOT using the server-supplied principal from SPNEGO
[metze/samba/wip.git] / source3 / libsmb / cliconnect.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client connect/disconnect routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Andrew Bartlett 2001-2003
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "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                         OIDs[0] == NULL) {
1234                 data_blob_free(&blob);
1235                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1236         }
1237         data_blob_free(&blob);
1238
1239         /* make sure the server understands kerberos */
1240         for (i=0;OIDs[i];i++) {
1241                 if (i == 0)
1242                         DEBUG(3,("got OID=%s\n", OIDs[i]));
1243                 else
1244                         DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1245                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1246                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1247                         cli->got_kerberos_mechanism = True;
1248                 }
1249                 talloc_free(OIDs[i]);
1250         }
1251
1252         DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1253
1254         status = cli_set_username(cli, user);
1255         if (!NT_STATUS_IS_OK(status)) {
1256                 TALLOC_FREE(principal);
1257                 return ADS_ERROR_NT(status);
1258         }
1259
1260 #ifdef HAVE_KRB5
1261         /* If password is set we reauthenticate to kerberos server
1262          * and do not store results */
1263
1264         if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1265                 ADS_STATUS rc;
1266
1267                 if (pass && *pass) {
1268                         int ret;
1269
1270                         use_in_memory_ccache();
1271                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1272
1273                         if (ret){
1274                                 TALLOC_FREE(principal);
1275                                 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1276                                 if (cli->fallback_after_kerberos)
1277                                         goto ntlmssp;
1278                                 return ADS_ERROR_KRB5(ret);
1279                         }
1280                 }
1281
1282                 /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
1283                  */
1284                 if (!lp_client_use_spnego_principal() || 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         int namelen = 0;
2233         char *tmp;
2234
2235         /* 445 doesn't have session request */
2236         if (cli->port == 445)
2237                 return True;
2238
2239         memcpy(&(cli->calling), calling, sizeof(*calling));
2240         memcpy(&(cli->called ), called , sizeof(*called ));
2241
2242         /* put in the destination name */
2243
2244         tmp = name_mangle(talloc_tos(), cli->called.name,
2245                           cli->called.name_type);
2246         if (tmp == NULL) {
2247                 return false;
2248         }
2249
2250         p = cli->outbuf+len;
2251         namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2252         if (namelen > 0) {
2253                 memcpy(p, tmp, namelen);
2254                 len += namelen;
2255         }
2256         TALLOC_FREE(tmp);
2257
2258         /* and my name */
2259
2260         tmp = name_mangle(talloc_tos(), cli->calling.name,
2261                           cli->calling.name_type);
2262         if (tmp == NULL) {
2263                 return false;
2264         }
2265
2266         p = cli->outbuf+len;
2267         namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
2268         if (namelen > 0) {
2269                 memcpy(p, tmp, namelen);
2270                 len += namelen;
2271         }
2272         TALLOC_FREE(tmp);
2273
2274         /* send a session request (RFC 1002) */
2275         /* setup the packet length
2276          * Remove four bytes from the length count, since the length
2277          * field in the NBT Session Service header counts the number
2278          * of bytes which follow.  The cli_send_smb() function knows
2279          * about this and accounts for those four bytes.
2280          * CRH.
2281          */
2282         len -= 4;
2283         _smb_setlen(cli->outbuf,len);
2284         SCVAL(cli->outbuf,0,0x81);
2285
2286         cli_send_smb(cli);
2287         DEBUG(5,("Sent session request\n"));
2288
2289         if (!cli_receive_smb(cli))
2290                 return False;
2291
2292         if (CVAL(cli->inbuf,0) == 0x84) {
2293                 /* C. Hoch  9/14/95 Start */
2294                 /* For information, here is the response structure.
2295                  * We do the byte-twiddling to for portability.
2296                 struct RetargetResponse{
2297                 unsigned char type;
2298                 unsigned char flags;
2299                 int16 length;
2300                 int32 ip_addr;
2301                 int16 port;
2302                 };
2303                 */
2304                 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2305                 struct in_addr dest_ip;
2306                 NTSTATUS status;
2307
2308                 /* SESSION RETARGET */
2309                 putip((char *)&dest_ip,cli->inbuf+4);
2310                 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2311
2312                 status = open_socket_out(&cli->dest_ss, port,
2313                                          LONG_CONNECT_TIMEOUT, &cli->fd);
2314                 if (!NT_STATUS_IS_OK(status)) {
2315                         return False;
2316                 }
2317
2318                 DEBUG(3,("Retargeted\n"));
2319
2320                 set_socket_options(cli->fd, lp_socket_options());
2321
2322                 /* Try again */
2323                 {
2324                         static int depth;
2325                         bool ret;
2326                         if (depth > 4) {
2327                                 DEBUG(0,("Retarget recursion - failing\n"));
2328                                 return False;
2329                         }
2330                         depth++;
2331                         ret = cli_session_request(cli, calling, called);
2332                         depth--;
2333                         return ret;
2334                 }
2335         } /* C. Hoch 9/14/95 End */
2336
2337         if (CVAL(cli->inbuf,0) != 0x82) {
2338                 /* This is the wrong place to put the error... JRA. */
2339                 cli->rap_error = CVAL(cli->inbuf,4);
2340                 return False;
2341         }
2342         return(True);
2343 }
2344
2345 struct fd_struct {
2346         int fd;
2347 };
2348
2349 static void smb_sock_connected(struct tevent_req *req)
2350 {
2351         struct fd_struct *pfd = tevent_req_callback_data(
2352                 req, struct fd_struct);
2353         int fd;
2354         NTSTATUS status;
2355
2356         status = open_socket_out_defer_recv(req, &fd);
2357         if (NT_STATUS_IS_OK(status)) {
2358                 pfd->fd = fd;
2359         }
2360 }
2361
2362 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2363                                 uint16_t *port, int timeout, int *pfd)
2364 {
2365         struct event_context *ev;
2366         struct tevent_req *r139, *r445;
2367         struct fd_struct *fd139, *fd445;
2368         NTSTATUS status = NT_STATUS_NO_MEMORY;
2369
2370         if (*port != 0) {
2371                 return open_socket_out(pss, *port, timeout, pfd);
2372         }
2373
2374         ev = event_context_init(talloc_tos());
2375         if (ev == NULL) {
2376                 return NT_STATUS_NO_MEMORY;
2377         }
2378
2379         fd139 = talloc(ev, struct fd_struct);
2380         if (fd139 == NULL) {
2381                 goto done;
2382         }
2383         fd139->fd = -1;
2384
2385         fd445 = talloc(ev, struct fd_struct);
2386         if (fd445 == NULL) {
2387                 goto done;
2388         }
2389         fd445->fd = -1;
2390
2391         r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2392                                           pss, 445, timeout);
2393         r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2394                                           pss, 139, timeout);
2395         if ((r445 == NULL) || (r139 == NULL)) {
2396                 goto done;
2397         }
2398         tevent_req_set_callback(r445, smb_sock_connected, fd445);
2399         tevent_req_set_callback(r139, smb_sock_connected, fd139);
2400
2401         while ((fd445->fd == -1) && (fd139->fd == -1)
2402                && (tevent_req_is_in_progress(r139)
2403                    || tevent_req_is_in_progress(r445))) {
2404                 event_loop_once(ev);
2405         }
2406
2407         if ((fd139->fd != -1) && (fd445->fd != -1)) {
2408                 close(fd139->fd);
2409                 fd139->fd = -1;
2410         }
2411
2412         if (fd445->fd != -1) {
2413                 *port = 445;
2414                 *pfd = fd445->fd;
2415                 status = NT_STATUS_OK;
2416                 goto done;
2417         }
2418         if (fd139->fd != -1) {
2419                 *port = 139;
2420                 *pfd = fd139->fd;
2421                 status = NT_STATUS_OK;
2422                 goto done;
2423         }
2424
2425         status = open_socket_out_defer_recv(r445, &fd445->fd);
2426  done:
2427         TALLOC_FREE(ev);
2428         return status;
2429 }
2430
2431 /****************************************************************************
2432  Open the client sockets.
2433 ****************************************************************************/
2434
2435 NTSTATUS cli_connect(struct cli_state *cli,
2436                 const char *host,
2437                 struct sockaddr_storage *dest_ss)
2438
2439 {
2440         int name_type = 0x20;
2441         TALLOC_CTX *frame = talloc_stackframe();
2442         unsigned int num_addrs = 0;
2443         unsigned int i = 0;
2444         struct sockaddr_storage *ss_arr = NULL;
2445         char *p = NULL;
2446
2447         /* reasonable default hostname */
2448         if (!host) {
2449                 host = STAR_SMBSERVER;
2450         }
2451
2452         fstrcpy(cli->desthost, host);
2453
2454         /* allow hostnames of the form NAME#xx and do a netbios lookup */
2455         if ((p = strchr(cli->desthost, '#'))) {
2456                 name_type = strtol(p+1, NULL, 16);
2457                 *p = 0;
2458         }
2459
2460         if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2461                 NTSTATUS status =resolve_name_list(frame,
2462                                         cli->desthost,
2463                                         name_type,
2464                                         &ss_arr,
2465                                         &num_addrs);
2466                 if (!NT_STATUS_IS_OK(status)) {
2467                         TALLOC_FREE(frame);
2468                         return NT_STATUS_BAD_NETWORK_NAME;
2469                 }
2470         } else {
2471                 num_addrs = 1;
2472                 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2473                 if (!ss_arr) {
2474                         TALLOC_FREE(frame);
2475                         return NT_STATUS_NO_MEMORY;
2476                 }
2477                 *ss_arr = *dest_ss;
2478         }
2479
2480         for (i = 0; i < num_addrs; i++) {
2481                 cli->dest_ss = ss_arr[i];
2482                 if (getenv("LIBSMB_PROG")) {
2483                         cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2484                 } else {
2485                         uint16_t port = cli->port;
2486                         NTSTATUS status;
2487                         status = open_smb_socket(&cli->dest_ss, &port,
2488                                                  cli->timeout, &cli->fd);
2489                         if (NT_STATUS_IS_OK(status)) {
2490                                 cli->port = port;
2491                         }
2492                 }
2493                 if (cli->fd == -1) {
2494                         char addr[INET6_ADDRSTRLEN];
2495                         print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2496                         DEBUG(2,("Error connecting to %s (%s)\n",
2497                                  dest_ss?addr:host,strerror(errno)));
2498                 } else {
2499                         /* Exit from loop on first connection. */
2500                         break;
2501                 }
2502         }
2503
2504         if (cli->fd == -1) {
2505                 TALLOC_FREE(frame);
2506                 return map_nt_error_from_unix(errno);
2507         }
2508
2509         if (dest_ss) {
2510                 *dest_ss = cli->dest_ss;
2511         }
2512
2513         set_socket_options(cli->fd, lp_socket_options());
2514
2515         TALLOC_FREE(frame);
2516         return NT_STATUS_OK;
2517 }
2518
2519 /**
2520    establishes a connection to after the negprot. 
2521    @param output_cli A fully initialised cli structure, non-null only on success
2522    @param dest_host The netbios name of the remote host
2523    @param dest_ss (optional) The the destination IP, NULL for name based lookup
2524    @param port (optional) The destination port (0 for default)
2525    @param retry bool. Did this connection fail with a retryable error ?
2526
2527 */
2528 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
2529                               const char *my_name, 
2530                               const char *dest_host, 
2531                               struct sockaddr_storage *dest_ss, int port,
2532                               int signing_state, int flags,
2533                               bool *retry) 
2534 {
2535         NTSTATUS nt_status;
2536         struct nmb_name calling;
2537         struct nmb_name called;
2538         struct cli_state *cli;
2539         struct sockaddr_storage ss;
2540
2541         if (retry)
2542                 *retry = False;
2543
2544         if (!my_name) 
2545                 my_name = global_myname();
2546
2547         if (!(cli = cli_initialise_ex(signing_state))) {
2548                 return NT_STATUS_NO_MEMORY;
2549         }
2550
2551         make_nmb_name(&calling, my_name, 0x0);
2552         make_nmb_name(&called , dest_host, 0x20);
2553
2554         cli_set_port(cli, port);
2555         cli_set_timeout(cli, 10000); /* 10 seconds. */
2556
2557         if (dest_ss) {
2558                 ss = *dest_ss;
2559         } else {
2560                 zero_sockaddr(&ss);
2561         }
2562
2563 again:
2564
2565         DEBUG(3,("Connecting to host=%s\n", dest_host));
2566
2567         nt_status = cli_connect(cli, dest_host, &ss);
2568         if (!NT_STATUS_IS_OK(nt_status)) {
2569                 char addr[INET6_ADDRSTRLEN];
2570                 print_sockaddr(addr, sizeof(addr), &ss);
2571                 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2572                          nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2573                 cli_shutdown(cli);
2574                 return nt_status;
2575         }
2576
2577         if (retry)
2578                 *retry = True;
2579
2580         if (!cli_session_request(cli, &calling, &called)) {
2581                 char *p;
2582                 DEBUG(1,("session request to %s failed (%s)\n",
2583                          called.name, cli_errstr(cli)));
2584                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2585                         *p = 0;
2586                         goto again;
2587                 }
2588                 if (strcmp(called.name, STAR_SMBSERVER)) {
2589                         make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2590                         goto again;
2591                 }
2592                 return NT_STATUS_BAD_NETWORK_NAME;
2593         }
2594
2595         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2596                 cli->use_spnego = False;
2597         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2598                 cli->use_kerberos = True;
2599
2600         if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2601              cli->use_kerberos) {
2602                 cli->fallback_after_kerberos = true;
2603         }
2604         if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
2605                 cli->use_ccache = true;
2606         }
2607
2608         nt_status = cli_negprot(cli);
2609         if (!NT_STATUS_IS_OK(nt_status)) {
2610                 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2611                 cli_shutdown(cli);
2612                 return nt_status;
2613         }
2614
2615         *output_cli = cli;
2616         return NT_STATUS_OK;
2617 }
2618
2619
2620 /**
2621    establishes a connection right up to doing tconX, password specified.
2622    @param output_cli A fully initialised cli structure, non-null only on success
2623    @param dest_host The netbios name of the remote host
2624    @param dest_ip (optional) The the destination IP, NULL for name based lookup
2625    @param port (optional) The destination port (0 for default)
2626    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
2627    @param service_type The 'type' of serivice. 
2628    @param user Username, unix string
2629    @param domain User's domain
2630    @param password User's password, unencrypted unix string.
2631    @param retry bool. Did this connection fail with a retryable error ?
2632 */
2633
2634 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
2635                              const char *my_name, 
2636                              const char *dest_host, 
2637                              struct sockaddr_storage *dest_ss, int port,
2638                              const char *service, const char *service_type,
2639                              const char *user, const char *domain, 
2640                              const char *password, int flags,
2641                              int signing_state,
2642                              bool *retry) 
2643 {
2644         NTSTATUS nt_status;
2645         struct cli_state *cli = NULL;
2646         int pw_len = password ? strlen(password)+1 : 0;
2647
2648         *output_cli = NULL;
2649
2650         if (password == NULL) {
2651                 password = "";
2652         }
2653
2654         nt_status = cli_start_connection(&cli, my_name, dest_host,
2655                                          dest_ss, port, signing_state,
2656                                          flags, retry);
2657
2658         if (!NT_STATUS_IS_OK(nt_status)) {
2659                 return nt_status;
2660         }
2661
2662         cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2663         cli->use_level_II_oplocks =
2664                 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2665
2666         nt_status = cli_session_setup(cli, user, password, pw_len, password,
2667                                       pw_len, domain);
2668         if (!NT_STATUS_IS_OK(nt_status)) {
2669
2670                 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2671                         DEBUG(1,("failed session setup with %s\n",
2672                                  nt_errstr(nt_status)));
2673                         cli_shutdown(cli);
2674                         return nt_status;
2675                 }
2676
2677                 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2678                 if (!NT_STATUS_IS_OK(nt_status)) {
2679                         DEBUG(1,("anonymous failed session setup with %s\n",
2680                                  nt_errstr(nt_status)));
2681                         cli_shutdown(cli);
2682                         return nt_status;
2683                 }
2684         }
2685
2686         if (service) {
2687                 nt_status = cli_tcon_andx(cli, service, service_type, password,
2688                                           pw_len);
2689                 if (!NT_STATUS_IS_OK(nt_status)) {
2690                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2691                         cli_shutdown(cli);
2692                         if (NT_STATUS_IS_OK(nt_status)) {
2693                                 nt_status = NT_STATUS_UNSUCCESSFUL;
2694                         }
2695                         return nt_status;
2696                 }
2697         }
2698
2699         nt_status = cli_init_creds(cli, user, domain, password);
2700         if (!NT_STATUS_IS_OK(nt_status)) {
2701                 cli_shutdown(cli);
2702                 return nt_status;
2703         }
2704
2705         *output_cli = cli;
2706         return NT_STATUS_OK;
2707 }
2708
2709 /****************************************************************************
2710  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2711 ****************************************************************************/
2712
2713 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2714                                      struct sockaddr_storage *pdest_ss)
2715 {
2716         struct nmb_name calling, called;
2717
2718         make_nmb_name(&calling, srchost, 0x0);
2719
2720         /*
2721          * If the called name is an IP address
2722          * then use *SMBSERVER immediately.
2723          */
2724
2725         if(is_ipaddress(desthost)) {
2726                 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2727         } else {
2728                 make_nmb_name(&called, desthost, 0x20);
2729         }
2730
2731         if (!cli_session_request(*ppcli, &calling, &called)) {
2732                 NTSTATUS status;
2733                 struct nmb_name smbservername;
2734
2735                 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2736
2737                 /*
2738                  * If the name wasn't *SMBSERVER then
2739                  * try with *SMBSERVER if the first name fails.
2740                  */
2741
2742                 if (nmb_name_equal(&called, &smbservername)) {
2743
2744                         /*
2745                          * The name used was *SMBSERVER, don't bother with another name.
2746                          */
2747
2748                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2749 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2750                         return False;
2751                 }
2752
2753                 /* Try again... */
2754                 cli_shutdown(*ppcli);
2755
2756                 *ppcli = cli_initialise();
2757                 if (!*ppcli) {
2758                         /* Out of memory... */
2759                         return False;
2760                 }
2761
2762                 status = cli_connect(*ppcli, desthost, pdest_ss);
2763                 if (!NT_STATUS_IS_OK(status) ||
2764                                 !cli_session_request(*ppcli, &calling, &smbservername)) {
2765                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2766 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2767                         return False;
2768                 }
2769         }
2770
2771         return True;
2772 }
2773
2774 /****************************************************************************
2775  Send an old style tcon.
2776 ****************************************************************************/
2777 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
2778                       const char *service, const char *pass, const char *dev,
2779                       uint16 *max_xmit, uint16 *tid)
2780 {
2781         char *p;
2782
2783         if (!lp_client_plaintext_auth() && (*pass)) {
2784                 DEBUG(1, ("Server requested plaintext password but 'client "
2785                           "plaintext auth' is disabled\n"));
2786                 return NT_STATUS_ACCESS_DENIED;
2787         }
2788
2789         memset(cli->outbuf,'\0',smb_size);
2790         memset(cli->inbuf,'\0',smb_size);
2791
2792         cli_set_message(cli->outbuf, 0, 0, True);
2793         SCVAL(cli->outbuf,smb_com,SMBtcon);
2794         cli_setup_packet(cli);
2795
2796         p = smb_buf(cli->outbuf);
2797         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2798         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2799         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2800
2801         cli_setup_bcc(cli, p);
2802
2803         cli_send_smb(cli);
2804         if (!cli_receive_smb(cli)) {
2805                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2806         }
2807
2808         if (cli_is_error(cli)) {
2809                 return cli_nt_error(cli);
2810         }
2811
2812         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2813         *tid = SVAL(cli->inbuf, smb_vwv1);
2814
2815         return NT_STATUS_OK;
2816 }
2817
2818 /* Return a cli_state pointing at the IPC$ share for the given server */
2819
2820 struct cli_state *get_ipc_connect(char *server,
2821                                 struct sockaddr_storage *server_ss,
2822                                 const struct user_auth_info *user_info)
2823 {
2824         struct cli_state *cli;
2825         NTSTATUS nt_status;
2826         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2827
2828         if (user_info->use_kerberos) {
2829                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2830         }
2831
2832         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
2833                                         user_info->username ? user_info->username : "",
2834                                         lp_workgroup(),
2835                                         user_info->password ? user_info->password : "",
2836                                         flags,
2837                                         Undefined, NULL);
2838
2839         if (NT_STATUS_IS_OK(nt_status)) {
2840                 return cli;
2841         } else if (is_ipaddress(server)) {
2842             /* windows 9* needs a correct NMB name for connections */
2843             fstring remote_name;
2844
2845             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2846                 cli = get_ipc_connect(remote_name, server_ss, user_info);
2847                 if (cli)
2848                     return cli;
2849             }
2850         }
2851         return NULL;
2852 }
2853
2854 /*
2855  * Given the IP address of a master browser on the network, return its
2856  * workgroup and connect to it.
2857  *
2858  * This function is provided to allow additional processing beyond what
2859  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2860  * browsers and obtain each master browsers' list of domains (in case the
2861  * first master browser is recently on the network and has not yet
2862  * synchronized with other master browsers and therefore does not yet have the
2863  * entire network browse list)
2864  */
2865
2866 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2867                                 struct ip_service *mb_ip,
2868                                 const struct user_auth_info *user_info,
2869                                 char **pp_workgroup_out)
2870 {
2871         char addr[INET6_ADDRSTRLEN];
2872         fstring name;
2873         struct cli_state *cli;
2874         struct sockaddr_storage server_ss;
2875
2876         *pp_workgroup_out = NULL;
2877
2878         print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2879         DEBUG(99, ("Looking up name of master browser %s\n",
2880                    addr));
2881
2882         /*
2883          * Do a name status query to find out the name of the master browser.
2884          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2885          * master browser will not respond to a wildcard query (or, at least,
2886          * an NT4 server acting as the domain master browser will not).
2887          *
2888          * We might be able to use ONLY the query on MSBROWSE, but that's not
2889          * yet been tested with all Windows versions, so until it is, leave
2890          * the original wildcard query as the first choice and fall back to
2891          * MSBROWSE if the wildcard query fails.
2892          */
2893         if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2894             !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2895
2896                 DEBUG(99, ("Could not retrieve name status for %s\n",
2897                            addr));
2898                 return NULL;
2899         }
2900
2901         if (!find_master_ip(name, &server_ss)) {
2902                 DEBUG(99, ("Could not find master ip for %s\n", name));
2903                 return NULL;
2904         }
2905
2906         *pp_workgroup_out = talloc_strdup(ctx, name);
2907
2908         DEBUG(4, ("found master browser %s, %s\n", name, addr));
2909
2910         print_sockaddr(addr, sizeof(addr), &server_ss);
2911         cli = get_ipc_connect(addr, &server_ss, user_info);
2912
2913         return cli;
2914 }
2915
2916 /*
2917  * Return the IP address and workgroup of a master browser on the network, and
2918  * connect to it.
2919  */
2920
2921 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2922                                         const struct user_auth_info *user_info,
2923                                         char **pp_workgroup_out)
2924 {
2925         struct ip_service *ip_list;
2926         struct cli_state *cli;
2927         int i, count;
2928
2929         *pp_workgroup_out = NULL;
2930
2931         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2932
2933         /* Go looking for workgroups by broadcasting on the local network */
2934
2935         if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2936                                                 &count))) {
2937                 DEBUG(99, ("No master browsers responded\n"));
2938                 return False;
2939         }
2940
2941         for (i = 0; i < count; i++) {
2942                 char addr[INET6_ADDRSTRLEN];
2943                 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2944                 DEBUG(99, ("Found master browser %s\n", addr));
2945
2946                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2947                                 user_info, pp_workgroup_out);
2948                 if (cli)
2949                         return(cli);
2950         }
2951
2952         return NULL;
2953 }