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