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