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