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