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