Make cli_session_setup_guest async
[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_error(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 bool cli_send_tconX(struct cli_state *cli, 
1177                     const char *share, const char *dev, const char *pass, int passlen)
1178 {
1179         fstring fullshare, pword;
1180         char *p;
1181         memset(cli->outbuf,'\0',smb_size);
1182         memset(cli->inbuf,'\0',smb_size);
1183
1184         fstrcpy(cli->share, share);
1185
1186         /* in user level security don't send a password now */
1187         if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
1188                 passlen = 1;
1189                 pass = "";
1190         } else if (!pass) {
1191                 DEBUG(1, ("Server not using user level security and no password supplied.\n"));
1192                 return False;
1193         }
1194
1195         if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
1196             *pass && passlen != 24) {
1197                 if (!lp_client_lanman_auth()) {
1198                         DEBUG(1, ("Server requested LANMAN password "
1199                                   "(share-level security) but "
1200                                   "'client lanman auth' is disabled\n"));
1201                         return False;
1202                 }
1203
1204                 /*
1205                  * Non-encrypted passwords - convert to DOS codepage before encryption.
1206                  */
1207                 passlen = 24;
1208                 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
1209         } else {
1210                 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
1211                         if (!lp_client_plaintext_auth() && (*pass)) {
1212                                 DEBUG(1, ("Server requested plaintext "
1213                                           "password but 'client plaintext "
1214                                           "auth' is disabled\n"));
1215                                 return False;
1216                         }
1217
1218                         /*
1219                          * Non-encrypted passwords - convert to DOS codepage before using.
1220                          */
1221                         passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
1222
1223                 } else {
1224                         if (passlen) {
1225                                 memcpy(pword, pass, passlen);
1226                         }
1227                 }
1228         }
1229
1230         slprintf(fullshare, sizeof(fullshare)-1,
1231                  "\\\\%s\\%s", cli->desthost, share);
1232
1233         cli_set_message(cli->outbuf,4, 0, True);
1234         SCVAL(cli->outbuf,smb_com,SMBtconX);
1235         cli_setup_packet(cli);
1236
1237         SSVAL(cli->outbuf,smb_vwv0,0xFF);
1238         SSVAL(cli->outbuf,smb_vwv2,TCONX_FLAG_EXTENDED_RESPONSE);
1239         SSVAL(cli->outbuf,smb_vwv3,passlen);
1240
1241         p = smb_buf(cli->outbuf);
1242         if (passlen) {
1243                 memcpy(p,pword,passlen);
1244         }
1245         p += passlen;
1246         p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
1247         p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII);
1248
1249         cli_setup_bcc(cli, p);
1250
1251         cli_send_smb(cli);
1252         if (!cli_receive_smb(cli))
1253                 return False;
1254
1255         if (cli_is_error(cli))
1256                 return False;
1257
1258         clistr_pull(cli->inbuf, cli->dev, smb_buf(cli->inbuf), sizeof(fstring),
1259                     -1, STR_TERMINATE|STR_ASCII);
1260
1261         if (cli->protocol >= PROTOCOL_NT1 &&
1262             smb_buflen(cli->inbuf) == 3) {
1263                 /* almost certainly win95 - enable bug fixes */
1264                 cli->win95 = True;
1265         }
1266
1267         /* Make sure that we have the optional support 16-bit field.  WCT > 2 */
1268         /* Avoids issues when connecting to Win9x boxes sharing files */
1269
1270         cli->dfsroot = False;
1271         if ( (CVAL(cli->inbuf, smb_wct))>2 && cli->protocol >= PROTOCOL_LANMAN2 )
1272                 cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS) ? True : False;
1273
1274         cli->cnum = SVAL(cli->inbuf,smb_tid);
1275         return True;
1276 }
1277
1278 /****************************************************************************
1279  Send a tree disconnect.
1280 ****************************************************************************/
1281
1282 bool cli_tdis(struct cli_state *cli)
1283 {
1284         memset(cli->outbuf,'\0',smb_size);
1285         cli_set_message(cli->outbuf,0,0,True);
1286         SCVAL(cli->outbuf,smb_com,SMBtdis);
1287         SSVAL(cli->outbuf,smb_tid,cli->cnum);
1288         cli_setup_packet(cli);
1289
1290         cli_send_smb(cli);
1291         if (!cli_receive_smb(cli))
1292                 return False;
1293
1294         if (cli_is_error(cli)) {
1295                 return False;
1296         }
1297
1298         cli->cnum = -1;
1299         return True;
1300 }
1301
1302 /****************************************************************************
1303  Send a negprot command.
1304 ****************************************************************************/
1305
1306 void cli_negprot_sendsync(struct cli_state *cli)
1307 {
1308         char *p;
1309         int numprots;
1310
1311         if (cli->protocol < PROTOCOL_NT1)
1312                 cli->use_spnego = False;
1313
1314         memset(cli->outbuf,'\0',smb_size);
1315
1316         /* setup the protocol strings */
1317         cli_set_message(cli->outbuf,0,0,True);
1318
1319         p = smb_buf(cli->outbuf);
1320         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1321                 if (prots[numprots].prot > cli->protocol) {
1322                         break;
1323                 }
1324                 *p++ = 2;
1325                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
1326         }
1327
1328         SCVAL(cli->outbuf,smb_com,SMBnegprot);
1329         cli_setup_bcc(cli, p);
1330         cli_setup_packet(cli);
1331
1332         SCVAL(smb_buf(cli->outbuf),0,2);
1333
1334         cli_send_smb(cli);
1335 }
1336
1337 /****************************************************************************
1338  Send a negprot command.
1339 ****************************************************************************/
1340
1341 struct async_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
1342                                    struct event_context *ev,
1343                                    struct cli_state *cli)
1344 {
1345         struct async_req *result;
1346         uint8_t *bytes = NULL;
1347         int numprots;
1348
1349         if (cli->protocol < PROTOCOL_NT1)
1350                 cli->use_spnego = False;
1351
1352         /* setup the protocol strings */
1353         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
1354                 uint8_t c = 2;
1355                 if (prots[numprots].prot > cli->protocol) {
1356                         break;
1357                 }
1358                 bytes = (uint8_t *)talloc_append_blob(
1359                         talloc_tos(), bytes, data_blob_const(&c, sizeof(c)));
1360                 if (bytes == NULL) {
1361                         return NULL;
1362                 }
1363                 bytes = smb_bytes_push_str(bytes, false,
1364                                            prots[numprots].name,
1365                                            strlen(prots[numprots].name)+1,
1366                                            NULL);
1367                 if (bytes == NULL) {
1368                         return NULL;
1369                 }
1370         }
1371
1372         result = cli_request_send(mem_ctx, ev, cli, SMBnegprot, 0, 0, NULL, 0,
1373                                   talloc_get_size(bytes), bytes);
1374         TALLOC_FREE(bytes);
1375         return result;
1376 }
1377
1378 NTSTATUS cli_negprot_recv(struct async_req *req)
1379 {
1380         struct cli_request *cli_req = talloc_get_type_abort(
1381                 req->private_data, struct cli_request);
1382         struct cli_state *cli = cli_req->cli;
1383         uint8_t wct;
1384         uint16_t *vwv;
1385         uint16_t num_bytes;
1386         uint8_t *bytes;
1387         NTSTATUS status;
1388         uint16_t protnum;
1389
1390         if (async_req_is_error(req, &status)) {
1391                 return status;
1392         }
1393
1394         status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
1395         if (!NT_STATUS_IS_OK(status)) {
1396                 return status;
1397         }
1398
1399         protnum = SVAL(vwv, 0);
1400
1401         if ((protnum >= ARRAY_SIZE(prots))
1402             || (prots[protnum].prot > cli_req->cli->protocol)) {
1403                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
1404         }
1405
1406         cli->protocol = prots[protnum].prot;
1407
1408         if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
1409                 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
1410                 return NT_STATUS_ACCESS_DENIED;
1411         }
1412
1413         if (cli->protocol >= PROTOCOL_NT1) {    
1414                 struct timespec ts;
1415                 /* NT protocol */
1416                 cli->sec_mode = CVAL(vwv + 1, 0);
1417                 cli->max_mux = SVAL(vwv + 1, 1);
1418                 cli->max_xmit = IVAL(vwv + 3, 1);
1419                 cli->sesskey = IVAL(vwv + 7, 1);
1420                 cli->serverzone = SVALS(vwv + 15, 1);
1421                 cli->serverzone *= 60;
1422                 /* this time arrives in real GMT */
1423                 ts = interpret_long_date(((char *)(vwv+11))+1);
1424                 cli->servertime = ts.tv_sec;
1425                 cli->secblob = data_blob(bytes, num_bytes);
1426                 cli->capabilities = IVAL(vwv + 9, 1);
1427                 if (cli->capabilities & CAP_RAW_MODE) {
1428                         cli->readbraw_supported = True;
1429                         cli->writebraw_supported = True;      
1430                 }
1431                 /* work out if they sent us a workgroup */
1432                 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1433                     smb_buflen(cli->inbuf) > 8) {
1434                         clistr_pull(cli->inbuf, cli->server_domain,
1435                                     bytes+8, sizeof(cli->server_domain),
1436                                     num_bytes-8,
1437                                     STR_UNICODE|STR_NOALIGN);
1438                 }
1439
1440                 /*
1441                  * As signing is slow we only turn it on if either the client or
1442                  * the server require it. JRA.
1443                  */
1444
1445                 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
1446                         /* Fail if server says signing is mandatory and we don't want to support it. */
1447                         if (!cli->sign_info.allow_smb_signing) {
1448                                 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
1449                                 return NT_STATUS_ACCESS_DENIED;
1450                         }
1451                         cli->sign_info.negotiated_smb_signing = True;
1452                         cli->sign_info.mandatory_signing = True;
1453                 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
1454                         /* Fail if client says signing is mandatory and the server doesn't support it. */
1455                         if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
1456                                 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
1457                                 return NT_STATUS_ACCESS_DENIED;
1458                         }
1459                         cli->sign_info.negotiated_smb_signing = True;
1460                         cli->sign_info.mandatory_signing = True;
1461                 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
1462                         cli->sign_info.negotiated_smb_signing = True;
1463                 }
1464
1465                 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
1466                         SAFE_FREE(cli->outbuf);
1467                         SAFE_FREE(cli->inbuf);
1468                         cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1469                         cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
1470                         cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
1471                 }
1472
1473         } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1474                 cli->use_spnego = False;
1475                 cli->sec_mode = SVAL(vwv + 1, 0);
1476                 cli->max_xmit = SVAL(vwv + 2, 0);
1477                 cli->max_mux = SVAL(vwv + 3, 0);
1478                 cli->sesskey = IVAL(vwv + 6, 0);
1479                 cli->serverzone = SVALS(vwv + 10, 0);
1480                 cli->serverzone *= 60;
1481                 /* this time is converted to GMT by make_unix_date */
1482                 cli->servertime = cli_make_unix_date(
1483                         cli, (char *)(vwv + 8));
1484                 cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
1485                 cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
1486                 cli->secblob = data_blob(bytes, num_bytes);
1487         } else {
1488                 /* the old core protocol */
1489                 cli->use_spnego = False;
1490                 cli->sec_mode = 0;
1491                 cli->serverzone = get_time_zone(time(NULL));
1492         }
1493
1494         cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1495
1496         /* a way to force ascii SMB */
1497         if (getenv("CLI_FORCE_ASCII"))
1498                 cli->capabilities &= ~CAP_UNICODE;
1499
1500         return NT_STATUS_OK;
1501 }
1502
1503 NTSTATUS cli_negprot(struct cli_state *cli)
1504 {
1505         TALLOC_CTX *frame = talloc_stackframe();
1506         struct event_context *ev;
1507         struct async_req *req;
1508         NTSTATUS status = NT_STATUS_NO_MEMORY;
1509
1510         if (cli->fd_event != NULL) {
1511                 /*
1512                  * Can't use sync call while an async call is in flight
1513                  */
1514                 cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
1515                 goto fail;
1516         }
1517
1518         ev = event_context_init(frame);
1519         if (ev == NULL) {
1520                 goto fail;
1521         }
1522
1523         req = cli_negprot_send(frame, ev, cli);
1524         if (req == NULL) {
1525                 goto fail;
1526         }
1527
1528         while (req->state < ASYNC_REQ_DONE) {
1529                 event_loop_once(ev);
1530         }
1531
1532         status = cli_negprot_recv(req);
1533  fail:
1534         TALLOC_FREE(frame);
1535         return status;
1536 }
1537
1538 /****************************************************************************
1539  Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1540 ****************************************************************************/
1541
1542 bool cli_session_request(struct cli_state *cli,
1543                          struct nmb_name *calling, struct nmb_name *called)
1544 {
1545         char *p;
1546         int len = 4;
1547
1548         /* 445 doesn't have session request */
1549         if (cli->port == 445)
1550                 return True;
1551
1552         memcpy(&(cli->calling), calling, sizeof(*calling));
1553         memcpy(&(cli->called ), called , sizeof(*called ));
1554
1555         /* put in the destination name */
1556         p = cli->outbuf+len;
1557         name_mangle(cli->called .name, p, cli->called .name_type);
1558         len += name_len(p);
1559
1560         /* and my name */
1561         p = cli->outbuf+len;
1562         name_mangle(cli->calling.name, p, cli->calling.name_type);
1563         len += name_len(p);
1564
1565         /* send a session request (RFC 1002) */
1566         /* setup the packet length
1567          * Remove four bytes from the length count, since the length
1568          * field in the NBT Session Service header counts the number
1569          * of bytes which follow.  The cli_send_smb() function knows
1570          * about this and accounts for those four bytes.
1571          * CRH.
1572          */
1573         len -= 4;
1574         _smb_setlen(cli->outbuf,len);
1575         SCVAL(cli->outbuf,0,0x81);
1576
1577         cli_send_smb(cli);
1578         DEBUG(5,("Sent session request\n"));
1579
1580         if (!cli_receive_smb(cli))
1581                 return False;
1582
1583         if (CVAL(cli->inbuf,0) == 0x84) {
1584                 /* C. Hoch  9/14/95 Start */
1585                 /* For information, here is the response structure.
1586                  * We do the byte-twiddling to for portability.
1587                 struct RetargetResponse{
1588                 unsigned char type;
1589                 unsigned char flags;
1590                 int16 length;
1591                 int32 ip_addr;
1592                 int16 port;
1593                 };
1594                 */
1595                 uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1596                 struct in_addr dest_ip;
1597                 NTSTATUS status;
1598
1599                 /* SESSION RETARGET */
1600                 putip((char *)&dest_ip,cli->inbuf+4);
1601                 in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
1602
1603                 status = open_socket_out(&cli->dest_ss, port,
1604                                          LONG_CONNECT_TIMEOUT, &cli->fd);
1605                 if (!NT_STATUS_IS_OK(status)) {
1606                         return False;
1607                 }
1608
1609                 DEBUG(3,("Retargeted\n"));
1610
1611                 set_socket_options(cli->fd, lp_socket_options());
1612
1613                 /* Try again */
1614                 {
1615                         static int depth;
1616                         bool ret;
1617                         if (depth > 4) {
1618                                 DEBUG(0,("Retarget recursion - failing\n"));
1619                                 return False;
1620                         }
1621                         depth++;
1622                         ret = cli_session_request(cli, calling, called);
1623                         depth--;
1624                         return ret;
1625                 }
1626         } /* C. Hoch 9/14/95 End */
1627
1628         if (CVAL(cli->inbuf,0) != 0x82) {
1629                 /* This is the wrong place to put the error... JRA. */
1630                 cli->rap_error = CVAL(cli->inbuf,4);
1631                 return False;
1632         }
1633         return(True);
1634 }
1635
1636 static void smb_sock_connected(struct async_req *req)
1637 {
1638         int *pfd = (int *)req->async.priv;
1639         int fd;
1640         NTSTATUS status;
1641
1642         status = open_socket_out_defer_recv(req, &fd);
1643         if (NT_STATUS_IS_OK(status)) {
1644                 *pfd = fd;
1645         }
1646 }
1647
1648 static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
1649                                 uint16_t *port, int timeout, int *pfd)
1650 {
1651         struct event_context *ev;
1652         struct async_req *r139, *r445;
1653         int fd139 = -1;
1654         int fd445 = -1;
1655         NTSTATUS status;
1656
1657         if (*port != 0) {
1658                 return open_socket_out(pss, *port, timeout, pfd);
1659         }
1660
1661         ev = event_context_init(talloc_tos());
1662         if (ev == NULL) {
1663                 return NT_STATUS_NO_MEMORY;
1664         }
1665
1666         r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
1667                                           pss, 445, timeout);
1668         r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
1669                                           pss, 139, timeout);
1670         if ((r445 == NULL) || (r139 == NULL)) {
1671                 status = NT_STATUS_NO_MEMORY;
1672                 goto done;
1673         }
1674         r445->async.fn = smb_sock_connected;
1675         r445->async.priv = &fd445;
1676         r139->async.fn = smb_sock_connected;
1677         r139->async.priv = &fd139;
1678
1679         while ((fd139 == -1) && (r139->state < ASYNC_REQ_DONE)
1680                && (fd445 == -1) && (r445->state < ASYNC_REQ_DONE)) {
1681                 event_loop_once(ev);
1682         }
1683
1684         if ((fd139 != -1) && (fd445 != -1)) {
1685                 close(fd139);
1686                 fd139 = -1;
1687         }
1688
1689         if (fd445 != -1) {
1690                 *port = 445;
1691                 *pfd = fd445;
1692                 status = NT_STATUS_OK;
1693                 goto done;
1694         }
1695         if (fd139 != -1) {
1696                 *port = 139;
1697                 *pfd = fd139;
1698                 status = NT_STATUS_OK;
1699                 goto done;
1700         }
1701
1702         status = open_socket_out_defer_recv(r445, &fd445);
1703  done:
1704         TALLOC_FREE(ev);
1705         return status;
1706 }
1707
1708 /****************************************************************************
1709  Open the client sockets.
1710 ****************************************************************************/
1711
1712 NTSTATUS cli_connect(struct cli_state *cli,
1713                 const char *host,
1714                 struct sockaddr_storage *dest_ss)
1715
1716 {
1717         int name_type = 0x20;
1718         TALLOC_CTX *frame = talloc_stackframe();
1719         unsigned int num_addrs = 0;
1720         unsigned int i = 0;
1721         struct sockaddr_storage *ss_arr = NULL;
1722         char *p = NULL;
1723
1724         /* reasonable default hostname */
1725         if (!host) {
1726                 host = STAR_SMBSERVER;
1727         }
1728
1729         fstrcpy(cli->desthost, host);
1730
1731         /* allow hostnames of the form NAME#xx and do a netbios lookup */
1732         if ((p = strchr(cli->desthost, '#'))) {
1733                 name_type = strtol(p+1, NULL, 16);
1734                 *p = 0;
1735         }
1736
1737         if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
1738                 NTSTATUS status =resolve_name_list(frame,
1739                                         cli->desthost,
1740                                         name_type,
1741                                         &ss_arr,
1742                                         &num_addrs);
1743                 if (!NT_STATUS_IS_OK(status)) {
1744                         TALLOC_FREE(frame);
1745                         return NT_STATUS_BAD_NETWORK_NAME;
1746                 }
1747         } else {
1748                 num_addrs = 1;
1749                 ss_arr = TALLOC_P(frame, struct sockaddr_storage);
1750                 if (!ss_arr) {
1751                         TALLOC_FREE(frame);
1752                         return NT_STATUS_NO_MEMORY;
1753                 }
1754                 *ss_arr = *dest_ss;
1755         }
1756
1757         for (i = 0; i < num_addrs; i++) {
1758                 cli->dest_ss = ss_arr[i];
1759                 if (getenv("LIBSMB_PROG")) {
1760                         cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1761                 } else {
1762                         uint16_t port = cli->port;
1763                         NTSTATUS status;
1764                         status = open_smb_socket(&cli->dest_ss, &port,
1765                                                  cli->timeout, &cli->fd);
1766                         if (NT_STATUS_IS_OK(status)) {
1767                                 cli->port = port;
1768                         }
1769                 }
1770                 if (cli->fd == -1) {
1771                         char addr[INET6_ADDRSTRLEN];
1772                         print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
1773                         DEBUG(2,("Error connecting to %s (%s)\n",
1774                                  dest_ss?addr:host,strerror(errno)));
1775                 } else {
1776                         /* Exit from loop on first connection. */
1777                         break;
1778                 }
1779         }
1780
1781         if (cli->fd == -1) {
1782                 TALLOC_FREE(frame);
1783                 return map_nt_error_from_unix(errno);
1784         }
1785
1786         if (dest_ss) {
1787                 *dest_ss = cli->dest_ss;
1788         }
1789
1790         set_socket_options(cli->fd, lp_socket_options());
1791
1792         TALLOC_FREE(frame);
1793         return NT_STATUS_OK;
1794 }
1795
1796 /**
1797    establishes a connection to after the negprot. 
1798    @param output_cli A fully initialised cli structure, non-null only on success
1799    @param dest_host The netbios name of the remote host
1800    @param dest_ss (optional) The the destination IP, NULL for name based lookup
1801    @param port (optional) The destination port (0 for default)
1802    @param retry bool. Did this connection fail with a retryable error ?
1803
1804 */
1805 NTSTATUS cli_start_connection(struct cli_state **output_cli, 
1806                               const char *my_name, 
1807                               const char *dest_host, 
1808                               struct sockaddr_storage *dest_ss, int port,
1809                               int signing_state, int flags,
1810                               bool *retry) 
1811 {
1812         NTSTATUS nt_status;
1813         struct nmb_name calling;
1814         struct nmb_name called;
1815         struct cli_state *cli;
1816         struct sockaddr_storage ss;
1817
1818         if (retry)
1819                 *retry = False;
1820
1821         if (!my_name) 
1822                 my_name = global_myname();
1823
1824         if (!(cli = cli_initialise())) {
1825                 return NT_STATUS_NO_MEMORY;
1826         }
1827
1828         make_nmb_name(&calling, my_name, 0x0);
1829         make_nmb_name(&called , dest_host, 0x20);
1830
1831         cli_set_port(cli, port);
1832         cli_set_timeout(cli, 10000); /* 10 seconds. */
1833
1834         if (dest_ss) {
1835                 ss = *dest_ss;
1836         } else {
1837                 zero_sockaddr(&ss);
1838         }
1839
1840 again:
1841
1842         DEBUG(3,("Connecting to host=%s\n", dest_host));
1843
1844         nt_status = cli_connect(cli, dest_host, &ss);
1845         if (!NT_STATUS_IS_OK(nt_status)) {
1846                 char addr[INET6_ADDRSTRLEN];
1847                 print_sockaddr(addr, sizeof(addr), &ss);
1848                 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
1849                          nmb_namestr(&called), addr, nt_errstr(nt_status) ));
1850                 cli_shutdown(cli);
1851                 return nt_status;
1852         }
1853
1854         if (retry)
1855                 *retry = True;
1856
1857         if (!cli_session_request(cli, &calling, &called)) {
1858                 char *p;
1859                 DEBUG(1,("session request to %s failed (%s)\n",
1860                          called.name, cli_errstr(cli)));
1861                 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1862                         *p = 0;
1863                         goto again;
1864                 }
1865                 if (strcmp(called.name, STAR_SMBSERVER)) {
1866                         make_nmb_name(&called , STAR_SMBSERVER, 0x20);
1867                         goto again;
1868                 }
1869                 return NT_STATUS_BAD_NETWORK_NAME;
1870         }
1871
1872         cli_setup_signing_state(cli, signing_state);
1873
1874         if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1875                 cli->use_spnego = False;
1876         else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1877                 cli->use_kerberos = True;
1878
1879         if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
1880              cli->use_kerberos) {
1881                 cli->fallback_after_kerberos = true;
1882         }
1883
1884         nt_status = cli_negprot(cli);
1885         if (!NT_STATUS_IS_OK(nt_status)) {
1886                 DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
1887                 cli_shutdown(cli);
1888                 return nt_status;
1889         }
1890
1891         *output_cli = cli;
1892         return NT_STATUS_OK;
1893 }
1894
1895
1896 /**
1897    establishes a connection right up to doing tconX, password specified.
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_ip (optional) The the destination IP, NULL for name based lookup
1901    @param port (optional) The destination port (0 for default)
1902    @param service (optional) The share to make the connection to.  Should be 'unqualified' in any way.
1903    @param service_type The 'type' of serivice. 
1904    @param user Username, unix string
1905    @param domain User's domain
1906    @param password User's password, unencrypted unix string.
1907    @param retry bool. Did this connection fail with a retryable error ?
1908 */
1909
1910 NTSTATUS cli_full_connection(struct cli_state **output_cli, 
1911                              const char *my_name, 
1912                              const char *dest_host, 
1913                              struct sockaddr_storage *dest_ss, int port,
1914                              const char *service, const char *service_type,
1915                              const char *user, const char *domain, 
1916                              const char *password, int flags,
1917                              int signing_state,
1918                              bool *retry) 
1919 {
1920         NTSTATUS nt_status;
1921         struct cli_state *cli = NULL;
1922         int pw_len = password ? strlen(password)+1 : 0;
1923
1924         *output_cli = NULL;
1925
1926         if (password == NULL) {
1927                 password = "";
1928         }
1929
1930         nt_status = cli_start_connection(&cli, my_name, dest_host,
1931                                          dest_ss, port, signing_state,
1932                                          flags, retry);
1933
1934         if (!NT_STATUS_IS_OK(nt_status)) {
1935                 return nt_status;
1936         }
1937
1938         nt_status = cli_session_setup(cli, user, password, pw_len, password,
1939                                       pw_len, domain);
1940         if (!NT_STATUS_IS_OK(nt_status)) {
1941
1942                 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
1943                         DEBUG(1,("failed session setup with %s\n",
1944                                  nt_errstr(nt_status)));
1945                         cli_shutdown(cli);
1946                         return nt_status;
1947                 }
1948
1949                 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
1950                 if (!NT_STATUS_IS_OK(nt_status)) {
1951                         DEBUG(1,("anonymous failed session setup with %s\n",
1952                                  nt_errstr(nt_status)));
1953                         cli_shutdown(cli);
1954                         return nt_status;
1955                 }
1956         }
1957
1958         if (service) {
1959                 if (!cli_send_tconX(cli, service, service_type, password, pw_len)) {
1960                         nt_status = cli_nt_error(cli);
1961                         DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1962                         cli_shutdown(cli);
1963                         if (NT_STATUS_IS_OK(nt_status)) {
1964                                 nt_status = NT_STATUS_UNSUCCESSFUL;
1965                         }
1966                         return nt_status;
1967                 }
1968         }
1969
1970         cli_init_creds(cli, user, domain, password);
1971
1972         *output_cli = cli;
1973         return NT_STATUS_OK;
1974 }
1975
1976 /****************************************************************************
1977  Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1978 ****************************************************************************/
1979
1980 bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
1981                                      struct sockaddr_storage *pdest_ss)
1982 {
1983         struct nmb_name calling, called;
1984
1985         make_nmb_name(&calling, srchost, 0x0);
1986
1987         /*
1988          * If the called name is an IP address
1989          * then use *SMBSERVER immediately.
1990          */
1991
1992         if(is_ipaddress(desthost)) {
1993                 make_nmb_name(&called, STAR_SMBSERVER, 0x20);
1994         } else {
1995                 make_nmb_name(&called, desthost, 0x20);
1996         }
1997
1998         if (!cli_session_request(*ppcli, &calling, &called)) {
1999                 NTSTATUS status;
2000                 struct nmb_name smbservername;
2001
2002                 make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
2003
2004                 /*
2005                  * If the name wasn't *SMBSERVER then
2006                  * try with *SMBSERVER if the first name fails.
2007                  */
2008
2009                 if (nmb_name_equal(&called, &smbservername)) {
2010
2011                         /*
2012                          * The name used was *SMBSERVER, don't bother with another name.
2013                          */
2014
2015                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
2016 with error %s.\n", desthost, cli_errstr(*ppcli) ));
2017                         return False;
2018                 }
2019
2020                 /* Try again... */
2021                 cli_shutdown(*ppcli);
2022
2023                 *ppcli = cli_initialise();
2024                 if (!*ppcli) {
2025                         /* Out of memory... */
2026                         return False;
2027                 }
2028
2029                 status = cli_connect(*ppcli, desthost, pdest_ss);
2030                 if (!NT_STATUS_IS_OK(status) ||
2031                                 !cli_session_request(*ppcli, &calling, &smbservername)) {
2032                         DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
2033 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
2034                         return False;
2035                 }
2036         }
2037
2038         return True;
2039 }
2040
2041 /****************************************************************************
2042  Send an old style tcon.
2043 ****************************************************************************/
2044 NTSTATUS cli_raw_tcon(struct cli_state *cli, 
2045                       const char *service, const char *pass, const char *dev,
2046                       uint16 *max_xmit, uint16 *tid)
2047 {
2048         char *p;
2049
2050         if (!lp_client_plaintext_auth() && (*pass)) {
2051                 DEBUG(1, ("Server requested plaintext password but 'client "
2052                           "plaintext auth' is disabled\n"));
2053                 return NT_STATUS_ACCESS_DENIED;
2054         }
2055
2056         memset(cli->outbuf,'\0',smb_size);
2057         memset(cli->inbuf,'\0',smb_size);
2058
2059         cli_set_message(cli->outbuf, 0, 0, True);
2060         SCVAL(cli->outbuf,smb_com,SMBtcon);
2061         cli_setup_packet(cli);
2062
2063         p = smb_buf(cli->outbuf);
2064         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
2065         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
2066         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
2067
2068         cli_setup_bcc(cli, p);
2069
2070         cli_send_smb(cli);
2071         if (!cli_receive_smb(cli)) {
2072                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2073         }
2074
2075         if (cli_is_error(cli)) {
2076                 return cli_nt_error(cli);
2077         }
2078
2079         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
2080         *tid = SVAL(cli->inbuf, smb_vwv1);
2081
2082         return NT_STATUS_OK;
2083 }
2084
2085 /* Return a cli_state pointing at the IPC$ share for the given server */
2086
2087 struct cli_state *get_ipc_connect(char *server,
2088                                 struct sockaddr_storage *server_ss,
2089                                 const struct user_auth_info *user_info)
2090 {
2091         struct cli_state *cli;
2092         NTSTATUS nt_status;
2093         uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
2094
2095         if (user_info->use_kerberos) {
2096                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
2097         }
2098
2099         nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC", 
2100                                         user_info->username ? user_info->username : "",
2101                                         lp_workgroup(),
2102                                         user_info->password ? user_info->password : "",
2103                                         flags,
2104                                         Undefined, NULL);
2105
2106         if (NT_STATUS_IS_OK(nt_status)) {
2107                 return cli;
2108         } else if (is_ipaddress(server)) {
2109             /* windows 9* needs a correct NMB name for connections */
2110             fstring remote_name;
2111
2112             if (name_status_find("*", 0, 0, server_ss, remote_name)) {
2113                 cli = get_ipc_connect(remote_name, server_ss, user_info);
2114                 if (cli)
2115                     return cli;
2116             }
2117         }
2118         return NULL;
2119 }
2120
2121 /*
2122  * Given the IP address of a master browser on the network, return its
2123  * workgroup and connect to it.
2124  *
2125  * This function is provided to allow additional processing beyond what
2126  * get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
2127  * browsers and obtain each master browsers' list of domains (in case the
2128  * first master browser is recently on the network and has not yet
2129  * synchronized with other master browsers and therefore does not yet have the
2130  * entire network browse list)
2131  */
2132
2133 struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
2134                                 struct ip_service *mb_ip,
2135                                 const struct user_auth_info *user_info,
2136                                 char **pp_workgroup_out)
2137 {
2138         char addr[INET6_ADDRSTRLEN];
2139         fstring name;
2140         struct cli_state *cli;
2141         struct sockaddr_storage server_ss;
2142
2143         *pp_workgroup_out = NULL;
2144
2145         print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
2146         DEBUG(99, ("Looking up name of master browser %s\n",
2147                    addr));
2148
2149         /*
2150          * Do a name status query to find out the name of the master browser.
2151          * We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
2152          * master browser will not respond to a wildcard query (or, at least,
2153          * an NT4 server acting as the domain master browser will not).
2154          *
2155          * We might be able to use ONLY the query on MSBROWSE, but that's not
2156          * yet been tested with all Windows versions, so until it is, leave
2157          * the original wildcard query as the first choice and fall back to
2158          * MSBROWSE if the wildcard query fails.
2159          */
2160         if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
2161             !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
2162
2163                 DEBUG(99, ("Could not retrieve name status for %s\n",
2164                            addr));
2165                 return NULL;
2166         }
2167
2168         if (!find_master_ip(name, &server_ss)) {
2169                 DEBUG(99, ("Could not find master ip for %s\n", name));
2170                 return NULL;
2171         }
2172
2173         *pp_workgroup_out = talloc_strdup(ctx, name);
2174
2175         DEBUG(4, ("found master browser %s, %s\n", name, addr));
2176
2177         print_sockaddr(addr, sizeof(addr), &server_ss);
2178         cli = get_ipc_connect(addr, &server_ss, user_info);
2179
2180         return cli;
2181 }
2182
2183 /*
2184  * Return the IP address and workgroup of a master browser on the network, and
2185  * connect to it.
2186  */
2187
2188 struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
2189                                         const struct user_auth_info *user_info,
2190                                         char **pp_workgroup_out)
2191 {
2192         struct ip_service *ip_list;
2193         struct cli_state *cli;
2194         int i, count;
2195
2196         *pp_workgroup_out = NULL;
2197
2198         DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
2199
2200         /* Go looking for workgroups by broadcasting on the local network */
2201
2202         if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
2203                                                 &count))) {
2204                 DEBUG(99, ("No master browsers responded\n"));
2205                 return False;
2206         }
2207
2208         for (i = 0; i < count; i++) {
2209                 char addr[INET6_ADDRSTRLEN];
2210                 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
2211                 DEBUG(99, ("Found master browser %s\n", addr));
2212
2213                 cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
2214                                 user_info, pp_workgroup_out);
2215                 if (cli)
2216                         return(cli);
2217         }
2218
2219         return NULL;
2220 }