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