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