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