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