From b2edf254eda92f775e7d3d9b6793b4d77f9000b6 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 17 Aug 2002 17:00:51 +0000 Subject: sync 3.0 branch with head (This used to be commit 3928578b52cfc949be5e0ef444fce1558d75f290) --- source3/libsmb/cliconnect.c | 47 +++++++++++++++++------------- source3/libsmb/clispnego.c | 61 +++++++++++++++++++++++++++++++++++++++ source3/libsmb/namequery.c | 67 +++++++++++++++++++++++++++++++++++++------ source3/libsmb/smbencrypt.c | 16 +++++------ source3/libsmb/trust_passwd.c | 2 +- 5 files changed, 155 insertions(+), 38 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 472db69fd0..93cf3d95db 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -54,9 +54,6 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, char *user, return False; } - /* Lanman2 cannot use SMB signing. */ - cli->sign_info.use_smb_signing = False; - /* if in share level security then don't send a password now */ if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) { passlen = 0; @@ -209,12 +206,11 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user, SSVAL(cli->outbuf,smb_vwv3,2); SSVAL(cli->outbuf,smb_vwv4,cli->pid); SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); - SSVAL(cli->outbuf,smb_vwv7,passlen); SSVAL(cli->outbuf,smb_vwv8,0); SIVAL(cli->outbuf,smb_vwv11,capabilities); p = smb_buf(cli->outbuf); - memcpy(p, pword, passlen); - p += passlen; + p += clistr_push(cli, p, pword, -1, STR_TERMINATE); /* password */ + SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf))); p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */ p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */ p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); @@ -257,11 +253,12 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user, char *workgroup) { uint32 capabilities = cli_session_setup_capabilities(cli); - fstring pword, ntpword; + uchar pword[24]; + uchar ntpword[24]; char *p; BOOL tried_signing = False; - if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) { + if (passlen > sizeof(pword) || ntpasslen > sizeof(ntpword)) { return False; } @@ -269,15 +266,21 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user, /* non encrypted password supplied. Ignore ntpass. */ passlen = 24; ntpasslen = 24; - SMBencrypt((uchar *)pass,cli->secblob.data,(uchar *)pword); - SMBNTencrypt((uchar *)pass,cli->secblob.data,(uchar *)ntpword); + SMBencrypt(pass,cli->secblob.data,pword); + SMBNTencrypt(pass,cli->secblob.data,ntpword); if (!cli->sign_info.use_smb_signing && cli->sign_info.negotiated_smb_signing) { - cli_calculate_mac_key(cli, (uchar *)pass, (uchar *)ntpword); + cli_calculate_mac_key(cli, pass, ntpword); tried_signing = True; } } else { - memcpy(pword, pass, passlen); - memcpy(ntpword, ntpass, ntpasslen); + /* pre-encrypted password supplied. Only used for security=server, can't do + signing becouse we don't have oringial key */ + memcpy(pword, pass, 24); + if (ntpasslen == 24) { + memcpy(ntpword, ntpass, 24); + } else { + ZERO_STRUCT(ntpword); + } } /* send a session setup command */ @@ -305,8 +308,13 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user, cli_setup_bcc(cli, p); cli_send_smb(cli); - if (!cli_receive_smb(cli)) + if (!cli_receive_smb(cli)) { + if (tried_signing) { + /* We only use it if we have a successful non-guest connect */ + cli->sign_info.use_smb_signing = False; + } return False; + } show_msg(cli->inbuf); @@ -482,8 +490,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user, /* encrypt the password with the challenge */ memcpy(challenge, chal1.data + 24, 8); - SMBencrypt((unsigned char *)pass, challenge,lmhash); - SMBNTencrypt((unsigned char *)pass, challenge,nthash); + SMBencrypt(pass, challenge,lmhash); + SMBNTencrypt(pass, challenge,nthash); #if 0 file_save("nthash.dat", nthash, 24); @@ -1062,7 +1070,7 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) } if (cli->fd == -1) { DEBUG(1,("Error connecting to %s (%s)\n", - inet_ntoa(*ip),strerror(errno))); + ip?inet_ntoa(*ip):host,strerror(errno))); return False; } @@ -1182,9 +1190,8 @@ again: if (!cli_session_setup(cli, user, password, strlen(password)+1, password, strlen(password)+1, domain)) { - if (!(flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK) - || cli_session_setup(cli, "", "", 0, - "", 0, domain)) { + if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK) + && cli_session_setup(cli, "", "", 0, "", 0, domain)) { } else { nt_status = cli_nt_error(cli); DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status))); diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c index 469b946088..16702c375b 100644 --- a/source3/libsmb/clispnego.c +++ b/source3/libsmb/clispnego.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. simple kerberos5/SPNEGO routines Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jim McDonough 2002 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -439,6 +440,28 @@ BOOL spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth) return True; } +/* + generate a minimal SPNEGO NTLMSSP response packet. Doesn't contain much. +*/ +DATA_BLOB spnego_gen_auth_response(void) +{ + ASN1_DATA data; + DATA_BLOB ret; + + memset(&data, 0, sizeof(data)); + + asn1_push_tag(&data, ASN1_CONTEXT(1)); + asn1_push_tag(&data, ASN1_SEQUENCE(0)); + asn1_push_tag(&data, ASN1_CONTEXT(0)); + asn1_write_enumerated(&data, 0); + asn1_pop_tag(&data); + asn1_pop_tag(&data); + asn1_pop_tag(&data); + + ret = data_blob(data.data, data.length); + asn1_free(&data); + return ret; +} /* this is a tiny msrpc packet generator. I am only using this to @@ -449,6 +472,7 @@ BOOL spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth) format specifiers are: U = unicode string (input is unix string) + a = address (1 byte type, 1 byte length, unicode string, all inline) B = data blob (pointer + length) b = data blob in header (pointer + length) d = word (4 bytes) @@ -473,6 +497,11 @@ BOOL msrpc_gen(DATA_BLOB *blob, head_size += 8; data_size += str_charnum(s) * 2; break; + case 'a': + n = va_arg(ap, int); + s = va_arg(ap, char *); + data_size += (str_charnum(s) * 2) + 4; + break; case 'B': b = va_arg(ap, uint8 *); head_size += 8; @@ -512,6 +541,19 @@ BOOL msrpc_gen(DATA_BLOB *blob, push_string(NULL, blob->data+data_ofs, s, n*2, STR_UNICODE|STR_NOALIGN); data_ofs += n*2; break; + case 'a': + n = va_arg(ap, int); + SSVAL(blob->data, data_ofs, n); data_ofs += 2; + s = va_arg(ap, char *); + n = str_charnum(s); + SSVAL(blob->data, data_ofs, n*2); data_ofs += 2; + if (0 < n) { + push_string(NULL, blob->data+data_ofs, s, n*2, + STR_UNICODE|STR_NOALIGN); + } + data_ofs += n*2; + break; + case 'B': b = va_arg(ap, uint8 *); n = va_arg(ap, int); @@ -550,6 +592,7 @@ BOOL msrpc_gen(DATA_BLOB *blob, format specifiers are: U = unicode string (output is unix string) + A = ascii string B = data blob b = data blob in header d = word (4 bytes) @@ -584,6 +627,24 @@ BOOL msrpc_parse(DATA_BLOB *blob, STR_UNICODE|STR_NOALIGN); (*ps) = strdup(p); break; + case 'A': + len1 = SVAL(blob->data, head_ofs); head_ofs += 2; + len2 = SVAL(blob->data, head_ofs); head_ofs += 2; + ptr = IVAL(blob->data, head_ofs); head_ofs += 4; + + /* make sure its in the right format - be strict */ + if (len1 != len2 || ptr + len1 > blob->length) { + return False; + } + ps = va_arg(ap, char **); + if (0 < len1) { + pull_string(NULL, p, blob->data + ptr, -1, + len1, STR_ASCII|STR_NOALIGN); + (*ps) = strdup(p); + } else { + (*ps) = NULL; + } + break; case 'B': len1 = SVAL(blob->data, head_ofs); head_ofs += 2; len2 = SVAL(blob->data, head_ofs); head_ofs += 2; diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 18564bccf4..40a353fa8b 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -170,6 +170,11 @@ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr t int sock; BOOL result = False; + if (lp_disable_netbios()) { + DEBUG(5,("name_status_find(%s#%02x): netbios is disabled\n", q_name, q_type)); + return False; + } + DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name, q_type, inet_ntoa(to_ip))); @@ -191,7 +196,7 @@ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr t if (i == count) goto done; - pull_ascii(name, status[i].name, 15, -1, STR_TERMINATE); + pull_ascii(name, status[i].name, 16, 15, STR_TERMINATE); result = True; done: @@ -211,7 +216,7 @@ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr t /* comparison function used by sort_ip_list */ -static int ip_compare(struct in_addr *ip1, struct in_addr *ip2) +int ip_compare(struct in_addr *ip1, struct in_addr *ip2) { int max_bits1=0, max_bits2=0; int num_interfaces = iface_count(); @@ -273,6 +278,11 @@ struct in_addr *name_query(int fd,const char *name,int name_type, struct nmb_packet *nmb = &p.packet.nmb; struct in_addr *ip_list = NULL; + if (lp_disable_netbios()) { + DEBUG(5,("name_query(%s#%02x): netbios is disabled\n", name, name_type)); + return NULL; + } + if (timed_out) { *timed_out = False; } @@ -556,6 +566,11 @@ BOOL name_resolve_bcast(const char *name, int name_type, int sock, i; int num_interfaces = iface_count(); + if (lp_disable_netbios()) { + DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n", name, name_type)); + return False; + } + *return_ip_list = NULL; *return_count = 0; @@ -602,6 +617,11 @@ BOOL resolve_wins(const char *name, int name_type, char **wins_tags; struct in_addr src_ip; + if (lp_disable_netbios()) { + DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n", name, name_type)); + return False; + } + *return_iplist = NULL; *return_count = 0; @@ -763,7 +783,7 @@ static BOOL resolve_hosts(const char *name, *********************************************************/ static BOOL internal_resolve_name(const char *name, int name_type, - struct in_addr **return_iplist, int *return_count) + struct in_addr **return_iplist, int *return_count) { pstring name_resolve_list; fstring tok; @@ -796,6 +816,15 @@ static BOOL internal_resolve_name(const char *name, int name_type, return True; } + /* Check netbios name cache */ + + if (namecache_fetch(name, name_type, return_iplist, return_count)) { + + /* This could be a negative response */ + + return (*return_count > 0); + } + pstrcpy(name_resolve_list, lp_name_resolve_order()); ptr = name_resolve_list; if (!ptr || !*ptr) @@ -803,9 +832,16 @@ static BOOL internal_resolve_name(const char *name, int name_type, while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) { if((strequal(tok, "host") || strequal(tok, "hosts"))) { - if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) { - result = True; - goto done; + if (name_type == 0x20) { + if (resolve_hosts(name, return_iplist, return_count)) { + result = True; + goto done; + } else { + + /* Store negative lookup result */ + + namecache_store(name, name_type, 0, NULL); + } } } else if(strequal( tok, "lmhosts")) { if (resolve_lmhosts(name, name_type, return_iplist, return_count)) { @@ -877,6 +913,10 @@ static BOOL internal_resolve_name(const char *name, int name_type, *return_iplist = nodupes_iplist; *return_count = nodupes_count; } + + /* Save in name cache */ + + namecache_store(name, name_type, *return_count, *return_iplist); /* Display some debugging info */ @@ -930,11 +970,16 @@ BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type) Find the IP address of the master browser or DMB for a workgroup. *********************************************************/ -BOOL find_master_ip(char *group, struct in_addr *master_ip) +BOOL find_master_ip(const char *group, struct in_addr *master_ip) { struct in_addr *ip_list = NULL; int count = 0; + if (lp_disable_netbios()) { + DEBUG(5,("find_master_ip(%s): netbios is disabled\n", group)); + return False; + } + if (internal_resolve_name(group, 0x1D, &ip_list, &count)) { *master_ip = ip_list[0]; SAFE_FREE(ip_list); @@ -957,10 +1002,14 @@ BOOL find_master_ip(char *group, struct in_addr *master_ip) BOOL lookup_dc_name(const char *srcname, const char *domain, struct in_addr *dc_ip, char *ret_name) { -#if !defined(I_HATE_WINDOWS_REPLY_CODE) - +#if !defined(I_HATE_WINDOWS_REPLY_CODE) fstring dc_name; BOOL ret; + + if (lp_disable_netbios()) { + DEBUG(5,("lookup_dc_name(%s): netbios is disabled\n", domain)); + return False; + } /* * Due to the fact win WinNT *sucks* we must do a node status diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index 95434d0ae4..dfa355a7ec 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -28,7 +28,7 @@ This implements the X/Open SMB password encryption It takes a password ('unix' string), a 8 byte "crypt key" and puts 24 bytes of encrypted password into p24 */ -void SMBencrypt(const char *passwd, const uchar *c8, uchar *p24) +void SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24]) { uchar p21[21]; @@ -66,9 +66,9 @@ void E_md4hash(const char *passwd, uchar p16[16]) } /** - * Creates the MD4 Hash of the users password in NT UNICODE. + * Creates the DES forward-only Hash of the users password in DOS ASCII charset * @param passwd password in 'unix' charset. - * @param p16 return password hashed with md4, caller allocated 16 byte buffer + * @param p16 return password hashed with DES, caller allocated 16 byte buffer */ void E_deshash(const char *passwd, uchar p16[16]) @@ -77,7 +77,7 @@ void E_deshash(const char *passwd, uchar p16[16]) ZERO_STRUCT(dospwd); ZERO_STRUCTP(p16); - /* Password must be converted to DOS charset - null terminated. */ + /* Password must be converted to DOS charset - null terminated, uppercase. */ push_ascii(dospwd, (const char *)passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE); E_P16(dospwd, p16); @@ -175,7 +175,7 @@ void NTLMSSPOWFencrypt(const uchar passwd[8], const uchar *ntlmchalresp, uchar p /* Does the NT MD4 hash then des encryption. */ -void SMBNTencrypt(const uchar *passwd, uchar *c8, uchar *p24) +void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24) { uchar p21[21]; @@ -226,14 +226,14 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[ void SMBOWFencrypt_ntv2(const uchar kr[16], const DATA_BLOB srv_chal, const DATA_BLOB cli_chal, - char resp_buf[16]) + uchar resp_buf[16]) { HMACMD5Context ctx; hmac_md5_init_limK_to_64(kr, 16, &ctx); hmac_md5_update(srv_chal.data, srv_chal.length, &ctx); hmac_md5_update(cli_chal.data, cli_chal.length, &ctx); - hmac_md5_final((unsigned char *)resp_buf, &ctx); + hmac_md5_final(resp_buf, &ctx); #ifdef DEBUG_PASSWORD DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n")); @@ -337,7 +337,7 @@ BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd, SMB signing - setup the MAC key. ************************************************************/ -void cli_calculate_mac_key(struct cli_state *cli, const unsigned char *ntpasswd, const uchar resp[24]) +void cli_calculate_mac_key(struct cli_state *cli, const char *ntpasswd, const uchar resp[24]) { /* Get first 16 bytes. */ E_md4hash(ntpasswd,&cli->sign_info.mac_key[0]); diff --git a/source3/libsmb/trust_passwd.c b/source3/libsmb/trust_passwd.c index 3b77f7330e..fe6b673e39 100644 --- a/source3/libsmb/trust_passwd.c +++ b/source3/libsmb/trust_passwd.c @@ -35,7 +35,7 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_ unsigned char new_trust_passwd_hash[16]) { NTSTATUS result; - result = new_cli_nt_setup_creds(cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ? + result = cli_nt_setup_creds(cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ? SEC_CHAN_WKSTA : SEC_CHAN_BDC, orig_trust_passwd_hash); if (!NT_STATUS_IS_OK(result)) { -- cgit