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