From dc20a3024900c47dd2ee44b9707e6df38f7d62a5 Mon Sep 17 00:00:00 2001 From: as200622 Date: Sat, 5 Jan 2008 20:52:22 -0800 Subject: 6560095 SNAS shows SIDs for Built-in Groups members instead of name 6582153 SMB signing and sealing (redirector) 6582192 Remove SMB config cache 6582210 Consistent Logging Strategy 6582214 Unified error reporting strategy 6593360 Confusing log message: [ID 334764 user.error] Ads is not enable 6597854 The shares are not accessible if doing Run \\ip-addr 6610587 RPC-WINREG test has failed on smbtorture. 6610650 Workgroup: authentication problem when client's LM level > 2 6611277 Should not be able to join domain when Snas ipc-mode=anon and W2K DC IPC=No access without anonymous 6613675 Creating a file with DOS readonly bit set requires special handling 6626113 libshare_smb leaks file descriptor on unload 6626119 libshare_smb leaks file descriptor on door call failure 6626126 libsmb configuration leaks memory 6629314 smbd logging forgets newlines, creating a mess 6629954 smb local group support should be re-enabled 6630424 libshare having trouble starting smb/server 6631739 rdr_ipcmode does change to "Fallback,anon". 6631985 SMB daemon doesn't locate a new ADS server if ads_site property has been modified. 6631987 SMB daemon reads /etc/resolv.conf once when it starts up. 6633202 smbfs client caused CIFS server panic 6635175 lint error reported when building smbsrv module when either mars or ceres lint was used 6636763 Get core if using sharemgr set-share -r with nonexistent share 6640934 libshare tries to enable smb service if any filesystem is shared over smb 6641051 The CIFS server needs to use the VFS nbmand mechanism for system-wide share reservations 6642047 Changes to SMF properties of the CIFS service - PSARC/2007/686 6642302 Do not add null when marshalling non-null-terminated NDR strings 6642368 Cross protocol byte range locking is needed --HG-- rename : usr/src/lib/smbsrv/libmlsvc/common/mlsvc_handle.c => deleted_files/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_handle.c rename : usr/src/lib/smbsrv/libsmb/common/smb_group_door_encdec.c => deleted_files/usr/src/lib/smbsrv/libsmb/common/smb_group_door_encdec.c rename : usr/src/lib/smbsrv/libsmb/common/smb_group_xdr.c => deleted_files/usr/src/lib/smbsrv/libsmb/common/smb_group_xdr.c rename : usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c => usr/src/lib/smbsrv/libmlrpc/common/ndr_client.c rename : usr/src/lib/smbsrv/libmlrpc/common/mlrpc_heap.c => usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c rename : usr/src/lib/smbsrv/libmlrpc/common/mlrpc_encdec.c => usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c rename : usr/src/lib/smbsrv/libmlrpc/common/mlndo.c => usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c rename : usr/src/lib/smbsrv/libmlrpc/common/mlndr.c => usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c rename : usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c => usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c rename : usr/src/lib/smbsrv/libmlrpc/common/mlrpc_svc.c => usr/src/lib/smbsrv/libmlrpc/common/ndr_svc.c --- usr/src/lib/smbsrv/libsmb/common/smb_auth.c | 138 ++++++++++++++++++---------- 1 file changed, 90 insertions(+), 48 deletions(-) (limited to 'usr/src/lib/smbsrv/libsmb/common/smb_auth.c') diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_auth.c b/usr/src/lib/smbsrv/libsmb/common/smb_auth.c index d8950616db..ccd33ca1af 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_auth.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_auth.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -303,7 +303,6 @@ smb_auth_ntlmv2_hash(unsigned char *ntlm_hash, return (SMBAUTH_FAILURE); (void) utf8_strupr(username); - (void) utf8_strupr(ntdomain); data_len = strlen(username) + strlen(ntdomain); buf = (unsigned char *)malloc((data_len + 1) * sizeof (char)); @@ -397,6 +396,7 @@ smb_auth_set_info(char *username, unsigned short blob_len; unsigned char blob_buf[SMBAUTH_BLOB_MAXLEN]; int rc; + char *uppercase_dom; auth->lmcompatibility_lvl = lmcomp_lvl; if (lmcomp_lvl == 2) { @@ -421,12 +421,23 @@ smb_auth_set_info(char *username, (void) memcpy(auth->hash, ntlm_hash, SMBAUTH_HASH_SZ); } + if (!domain) + return (-1); + + if ((uppercase_dom = strdup(domain)) == NULL) + return (-1); + + (void) utf8_strupr(uppercase_dom); + if (smb_auth_ntlmv2_hash(auth->hash, username, - domain, auth->hash_v2) != SMBAUTH_SUCCESS) + uppercase_dom, auth->hash_v2) != SMBAUTH_SUCCESS) { + free(uppercase_dom); return (-1); + } /* generate data blob */ - smb_auth_gen_data_blob(&auth->data_blob, domain); + smb_auth_gen_data_blob(&auth->data_blob, uppercase_dom); + free(uppercase_dom); blob_len = smb_auth_blob_to_string(&auth->data_blob, blob_buf); /* generate NTLMv2 response */ @@ -538,67 +549,90 @@ smb_ntlmv2_password_ok( unsigned char *ntlm_hash, unsigned char *passwd, int pwdlen, + char *domain, char *username) { unsigned char *clnt_blob; int clnt_blob_len; unsigned char ntlmv2_hash[SMBAUTH_HASH_SZ]; unsigned char *ntlmv2_resp; - boolean_t ok; + boolean_t ok = B_FALSE; + char *dest[3]; + int i; clnt_blob_len = pwdlen - SMBAUTH_HASH_SZ; clnt_blob = &passwd[SMBAUTH_HASH_SZ]; + dest[0] = domain; + if ((dest[1] = strdup(domain)) == NULL) + return (B_FALSE); + (void) utf8_strupr(dest[1]); + dest[2] = ""; /* * 15.5.2 The NTLMv2 Password Hash, pg. 279, of the "Implementing CIFS" * - * * The NTLMv2 Hash is created from: + * The NTLMv2 Hash is created from: * - NTLM hash * - user's username, and * - the name of the logon destination(i.e. the NetBIOS name of either - * the SMB server or NT Domain against which the suer is trying to + * the SMB server or NT Domain against which the user is trying to * authenticate. * - * (N.L.) With my experience, this is not exactly true. It's really - * tricky how the NTLMv2 hash is generated by the Windows client when - * logging into a standalone server using NTLMv2 challenge / response. - * The NTLMv2 hash is actually created with the destination info="" - * as opposed to the SMB server name mentioned in the book. + * Experiments show this is not exactly the case. + * For Windows Server 2003, the domain name needs to be included and + * converted to uppercase. For Vista, the domain name needs to be + * included also, but leave the case alone. And in some cases it needs + * to be empty. All three variants are tried here. */ - if (smb_auth_ntlmv2_hash(ntlm_hash, username, "", ntlmv2_hash) != - SMBAUTH_SUCCESS) { - return (B_FALSE); - } ntlmv2_resp = (unsigned char *)malloc(SMBAUTH_HASH_SZ + clnt_blob_len); - if (ntlmv2_resp == NULL) - return (B_FALSE); - - if (smb_auth_v2_response(ntlmv2_hash, challenge, - clen, clnt_blob, clnt_blob_len, ntlmv2_resp) < 0) { - free(ntlmv2_resp); + if (ntlmv2_resp == NULL) { + free(dest[1]); return (B_FALSE); } - ok = (bcmp(passwd, ntlmv2_resp, pwdlen) == 0); + for (i = 0; i < (sizeof (dest) / sizeof (char *)); i++) { + if (smb_auth_ntlmv2_hash(ntlm_hash, username, dest[i], + ntlmv2_hash) != SMBAUTH_SUCCESS) + break; + + if (smb_auth_v2_response(ntlmv2_hash, challenge, + clen, clnt_blob, clnt_blob_len, ntlmv2_resp) < 0) + break; + + ok = (bcmp(passwd, ntlmv2_resp, pwdlen) == 0); + if (ok == B_TRUE) + break; + } + + free(dest[1]); free(ntlmv2_resp); return (ok); } -static int +static boolean_t smb_lmv2_password_ok( unsigned char *challenge, uint32_t clen, unsigned char *ntlm_hash, unsigned char *passwd, + char *domain, char *username) { unsigned char *clnt_challenge; unsigned char ntlmv2_hash[SMBAUTH_HASH_SZ]; unsigned char lmv2_resp[SMBAUTH_LM_RESP_SZ]; + boolean_t ok = B_FALSE; + char *dest[3]; + int i; clnt_challenge = &passwd[SMBAUTH_HASH_SZ]; + dest[0] = domain; + if ((dest[1] = strdup(domain)) == NULL) + return (B_FALSE); + (void) utf8_strupr(dest[1]); + dest[2] = ""; /* * 15.5.2 The NTLMv2 Password Hash, pg. 279, of the "Implementing CIFS" @@ -610,23 +644,31 @@ smb_lmv2_password_ok( * the SMB server or NT Domain against which the suer is trying to * authenticate. * - * (N.L.) With my experience, this is not exactly true. It's really - * tricky how the NTLMv2 hash is generated by the Windows client when - * logging into a standalone server using LMv2 challenge/response. - * The NTLMv2 hash is actually created with the destination info = "" - * as opposed to the SMB server name mentioned in the book. + * Experiments show this is not exactly the case. + * For Windows Server 2003, the domain name needs to be included and + * converted to uppercase. For Vista, the domain name needs to be + * included also, but leave the case alone. And in some cases it needs + * to be empty. All three variants are tried here. */ - if (smb_auth_ntlmv2_hash(ntlm_hash, username, "", ntlmv2_hash) != - SMBAUTH_SUCCESS) { - return (B_FALSE); - } - if (smb_auth_v2_response(ntlmv2_hash, challenge, - clen, clnt_challenge, SMBAUTH_V2_CLNT_CHALLENGE_SZ, - lmv2_resp) < 0) { - return (B_FALSE); + + for (i = 0; i < (sizeof (dest) / sizeof (char *)); i++) { + if (smb_auth_ntlmv2_hash(ntlm_hash, username, dest[i], + ntlmv2_hash) != SMBAUTH_SUCCESS) + break; + + if (smb_auth_v2_response(ntlmv2_hash, challenge, + clen, clnt_challenge, SMBAUTH_V2_CLNT_CHALLENGE_SZ, + lmv2_resp) < 0) + break; + + ok = (bcmp(passwd, lmv2_resp, SMBAUTH_LM_RESP_SZ) == 0); + if (ok == B_TRUE) + break; + } - return (bcmp(passwd, lmv2_resp, SMBAUTH_LM_RESP_SZ) == 0); + free(dest[1]); + return (ok); } /* @@ -644,17 +686,17 @@ smb_auth_validate_lm( smb_passwd_t *smbpw, unsigned char *passwd, int pwdlen, + char *domain, char *username) { - int lmlevel; boolean_t ok = B_FALSE; + int64_t lmlevel; if (pwdlen != SMBAUTH_LM_RESP_SZ) return (B_FALSE); - smb_config_rdlock(); - lmlevel = smb_config_getnum(SMB_CI_LM_LEVEL); - smb_config_unlock(); + if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK) + return (B_FALSE); if (lmlevel <= 3) { ok = smb_lm_password_ok(challenge, clen, smbpw->pw_lmhash, @@ -663,7 +705,7 @@ smb_auth_validate_lm( if (!ok) ok = smb_lmv2_password_ok(challenge, clen, smbpw->pw_nthash, - passwd, username); + passwd, domain, username); return (ok); } @@ -683,21 +725,21 @@ smb_auth_validate_nt( smb_passwd_t *smbpw, unsigned char *passwd, int pwdlen, + char *domain, char *username) { - int lmlevel; + int64_t lmlevel; boolean_t ok; - smb_config_rdlock(); - lmlevel = smb_config_getnum(SMB_CI_LM_LEVEL); - smb_config_unlock(); + if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK) + return (B_FALSE); if ((lmlevel == 5) && (pwdlen <= SMBAUTH_LM_RESP_SZ)) return (B_FALSE); if (pwdlen > SMBAUTH_LM_RESP_SZ) ok = smb_ntlmv2_password_ok(challenge, clen, - smbpw->pw_nthash, passwd, pwdlen, username); + smbpw->pw_nthash, passwd, pwdlen, domain, username); else ok = smb_ntlm_password_ok(challenge, clen, smbpw->pw_nthash, passwd); -- cgit v1.2.3