s3: Add ccache use to cli_session_setup_ntlmssp
[samba.git] / source3 / libsmb / cliconnect.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client connect/disconnect routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Andrew Bartlett 2001-2003
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "../libcli/auth/libcli_auth.h"
23 #include "../libcli/auth/spnego.h"
24 #include "smb_krb5.h"
25 #include "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         char *inbuf;
268         uint8_t *bytes;
269         uint8_t *p;
270         NTSTATUS status;
271
272         status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes);
273         if (!NT_STATUS_IS_OK(status)) {
274                 TALLOC_FREE(subreq);
275                 tevent_req_nterror(req, status);
276                 return;
277         }
278
279         inbuf = (char *)cli_smb_inbuf(subreq);
280         p = bytes;
281
282         cli->vuid = SVAL(inbuf, smb_uid);
283
284         p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
285                          bytes+num_bytes-p, STR_TERMINATE);
286         p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
287                          bytes+num_bytes-p, STR_TERMINATE);
288         p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
289                          bytes+num_bytes-p, STR_TERMINATE);
290
291         if (strstr(cli->server_type, "Samba")) {
292                 cli->is_samba = True;
293         }
294
295         TALLOC_FREE(subreq);
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
734         status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
735         if (!NT_STATUS_IS_OK(status)
736             && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
737                 TALLOC_FREE(subreq);
738                 tevent_req_nterror(req, status);
739                 return;
740         }
741
742         state->status = status;
743         TALLOC_FREE(state->buf);
744
745         state->inbuf = (char *)cli_smb_inbuf(subreq);
746         cli->vuid = SVAL(state->inbuf, smb_uid);
747
748         blob_length = SVAL(vwv+3, 0);
749         if (blob_length > num_bytes) {
750                 TALLOC_FREE(subreq);
751                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
752                 return;
753         }
754         state->ret_blob = data_blob_const(bytes, blob_length);
755
756         p = bytes + blob_length;
757
758         p += clistr_pull(state->inbuf, cli->server_os,
759                          (char *)p, sizeof(fstring),
760                          bytes+num_bytes-p, STR_TERMINATE);
761         p += clistr_pull(state->inbuf, cli->server_type,
762                          (char *)p, sizeof(fstring),
763                          bytes+num_bytes-p, STR_TERMINATE);
764         p += clistr_pull(state->inbuf, cli->server_domain,
765                          (char *)p, sizeof(fstring),
766                          bytes+num_bytes-p, STR_TERMINATE);
767
768         if (strstr(cli->server_type, "Samba")) {
769                 cli->is_samba = True;
770         }
771
772         if (state->blob.length != 0) {
773                 TALLOC_FREE(subreq);
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                 ntlmssp_end(&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
988         req = tevent_req_create(mem_ctx, &state,
989                                 struct cli_session_setup_ntlmssp_state);
990         if (req == NULL) {
991                 return NULL;
992         }
993         state->ev = ev;
994         state->cli = cli;
995         state->turn = 1;
996
997         state->ntlmssp_state = NULL;
998         talloc_set_destructor(
999                 state, cli_session_setup_ntlmssp_state_destructor);
1000
1001         cli_temp_set_signing(cli);
1002
1003         status = ntlmssp_client_start(&state->ntlmssp_state);
1004         if (!NT_STATUS_IS_OK(status)) {
1005                 goto fail;
1006         }
1007         ntlmssp_want_feature(state->ntlmssp_state,
1008                              NTLMSSP_FEATURE_SESSION_KEY);
1009         if (cli->use_ccache) {
1010                 ntlmssp_want_feature(state->ntlmssp_state,
1011                                      NTLMSSP_FEATURE_CCACHE);
1012         }
1013         status = ntlmssp_set_username(state->ntlmssp_state, user);
1014         if (!NT_STATUS_IS_OK(status)) {
1015                 goto fail;
1016         }
1017         status = ntlmssp_set_domain(state->ntlmssp_state, domain);
1018         if (!NT_STATUS_IS_OK(status)) {
1019                 goto fail;
1020         }
1021         status = ntlmssp_set_password(state->ntlmssp_state, pass);
1022         if (!NT_STATUS_IS_OK(status)) {
1023                 goto fail;
1024         }
1025         status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
1026                                 &blob_out);
1027         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1028                 goto fail;
1029         }
1030
1031         state->blob_out = gen_negTokenInit(OID_NTLMSSP, blob_out);
1032         data_blob_free(&blob_out);
1033
1034         subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
1035         if (tevent_req_nomem(subreq, req)) {
1036                 return tevent_req_post(req, ev);
1037         }
1038         tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1039         return req;
1040 fail:
1041         tevent_req_nterror(req, status);
1042         return tevent_req_post(req, ev);
1043 }
1044
1045 static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
1046 {
1047         struct tevent_req *req = tevent_req_callback_data(
1048                 subreq, struct tevent_req);
1049         struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1050                 req, struct cli_session_setup_ntlmssp_state);
1051         DATA_BLOB blob_in, msg_in, blob_out;
1052         char *inbuf = NULL;
1053         bool parse_ret;
1054         NTSTATUS status;
1055
1056         status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
1057                                          &inbuf);
1058         TALLOC_FREE(subreq);
1059         data_blob_free(&state->blob_out);
1060
1061         if (NT_STATUS_IS_OK(status)) {
1062                 if (state->cli->server_domain[0] == '\0') {
1063                         fstrcpy(state->cli->server_domain,
1064                                 state->ntlmssp_state->server_domain);
1065                 }
1066                 cli_set_session_key(
1067                         state->cli, state->ntlmssp_state->session_key);
1068
1069                 if (cli_simple_set_signing(
1070                             state->cli, state->ntlmssp_state->session_key,
1071                             data_blob_null)
1072                     && !cli_check_sign_mac(state->cli, inbuf, 1)) {
1073                         TALLOC_FREE(subreq);
1074                         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1075                         return;
1076                 }
1077                 TALLOC_FREE(subreq);
1078                 ntlmssp_end(&state->ntlmssp_state);
1079                 tevent_req_done(req);
1080                 return;
1081         }
1082         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1083                 tevent_req_nterror(req, status);
1084                 return;
1085         }
1086
1087         if (blob_in.length == 0) {
1088                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1089                 return;
1090         }
1091
1092         if ((state->turn == 1)
1093             && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1094                 DATA_BLOB tmp_blob = data_blob_null;
1095                 /* the server might give us back two challenges */
1096                 parse_ret = spnego_parse_challenge(blob_in, &msg_in,
1097                                                    &tmp_blob);
1098                 data_blob_free(&tmp_blob);
1099         } else {
1100                 parse_ret = spnego_parse_auth_response(blob_in, status,
1101                                                        OID_NTLMSSP, &msg_in);
1102         }
1103         state->turn += 1;
1104
1105         if (!parse_ret) {
1106                 DEBUG(3,("Failed to parse auth response\n"));
1107                 if (NT_STATUS_IS_OK(status)
1108                     || NT_STATUS_EQUAL(status,
1109                                        NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1110                         tevent_req_nterror(
1111                                 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
1112                         return;
1113                 }
1114         }
1115
1116         status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
1117
1118         if (!NT_STATUS_IS_OK(status)
1119             && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1120                 TALLOC_FREE(subreq);
1121                 ntlmssp_end(&state->ntlmssp_state);
1122                 tevent_req_nterror(req, status);
1123                 return;
1124         }
1125
1126         state->blob_out = spnego_gen_auth(blob_out);
1127         TALLOC_FREE(subreq);
1128         if (tevent_req_nomem(state->blob_out.data, req)) {
1129                 return;
1130         }
1131
1132         subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
1133                                          state->blob_out);
1134         if (tevent_req_nomem(subreq, req)) {
1135                 return;
1136         }
1137         tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
1138 }
1139
1140 static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
1141 {
1142         struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
1143                 req, struct cli_session_setup_ntlmssp_state);
1144         NTSTATUS status;
1145
1146         if (tevent_req_is_nterror(req, &status)) {
1147                 state->cli->vuid = 0;
1148                 return status;
1149         }
1150         return NT_STATUS_OK;
1151 }
1152
1153 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
1154                                           const char *user,
1155                                           const char *pass,
1156                                           const char *domain)
1157 {
1158         struct tevent_context *ev;
1159         struct tevent_req *req;
1160         NTSTATUS status = NT_STATUS_NO_MEMORY;
1161
1162         if (cli_has_async_calls(cli)) {
1163                 return NT_STATUS_INVALID_PARAMETER;
1164         }
1165         ev = tevent_context_init(talloc_tos());
1166         if (ev == NULL) {
1167                 goto fail;
1168         }
1169         req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
1170         if (req == NULL) {
1171                 goto fail;
1172         }
1173         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1174                 goto fail;
1175         }
1176         status = cli_session_setup_ntlmssp_recv(req);
1177 fail:
1178         TALLOC_FREE(ev);
1179         if (!NT_STATUS_IS_OK(status)) {
1180                 cli_set_error(cli, status);
1181         }
1182         return status;
1183 }
1184
1185 /****************************************************************************
1186  Do a spnego encrypted session setup.
1187
1188  user_domain: The shortname of the domain the user/machine is a member of.
1189  dest_realm: The realm we're connecting to, if NULL we use our default realm.
1190 ****************************************************************************/
1191
1192 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 
1193                               const char *pass, const char *user_domain,
1194                               const char * dest_realm)
1195 {
1196         char *principal = NULL;
1197         char *OIDs[ASN1_MAX_OIDS];
1198         int i;
1199         DATA_BLOB blob;
1200         const char *p = NULL;
1201         char *account = NULL;
1202         NTSTATUS status;
1203
1204         DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
1205
1206         /* the server might not even do spnego */
1207         if (cli->secblob.length <= 16) {
1208                 DEBUG(3,("server didn't supply a full spnego negprot\n"));
1209                 goto ntlmssp;
1210         }
1211
1212 #if 0
1213         file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
1214 #endif
1215
1216         /* there is 16 bytes of GUID before the real spnego packet starts */
1217         blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
1218
1219         /* The server sent us the first part of the SPNEGO exchange in the
1220          * negprot reply. It is WRONG to depend on the principal sent in the
1221          * negprot reply, but right now we do it. If we don't receive one,
1222          * we try to best guess, then fall back to NTLM.  */
1223         if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
1224                 data_blob_free(&blob);
1225                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1226         }
1227         data_blob_free(&blob);
1228
1229         /* make sure the server understands kerberos */
1230         for (i=0;OIDs[i];i++) {
1231                 if (i == 0)
1232                         DEBUG(3,("got OID=%s\n", OIDs[i]));
1233                 else
1234                         DEBUGADD(3,("got OID=%s\n", OIDs[i]));
1235                 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
1236                     strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1237                         cli->got_kerberos_mechanism = True;
1238                 }
1239                 talloc_free(OIDs[i]);
1240         }
1241
1242         DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
1243
1244         status = cli_set_username(cli, user);
1245         if (!NT_STATUS_IS_OK(status)) {
1246                 return ADS_ERROR_NT(status);
1247         }
1248
1249 #ifdef HAVE_KRB5
1250         /* If password is set we reauthenticate to kerberos server
1251          * and do not store results */
1252
1253         if (cli->got_kerberos_mechanism && cli->use_kerberos) {
1254                 ADS_STATUS rc;
1255
1256                 if (pass && *pass) {
1257                         int ret;
1258
1259                         use_in_memory_ccache();
1260                         ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
1261
1262                         if (ret){
1263                                 TALLOC_FREE(principal);
1264                                 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
1265                                 if (cli->fallback_after_kerberos)
1266                                         goto ntlmssp;
1267                                 return ADS_ERROR_KRB5(ret);
1268                         }
1269                 }
1270
1271                 /* If we get a bad principal, try to guess it if
1272                    we have a valid host NetBIOS name.
1273                  */
1274                 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
1275                         TALLOC_FREE(principal);
1276                 }
1277
1278                 if (principal == NULL &&
1279                         !is_ipaddress(cli->desthost) &&
1280                         !strequal(STAR_SMBSERVER,
1281                                 cli->desthost)) {
1282                         char *realm = NULL;
1283                         char *machine = NULL;
1284                         char *host = NULL;
1285                         DEBUG(3,("cli_session_setup_spnego: got a "
1286                                 "bad server principal, trying to guess ...\n"));
1287
1288                         host = strchr_m(cli->desthost, '.');
1289                         if (host) {
1290                                 machine = SMB_STRNDUP(cli->desthost,
1291                                         host - cli->desthost);
1292                         } else {
1293                                 machine = SMB_STRDUP(cli->desthost);
1294                         }
1295                         if (machine == NULL) {
1296                                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1297                         }
1298
1299                         if (dest_realm) {
1300                                 realm = SMB_STRDUP(dest_realm);
1301                                 strupper_m(realm);
1302                         } else {
1303                                 realm = kerberos_get_default_realm_from_ccache();
1304                         }
1305                         if (realm && *realm) {
1306                                 principal = talloc_asprintf(NULL, "%s$@%s",
1307                                                         machine, realm);
1308                                 if (!principal) {
1309                                         SAFE_FREE(machine);
1310                                         SAFE_FREE(realm);
1311                                         return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1312                                 }
1313                                 DEBUG(3,("cli_session_setup_spnego: guessed "
1314                                         "server principal=%s\n",
1315                                         principal ? principal : "<null>"));
1316                         }
1317                         SAFE_FREE(machine);
1318                         SAFE_FREE(realm);
1319                 }
1320
1321                 if (principal) {
1322                         rc = cli_session_setup_kerberos(cli, principal,
1323                                 dest_realm);
1324                         if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
1325                                 TALLOC_FREE(principal);
1326                                 return rc;
1327                         }
1328                 }
1329         }
1330 #endif
1331
1332         TALLOC_FREE(principal);
1333
1334 ntlmssp:
1335
1336         account = talloc_strdup(talloc_tos(), user);
1337         if (!account) {
1338                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1339         }
1340
1341         /* when falling back to ntlmssp while authenticating with a machine
1342          * account strip off the realm - gd */
1343
1344         if ((p = strchr_m(user, '@')) != NULL) {
1345                 account[PTR_DIFF(p,user)] = '\0';
1346         }
1347
1348         return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
1349 }
1350
1351 /****************************************************************************
1352  Send a session setup. The username and workgroup is in UNIX character
1353  format and must be converted to DOS codepage format before sending. If the
1354  password is in plaintext, the same should be done.
1355 ****************************************************************************/
1356
1357 NTSTATUS cli_session_setup(struct cli_state *cli,
1358                            const char *user,
1359                            const char *pass, int passlen,
1360                            const char *ntpass, int ntpasslen,
1361                            const char *workgroup)
1362 {
1363         char *p;
1364         fstring user2;
1365
1366         if (user) {
1367                 fstrcpy(user2, user);
1368         } else {
1369                 user2[0] ='\0';
1370         }
1371
1372         if (!workgroup) {
1373                 workgroup = "";
1374         }
1375
1376         /* allow for workgroups as part of the username */
1377         if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
1378             (p=strchr_m(user2,*lp_winbind_separator()))) {
1379                 *p = 0;
1380                 user = p+1;
1381                 workgroup = user2;
1382         }
1383
1384         if (cli->protocol < PROTOCOL_LANMAN1) {
1385                 return NT_STATUS_OK;
1386         }
1387
1388         /* now work out what sort of session setup we are going to
1389            do. I have split this into separate functions to make the
1390            flow a bit easier to understand (tridge) */
1391
1392         /* if its an older server then we have to use the older request format */
1393
1394         if (cli->protocol < PROTOCOL_NT1) {
1395                 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
1396                         DEBUG(1, ("Server requested LM password but 'client lanman auth'"
1397                                   " is disabled\n"));
1398                         return NT_STATUS_ACCESS_DENIED;
1399                 }
1400
1401                 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
1402                     !lp_client_plaintext_auth() && (*pass)) {
1403                         DEBUG(1, ("Server requested plaintext password but "
1404                                   "'client plaintext auth' is disabled\n"));
1405                         return NT_STATUS_ACCESS_DENIED;
1406                 }
1407
1408                 return cli_session_setup_lanman2(cli, user, pass, passlen,
1409                                                  workgroup);
1410         }
1411
1412         /* if no user is supplied then we have to do an anonymous connection.
1413            passwords are ignored */
1414
1415         if (!user || !*user)
1416                 return cli_session_setup_guest(cli);
1417
1418         /* if the server is share level then send a plaintext null
1419            password at this point. The password is sent in the tree
1420            connect */
1421
1422         if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) 
1423                 return cli_session_setup_plaintext(cli, user, "", workgroup);
1424
1425         /* if the server doesn't support encryption then we have to use 
1426            plaintext. The second password is ignored */
1427
1428         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
1429                 if (!lp_client_plaintext_auth() && (*pass)) {
1430                         DEBUG(1, ("Server requested plaintext password but "
1431                                   "'client plaintext auth' is disabled\n"));
1432                         return NT_STATUS_ACCESS_DENIED;
1433                 }
1434                 return cli_session_setup_plaintext(cli, user, pass, workgroup);
1435         }
1436
1437         /* if the server supports extended security then use SPNEGO */
1438
1439         if (cli->capabilities & CAP_EXTENDED_SECURITY) {
1440                 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
1441                                                              workgroup, NULL);
1442                 if (!ADS_ERR_OK(status)) {
1443                         DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
1444                         return ads_ntstatus(status);
1445                 }
1446         } else {
1447                 NTSTATUS status;
1448
1449                 /* otherwise do a NT1 style session setup */
1450                 status = cli_session_setup_nt1(cli, user, pass, passlen,
1451                                                ntpass, ntpasslen, workgroup);
1452                 if (!NT_STATUS_IS_OK(status)) {
1453                         DEBUG(3,("cli_session_setup: NT1 session setup "
1454                                  "failed: %s\n", nt_errstr(status)));
1455                         return status;
1456                 }
1457         }
1458
1459         if (strstr(cli->server_type, "Samba")) {
1460                 cli->is_samba = True;
1461         }
1462
1463         return NT_STATUS_OK;
1464 }
1465
1466 /****************************************************************************
1467  Send a uloggoff.
1468 *****************************************************************************/
1469
1470 struct cli_ulogoff_state {
1471         struct cli_state *cli;
1472         uint16_t vwv[2];
1473 };
1474
1475 static void cli_ulogoff_done(struct tevent_req *subreq);
1476
1477 struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
1478                                     struct tevent_context *ev,
1479                                     struct cli_state *cli)
1480 {
1481         struct tevent_req *req, *subreq;
1482         struct cli_ulogoff_state *state;
1483
1484         req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
1485         if (req == NULL) {
1486                 return NULL;
1487         }
1488         state->cli = cli;
1489
1490         SCVAL(state->vwv+0, 0, 0xFF);
1491         SCVAL(state->vwv+1, 0, 0);
1492         SSVAL(state->vwv+2, 0, 0);
1493
1494         subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
1495                               0, NULL);
1496         if (tevent_req_nomem(subreq, req)) {
1497                 return tevent_req_post(req, ev);
1498         }
1499         tevent_req_set_callback(subreq, cli_ulogoff_done, req);
1500         return req;
1501 }
1502
1503 static void cli_ulogoff_done(struct tevent_req *subreq)
1504 {
1505         struct tevent_req *req = tevent_req_callback_data(
1506                 subreq, struct tevent_req);
1507         struct cli_ulogoff_state *state = tevent_req_data(
1508                 req, struct cli_ulogoff_state);
1509         NTSTATUS status;
1510
1511         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
1512         if (!NT_STATUS_IS_OK(status)) {
1513                 tevent_req_nterror(req, status);
1514                 return;
1515         }
1516         state->cli->vuid = -1;
1517         tevent_req_done(req);
1518 }
1519
1520 NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
1521 {
1522         return tevent_req_simple_recv_ntstatus(req);
1523 }
1524
1525 NTSTATUS cli_ulogoff(struct cli_state *cli)
1526 {
1527         struct tevent_context *ev;
1528         struct tevent_req *req;
1529         NTSTATUS status = NT_STATUS_NO_MEMORY;
1530
1531         if (cli_has_async_calls(cli)) {
1532                 return NT_STATUS_INVALID_PARAMETER;
1533         }
1534         ev = tevent_context_init(talloc_tos());
1535         if (ev == NULL) {
1536                 goto fail;
1537         }
1538         req = cli_ulogoff_send(ev, ev, cli);
1539         if (req == NULL) {
1540                 goto fail;
1541         }
1542         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1543                 goto fail;
1544         }
1545         status = cli_ulogoff_recv(req);
1546 fail:
1547         TALLOC_FREE(ev);
1548         if (!NT_STATUS_IS_OK(status)) {
1549                 cli_set_error(cli, status);
1550         }
1551         return status;
1552 }
1553
1554 /****************************************************************************
1555  Send a tconX.
1556 ****************************************************************************/
1557
1558 struct cli_tcon_andx_state {
1559         struct cli_state *cli;
1560         uint16_t vwv[4];
1561         struct iovec bytes;
1562 };
1563
1564 static void cli_tcon_andx_done(struct tevent_req *subreq);
1565
1566 struct tevent_req *cli_tcon_andx_create(TALLOC_CTX *mem_ctx,
1567                                         struct event_context *ev,
1568                                         struct cli_state *cli,
1569                                         const char *share, const char *dev,
1570                                         const char *pass, int passlen,
1571                                         struct tevent_req **psmbreq)
1572 {
1573         struct tevent_req *req, *subreq;
1574         struct cli_tcon_andx_state *state;
1575         fstring pword;
1576         uint16_t *vwv;
1577         char *tmp = NULL;
1578         uint8_t *bytes;
1579
1580         *psmbreq = NULL;
1581
1582         req = tevent_req_create(mem_ctx, &state, struct cli_tcon_andx_state);
1583         if (req == NULL) {
1584                 return NULL;
1585         }
1586         state->cli = cli;
1587         vwv = state->vwv;
1588
1589         fstrcpy(cli->share, share);
1590
1591         /* in user level security don't send a password now */
1592         if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1593                 passlen = 1;
1594                 pass = "";
1595         } else if (pass == NULL) {
1596                 DEBUG(1, ("Server not using user level security and no "
1597                           "password supplied.\n"));
1598                 goto access_denied;
1599         }
1600
1601         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1602             *pass && passlen != 24) {
1603                 if (!lp_client_lanman_auth()) {
1604                         DEBUG(1, ("Server requested LANMAN password "
1605                                   "(share-level security) but "
1606                                   "'client lanman auth' is disabled\n"));
1607                         goto access_denied;
1608                 }
1609
1610                 /*
1611                  * Non-encrypted passwords - convert to DOS codepage before
1612                  * encryption.
1613                  */
1614                 passlen = 24;
1615                 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
1616         } else {
1617                 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
1618                                      |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
1619                    == 0) {
1620                         if (!lp_client_plaintext_auth() && (*pass)) {
1621                                 DEBUG(1, ("Server requested plaintext "
1622                                           "password but 'client plaintext "
1623                                           "auth' is disabled\n"));
1624                                 goto access_denied;
1625                         }
1626
1627                         /*
1628                          * Non-encrypted passwords - convert to DOS codepage
1629                          * before using.
1630                          */
1631                         passlen = clistr_push(cli, pword, pass, sizeof(pword),
1632                                               STR_TERMINATE);
1633                         if (passlen == -1) {
1634                                 DEBUG(1, ("clistr_push(pword) failed\n"));
1635                                 goto access_denied;
1636                         }
1637                 } else {
1638                         if (passlen) {
1639                                 memcpy(pword, pass, passlen);
1640                         }
1641                 }
1642         }
1643
1644         SCVAL(vwv+0, 0, 0xFF);
1645         SCVAL(vwv+0, 1, 0);
1646         SSVAL(vwv+1, 0, 0);
1647         SSVAL(vwv+2, 0, TCONX_FLAG_EXTENDED_RESPONSE);
1648         SSVAL(vwv+3, 0, passlen);
1649
1650         if (passlen) {
1651                 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
1652         } else {
1653                 bytes = talloc_array(state, uint8_t, 0);
1654         }
1655
1656         /*
1657          * Add the sharename
1658          */
1659         tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
1660                                          cli->desthost, share);
1661         if (tmp == NULL) {
1662                 TALLOC_FREE(req);
1663                 return NULL;
1664         }
1665         bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
1666                                    NULL);
1667         TALLOC_FREE(tmp);
1668
1669         /*
1670          * Add the devicetype
1671          */
1672         tmp = talloc_strdup_upper(talloc_tos(), dev);
1673         if (tmp == NULL) {
1674                 TALLOC_FREE(req);
1675                 return NULL;
1676         }
1677         bytes = smb_bytes_push_str(bytes, false, tmp, strlen(tmp)+1, NULL);
1678         TALLOC_FREE(tmp);
1679
1680         if (bytes == NULL) {
1681                 TALLOC_FREE(req);
1682                 return NULL;
1683         }
1684
1685         state->bytes.iov_base = (void *)bytes;
1686         state->bytes.iov_len = talloc_get_size(bytes);
1687
1688         subreq = cli_smb_req_create(state, ev, cli, SMBtconX, 0, 4, vwv,
1689                                     1, &state->bytes);
1690         if (subreq == NULL) {
1691                 TALLOC_FREE(req);
1692                 return NULL;
1693         }
1694         tevent_req_set_callback(subreq, cli_tcon_andx_done, req);
1695         *psmbreq = subreq;
1696         return req;
1697
1698  access_denied:
1699         tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1700         return tevent_req_post(req, ev);
1701 }
1702
1703 struct tevent_req *cli_tcon_andx_send(TALLOC_CTX *mem_ctx,
1704                                       struct event_context *ev,
1705                                       struct cli_state *cli,
1706                                       const char *share, const char *dev,
1707                                       const char *pass, int passlen)
1708 {
1709         struct tevent_req *req, *subreq;
1710         NTSTATUS status;
1711
1712         req = cli_tcon_andx_create(mem_ctx, ev, cli, share, dev, pass, passlen,
1713                                    &subreq);
1714         if (req == NULL) {
1715                 return NULL;
1716         }
1717         if (subreq == NULL) {
1718                 return req;
1719         }
1720         status = cli_smb_req_send(subreq);
1721         if (!NT_STATUS_IS_OK(status)) {
1722                 tevent_req_nterror(req, status);
1723                 return tevent_req_post(req, ev);
1724         }
1725         return req;
1726 }
1727
1728 static void cli_tcon_andx_done(struct tevent_req *subreq)
1729 {
1730         struct tevent_req *req = tevent_req_callback_data(
1731                 subreq, struct tevent_req);
1732         struct cli_tcon_andx_state *state = tevent_req_data(
1733                 req, struct cli_tcon_andx_state);
1734         struct cli_state *cli = state->cli;
1735         char *inbuf = (char *)cli_smb_inbuf(subreq);
1736         uint8_t wct;
1737         uint16_t *vwv;
1738         uint32_t num_bytes;
1739         uint8_t *bytes;
1740         NTSTATUS status;
1741
1742         status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
1743         if (!NT_STATUS_IS_OK(status)) {
1744                 TALLOC_FREE(subreq);
1745                 tevent_req_nterror(req, status);
1746                 return;
1747         }
1748
1749         clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
1750                     STR_TERMINATE|STR_ASCII);
1751
1752         if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
1753                 /* almost certainly win95 - enable bug fixes */
1754                 cli->win95 = True;
1755         }
1756
1757         /*
1758          * Make sure that we have the optional support 16-bit field. WCT > 2.
1759          * Avoids issues when connecting to Win9x boxes sharing files
1760          */
1761
1762         cli->dfsroot = false;
1763
1764         if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
1765                 cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
1766         }
1767
1768         cli->cnum = SVAL(inbuf,smb_tid);
1769         tevent_req_done(req);
1770 }
1771
1772 NTSTATUS cli_tcon_andx_recv(struct tevent_req *req)
1773 {
1774         return tevent_req_simple_recv_ntstatus(req);
1775 }
1776
1777 NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
1778                        const char *dev, const char *pass, int passlen)
1779 {
1780         TALLOC_CTX *frame = talloc_stackframe();
1781         struct event_context *ev;
1782         struct tevent_req *req;
1783         NTSTATUS status = NT_STATUS_OK;
1784
1785         if (cli_has_async_calls(cli)) {
1786                 /*
1787                  * Can't use sync call while an async call is in flight
1788                  */
1789                 status = NT_STATUS_INVALID_PARAMETER;
1790                 goto fail;
1791         }
1792
1793         ev = event_context_init(frame);
1794         if (ev == NULL) {
1795                 status = NT_STATUS_NO_MEMORY;
1796                 goto fail;
1797         }
1798
1799         req = cli_tcon_andx_send(frame, ev, cli, share, dev, pass, passlen);
1800         if (req == NULL) {
1801                 status = NT_STATUS_NO_MEMORY;
1802                 goto fail;
1803         }
1804
1805         if (!tevent_req_poll(req, ev)) {
1806                 status = map_nt_error_from_unix(errno);
1807                 goto fail;
1808         }
1809
1810         status = cli_tcon_andx_recv(req);
1811  fail:
1812         TALLOC_FREE(frame);
1813         if (!NT_STATUS_IS_OK(status)) {
1814                 cli_set_error(cli, status);
1815         }
1816         return status;
1817 }
1818
1819 /****************************************************************************
1820  Send a tree disconnect.
1821 ****************************************************************************/
1822
1823 struct cli_tdis_state {
1824         struct cli_state *cli;
1825 };
1826
1827 static void cli_tdis_done(struct tevent_req *subreq);
1828
1829 struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
1830                                  struct tevent_context *ev,
1831                                  struct cli_state *cli)
1832 {
1833         struct tevent_req *req, *subreq;
1834         struct cli_tdis_state *state;
1835
1836         req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
1837         if (req == NULL) {
1838                 return NULL;
1839         }
1840         state->cli = cli;
1841
1842         subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
1843         if (tevent_req_nomem(subreq, req)) {
1844                 return tevent_req_post(req, ev);
1845         }
1846         tevent_req_set_callback(subreq, cli_tdis_done, req);
1847         return req;
1848 }
1849
1850 static void cli_tdis_done(struct tevent_req *subreq)
1851 {
1852         struct tevent_req *req = tevent_req_callback_data(
1853                 subreq, struct tevent_req);
1854         struct cli_tdis_state *state = tevent_req_data(
1855                 req, struct cli_tdis_state);
1856         NTSTATUS status;
1857
1858         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
1859         TALLOC_FREE(subreq);
1860         if (!NT_STATUS_IS_OK(status)) {
1861                 tevent_req_nterror(req, status);
1862                 return;
1863         }
1864         state->cli->cnum = -1;
1865         tevent_req_done(req);
1866 }
1867
1868 NTSTATUS cli_tdis_recv(struct tevent_req *req)
1869 {
1870         return tevent_req_simple_recv_ntstatus(req);
1871 }
1872
1873 NTSTATUS cli_tdis(struct cli_state *cli)
1874 {
1875         struct tevent_context *ev;
1876         struct tevent_req *req;
1877         NTSTATUS status = NT_STATUS_NO_MEMORY;
1878
1879         if (cli_has_async_calls(cli)) {
1880                 return NT_STATUS_INVALID_PARAMETER;
1881         }
1882         ev = tevent_context_init(talloc_tos());
1883         if (ev == NULL) {
1884                 goto fail;
1885         }
1886         req = cli_tdis_send(ev, ev, cli);
1887         if (req == NULL) {
1888                 goto fail;
1889         }
1890         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1891                 goto fail;
1892         }
1893         status = cli_tdis_recv(req);
1894 fail:
1895         TALLOC_FREE(ev);
1896         if (!NT_STATUS_IS_OK(status)) {
1897                 cli_set_error(cli, status);
1898         }
1899         return status;
1900 }
1901
1902 /****************************************************************************
1903  Send a negprot command.
1904 ****************************************************************************/
1905
1906 void cli_negprot_sendsync(struct cli_state *cli)
1907 {
1908         char *p;
1909         int numprots;
1910
1911         if (cli->protocol < PROTOCOL_NT1)
1912                 cli->use_spnego = False;
1913
1914         memset(cli->outbuf,'\0',smb_size);
1915
1916         /* setup the protocol strings */
1917         cli_set_message(cli->outbuf,0,0,True);
1918
1919         p = smb_buf(cli->outbuf);
1920         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1921                 if (prots[numprots].prot > cli->protocol) {
1922                         break;
1923                 }
1924                 *p++ = 2;
1925                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1926         }
1927
1928         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1929         cli_setup_bcc(cli, p);
1930         cli_setup_packet(cli);
1931
1932         SCVAL(smb_buf(cli->outbuf),0,2);
1933
1934         cli_send_smb(cli);
1935 }
1936
1937 /****************************************************************************
1938  Send a negprot command.
1939 ****************************************************************************/
1940
1941 struct cli_negprot_state {
1942         struct cli_state *cli;
1943 };
1944
1945 static void cli_negprot_done(struct tevent_req *subreq);
1946
1947 struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1948                                     struct event_context *ev,
1949                                     struct cli_state *cli)
1950 {
1951         struct tevent_req *req, *subreq;
1952         struct cli_negprot_state *state;
1953         uint8_t *bytes = NULL;
1954         int numprots;
1955         uint16_t cnum;
1956
1957         req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
1958         if (req == NULL) {
1959                 return NULL;
1960         }
1961         state->cli = cli;
1962
1963         if (cli->protocol < PROTOCOL_NT1)
1964                 cli->use_spnego = False;
1965
1966         /* setup the protocol strings */
1967         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1968                 uint8_t c = 2;
1969                 if (prots[numprots].prot > cli->protocol) {
1970                         break;
1971                 }
1972                 bytes = (uint8_t *)talloc_append_blob(
1973                         state, bytes, data_blob_const(&c, sizeof(c)));
1974                 if (tevent_req_nomem(bytes, req)) {
1975                         return tevent_req_post(req, ev);
1976                 }
1977                 bytes = smb_bytes_push_str(bytes, false,
1978                                            prots[numprots].name,
1979                                            strlen(prots[numprots].name)+1,
1980                                            NULL);
1981                 if (tevent_req_nomem(bytes, req)) {
1982                         return tevent_req_post(req, ev);
1983                 }
1984         }
1985
1986         cnum = cli->cnum;
1987
1988         cli->cnum = 0;
1989         subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
1990                               talloc_get_size(bytes), bytes);
1991         cli->cnum = cnum;
1992
1993         if (tevent_req_nomem(subreq, req)) {
1994                 return tevent_req_post(req, ev);
1995         }
1996         tevent_req_set_callback(subreq, cli_negprot_done, req);
1997         return req;
1998 }
1999
2000 static void cli_negprot_done(struct tevent_req *subreq)
2001 {
2002         struct tevent_req *req = tevent_req_callback_data(
2003                 subreq, struct tevent_req);
2004         struct cli_negprot_state *state = tevent_req_data(
2005                 req, struct cli_negprot_state);
2006         struct cli_state *cli = state->cli;
2007         uint8_t wct;
2008         uint16_t *vwv;
2009         uint32_t num_bytes;
2010         uint8_t *bytes;
2011         NTSTATUS status;
2012         uint16_t protnum;
2013
2014         status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
2015         if (!NT_STATUS_IS_OK(status)) {
2016                 TALLOC_FREE(subreq);
2017                 tevent_req_nterror(req, status);
2018                 return;
2019         }
2020
2021         protnum = SVAL(vwv, 0);
2022
2023         if ((protnum >= ARRAY_SIZE(prots))
2024             || (prots[protnum].prot > cli->protocol)) {
2025                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
2026                 return;
2027         }
2028
2029         cli->protocol = prots[protnum].prot;
2030
2031         if ((cli->protocol < PROTOCOL_NT1) &&
2032             client_is_signing_mandatory(cli)) {
2033                 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
2034                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2035                 return;
2036         }
2037
2038         if (cli->protocol >= PROTOCOL_NT1) {    
2039                 struct timespec ts;
2040                 bool negotiated_smb_signing = false;
2041
2042                 /* NT protocol */
2043                 cli->sec_mode = CVAL(vwv + 1, 0);
2044                 cli->max_mux = SVAL(vwv + 1, 1);
2045                 cli->max_xmit = IVAL(vwv + 3, 1);
2046                 cli->sesskey = IVAL(vwv + 7, 1);
2047                 cli->serverzone = SVALS(vwv + 15, 1);
2048                 cli->serverzone *= 60;
2049                 /* this time arrives in real GMT */
2050                 ts = interpret_long_date(((char *)(vwv+11))+1);
2051                 cli->servertime = ts.tv_sec;
2052                 cli->secblob = data_blob(bytes, num_bytes);
2053                 cli->capabilities = IVAL(vwv + 9, 1);
2054                 if (cli->capabilities & CAP_RAW_MODE) {
2055                         cli->readbraw_supported = True;
2056                         cli->writebraw_supported = True;      
2057                 }
2058                 /* work out if they sent us a workgroup */
2059                 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
2060                     smb_buflen(cli->inbuf) > 8) {
2061                         clistr_pull(cli->inbuf, cli->server_domain,
2062                                     bytes+8, sizeof(cli->server_domain),
2063                                     num_bytes-8,
2064                                     STR_UNICODE|STR_NOALIGN);
2065                 }
2066
2067                 /*
2068                  * As signing is slow we only turn it on if either the client or
2069                  * the server require it. JRA.
2070                  */
2071
2072                 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
2073                         /* Fail if server says signing is mandatory and we don't want to support it. */
2074                         if (!client_is_signing_allowed(cli)) {
2075                                 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
2076                                 tevent_req_nterror(req,
2077                                                    NT_STATUS_ACCESS_DENIED);
2078                                 return;
2079                         }
2080                         negotiated_smb_signing = true;
2081                 } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
2082                         /* Fail if client says signing is mandatory and the server doesn't support it. */
2083                         if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
2084                                 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
2085                                 tevent_req_nterror(req,
2086                                                    NT_STATUS_ACCESS_DENIED);
2087                                 return;
2088                         }
2089                         negotiated_smb_signing = true;
2090                 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
2091                         negotiated_smb_signing = true;
2092                 }
2093
2094                 if (negotiated_smb_signing) {
2095                         cli_set_signing_negotiated(cli);
2096                 }
2097
2098                 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
2099                         SAFE_FREE(cli->outbuf);
2100                         SAFE_FREE(cli->inbuf);
2101                         cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2102                         cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
2103                         cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
2104                 }
2105
2106         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2107                 cli->use_spnego = False;
2108                 cli->sec_mode = SVAL(vwv + 1, 0);
2109                 cli->max_xmit = SVAL(vwv + 2, 0);
2110                 cli->max_mux = SVAL(vwv + 3, 0);
2111                 cli->sesskey = IVAL(vwv + 6, 0);
2112                 cli->serverzone = SVALS(vwv + 10, 0);
2113                 cli->serverzone *= 60;
2114                 /* this time is converted to GMT by make_unix_date */
2115                 cli->servertime = cli_make_unix_date(
2116                         cli, (char *)(vwv + 8));
2117                 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
2118                 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
2119                 cli->secblob = data_blob(bytes, num_bytes);
2120         } else {
2121                 /* the old core protocol */
2122                 cli->use_spnego = False;
2123                 cli->sec_mode = 0;
2124                 cli->serverzone = get_time_zone(time(NULL));
2125         }
2126
2127         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2128
2129         /* a way to force ascii SMB */
2130         if (getenv("CLI_FORCE_ASCII"))
2131                 cli->capabilities &= ~CAP_UNICODE;
2132
2133         tevent_req_done(req);
2134 }
2135
2136 NTSTATUS cli_negprot_recv(struct tevent_req *req)
2137 {
2138         return tevent_req_simple_recv_ntstatus(req);
2139 }
2140
2141 NTSTATUS cli_negprot(struct cli_state *cli)
2142 {
2143         TALLOC_CTX *frame = talloc_stackframe();
2144         struct event_context *ev;
2145         struct tevent_req *req;
2146         NTSTATUS status = NT_STATUS_OK;
2147
2148         if (cli_has_async_calls(cli)) {
2149                 /*
2150                  * Can't use sync call while an async call is in flight
2151                  */
2152                 status = NT_STATUS_INVALID_PARAMETER;
2153                 goto fail;
2154         }
2155
2156         ev = event_context_init(frame);
2157         if (ev == NULL) {
2158                 status = NT_STATUS_NO_MEMORY;
2159                 goto fail;
2160         }
2161
2162         req = cli_negprot_send(frame, ev, cli);
2163         if (req == NULL) {
2164                 status = NT_STATUS_NO_MEMORY;
2165                 goto fail;
2166         }
2167
2168         if (!tevent_req_poll(req, ev)) {
2169                 status = map_nt_error_from_unix(errno);
2170                 goto fail;
2171         }
2172
2173         status = cli_negprot_recv(req);
2174  fail:
2175         TALLOC_FREE(frame);
2176         if (!NT_STATUS_IS_OK(status)) {
2177                 cli_set_error(cli, status);
2178         }
2179         return status;
2180 }
2181
2182 /****************************************************************************
2183  Send a session request. See rfc1002.txt 4.3 and 4.3.2.
2184 ****************************************************************************/
2185
2186 bool cli_session_request(struct cli_state *cli,
2187                          struct nmb_name *calling, struct nmb_name *called)
2188 {
2189         char *p;
2190         int len = 4;
2191         char *tmp;
2192
2193         /* 445 doesn't have session request */
2194         if (cli->port == 445)
2195                 return True;
2196
2197         memcpy(&(cli->calling), calling, sizeof(*calling));
2198         memcpy(&(cli->called ), called , sizeof(*called ));
2199
2200         /* put in the destination name */
2201
2202         tmp = name_mangle(talloc_tos(), cli->called.name,
2203                           cli->called.name_type);
2204         if (tmp == NULL) {
2205                 return false;
2206         }
2207
2208         p = cli->outbuf+len;
2209         memcpy(p, tmp, name_len(tmp));
2210         len += name_len(tmp);
2211         TALLOC_FREE(tmp);
2212
2213         /* and my name */
2214
2215         tmp = name_mangle(talloc_tos(), cli->calling.name,
2216                           cli->calling.name_type);
2217         if (tmp == NULL) {
2218                 return false;
2219         }
2220
2221         p = cli->outbuf+len;
2222         memcpy(p, tmp, name_len(tmp));
2223         len += name_len(tmp);
2224         TALLOC_FREE(tmp);
2225
2226         /* send a session request (RFC 1002) */
2227         /* setup the packet length
2228          * Remove four bytes from the length count, since the length
2229          * field in the NBT Session Service header counts the number
2230          * of bytes which follow.  The cli_send_smb() function knows
2231          * about this and accounts for those four bytes.
2232          * CRH.
2233          */
2234         len -= 4;
2235         _smb_setlen(cli->outbuf,len);
2236         SCVAL(cli->outbuf,0,0x81);
2237
2238         cli_send_smb(cli);
2239         DEBUG(5,("Sent session request\n"));
2240
2241         if (!cli_receive_smb(cli))
2242                 return False;
2243
2244         if (CVAL(cli->inbuf,0) == 0x84) {
2245                 /* C. Hoch  9/14/95 Start */
2246                 /* For information, here is the response structure.
2247                  * We do the byte-twiddling to for portability.
2248                 struct RetargetResponse{
2249                 unsigned char type;
2250                 unsigned char flags;
2251                 int16 length;
2252                 int32 ip_addr;
2253                 int16 port;
2254                 };
2255                 */
2256                 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
2257                 struct in_addr dest_ip;
2258                 NTSTATUS status;
2259
2260                 /* SESSION RETARGET */
2261                 putip((char *)&dest_ip,cli->inbuf+4);
2262                 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
2263
2264                 status = open_socket_out(&cli->dest_ss, port,
2265                                          LONG_CONNECT_TIMEOUT, &cli->fd);
2266                 if (!NT_STATUS_IS_OK(status)) {
2267                         return False;
2268                 }
2269
2270                 DEBUG(3,("Retargeted\n"));
2271
2272                 set_socket_options(cli->fd, lp_socket_options());
2273
2274                 /* Try again */
2275                 {
2276                         static int depth;
2277                         bool ret;
2278                         if (depth > 4) {
2279                                 DEBUG(0,("Retarget recursion - failing\n"));
2280                                 return False;
2281                         }
2282                         depth++;
2283                         ret = cli_session_request(cli, calling, called);
2284                         depth--;
2285                         return ret;
2286                 }
2287         } /* C. Hoch 9/14/95 End */
2288
2289         if (CVAL(cli->inbuf,0) != 0x82) {
2290                 /* This is the wrong place to put the error... JRA. */
2291                 cli->rap_error = CVAL(cli->inbuf,4);
2292                 return False;
2293         }
2294         return(True);
2295 }
2296
2297 struct fd_struct {
2298         int fd;
2299 };
2300
2301 static void smb_sock_connected(struct tevent_req *req)
2302 {
2303         struct fd_struct *pfd = tevent_req_callback_data(
2304                 req, struct fd_struct);
2305         int fd;
2306         NTSTATUS status;
2307
2308         status = open_socket_out_defer_recv(req, &fd);
2309         if (NT_STATUS_IS_OK(status)) {
2310                 pfd->fd = fd;
2311         }
2312 }
2313
2314 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
2315                                 uint16_t *port, int timeout, int *pfd)
2316 {
2317         struct event_context *ev;
2318         struct tevent_req *r139, *r445;
2319         struct fd_struct *fd139, *fd445;
2320         NTSTATUS status = NT_STATUS_NO_MEMORY;
2321
2322         if (*port != 0) {
2323                 return open_socket_out(pss, *port, timeout, pfd);
2324         }
2325
2326         ev = event_context_init(talloc_tos());
2327         if (ev == NULL) {
2328                 return NT_STATUS_NO_MEMORY;
2329         }
2330
2331         fd139 = talloc(ev, struct fd_struct);
2332         if (fd139 == NULL) {
2333                 goto done;
2334         }
2335         fd139->fd = -1;
2336
2337         fd445 = talloc(ev, struct fd_struct);
2338         if (fd445 == NULL) {
2339                 goto done;
2340         }
2341         fd445->fd = -1;
2342
2343         r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
2344                                           pss, 445, timeout);
2345         r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
2346                                           pss, 139, timeout);
2347         if ((r445 == NULL) || (r139 == NULL)) {
2348                 goto done;
2349         }
2350         tevent_req_set_callback(r445, smb_sock_connected, fd445);
2351         tevent_req_set_callback(r139, smb_sock_connected, fd139);
2352
2353         while ((fd445->fd == -1) && (fd139->fd == -1)
2354                && (tevent_req_is_in_progress(r139)
2355                    || tevent_req_is_in_progress(r445))) {
2356                 event_loop_once(ev);
2357         }
2358
2359         if ((fd139->fd != -1) && (fd445->fd != -1)) {
2360                 close(fd139->fd);
2361                 fd139->fd = -1;
2362         }
2363
2364         if (fd445->fd != -1) {
2365                 *port = 445;
2366                 *pfd = fd445->fd;
2367                 status = NT_STATUS_OK;
2368                 goto done;
2369         }
2370         if (fd139->fd != -1) {
2371                 *port = 139;
2372                 *pfd = fd139->fd;
2373                 status = NT_STATUS_OK;
2374                 goto done;
2375         }
2376
2377         status = open_socket_out_defer_recv(r445, &fd445->fd);
2378  done:
2379         TALLOC_FREE(ev);
2380         return status;
2381 }
2382
2383 /****************************************************************************
2384  Open the client sockets.
2385 ****************************************************************************/
2386
2387 NTSTATUS cli_connect(struct cli_state *cli,
2388                 const char *host,
2389                 struct sockaddr_storage *dest_ss)
2390
2391 {
2392         int name_type = 0x20;
2393         TALLOC_CTX *frame = talloc_stackframe();
2394         unsigned int num_addrs = 0;
2395         unsigned int i = 0;
2396         struct sockaddr_storage *ss_arr = NULL;
2397         char *p = NULL;
2398
2399         /* reasonable default hostname */
2400         if (!host) {
2401                 host = STAR_SMBSERVER;
2402         }
2403
2404         fstrcpy(cli->desthost, host);
2405
2406         /* allow hostnames of the form NAME#xx and do a netbios lookup */
2407         if ((p = strchr(cli->desthost, '#'))) {
2408                 name_type = strtol(p+1, NULL, 16);
2409                 *p = 0;
2410         }
2411
2412         if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
2413                 NTSTATUS status =resolve_name_list(frame,
2414                                         cli->desthost,
2415                                         name_type,
2416                                         &ss_arr,
2417                                         &num_addrs);
2418                 if (!NT_STATUS_IS_OK(status)) {
2419                         TALLOC_FREE(frame);
2420                         return NT_STATUS_BAD_NETWORK_NAME;
2421                 }
2422         } else {
2423                 num_addrs = 1;
2424                 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
2425                 if (!ss_arr) {
2426                         TALLOC_FREE(frame);
2427                         return NT_STATUS_NO_MEMORY;
2428                 }
2429                 *ss_arr = *dest_ss;
2430         }
2431
2432         for (i = 0; i < num_addrs; i++) {
2433                 cli->dest_ss = ss_arr[i];
2434                 if (getenv("LIBSMB_PROG")) {
2435                         cli->fd = sock_exec(getenv("LIBSMB_PROG"));
2436                 } else {
2437                         uint16_t port = cli->port;
2438                         NTSTATUS status;
2439                         status = open_smb_socket(&cli->dest_ss, &port,
2440                                                  cli->timeout, &cli->fd);
2441                         if (NT_STATUS_IS_OK(status)) {
2442                                 cli->port = port;
2443                         }
2444                 }
2445                 if (cli->fd == -1) {
2446                         char addr[INET6_ADDRSTRLEN];
2447                         print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
2448                         DEBUG(2,("Error connecting to %s (%s)\n",
2449                                  dest_ss?addr:host,strerror(errno)));
2450                 } else {
2451                         /* Exit from loop on first connection. */
2452                         break;
2453                 }
2454         }
2455
2456         if (cli->fd == -1) {
2457                 TALLOC_FREE(frame);
2458                 return map_nt_error_from_unix(errno);
2459         }
2460
2461         if (dest_ss) {
2462                 *dest_ss = cli->dest_ss;
2463         }
2464
2465         set_socket_options(cli->fd, lp_socket_options());
2466
2467         TALLOC_FREE(frame);
2468         return NT_STATUS_OK;
2469 }
2470
2471 /**
2472    establishes a connection to after the negprot. 
2473    @param output_cli A fully initialised cli structure, non-null only on success
2474    @param dest_host The netbios name of the remote host
2475    @param dest_ss (optional) The the destination IP, NULL for name based lookup
2476    @param port (optional) The destination port (0 for default)
2477    @param retry bool. Did this connection fail with a retryable error ?
2478
2479 */
2480 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
2481                               const char *my_name, 
2482                               const char *dest_host, 
2483                               struct sockaddr_storage *dest_ss, int port,
2484                               int signing_state, int flags,
2485                               bool *retry) 
2486 {
2487         NTSTATUS nt_status;
2488         struct nmb_name calling;
2489         struct nmb_name called;
2490         struct cli_state *cli;
2491         struct sockaddr_storage ss;
2492
2493         if (retry)
2494                 *retry = False;
2495
2496         if (!my_name) 
2497                 my_name = global_myname();
2498
2499         if (!(cli = cli_initialise_ex(signing_state))) {
2500                 return NT_STATUS_NO_MEMORY;
2501         }
2502
2503         make_nmb_name(&calling, my_name, 0x0);
2504         make_nmb_name(&called , dest_host, 0x20);
2505
2506         cli_set_port(cli, port);
2507         cli_set_timeout(cli, 10000); /* 10 seconds. */
2508
2509         if (dest_ss) {
2510                 ss = *dest_ss;
2511         } else {
2512                 zero_sockaddr(&ss);
2513         }
2514
2515 again:
2516
2517         DEBUG(3,("Connecting to host=%s\n", dest_host));
2518
2519         nt_status = cli_connect(cli, dest_host, &ss);
2520         if (!NT_STATUS_IS_OK(nt_status)) {
2521                 char addr[INET6_ADDRSTRLEN];
2522                 print_sockaddr(addr, sizeof(addr), &ss);
2523                 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
2524                          nmb_namestr(&called), addr, nt_errstr(nt_status) ));
2525                 cli_shutdown(cli);
2526                 return nt_status;
2527         }
2528
2529         if (retry)
2530                 *retry = True;
2531
2532         if (!cli_session_request(cli, &calling, &called)) {
2533                 char *p;
2534                 DEBUG(1,("session request to %s failed (%s)\n",
2535                          called.name, cli_errstr(cli)));
2536                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
2537                         *p = 0;
2538                         goto again;
2539                 }
2540                 if (strcmp(called.name, STAR_SMBSERVER)) {
2541                         make_nmb_name(&called , STAR_SMBSERVER, 0x20);
2542                         goto again;
2543                 }
2544                 return NT_STATUS_BAD_NETWORK_NAME;
2545         }
2546
2547         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
2548                 cli->use_spnego = False;
2549         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
2550                 cli->use_kerberos = True;
2551
2552         if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
2553              cli->use_kerberos) {
2554                 cli->fallback_after_kerberos = true;
2555         }
2556
2557         nt_status = cli_negprot(cli);
2558         if (!NT_STATUS_IS_OK(nt_status)) {
2559                 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
2560                 cli_shutdown(cli);
2561                 return nt_status;
2562         }
2563
2564         *output_cli = cli;
2565         return NT_STATUS_OK;
2566 }
2567
2568
2569 /**
2570    establishes a connection right up to doing tconX, password specified.
2571    @param output_cli A fully initialised cli structure, non-null only on success
2572    @param dest_host The netbios name of the remote host
2573    @param dest_ip (optional) The the destination IP, NULL for name based lookup
2574    @param port (optional) The destination port (0 for default)
2575    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
2576    @param service_type The 'type' of serivice. 
2577    @param user Username, unix string
2578    @param domain User's domain
2579    @param password User's password, unencrypted unix string.
2580    @param retry bool. Did this connection fail with a retryable error ?
2581 */
2582
2583 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
2584                              const char *my_name, 
2585                              const char *dest_host, 
2586                              struct sockaddr_storage *dest_ss, int port,
2587                              const char *service, const char *service_type,
2588                              const char *user, const char *domain, 
2589                              const char *password, int flags,
2590                              int signing_state,
2591                              bool *retry) 
2592 {
2593         NTSTATUS nt_status;
2594         struct cli_state *cli = NULL;
2595         int pw_len = password ? strlen(password)+1 : 0;
2596
2597         *output_cli = NULL;
2598
2599         if (password == NULL) {
2600                 password = "";
2601         }
2602
2603         nt_status = cli_start_connection(&cli, my_name, dest_host,
2604                                          dest_ss, port, signing_state,
2605                                          flags, retry);
2606
2607         if (!NT_STATUS_IS_OK(nt_status)) {
2608                 return nt_status;
2609         }
2610
2611         cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
2612         cli->use_level_II_oplocks =
2613                 ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
2614
2615         nt_status = cli_session_setup(cli, user, password, pw_len, password,
2616                                       pw_len, domain);
2617         if (!NT_STATUS_IS_OK(nt_status)) {
2618
2619                 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
2620                         DEBUG(1,("failed session setup with %s\n",
2621                                  nt_errstr(nt_status)));
2622                         cli_shutdown(cli);
2623                         return nt_status;
2624                 }
2625
2626                 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
2627                 if (!NT_STATUS_IS_OK(nt_status)) {
2628                         DEBUG(1,("anonymous failed session setup with %s\n",
2629                                  nt_errstr(nt_status)));
2630                         cli_shutdown(cli);
2631                         return nt_status;
2632                 }
2633         }
2634
2635         if (service) {
2636                 nt_status = cli_tcon_andx(cli, service, service_type, password,
2637                                           pw_len);
2638                 if (!NT_STATUS_IS_OK(nt_status)) {
2639                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
2640                         cli_shutdown(cli);
2641                         if (NT_STATUS_IS_OK(nt_status)) {
2642                                 nt_status = NT_STATUS_UNSUCCESSFUL;
2643                         }
2644                         return nt_status;
2645                 }
2646         }
2647
2648         nt_status = cli_init_creds(cli, user, domain, password);
2649         if (!NT_STATUS_IS_OK(nt_status)) {
2650                 cli_shutdown(cli);
2651                 return nt_status;
2652         }
2653
2654         *output_cli = cli;
2655         return NT_STATUS_OK;
2656 }
2657
2658 /****************************************************************************
2659  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
2660 ****************************************************************************/
2661
2662 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
2663                                      struct sockaddr_storage *pdest_ss)
2664 {
2665         struct nmb_name calling, called;
2666
2667         make_nmb_name(&calling, srchost, 0x0);
2668
2669         /*
2670          * If the called name is an IP address
2671          * then use *SMBSERVER immediately.
2672          */
2673
2674         if(is_ipaddress(desthost)) {
2675                 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
2676         } else {
2677                 make_nmb_name(&called, desthost, 0x20);
2678         }
2679
2680         if (!cli_session_request(*ppcli, &calling, &called)) {
2681                 NTSTATUS status;
2682                 struct nmb_name smbservername;
2683
2684                 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2685
2686                 /*
2687                  * If the name wasn't *SMBSERVER then
2688                  * try with *SMBSERVER if the first name fails.
2689                  */
2690
2691                 if (nmb_name_equal(&called, &smbservername)) {
2692
2693                         /*
2694                          * The name used was *SMBSERVER, don't bother with another name.
2695                          */
2696
2697                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2698 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2699                         return False;
2700                 }
2701
2702                 /* Try again... */
2703                 cli_shutdown(*ppcli);
2704
2705                 *ppcli = cli_initialise();
2706                 if (!*ppcli) {
2707                         /* Out of memory... */
2708                         return False;
2709                 }
2710
2711                 status = cli_connect(*ppcli, desthost, pdest_ss);
2712                 if (!NT_STATUS_IS_OK(status) ||
2713                                 !cli_session_request(*ppcli, &calling, &smbservername)) {
2714                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2715 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2716                         return False;
2717                 }
2718         }
2719
2720         return True;
2721 }
2722
2723 /****************************************************************************
2724  Send an old style tcon.
2725 ****************************************************************************/
2726 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
2727                       const char *service, const char *pass, const char *dev,
2728                       uint16 *max_xmit, uint16 *tid)
2729 {
2730         char *p;
2731
2732         if (!lp_client_plaintext_auth() && (*pass)) {
2733                 DEBUG(1, ("Server requested plaintext password but 'client "
2734                           "plaintext auth' is disabled\n"));
2735                 return NT_STATUS_ACCESS_DENIED;
2736         }
2737
2738         memset(cli->outbuf,'\0',smb_size);
2739         memset(cli->inbuf,'\0',smb_size);
2740
2741         cli_set_message(cli->outbuf, 0, 0, True);
2742         SCVAL(cli->outbuf,smb_com,SMBtcon);
2743         cli_setup_packet(cli);
2744
2745         p = smb_buf(cli->outbuf);
2746         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2747         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2748         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2749
2750         cli_setup_bcc(cli, p);
2751
2752         cli_send_smb(cli);
2753         if (!cli_receive_smb(cli)) {
2754                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2755         }
2756
2757         if (cli_is_error(cli)) {
2758                 return cli_nt_error(cli);
2759         }
2760
2761         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2762         *tid = SVAL(cli->inbuf, smb_vwv1);
2763
2764         return NT_STATUS_OK;
2765 }
2766
2767 /* Return a cli_state pointing at the IPC$ share for the given server */
2768
2769 struct cli_state *get_ipc_connect(char *server,
2770                                 struct sockaddr_storage *server_ss,
2771                                 const struct user_auth_info *user_info)
2772 {
2773         struct cli_state *cli;
2774         NTSTATUS nt_status;
2775         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2776
2777         if (user_info->use_kerberos) {
2778                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2779         }
2780
2781         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
2782                                         user_info->username ? user_info->username : "",
2783                                         lp_workgroup(),
2784                                         user_info->password ? user_info->password : "",
2785                                         flags,
2786                                         Undefined, NULL);
2787
2788         if (NT_STATUS_IS_OK(nt_status)) {
2789                 return cli;
2790         } else if (is_ipaddress(server)) {
2791             /* windows 9* needs a correct NMB name for connections */
2792             fstring remote_name;
2793
2794             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2795                 cli = get_ipc_connect(remote_name, server_ss, user_info);
2796                 if (cli)
2797                     return cli;
2798             }
2799         }
2800         return NULL;
2801 }
2802
2803 /*
2804  * Given the IP address of a master browser on the network, return its
2805  * workgroup and connect to it.
2806  *
2807  * This function is provided to allow additional processing beyond what
2808  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2809  * browsers and obtain each master browsers' list of domains (in case the
2810  * first master browser is recently on the network and has not yet
2811  * synchronized with other master browsers and therefore does not yet have the
2812  * entire network browse list)
2813  */
2814
2815 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2816                                 struct ip_service *mb_ip,
2817                                 const struct user_auth_info *user_info,
2818                                 char **pp_workgroup_out)
2819 {
2820         char addr[INET6_ADDRSTRLEN];
2821         fstring name;
2822         struct cli_state *cli;
2823         struct sockaddr_storage server_ss;
2824
2825         *pp_workgroup_out = NULL;
2826
2827         print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2828         DEBUG(99, ("Looking up name of master browser %s\n",
2829                    addr));
2830
2831         /*
2832          * Do a name status query to find out the name of the master browser.
2833          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2834          * master browser will not respond to a wildcard query (or, at least,
2835          * an NT4 server acting as the domain master browser will not).
2836          *
2837          * We might be able to use ONLY the query on MSBROWSE, but that's not
2838          * yet been tested with all Windows versions, so until it is, leave
2839          * the original wildcard query as the first choice and fall back to
2840          * MSBROWSE if the wildcard query fails.
2841          */
2842         if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2843             !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2844
2845                 DEBUG(99, ("Could not retrieve name status for %s\n",
2846                            addr));
2847                 return NULL;
2848         }
2849
2850         if (!find_master_ip(name, &server_ss)) {
2851                 DEBUG(99, ("Could not find master ip for %s\n", name));
2852                 return NULL;
2853         }
2854
2855         *pp_workgroup_out = talloc_strdup(ctx, name);
2856
2857         DEBUG(4, ("found master browser %s, %s\n", name, addr));
2858
2859         print_sockaddr(addr, sizeof(addr), &server_ss);
2860         cli = get_ipc_connect(addr, &server_ss, user_info);
2861
2862         return cli;
2863 }
2864
2865 /*
2866  * Return the IP address and workgroup of a master browser on the network, and
2867  * connect to it.
2868  */
2869
2870 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2871                                         const struct user_auth_info *user_info,
2872                                         char **pp_workgroup_out)
2873 {
2874         struct ip_service *ip_list;
2875         struct cli_state *cli;
2876         int i, count;
2877
2878         *pp_workgroup_out = NULL;
2879
2880         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2881
2882         /* Go looking for workgroups by broadcasting on the local network */
2883
2884         if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2885                                                 &count))) {
2886                 DEBUG(99, ("No master browsers responded\n"));
2887                 return False;
2888         }
2889
2890         for (i = 0; i < count; i++) {
2891                 char addr[INET6_ADDRSTRLEN];
2892                 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2893                 DEBUG(99, ("Found master browser %s\n", addr));
2894
2895                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2896                                 user_info, pp_workgroup_out);
2897                 if (cli)
2898                         return(cli);
2899         }
2900
2901         return NULL;
2902 }