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