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