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