2 Unix SMB/CIFS implementation.
3 client connect/disconnect routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Andrew Barteltt 2001-2003
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 2 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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,"Samba"},
38 {PROTOCOL_NT1,"NT LANMAN 1.0"},
39 {PROTOCOL_NT1,"NT LM 0.12"},
43 /****************************************************************************
44 Do an old lanman2 style session setup.
45 ****************************************************************************/
47 static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
48 const char *pass, size_t passlen, const char *workgroup)
53 if (passlen > sizeof(pword)-1)
56 /* if in share level security then don't send a password now */
57 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
60 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
61 /* Encrypted mode needed, and non encrypted password supplied. */
63 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
64 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
65 /* Encrypted mode needed, and encrypted password supplied. */
66 memcpy(pword, pass, passlen);
67 } else if (passlen > 0) {
68 /* Plaintext mode needed, assume plaintext supplied. */
69 passlen = clistr_push(cli, pword, pass, -1, STR_TERMINATE);
72 /* send a session setup command */
73 memset(cli->outbuf,'\0',smb_size);
74 set_message(cli->outbuf,10, 0, True);
75 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
76 cli_setup_packet(cli);
78 SCVAL(cli->outbuf,smb_vwv0,0xFF);
79 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
80 SSVAL(cli->outbuf,smb_vwv3,2);
81 SSVAL(cli->outbuf,smb_vwv4,1);
82 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
83 SSVAL(cli->outbuf,smb_vwv7,passlen);
85 p = smb_buf(cli->outbuf);
86 memcpy(p,pword,passlen);
88 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
89 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
90 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
91 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
92 cli_setup_bcc(cli, p);
95 if (!cli_receive_smb(cli))
100 if (cli_is_error(cli))
103 /* use the returned vuid from now on */
104 cli->vuid = SVAL(cli->inbuf,smb_uid);
105 fstrcpy(cli->user_name, user);
110 /****************************************************************************
111 Work out suitable capabilities to offer the server.
112 ****************************************************************************/
114 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
116 uint32 capabilities = CAP_NT_SMBS;
118 if (!cli->force_dos_errors)
119 capabilities |= CAP_STATUS32;
121 if (cli->use_level_II_oplocks)
122 capabilities |= CAP_LEVEL_II_OPLOCKS;
124 if (cli->capabilities & CAP_UNICODE)
125 capabilities |= CAP_UNICODE;
127 if (cli->capabilities & CAP_LARGE_FILES)
128 capabilities |= CAP_LARGE_FILES;
133 /****************************************************************************
134 Do a NT1 guest session setup.
135 ****************************************************************************/
137 static BOOL cli_session_setup_guest(struct cli_state *cli)
140 uint32 capabilities = cli_session_setup_capabilities(cli);
142 set_message(cli->outbuf,13,0,True);
143 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
144 cli_setup_packet(cli);
146 SCVAL(cli->outbuf,smb_vwv0,0xFF);
147 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
148 SSVAL(cli->outbuf,smb_vwv3,2);
149 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
150 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
151 SSVAL(cli->outbuf,smb_vwv7,0);
152 SSVAL(cli->outbuf,smb_vwv8,0);
153 SIVAL(cli->outbuf,smb_vwv11,capabilities);
154 p = smb_buf(cli->outbuf);
155 p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */
156 p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */
157 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
158 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
159 cli_setup_bcc(cli, p);
162 if (!cli_receive_smb(cli))
165 show_msg(cli->inbuf);
167 if (cli_is_error(cli))
170 cli->vuid = SVAL(cli->inbuf,smb_uid);
172 p = smb_buf(cli->inbuf);
173 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
174 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
175 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
177 fstrcpy(cli->user_name, "");
182 /****************************************************************************
183 Do a NT1 plaintext session setup.
184 ****************************************************************************/
186 static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
187 const char *pass, const char *workgroup)
189 uint32 capabilities = cli_session_setup_capabilities(cli);
192 set_message(cli->outbuf,13,0,True);
193 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
194 cli_setup_packet(cli);
196 SCVAL(cli->outbuf,smb_vwv0,0xFF);
197 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
198 SSVAL(cli->outbuf,smb_vwv3,2);
199 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
200 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
201 SSVAL(cli->outbuf,smb_vwv8,0);
202 SIVAL(cli->outbuf,smb_vwv11,capabilities);
203 p = smb_buf(cli->outbuf);
204 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
205 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
206 p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
207 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
208 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
209 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
210 cli_setup_bcc(cli, p);
213 if (!cli_receive_smb(cli))
216 show_msg(cli->inbuf);
218 if (cli_is_error(cli))
221 cli->vuid = SVAL(cli->inbuf,smb_uid);
222 p = smb_buf(cli->inbuf);
223 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
224 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
225 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
226 fstrcpy(cli->user_name, user);
231 static void set_signing_on_cli (struct cli_state *cli, uint8 user_session_key[16], DATA_BLOB response)
234 ZERO_STRUCT(zero_sig);
236 DEBUG(5, ("Server returned security sig:\n"));
237 dump_data(5, &cli->inbuf[smb_ss_field], 8);
239 if (cli->sign_info.use_smb_signing) {
240 DEBUG(5, ("smb signing already active on connection\n"));
241 } else if (memcmp(&cli->inbuf[smb_ss_field], zero_sig, 8) != 0) {
243 DEBUG(3, ("smb signing enabled!\n"));
244 cli->sign_info.use_smb_signing = True;
245 cli_calculate_mac_key(cli, user_session_key, response);
247 DEBUG(5, ("smb signing NOT enabled!\n"));
251 static void set_temp_signing_on_cli(struct cli_state *cli)
253 if (cli->sign_info.negotiated_smb_signing)
254 cli->sign_info.temp_smb_signing = True;
258 /****************************************************************************
259 do a NT1 NTLM/LM encrypted session setup
260 @param cli client state to create do session setup on
262 @param pass *either* cleartext password (passlen !=24) or LM response.
263 @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
264 @param workgroup The user's domain.
265 ****************************************************************************/
267 static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
268 const char *pass, size_t passlen,
269 const char *ntpass, size_t ntpasslen,
270 const char *workgroup)
272 uint32 capabilities = cli_session_setup_capabilities(cli);
273 DATA_BLOB lm_response = data_blob(NULL, 0);
274 DATA_BLOB nt_response = data_blob(NULL, 0);
275 uchar user_session_key[16];
277 BOOL have_plaintext = False;
281 E_md4hash(pass, nt_hash);
283 if (lp_client_ntlmv2_auth()) {
284 uchar ntlm_v2_hash[16];
285 uchar ntlmv2_response[16];
286 uchar lmv2_response[16];
287 DATA_BLOB ntlmv2_client_data;
288 DATA_BLOB lmv2_client_data;
289 DATA_BLOB server_chal;
291 /* We don't use the NT# directly. Instead we use it mashed up with
292 the username and domain.
293 This prevents username swapping during the auth exchange
295 if (!ntv2_owf_gen(nt_hash, user, workgroup, ntlm_v2_hash)) {
299 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
303 /* We also get to specify some random data */
304 ntlmv2_client_data = data_blob(NULL, 20);
305 generate_random_buffer(ntlmv2_client_data.data, ntlmv2_client_data.length, False);
306 memset(ntlmv2_client_data.data, 'A', ntlmv2_client_data.length);
308 /* Given that data, and the challenge from the server, generate a response */
309 SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, ntlmv2_client_data, ntlmv2_response);
311 /* put it into nt_response, for the code below to put into the packet */
312 nt_response = data_blob(NULL, ntlmv2_client_data.length + sizeof(ntlmv2_response));
313 memcpy(nt_response.data, ntlmv2_response, sizeof(ntlmv2_response));
314 /* after the first 16 bytes is the random data we generated above, so the server can verify us with it */
315 memcpy(nt_response.data + sizeof(ntlmv2_response), ntlmv2_client_data.data, ntlmv2_client_data.length);
316 data_blob_free(&ntlmv2_client_data);
321 /* We also get to specify some random data, but only 8 bytes (24 byte total response) */
322 lmv2_client_data = data_blob(NULL, 8);
323 generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length, False);
324 memset(lmv2_client_data.data, 'B', lmv2_client_data.length);
326 /* Calculate response */
327 SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, lmv2_client_data, lmv2_response);
329 /* Calculate response */
330 lm_response = data_blob(NULL, lmv2_client_data.length + sizeof(lmv2_response));
331 memcpy(lm_response.data, lmv2_response, sizeof(lmv2_response));
332 /* after the first 16 bytes is the 8 bytes of random data we made above */
333 memcpy(lm_response.data + sizeof(lmv2_response), lmv2_client_data.data, lmv2_client_data.length);
334 data_blob_free(&lmv2_client_data);
336 data_blob_free(&server_chal);
338 /* The NTLMv2 calculations also provide a session key, for signing etc later */
339 SMBsesskeygen_ntv2(ntlm_v2_hash, ntlmv2_response, user_session_key);
342 /* non encrypted password supplied. Ignore ntpass. */
343 if (lp_client_lanman_auth()) {
344 lm_response = data_blob(NULL, 24);
345 SMBencrypt(pass,cli->secblob.data,lm_response.data);
348 nt_response = data_blob(NULL, 24);
349 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
350 SMBsesskeygen_ntv1(nt_hash, NULL, user_session_key);
353 have_plaintext = True;
354 set_temp_signing_on_cli(cli);
356 /* pre-encrypted password supplied. Only used for
357 security=server, can't do
358 signing becouse we don't have oringial key */
360 lm_response = data_blob(pass, passlen);
361 nt_response = data_blob(ntpass, ntpasslen);
364 /* send a session setup command */
365 memset(cli->outbuf,'\0',smb_size);
367 set_message(cli->outbuf,13,0,True);
368 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
369 cli_setup_packet(cli);
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_vwv7,lm_response.length);
377 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
378 SIVAL(cli->outbuf,smb_vwv11,capabilities);
379 p = smb_buf(cli->outbuf);
380 if (lm_response.length) {
381 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
383 if (nt_response.length) {
384 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
386 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
387 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE);
388 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
389 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
390 cli_setup_bcc(cli, p);
392 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
393 data_blob_free(&lm_response);
394 data_blob_free(&nt_response);
398 show_msg(cli->inbuf);
400 if (cli_is_error(cli)) {
401 data_blob_free(&lm_response);
402 data_blob_free(&nt_response);
406 /* use the returned vuid from now on */
407 cli->vuid = SVAL(cli->inbuf,smb_uid);
409 p = smb_buf(cli->inbuf);
410 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
411 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
412 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
414 fstrcpy(cli->user_name, user);
416 if (have_plaintext) {
417 /* Have plaintext orginal */
418 set_signing_on_cli(cli, user_session_key, nt_response);
421 data_blob_free(&lm_response);
422 data_blob_free(&nt_response);
426 /****************************************************************************
427 Send a extended security session setup blob, returning a reply blob.
428 ****************************************************************************/
430 static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
432 uint32 capabilities = cli_session_setup_capabilities(cli);
437 blob2 = data_blob(NULL, 0);
439 capabilities |= CAP_EXTENDED_SECURITY;
441 /* send a session setup command */
442 memset(cli->outbuf,'\0',smb_size);
444 set_message(cli->outbuf,12,0,True);
445 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
447 set_temp_signing_on_cli(cli);
449 cli_setup_packet(cli);
451 SCVAL(cli->outbuf,smb_vwv0,0xFF);
452 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
453 SSVAL(cli->outbuf,smb_vwv3,2);
454 SSVAL(cli->outbuf,smb_vwv4,1);
455 SIVAL(cli->outbuf,smb_vwv5,0);
456 SSVAL(cli->outbuf,smb_vwv7,blob.length);
457 SIVAL(cli->outbuf,smb_vwv10,capabilities);
458 p = smb_buf(cli->outbuf);
459 memcpy(p, blob.data, blob.length);
461 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
462 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
463 cli_setup_bcc(cli, p);
466 if (!cli_receive_smb(cli))
469 show_msg(cli->inbuf);
471 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
472 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
476 /* use the returned vuid from now on */
477 cli->vuid = SVAL(cli->inbuf,smb_uid);
479 p = smb_buf(cli->inbuf);
481 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
484 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
486 /* w2k with kerberos doesn't properly null terminate this field */
487 len = smb_buflen(cli->inbuf) - PTR_DIFF(p, smb_buf(cli->inbuf));
488 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0);
494 /****************************************************************************
495 Do a spnego/kerberos encrypted session setup.
496 ****************************************************************************/
498 static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
500 DATA_BLOB blob2, negTokenTarg;
502 DEBUG(2,("Doing kerberos session setup\n"));
504 /* generate the encapsulated kerberos5 ticket */
505 negTokenTarg = spnego_gen_negTokenTarg(principal, 0);
507 if (!negTokenTarg.data) return False;
510 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
513 blob2 = cli_session_setup_blob(cli, negTokenTarg);
515 /* we don't need this blob for kerberos */
516 data_blob_free(&blob2);
518 data_blob_free(&negTokenTarg);
520 return !cli_is_error(cli);
524 /****************************************************************************
525 Do a spnego/NTLMSSP encrypted session setup.
526 ****************************************************************************/
528 static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
529 const char *pass, const char *workgroup)
531 DATA_BLOB msg1, struct_blob;
532 DATA_BLOB blob, chal1, chal2, auth, challenge_blob;
534 uint8 nthash[24], lmhash[24], sess_key[16];
535 uint32 neg_flags, chal_flags, ntlmssp_command, unkn1, unkn2;
536 pstring server_domain; /* FIX THIS, SHOULD be UCS2-LE */
538 neg_flags = NTLMSSP_NEGOTIATE_UNICODE |
539 NTLMSSP_NEGOTIATE_128 |
540 NTLMSSP_NEGOTIATE_NTLM |
541 NTLMSSP_REQUEST_TARGET;
543 memset(sess_key, 0, 16);
545 DEBUG(10, ("sending NTLMSSP_NEGOTIATE\n"));
547 /* generate the ntlmssp negotiate packet */
548 msrpc_gen(&blob, "CddAA",
554 DEBUG(10, ("neg_flags: %0X, workgroup: %s, calling name %s\n",
555 neg_flags, workgroup, cli->calling.name));
556 /* and wrap it in a SPNEGO wrapper */
557 msg1 = gen_negTokenInit(OID_NTLMSSP, blob);
558 data_blob_free(&blob);
560 /* now send that blob on its way */
561 blob = cli_session_setup_blob(cli, msg1);
563 data_blob_free(&msg1);
565 if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_MORE_PROCESSING_REQUIRED))
569 file_save("chal.dat", blob.data, blob.length);
572 /* the server gives us back two challenges */
573 if (!spnego_parse_challenge(blob, &chal1, &chal2)) {
574 DEBUG(3,("Failed to parse challenges\n"));
578 data_blob_free(&blob);
581 * Ok, chal1 and chal2 are actually two identical copies of
582 * the NTLMSSP Challenge BLOB, and they contain, encoded in them
583 * the challenge to use.
586 if (!msrpc_parse(&chal1, "CdUdbddB",
594 DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n"));
598 if (ntlmssp_command != NTLMSSP_CHALLENGE) {
599 DEBUG(0, ("NTLMSSP Response != NTLMSSP_CHALLENGE. Got %0X\n",
604 if (challenge_blob.length < 8) {
608 DEBUG(10, ("Challenge:\n"));
609 dump_data(10, challenge_blob.data, 8);
611 /* encrypt the password with the challenge which is in the blob */
612 memcpy(challenge, challenge_blob.data, 8);
613 SMBencrypt(pass, challenge,lmhash);
614 SMBNTencrypt(pass, challenge,nthash);
615 data_blob_free(&challenge_blob);
618 file_save("nthash.dat", nthash, 24);
619 file_save("lmhash.dat", lmhash, 24);
620 file_save("chal1.dat", chal1.data, chal1.length);
623 data_blob_free(&chal1);
624 data_blob_free(&chal2);
626 /* this generates the actual auth packet */
627 msrpc_gen(&blob, "CdBBUUUBd",
638 /* wrap it in SPNEGO */
639 auth = spnego_gen_auth(blob);
641 data_blob_free(&blob);
643 /* now send the auth packet and we should be done */
644 blob = cli_session_setup_blob(cli, auth);
646 data_blob_free(&auth);
647 data_blob_free(&blob);
649 if (cli_is_error(cli))
655 /****************************************************************************
656 Do a spnego encrypted session setup.
657 ****************************************************************************/
659 static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
660 const char *pass, const char *workgroup)
663 char *OIDs[ASN1_MAX_OIDS];
665 BOOL got_kerberos_mechanism = False;
668 DEBUG(2,("Doing spnego session setup (blob length=%d)\n", cli->secblob.length));
670 /* the server might not even do spnego */
671 if (cli->secblob.length <= 16) {
672 DEBUG(3,("server didn't supply a full spnego negprot\n"));
677 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
680 /* there is 16 bytes of GUID before the real spnego packet starts */
681 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
683 /* the server sent us the first part of the SPNEGO exchange in the negprot
685 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
686 data_blob_free(&blob);
689 data_blob_free(&blob);
691 /* make sure the server understands kerberos */
692 for (i=0;OIDs[i];i++) {
693 DEBUG(3,("got OID=%s\n", OIDs[i]));
694 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
695 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
696 got_kerberos_mechanism = True;
700 DEBUG(3,("got principal=%s\n", principal));
702 fstrcpy(cli->user_name, user);
705 if (got_kerberos_mechanism && cli->use_kerberos) {
706 return cli_session_setup_kerberos(cli, principal, workgroup);
714 return cli_session_setup_ntlmssp(cli, user, pass, workgroup);
717 /****************************************************************************
718 Send a session setup. The username and workgroup is in UNIX character
719 format and must be converted to DOS codepage format before sending. If the
720 password is in plaintext, the same should be done.
721 ****************************************************************************/
723 BOOL cli_session_setup(struct cli_state *cli,
725 const char *pass, int passlen,
726 const char *ntpass, int ntpasslen,
727 const char *workgroup)
732 /* allow for workgroups as part of the username */
733 fstrcpy(user2, user);
734 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
735 (p=strchr_m(user2,*lp_winbind_separator()))) {
741 if (cli->protocol < PROTOCOL_LANMAN1)
744 /* now work out what sort of session setup we are going to
745 do. I have split this into separate functions to make the
746 flow a bit easier to understand (tridge) */
748 /* if its an older server then we have to use the older request format */
750 if (cli->protocol < PROTOCOL_NT1)
751 return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
753 /* if no user is supplied then we have to do an anonymous connection.
754 passwords are ignored */
757 return cli_session_setup_guest(cli);
759 /* if the server is share level then send a plaintext null
760 password at this point. The password is sent in the tree
763 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
764 return cli_session_setup_plaintext(cli, user, "", workgroup);
766 /* if the server doesn't support encryption then we have to use
767 plaintext. The second password is ignored */
769 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0)
770 return cli_session_setup_plaintext(cli, user, pass, workgroup);
772 /* Indidicate signing */
774 /* if the server supports extended security then use SPNEGO */
776 if (cli->capabilities & CAP_EXTENDED_SECURITY)
777 return cli_session_setup_spnego(cli, user, pass, workgroup);
779 /* otherwise do a NT1 style session setup */
781 return cli_session_setup_nt1(cli, user,
782 pass, passlen, ntpass, ntpasslen,
786 /****************************************************************************
788 *****************************************************************************/
790 BOOL cli_ulogoff(struct cli_state *cli)
792 memset(cli->outbuf,'\0',smb_size);
793 set_message(cli->outbuf,2,0,True);
794 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
795 cli_setup_packet(cli);
796 SSVAL(cli->outbuf,smb_vwv0,0xFF);
797 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
800 if (!cli_receive_smb(cli))
803 return !cli_is_error(cli);
806 /****************************************************************************
808 ****************************************************************************/
810 BOOL cli_send_tconX(struct cli_state *cli,
811 const char *share, const char *dev, const char *pass, int passlen)
813 fstring fullshare, pword;
815 memset(cli->outbuf,'\0',smb_size);
816 memset(cli->inbuf,'\0',smb_size);
818 fstrcpy(cli->share, share);
820 /* in user level security don't send a password now */
821 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
826 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) {
828 * Non-encrypted passwords - convert to DOS codepage before encryption.
831 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
833 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
835 * Non-encrypted passwords - convert to DOS codepage before using.
837 passlen = clistr_push(cli, pword, pass, -1, STR_TERMINATE);
839 memcpy(pword, pass, passlen);
843 if (cli->port == 445) {
844 slprintf(fullshare, sizeof(fullshare)-1,
847 slprintf(fullshare, sizeof(fullshare)-1,
848 "\\\\%s\\%s", cli->desthost, share);
851 set_message(cli->outbuf,4, 0, True);
852 SCVAL(cli->outbuf,smb_com,SMBtconX);
853 cli_setup_packet(cli);
855 SSVAL(cli->outbuf,smb_vwv0,0xFF);
856 SSVAL(cli->outbuf,smb_vwv3,passlen);
858 p = smb_buf(cli->outbuf);
859 memcpy(p,pword,passlen);
861 p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
862 fstrcpy(p, dev); p += strlen(dev)+1;
864 cli_setup_bcc(cli, p);
867 if (!cli_receive_smb(cli))
870 if (cli_is_error(cli))
873 clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
875 if (strcasecmp(share,"IPC$")==0)
876 fstrcpy(cli->dev, "IPC");
878 if (cli->protocol >= PROTOCOL_NT1 &&
879 smb_buflen(cli->inbuf) == 3) {
880 /* almost certainly win95 - enable bug fixes */
884 cli->cnum = SVAL(cli->inbuf,smb_tid);
888 /****************************************************************************
889 Send a tree disconnect.
890 ****************************************************************************/
892 BOOL cli_tdis(struct cli_state *cli)
894 memset(cli->outbuf,'\0',smb_size);
895 set_message(cli->outbuf,0,0,True);
896 SCVAL(cli->outbuf,smb_com,SMBtdis);
897 SSVAL(cli->outbuf,smb_tid,cli->cnum);
898 cli_setup_packet(cli);
901 if (!cli_receive_smb(cli))
904 return !cli_is_error(cli);
907 /****************************************************************************
908 Send a negprot command.
909 ****************************************************************************/
911 void cli_negprot_send(struct cli_state *cli)
916 if (cli->protocol < PROTOCOL_NT1)
917 cli->use_spnego = False;
919 memset(cli->outbuf,'\0',smb_size);
921 /* setup the protocol strings */
922 set_message(cli->outbuf,0,0,True);
924 p = smb_buf(cli->outbuf);
926 prots[numprots].name && prots[numprots].prot<=cli->protocol;
929 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
932 SCVAL(cli->outbuf,smb_com,SMBnegprot);
933 cli_setup_bcc(cli, p);
934 cli_setup_packet(cli);
936 SCVAL(smb_buf(cli->outbuf),0,2);
941 /****************************************************************************
942 Send a negprot command.
943 ****************************************************************************/
945 BOOL cli_negprot(struct cli_state *cli)
951 if (cli->sign_info.use_smb_signing) {
952 DEBUG(0, ("Cannot send negprot again, particularly after setting up SMB Signing\n"));
956 if (cli->protocol < PROTOCOL_NT1)
957 cli->use_spnego = False;
959 memset(cli->outbuf,'\0',smb_size);
961 /* setup the protocol strings */
962 for (plength=0,numprots=0;
963 prots[numprots].name && prots[numprots].prot<=cli->protocol;
965 plength += strlen(prots[numprots].name)+2;
967 set_message(cli->outbuf,0,plength,True);
969 p = smb_buf(cli->outbuf);
971 prots[numprots].name && prots[numprots].prot<=cli->protocol;
974 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
977 SCVAL(cli->outbuf,smb_com,SMBnegprot);
978 cli_setup_packet(cli);
980 SCVAL(smb_buf(cli->outbuf),0,2);
983 if (!cli_receive_smb(cli))
986 show_msg(cli->inbuf);
988 if (cli_is_error(cli) ||
989 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
993 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
995 if (cli->protocol >= PROTOCOL_NT1) {
997 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
998 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
999 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
1000 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
1001 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
1002 cli->serverzone *= 60;
1003 /* this time arrives in real GMT */
1004 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
1005 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1006 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
1007 if (cli->capabilities & CAP_RAW_MODE) {
1008 cli->readbraw_supported = True;
1009 cli->writebraw_supported = True;
1011 /* work out if they sent us a workgroup */
1012 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
1013 smb_buflen(cli->inbuf) > 8) {
1014 clistr_pull(cli, cli->server_domain,
1015 smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
1016 smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
1019 if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED))
1020 cli->sign_info.negotiated_smb_signing = True;
1022 if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && cli->sign_info.allow_smb_signing)
1023 cli->sign_info.negotiated_smb_signing = True;
1025 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
1026 cli->use_spnego = False;
1027 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
1028 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
1029 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
1030 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
1031 cli->serverzone *= 60;
1032 /* this time is converted to GMT by make_unix_date */
1033 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
1034 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
1035 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
1036 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
1038 /* the old core protocol */
1039 cli->use_spnego = False;
1041 cli->serverzone = TimeDiff(time(NULL));
1044 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
1046 /* a way to force ascii SMB */
1047 if (getenv("CLI_FORCE_ASCII"))
1048 cli->capabilities &= ~CAP_UNICODE;
1053 /****************************************************************************
1054 Send a session request. See rfc1002.txt 4.3 and 4.3.2.
1055 ****************************************************************************/
1057 BOOL cli_session_request(struct cli_state *cli,
1058 struct nmb_name *calling, struct nmb_name *called)
1062 extern pstring user_socket_options;
1064 memcpy(&(cli->calling), calling, sizeof(*calling));
1065 memcpy(&(cli->called ), called , sizeof(*called ));
1067 /* put in the destination name */
1068 p = cli->outbuf+len;
1069 name_mangle(cli->called .name, p, cli->called .name_type);
1073 p = cli->outbuf+len;
1074 name_mangle(cli->calling.name, p, cli->calling.name_type);
1077 /* 445 doesn't have session request */
1078 if (cli->port == 445)
1081 if (cli->sign_info.use_smb_signing) {
1082 DEBUG(0, ("Cannot send session resquest again, particularly after setting up SMB Signing\n"));
1086 /* send a session request (RFC 1002) */
1087 /* setup the packet length
1088 * Remove four bytes from the length count, since the length
1089 * field in the NBT Session Service header counts the number
1090 * of bytes which follow. The cli_send_smb() function knows
1091 * about this and accounts for those four bytes.
1095 _smb_setlen(cli->outbuf,len);
1096 SCVAL(cli->outbuf,0,0x81);
1099 DEBUG(5,("Sent session request\n"));
1101 if (!cli_receive_smb(cli))
1104 if (CVAL(cli->inbuf,0) == 0x84) {
1105 /* C. Hoch 9/14/95 Start */
1106 /* For information, here is the response structure.
1107 * We do the byte-twiddling to for portability.
1108 struct RetargetResponse{
1110 unsigned char flags;
1116 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
1117 /* SESSION RETARGET */
1118 putip((char *)&cli->dest_ip,cli->inbuf+4);
1120 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
1124 DEBUG(3,("Retargeted\n"));
1126 set_socket_options(cli->fd,user_socket_options);
1133 DEBUG(0,("Retarget recursion - failing\n"));
1137 ret = cli_session_request(cli, calling, called);
1141 } /* C. Hoch 9/14/95 End */
1143 if (CVAL(cli->inbuf,0) != 0x82) {
1144 /* This is the wrong place to put the error... JRA. */
1145 cli->rap_error = CVAL(cli->inbuf,4);
1151 /****************************************************************************
1152 Open the client sockets.
1153 ****************************************************************************/
1155 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
1157 extern pstring user_socket_options;
1158 int name_type = 0x20;
1161 /* reasonable default hostname */
1162 if (!host) host = "*SMBSERVER";
1164 fstrcpy(cli->desthost, host);
1166 /* allow hostnames of the form NAME#xx and do a netbios lookup */
1167 if ((p = strchr(cli->desthost, '#'))) {
1168 name_type = strtol(p+1, NULL, 16);
1172 if (!ip || is_zero_ip(*ip)) {
1173 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
1176 if (ip) *ip = cli->dest_ip;
1181 if (getenv("LIBSMB_PROG")) {
1182 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
1184 /* try 445 first, then 139 */
1185 int port = cli->port?cli->port:445;
1186 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1187 port, cli->timeout);
1188 if (cli->fd == -1 && cli->port == 0) {
1190 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
1191 port, cli->timeout);
1196 if (cli->fd == -1) {
1197 DEBUG(1,("Error connecting to %s (%s)\n",
1198 ip?inet_ntoa(*ip):host,strerror(errno)));
1202 set_socket_options(cli->fd,user_socket_options);
1207 /****************************************************************************
1208 Initialise client credentials for authenticated pipe access.
1209 ****************************************************************************/
1211 static void init_creds(struct ntuser_creds *creds, const char* username,
1212 const char* domain, const char* password)
1214 ZERO_STRUCTP(creds);
1216 pwd_set_cleartext(&creds->pwd, password);
1218 fstrcpy(creds->user_name, username);
1219 fstrcpy(creds->domain, domain);
1222 creds->pwd.null_pwd = True;
1227 establishes a connection right up to doing tconX, password specified.
1228 @param output_cli A fully initialised cli structure, non-null only on success
1229 @param dest_host The netbios name of the remote host
1230 @param dest_ip (optional) The the destination IP, NULL for name based lookup
1231 @param port (optional) The destination port (0 for default)
1232 @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
1233 @param service_type The 'type' of serivice.
1234 @param user Username, unix string
1235 @param domain User's domain
1236 @param password User's password, unencrypted unix string.
1237 @param retry BOOL. Did this connection fail with a retryable error ?
1240 NTSTATUS cli_full_connection(struct cli_state **output_cli,
1241 const char *my_name,
1242 const char *dest_host,
1243 struct in_addr *dest_ip, int port,
1244 const char *service, const char *service_type,
1245 const char *user, const char *domain,
1246 const char *password, int flags,
1249 struct ntuser_creds creds;
1251 struct nmb_name calling;
1252 struct nmb_name called;
1253 struct cli_state *cli;
1260 my_name = global_myname();
1262 if (!(cli = cli_initialise(NULL)))
1263 return NT_STATUS_NO_MEMORY;
1265 make_nmb_name(&calling, my_name, 0x0);
1266 make_nmb_name(&called , dest_host, 0x20);
1268 if (cli_set_port(cli, port) != port) {
1270 return NT_STATUS_UNSUCCESSFUL;
1273 cli_set_timeout(cli, 10000); /* 10 seconds. */
1282 DEBUG(3,("Connecting to host=%s share=%s\n", dest_host, service));
1284 if (!cli_connect(cli, dest_host, &ip)) {
1285 DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n",
1286 nmb_namestr(&called), inet_ntoa(ip)));
1288 return NT_STATUS_UNSUCCESSFUL;
1294 if (!cli_session_request(cli, &calling, &called)) {
1296 DEBUG(1,("session request to %s failed (%s)\n",
1297 called.name, cli_errstr(cli)));
1298 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
1302 if (strcmp(called.name, "*SMBSERVER")) {
1303 make_nmb_name(&called , "*SMBSERVER", 0x20);
1306 return NT_STATUS_UNSUCCESSFUL;
1309 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
1310 cli->use_spnego = False;
1311 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
1312 cli->use_kerberos = True;
1314 if (!cli_negprot(cli)) {
1315 DEBUG(1,("failed negprot\n"));
1316 nt_status = NT_STATUS_UNSUCCESSFUL;
1321 if (!cli_session_setup(cli, user, password, strlen(password)+1,
1322 password, strlen(password)+1,
1324 if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
1325 && cli_session_setup(cli, "", "", 0, "", 0, domain)) {
1327 nt_status = cli_nt_error(cli);
1328 DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status)));
1330 if (NT_STATUS_IS_OK(nt_status))
1331 nt_status = NT_STATUS_UNSUCCESSFUL;
1337 if (!cli_send_tconX(cli, service, service_type,
1338 password, strlen(password)+1)) {
1339 nt_status = cli_nt_error(cli);
1340 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
1342 if (NT_STATUS_IS_OK(nt_status)) {
1343 nt_status = NT_STATUS_UNSUCCESSFUL;
1349 init_creds(&creds, user, domain, password);
1350 cli_init_creds(cli, &creds);
1353 return NT_STATUS_OK;
1356 /****************************************************************************
1357 Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
1358 ****************************************************************************/
1360 BOOL attempt_netbios_session_request(struct cli_state *cli, const char *srchost, const char *desthost,
1361 struct in_addr *pdest_ip)
1363 struct nmb_name calling, called;
1365 make_nmb_name(&calling, srchost, 0x0);
1368 * If the called name is an IP address
1369 * then use *SMBSERVER immediately.
1372 if(is_ipaddress(desthost))
1373 make_nmb_name(&called, "*SMBSERVER", 0x20);
1375 make_nmb_name(&called, desthost, 0x20);
1377 if (!cli_session_request(cli, &calling, &called)) {
1378 struct nmb_name smbservername;
1380 make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
1383 * If the name wasn't *SMBSERVER then
1384 * try with *SMBSERVER if the first name fails.
1387 if (nmb_name_equal(&called, &smbservername)) {
1390 * The name used was *SMBSERVER, don't bother with another name.
1393 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
1394 with error %s.\n", desthost, cli_errstr(cli) ));
1399 * We need to close the connection here but can't call cli_shutdown as
1400 * will free an allocated cli struct. cli_close_connection was invented
1401 * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
1404 cli_close_connection(cli);
1406 if (!cli_initialise(cli) ||
1407 !cli_connect(cli, desthost, pdest_ip) ||
1408 !cli_session_request(cli, &calling, &smbservername)) {
1409 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
1410 name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));