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