From 9f7cb41f11c0d2fc09104f6998f75c59bc363b26 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 Oct 2001 04:49:42 +0000 Subject: added NTLMSSP authentication to libsmb. It seems to work well so I have enabled it by default if the server supports it. Let me know if this breaks anything. Choose kerberos with the -k flag to smbclient, otherwise it will use SPNEGO/NTLMSSP/NTLM (This used to be commit 076aa97bee54d182288d9e93ae160ae22a5f7757) --- source3/libsmb/cliconnect.c | 206 +++++++++++++++++++++++++++++++++----------- 1 file changed, 154 insertions(+), 52 deletions(-) (limited to 'source3/libsmb/cliconnect.c') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 36aedf2d59..11852a09cc 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -34,6 +34,7 @@ prots[] = {PROTOCOL_LANMAN1,"LANMAN1.0"}, {PROTOCOL_LANMAN1,"Windows for Workgroups 3.1a"}, {PROTOCOL_LANMAN2,"LM1.2X002"}, + {PROTOCOL_NT1,"Samba"}, {PROTOCOL_NT1,"LANMAN2.1"}, {PROTOCOL_NT1,"NT LM 0.12"}, {-1,NULL} @@ -315,49 +316,17 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user, return True; } -#if HAVE_KRB5 + /**************************************************************************** -do a spnego encrypted session setup +send a extended security session setup blob, returning a reply blob ****************************************************************************/ -static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user, - char *pass, char *workgroup) +static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob) { uint32 capabilities = cli_session_setup_capabilities(cli); char *p; - DATA_BLOB blob2, negTokenTarg; - char *principle; - char *OIDs[ASN1_MAX_OIDS]; - uint8 guid[16]; - int i; - BOOL got_kerberos_mechanism = False; - - /* the server sent us the first part of the SPNEGO exchange in the negprot - reply */ - if (!spnego_parse_negTokenInit(cli->secblob, guid, OIDs, &principle)) { - return False; - } - - /* make sure the server understands kerberos */ - for (i=0;OIDs[i];i++) { - DEBUG(3,("got OID=%s\n", OIDs[i])); - if (strcmp(OIDs[i], "1 2 840 48018 1 2 2") == 0) { - got_kerberos_mechanism = True; - } - free(OIDs[i]); - } - DEBUG(3,("got principle=%s\n", principle)); - - if (!got_kerberos_mechanism) { - DEBUG(1,("Server didn't offer kerberos5 mechanism!?\n")); - return False; - } - - /* generate the encapsulated kerberos5 ticket */ - negTokenTarg = spnego_gen_negTokenTarg(cli, principle); - - free(principle); + DATA_BLOB blob2; - if (!negTokenTarg.data) return False; + blob2 = data_blob(NULL, 0); capabilities |= CAP_EXTENDED_SECURITY; @@ -373,23 +342,24 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user, SSVAL(cli->outbuf,smb_vwv3,2); SSVAL(cli->outbuf,smb_vwv4,0); SIVAL(cli->outbuf,smb_vwv5,0); - SSVAL(cli->outbuf,smb_vwv7,negTokenTarg.length); + SSVAL(cli->outbuf,smb_vwv7,blob.length); SIVAL(cli->outbuf,smb_vwv10,capabilities); p = smb_buf(cli->outbuf); - memcpy(p, negTokenTarg.data, negTokenTarg.length); - p += negTokenTarg.length; + memcpy(p, blob.data, blob.length); + p += blob.length; p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE); cli_setup_bcc(cli, p); cli_send_smb(cli); if (!cli_receive_smb(cli)) - return False; + return blob2; show_msg(cli->inbuf); - if (cli_is_error(cli)) { - return False; + if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli), + NT_STATUS_MORE_PROCESSING_REQUIRED)) { + return blob2; } /* use the returned vuid from now on */ @@ -404,17 +374,154 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user, p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE); p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE); - fstrcpy(cli->user_name, user); + return blob2; +} - data_blob_free(negTokenTarg); - /* we don't need this blob until we do NTLMSSP */ +#if HAVE_KRB5 +/**************************************************************************** +do a spnego/kerberos encrypted session setup +****************************************************************************/ +static BOOL cli_session_setup_kerberos(struct cli_state *cli, char *principle, char *workgroup) +{ + DATA_BLOB blob2, negTokenTarg; + + /* generate the encapsulated kerberos5 ticket */ + negTokenTarg = spnego_gen_negTokenTarg(cli, principle); + + if (!negTokenTarg.data) return False; + + blob2 = cli_session_setup_blob(cli, negTokenTarg); + + /* we don't need this blob for kerberos */ data_blob_free(blob2); - return True; + return !cli_is_error(cli); } #endif +/**************************************************************************** +do a spnego/NTLMSSP encrypted session setup +****************************************************************************/ +static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user, + char *pass, char *workgroup) +{ + const char *mechs[] = {"1 3 6 1 4 1 311 2 2 10", NULL}; + DATA_BLOB msg1; + DATA_BLOB blob, chal1, chal2, auth; + uint8 challenge[8]; + uint8 nthash[24], lmhash[24], sess_key[16]; + uint32 neg_flags; + + neg_flags = NTLMSSP_NEGOTIATE_UNICODE | + NTLMSSP_NEGOTIATE_LM_KEY | + NTLMSSP_NEGOTIATE_NTLM; + + memset(sess_key, 0, 16); + + /* generate the ntlmssp negotiate packet */ + msrpc_gen(&blob, "CddB", + "NTLMSSP", + NTLMSSP_NEGOTIATE, + neg_flags, + sess_key, 16); + + /* and wrap it in a SPNEGO wrapper */ + msg1 = gen_negTokenTarg(mechs, blob); + data_blob_free(blob); + + /* now send that blob on its way */ + blob = cli_session_setup_blob(cli, msg1); + + data_blob_free(msg1); + + if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_MORE_PROCESSING_REQUIRED)) { + return False; + } + + /* the server gives us back two challenges */ + if (!spnego_parse_challenge(blob, &chal1, &chal2)) { + return False; + } + + data_blob_free(blob); + + /* encrypt the password with the challenge */ + memcpy(challenge, chal1.data + 24, 8); + SMBencrypt(pass, challenge,lmhash); + SMBNTencrypt(pass, challenge,nthash); + + data_blob_free(chal1); + data_blob_free(chal2); + + /* this generates the actual auth packet */ + msrpc_gen(&blob, "CdBBUUUBd", + "NTLMSSP", + NTLMSSP_AUTH, + lmhash, 24, + nthash, 24, + workgroup, + user, + cli->calling.name, + sess_key, 16, + neg_flags); + + /* wrap it in SPNEGO */ + auth = spnego_gen_auth(blob); + + data_blob_free(blob); + + /* now send the auth packet and we should be done */ + blob = cli_session_setup_blob(cli, auth); + + data_blob_free(auth); + data_blob_free(blob); + + return !cli_is_error(cli); +} + + +/**************************************************************************** +do a spnego encrypted session setup +****************************************************************************/ +static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user, + char *pass, char *workgroup) +{ + char *principle; + char *OIDs[ASN1_MAX_OIDS]; + uint8 guid[16]; + int i; + BOOL got_kerberos_mechanism = False; + + /* the server sent us the first part of the SPNEGO exchange in the negprot + reply */ + if (!spnego_parse_negTokenInit(cli->secblob, guid, OIDs, &principle)) { + return False; + } + + /* make sure the server understands kerberos */ + for (i=0;OIDs[i];i++) { + DEBUG(3,("got OID=%s\n", OIDs[i])); + if (strcmp(OIDs[i], "1 2 840 48018 1 2 2") == 0) { + got_kerberos_mechanism = True; + } + free(OIDs[i]); + } + DEBUG(3,("got principle=%s\n", principle)); + + fstrcpy(cli->user_name, user); + +#if HAVE_KRB5 + if (got_kerberos_mechanism && cli->use_kerberos) { + return cli_session_setup_kerberos(cli, principle, workgroup); + } +#endif + + free(principle); + + return cli_session_setup_ntlmssp(cli, user, pass, workgroup); +} + /**************************************************************************** Send a session setup. The username and workgroup is in UNIX character @@ -674,11 +781,6 @@ BOOL cli_negprot(struct cli_state *cli) CVAL(smb_buf(cli->outbuf),0) = 2; - if (cli->use_spnego) { - SSVAL(cli->outbuf, smb_flg2, - SVAL(cli->outbuf, smb_flg2) | FLAGS2_EXTENDED_SECURITY); - } - cli_send_smb(cli); if (!cli_receive_smb(cli)) return False; -- cgit