15331Samw /* 25331Samw * CDDL HEADER START 35331Samw * 45331Samw * The contents of this file are subject to the terms of the 55331Samw * Common Development and Distribution License (the "License"). 65331Samw * You may not use this file except in compliance with the License. 75331Samw * 85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95331Samw * or http://www.opensolaris.org/os/licensing. 105331Samw * See the License for the specific language governing permissions 115331Samw * and limitations under the License. 125331Samw * 135331Samw * When distributing Covered Code, include this CDDL HEADER in each 145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155331Samw * If applicable, add the following below this CDDL HEADER, with the 165331Samw * fields enclosed by brackets "[]" replaced with your own identifying 175331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 185331Samw * 195331Samw * CDDL HEADER END 205331Samw */ 215331Samw /* 2210122SJordan.Brown@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw /* 275331Samw * NETR challenge/response client functions. 285331Samw * 295331Samw * NT_STATUS_INVALID_PARAMETER 305331Samw * NT_STATUS_NO_TRUST_SAM_ACCOUNT 315331Samw * NT_STATUS_ACCESS_DENIED 325331Samw */ 335331Samw 345331Samw #include <stdio.h> 355331Samw #include <stdlib.h> 365331Samw #include <strings.h> 375331Samw #include <unistd.h> 385331Samw #include <ctype.h> 397052Samw #include <security/cryptoki.h> 407052Samw #include <security/pkcs11.h> 415331Samw 425331Samw #include <smbsrv/libsmb.h> 436432Sas200622 #include <smbsrv/libsmbns.h> 448334SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h> 455331Samw #include <smbsrv/ndl/netlogon.ndl> 465331Samw #include <smbsrv/ntstatus.h> 475331Samw #include <smbsrv/smbinfo.h> 485331Samw #include <smbsrv/netrauth.h> 495331Samw 507052Samw #define NETR_SESSKEY_ZEROBUF_SZ 4 517619SJose.Borrego@Sun.COM /* The DES algorithm uses a 56-bit encryption key. */ 527052Samw #define NETR_DESKEY_LEN 7 537052Samw 545331Samw int netr_setup_authenticator(netr_info_t *, struct netr_authenticator *, 555331Samw struct netr_authenticator *); 565331Samw DWORD netr_validate_chain(netr_info_t *, struct netr_authenticator *); 575331Samw 585331Samw static int netr_server_req_challenge(mlsvc_handle_t *, netr_info_t *); 595331Samw static int netr_server_authenticate2(mlsvc_handle_t *, netr_info_t *); 605331Samw static int netr_gen_password(BYTE *, BYTE *, BYTE *); 615331Samw 625331Samw /* 635331Samw * Shared with netr_logon.c 645331Samw */ 655331Samw netr_info_t netr_global_info; 665331Samw 675331Samw /* 685331Samw * netlogon_auth 695331Samw * 705331Samw * This is the core of the NETLOGON authentication protocol. 715331Samw * Do the challenge response authentication. 725331Samw * 735331Samw * Prior to calling this function, an anonymous session to the NETLOGON 745331Samw * pipe on a domain controller(server) should have already been opened. 756139Sjb150015 * 766139Sjb150015 * Upon a successful NETLOGON credential chain establishment, the 776139Sjb150015 * netlogon sequence number will be set to match the kpasswd sequence 786139Sjb150015 * number. 796139Sjb150015 * 805331Samw */ 815331Samw DWORD 825331Samw netlogon_auth(char *server, mlsvc_handle_t *netr_handle, DWORD flags) 835331Samw { 845331Samw netr_info_t *netr_info; 855331Samw int rc; 865521Sas200622 DWORD leout_rc[2]; 875331Samw 885331Samw netr_info = &netr_global_info; 895331Samw bzero(netr_info, sizeof (netr_info_t)); 905331Samw 915331Samw netr_info->flags |= flags; 925331Samw 937961SNatalie.Li@Sun.COM rc = smb_getnetbiosname(netr_info->hostname, NETBIOS_NAME_SZ); 945331Samw if (rc != 0) 955331Samw return (NT_STATUS_UNSUCCESSFUL); 965331Samw 975331Samw (void) snprintf(netr_info->server, sizeof (netr_info->server), 985331Samw "\\\\%s", server); 995331Samw 1005521Sas200622 LE_OUT32(&leout_rc[0], random()); 1015521Sas200622 LE_OUT32(&leout_rc[1], random()); 1025521Sas200622 (void) memcpy(&netr_info->client_challenge, leout_rc, 1035331Samw sizeof (struct netr_credential)); 1045331Samw 1055331Samw if ((rc = netr_server_req_challenge(netr_handle, netr_info)) == 0) { 1065331Samw rc = netr_server_authenticate2(netr_handle, netr_info); 1076139Sjb150015 if (rc == 0) { 1086139Sjb150015 smb_update_netlogon_seqnum(); 1095331Samw netr_info->flags |= NETR_FLG_VALID; 1106139Sjb150015 1116139Sjb150015 } 1125331Samw } 1135331Samw 1145331Samw return ((rc) ? NT_STATUS_UNSUCCESSFUL : NT_STATUS_SUCCESS); 1155331Samw } 1165331Samw 1175331Samw /* 1185331Samw * netr_open 1195331Samw * 12010122SJordan.Brown@Sun.COM * Open an anonymous session to the NETLOGON pipe on a domain controller 12110122SJordan.Brown@Sun.COM * and bind to the NETR RPC interface. 12210122SJordan.Brown@Sun.COM * 12310122SJordan.Brown@Sun.COM * We store the remote server information, which is used to drive Windows 12410122SJordan.Brown@Sun.COM * version specific behavior. 1255331Samw */ 1265331Samw int 1275331Samw netr_open(char *server, char *domain, mlsvc_handle_t *netr_handle) 1285331Samw { 129*10717Samw@Sun.COM char user[SMB_USERNAME_MAXLEN]; 1305331Samw 131*10717Samw@Sun.COM smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); 13210122SJordan.Brown@Sun.COM 1338334SJose.Borrego@Sun.COM if (ndr_rpc_bind(netr_handle, server, domain, user, "NETR") < 0) 1345331Samw return (-1); 1355331Samw 1365331Samw return (0); 1375331Samw } 1385331Samw 1395331Samw /* 1405331Samw * netr_close 1415331Samw * 1425331Samw * Close a NETLOGON pipe and free the RPC context. 1435331Samw */ 1445331Samw int 1455331Samw netr_close(mlsvc_handle_t *netr_handle) 1465331Samw { 1478334SJose.Borrego@Sun.COM ndr_rpc_unbind(netr_handle); 1485331Samw return (0); 1495331Samw } 1505331Samw 1515331Samw /* 1525331Samw * netr_server_req_challenge 1535331Samw */ 1545331Samw static int 1555331Samw netr_server_req_challenge(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) 1565331Samw { 1575331Samw struct netr_ServerReqChallenge arg; 1585331Samw int opnum; 1595331Samw 1605331Samw bzero(&arg, sizeof (struct netr_ServerReqChallenge)); 1615331Samw opnum = NETR_OPNUM_ServerReqChallenge; 1625331Samw 1635331Samw arg.servername = (unsigned char *)netr_info->server; 1645331Samw arg.hostname = (unsigned char *)netr_info->hostname; 1655331Samw 1665331Samw (void) memcpy(&arg.client_challenge, &netr_info->client_challenge, 1675331Samw sizeof (struct netr_credential)); 1685331Samw 1698334SJose.Borrego@Sun.COM if (ndr_rpc_call(netr_handle, opnum, &arg) != 0) 1708334SJose.Borrego@Sun.COM return (-1); 1718334SJose.Borrego@Sun.COM 1728334SJose.Borrego@Sun.COM if (arg.status != 0) { 1738334SJose.Borrego@Sun.COM ndr_rpc_status(netr_handle, opnum, arg.status); 1748334SJose.Borrego@Sun.COM ndr_rpc_release(netr_handle); 1758334SJose.Borrego@Sun.COM return (-1); 1765331Samw } 1775331Samw 1788334SJose.Borrego@Sun.COM (void) memcpy(&netr_info->server_challenge, &arg.server_challenge, 1798334SJose.Borrego@Sun.COM sizeof (struct netr_credential)); 1808334SJose.Borrego@Sun.COM 1818334SJose.Borrego@Sun.COM ndr_rpc_release(netr_handle); 1828334SJose.Borrego@Sun.COM return (0); 1835331Samw } 1845331Samw 1855331Samw /* 1865331Samw * netr_server_authenticate2 1875331Samw */ 1885331Samw static int 1895331Samw netr_server_authenticate2(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) 1905331Samw { 1915331Samw struct netr_ServerAuthenticate2 arg; 1925331Samw int opnum; 1935331Samw int rc; 1947961SNatalie.Li@Sun.COM char account_name[NETBIOS_NAME_SZ * 2]; 1955331Samw 1965331Samw bzero(&arg, sizeof (struct netr_ServerAuthenticate2)); 1975331Samw opnum = NETR_OPNUM_ServerAuthenticate2; 1985331Samw 1995331Samw (void) snprintf(account_name, sizeof (account_name), "%s$", 2005331Samw netr_info->hostname); 2015331Samw 2027619SJose.Borrego@Sun.COM smb_tracef("server=[%s] account_name=[%s] hostname=[%s]\n", 2037619SJose.Borrego@Sun.COM netr_info->server, account_name, netr_info->hostname); 2047619SJose.Borrego@Sun.COM 2055331Samw arg.servername = (unsigned char *)netr_info->server; 2065331Samw arg.account_name = (unsigned char *)account_name; 2075331Samw arg.account_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE; 2085331Samw arg.hostname = (unsigned char *)netr_info->hostname; 2097619SJose.Borrego@Sun.COM arg.negotiate_flags = NETR_NEGOTIATE_BASE_FLAGS; 2105331Samw 211*10717Samw@Sun.COM if (ndr_rpc_server_os(netr_handle) == NATIVE_OS_WIN2000) { 2127619SJose.Borrego@Sun.COM arg.negotiate_flags |= NETR_NEGOTIATE_STRONGKEY_FLAG; 2137619SJose.Borrego@Sun.COM if (netr_gen_skey128(netr_info) != SMBAUTH_SUCCESS) 2147619SJose.Borrego@Sun.COM return (-1); 2157619SJose.Borrego@Sun.COM } else { 2167619SJose.Borrego@Sun.COM if (netr_gen_skey64(netr_info) != SMBAUTH_SUCCESS) 2177619SJose.Borrego@Sun.COM return (-1); 2187619SJose.Borrego@Sun.COM } 2195331Samw 2207619SJose.Borrego@Sun.COM if (netr_gen_credentials(netr_info->session_key.key, 2217619SJose.Borrego@Sun.COM &netr_info->client_challenge, 0, 2225331Samw &netr_info->client_credential) != SMBAUTH_SUCCESS) { 2235331Samw return (-1); 2245331Samw } 2255331Samw 2267619SJose.Borrego@Sun.COM if (netr_gen_credentials(netr_info->session_key.key, 2277619SJose.Borrego@Sun.COM &netr_info->server_challenge, 0, 2285331Samw &netr_info->server_credential) != SMBAUTH_SUCCESS) { 2295331Samw return (-1); 2305331Samw } 2315331Samw 2325331Samw (void) memcpy(&arg.client_credential, &netr_info->client_credential, 2335331Samw sizeof (struct netr_credential)); 2345331Samw 2358334SJose.Borrego@Sun.COM if (ndr_rpc_call(netr_handle, opnum, &arg) != 0) 2368334SJose.Borrego@Sun.COM return (-1); 2375331Samw 2388334SJose.Borrego@Sun.COM if (arg.status != 0) { 2398334SJose.Borrego@Sun.COM ndr_rpc_status(netr_handle, opnum, arg.status); 2408334SJose.Borrego@Sun.COM ndr_rpc_release(netr_handle); 2418334SJose.Borrego@Sun.COM return (-1); 2425331Samw } 2435331Samw 2448334SJose.Borrego@Sun.COM rc = memcmp(&netr_info->server_credential, &arg.server_credential, 2458334SJose.Borrego@Sun.COM sizeof (struct netr_credential)); 2468334SJose.Borrego@Sun.COM 2478334SJose.Borrego@Sun.COM ndr_rpc_release(netr_handle); 2485331Samw return (rc); 2495331Samw } 2505331Samw 2515331Samw /* 2527619SJose.Borrego@Sun.COM * netr_gen_skey128 2535331Samw * 2547619SJose.Borrego@Sun.COM * Generate a 128-bit session key from the client and server challenges. 2557619SJose.Borrego@Sun.COM * See "Session-Key Computation" section of MS-NRPC document. 2565331Samw */ 2577052Samw int 2587619SJose.Borrego@Sun.COM netr_gen_skey128(netr_info_t *netr_info) 2597052Samw { 2607052Samw unsigned char ntlmhash[SMBAUTH_HASH_SZ]; 2617052Samw int rc = SMBAUTH_FAILURE; 2627052Samw CK_RV rv; 2637052Samw CK_MECHANISM mechanism; 2647052Samw CK_SESSION_HANDLE hSession; 2657052Samw CK_ULONG diglen = MD_DIGEST_LEN; 2667052Samw unsigned char md5digest[MD_DIGEST_LEN]; 2677052Samw unsigned char zerobuf[NETR_SESSKEY_ZEROBUF_SZ]; 2687052Samw 2697052Samw bzero(ntlmhash, SMBAUTH_HASH_SZ); 2707052Samw /* 2717052Samw * We should check (netr_info->flags & NETR_FLG_INIT) and use 2727052Samw * the appropriate password but it isn't working yet. So we 2737052Samw * always use the default one for now. 2747052Samw */ 2757052Samw bzero(netr_info->password, sizeof (netr_info->password)); 2767052Samw rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, 2777052Samw (char *)netr_info->password, sizeof (netr_info->password)); 2787052Samw 2797052Samw if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') { 2807052Samw return (SMBAUTH_FAILURE); 2817052Samw } 2827052Samw 2837052Samw rc = smb_auth_ntlm_hash((char *)netr_info->password, ntlmhash); 2847052Samw if (rc != SMBAUTH_SUCCESS) 2857052Samw return (SMBAUTH_FAILURE); 2867052Samw 2877052Samw bzero(zerobuf, NETR_SESSKEY_ZEROBUF_SZ); 2887052Samw 2897052Samw mechanism.mechanism = CKM_MD5; 2907052Samw mechanism.pParameter = 0; 2917052Samw mechanism.ulParameterLen = 0; 2927052Samw 2937052Samw rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession); 2947052Samw if (rv != CKR_OK) 2957052Samw return (SMBAUTH_FAILURE); 2967052Samw 2977052Samw rv = C_DigestInit(hSession, &mechanism); 2987052Samw if (rv != CKR_OK) 2997052Samw goto cleanup; 3007052Samw 3017052Samw rv = C_DigestUpdate(hSession, (CK_BYTE_PTR)zerobuf, 3027052Samw NETR_SESSKEY_ZEROBUF_SZ); 3037052Samw if (rv != CKR_OK) 3047052Samw goto cleanup; 3057052Samw 3067052Samw rv = C_DigestUpdate(hSession, 3077052Samw (CK_BYTE_PTR)netr_info->client_challenge.data, NETR_CRED_DATA_SZ); 3087052Samw if (rv != CKR_OK) 3097052Samw goto cleanup; 3107052Samw 3117052Samw rv = C_DigestUpdate(hSession, 3127052Samw (CK_BYTE_PTR)netr_info->server_challenge.data, NETR_CRED_DATA_SZ); 3137052Samw if (rv != CKR_OK) 3147052Samw goto cleanup; 3157052Samw 3167052Samw rv = C_DigestFinal(hSession, (CK_BYTE_PTR)md5digest, &diglen); 3177052Samw if (rv != CKR_OK) 3187052Samw goto cleanup; 3197052Samw 3207052Samw rc = smb_auth_hmac_md5(md5digest, diglen, ntlmhash, SMBAUTH_HASH_SZ, 3217619SJose.Borrego@Sun.COM netr_info->session_key.key); 3227052Samw 3237619SJose.Borrego@Sun.COM netr_info->session_key.len = NETR_SESSKEY128_SZ; 3247052Samw cleanup: 3257052Samw (void) C_CloseSession(hSession); 3267052Samw return (rc); 3277052Samw 3287052Samw } 3297619SJose.Borrego@Sun.COM /* 3307619SJose.Borrego@Sun.COM * netr_gen_skey64 3317619SJose.Borrego@Sun.COM * 3327619SJose.Borrego@Sun.COM * Generate a 64-bit session key from the client and server challenges. 3337619SJose.Borrego@Sun.COM * See "Session-Key Computation" section of MS-NRPC document. 3347619SJose.Borrego@Sun.COM * 3357619SJose.Borrego@Sun.COM * The algorithm is a two stage hash. For the first hash, the input is 3367619SJose.Borrego@Sun.COM * the combination of the client and server challenges, the key is 3377619SJose.Borrego@Sun.COM * the first 7 bytes of the password. The initial password is formed 3387619SJose.Borrego@Sun.COM * using the NT password hash on the local hostname in lower case. 3397619SJose.Borrego@Sun.COM * The result is stored in a temporary buffer. 3407619SJose.Borrego@Sun.COM * 3417619SJose.Borrego@Sun.COM * input: challenge 3427619SJose.Borrego@Sun.COM * key: passwd lower 7 bytes 3437619SJose.Borrego@Sun.COM * output: intermediate result 3447619SJose.Borrego@Sun.COM * 3457619SJose.Borrego@Sun.COM * For the second hash, the input is the result of the first hash and 3467619SJose.Borrego@Sun.COM * the key is the last 7 bytes of the password. 3477619SJose.Borrego@Sun.COM * 3487619SJose.Borrego@Sun.COM * input: result of first hash 3497619SJose.Borrego@Sun.COM * key: passwd upper 7 bytes 3507619SJose.Borrego@Sun.COM * output: session_key 3517619SJose.Borrego@Sun.COM * 3527619SJose.Borrego@Sun.COM * The final output should be the session key. 3537619SJose.Borrego@Sun.COM * 3547619SJose.Borrego@Sun.COM * FYI: smb_auth_DES(output, key, input) 3557619SJose.Borrego@Sun.COM * 3567619SJose.Borrego@Sun.COM * If any difficulties occur using the cryptographic framework, the 3577619SJose.Borrego@Sun.COM * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is 3587619SJose.Borrego@Sun.COM * returned. 3597619SJose.Borrego@Sun.COM */ 3605331Samw int 3617619SJose.Borrego@Sun.COM netr_gen_skey64(netr_info_t *netr_info) 3625331Samw { 3635331Samw unsigned char md4hash[32]; 3645331Samw unsigned char buffer[8]; 3655331Samw DWORD data[2]; 3665331Samw DWORD *client_challenge; 3675331Samw DWORD *server_challenge; 3685331Samw int rc; 3695521Sas200622 DWORD le_data[2]; 3705331Samw 3715331Samw client_challenge = (DWORD *)(uintptr_t)&netr_info->client_challenge; 3725331Samw server_challenge = (DWORD *)(uintptr_t)&netr_info->server_challenge; 3735331Samw bzero(md4hash, 32); 3745331Samw 3755331Samw /* 3765331Samw * We should check (netr_info->flags & NETR_FLG_INIT) and use 3775331Samw * the appropriate password but it isn't working yet. So we 3785331Samw * always use the default one for now. 3795331Samw */ 3805772Sas200622 bzero(netr_info->password, sizeof (netr_info->password)); 3815772Sas200622 rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, 3825772Sas200622 (char *)netr_info->password, sizeof (netr_info->password)); 3835331Samw 3845772Sas200622 if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') { 3857052Samw return (SMBAUTH_FAILURE); 3865331Samw } 3875331Samw 3885772Sas200622 rc = smb_auth_ntlm_hash((char *)netr_info->password, md4hash); 3895331Samw 3905331Samw if (rc != SMBAUTH_SUCCESS) 3915331Samw return (SMBAUTH_FAILURE); 3925331Samw 3935331Samw data[0] = LE_IN32(&client_challenge[0]) + LE_IN32(&server_challenge[0]); 3945331Samw data[1] = LE_IN32(&client_challenge[1]) + LE_IN32(&server_challenge[1]); 3955521Sas200622 LE_OUT32(&le_data[0], data[0]); 3965521Sas200622 LE_OUT32(&le_data[1], data[1]); 3977619SJose.Borrego@Sun.COM rc = smb_auth_DES(buffer, 8, md4hash, NETR_DESKEY_LEN, 3987619SJose.Borrego@Sun.COM (unsigned char *)le_data, 8); 3995331Samw 4005331Samw if (rc != SMBAUTH_SUCCESS) 4015331Samw return (rc); 4025331Samw 4037619SJose.Borrego@Sun.COM netr_info->session_key.len = NETR_SESSKEY64_SZ; 4047619SJose.Borrego@Sun.COM rc = smb_auth_DES(netr_info->session_key.key, 4057619SJose.Borrego@Sun.COM netr_info->session_key.len, &md4hash[9], NETR_DESKEY_LEN, buffer, 4067619SJose.Borrego@Sun.COM 8); 4077619SJose.Borrego@Sun.COM 4085331Samw return (rc); 4095331Samw } 4105331Samw 4115331Samw /* 4125331Samw * netr_gen_credentials 4135331Samw * 4145331Samw * Generate a set of credentials from a challenge and a session key. 4155331Samw * The algorithm is a two stage hash. For the first hash, the 4165331Samw * timestamp is added to the challenge and the result is stored in a 4175331Samw * temporary buffer: 4185331Samw * 4195331Samw * input: challenge (including timestamp) 4205331Samw * key: session_key 4215331Samw * output: intermediate result 4225331Samw * 4235331Samw * For the second hash, the input is the result of the first hash and 4245331Samw * a strange partial key is used: 4255331Samw * 4265331Samw * input: result of first hash 4275331Samw * key: funny partial key 4285331Samw * output: credentiails 4295331Samw * 4305331Samw * The final output should be an encrypted set of credentials. 4315331Samw * 4325331Samw * FYI: smb_auth_DES(output, key, input) 4335331Samw * 4345331Samw * If any difficulties occur using the cryptographic framework, the 4355331Samw * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is 4365331Samw * returned. 4375331Samw */ 4385331Samw int 4395331Samw netr_gen_credentials(BYTE *session_key, netr_cred_t *challenge, 4405331Samw DWORD timestamp, netr_cred_t *out_cred) 4415331Samw { 4425331Samw unsigned char buffer[8]; 4435331Samw DWORD data[2]; 4445521Sas200622 DWORD le_data[2]; 4455331Samw DWORD *p; 4465331Samw int rc; 4475331Samw 4485331Samw p = (DWORD *)(uintptr_t)challenge; 4495521Sas200622 data[0] = LE_IN32(&p[0]) + timestamp; 4505521Sas200622 data[1] = LE_IN32(&p[1]); 4515521Sas200622 4525521Sas200622 LE_OUT32(&le_data[0], data[0]); 4535521Sas200622 LE_OUT32(&le_data[1], data[1]); 4545331Samw 4557052Samw if (smb_auth_DES(buffer, 8, session_key, NETR_DESKEY_LEN, 4565521Sas200622 (unsigned char *)le_data, 8) != SMBAUTH_SUCCESS) 4575331Samw return (SMBAUTH_FAILURE); 4585331Samw 4597052Samw rc = smb_auth_DES(out_cred->data, 8, &session_key[NETR_DESKEY_LEN], 4607052Samw NETR_DESKEY_LEN, buffer, 8); 4615331Samw 4625331Samw return (rc); 4635331Samw } 4645331Samw 4655331Samw /* 4665331Samw * netr_server_password_set 4675331Samw * 4685331Samw * Attempt to change the trust account password for this system. 4695331Samw * 4705331Samw * Note that this call may legitimately fail if the registry on the 4715331Samw * domain controller has been setup to deny attempts to change the 4725331Samw * trust account password. In this case we should just continue to 4735331Samw * use the original password. 4745331Samw * 4755331Samw * Possible status values: 4765331Samw * NT_STATUS_ACCESS_DENIED 4775331Samw */ 4785331Samw int 4795331Samw netr_server_password_set(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) 4805331Samw { 4815331Samw struct netr_PasswordSet arg; 4825331Samw int opnum; 4835331Samw BYTE new_password[NETR_OWF_PASSWORD_SZ]; 4847961SNatalie.Li@Sun.COM char account_name[NETBIOS_NAME_SZ * 2]; 4855331Samw 4865331Samw bzero(&arg, sizeof (struct netr_PasswordSet)); 4875331Samw opnum = NETR_OPNUM_ServerPasswordSet; 4885331Samw 4895331Samw (void) snprintf(account_name, sizeof (account_name), "%s$", 4905331Samw netr_info->hostname); 4915331Samw 4925331Samw arg.servername = (unsigned char *)netr_info->server; 4935331Samw arg.account_name = (unsigned char *)account_name; 4945331Samw arg.account_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE; 4955331Samw arg.hostname = (unsigned char *)netr_info->hostname; 4965331Samw 4975331Samw /* 4985331Samw * Set up the client side authenticator. 4995331Samw */ 5005331Samw if (netr_setup_authenticator(netr_info, &arg.auth, 0) != 5015331Samw SMBAUTH_SUCCESS) { 5025331Samw return (-1); 5035331Samw } 5045331Samw 5055331Samw /* 5065331Samw * Generate a new password from the old password. 5075331Samw */ 5087619SJose.Borrego@Sun.COM if (netr_gen_password(netr_info->session_key.key, 5095331Samw netr_info->password, new_password) == SMBAUTH_FAILURE) { 5105331Samw return (-1); 5115331Samw } 5125331Samw 5135331Samw (void) memcpy(&arg.uas_new_password, &new_password, 5145331Samw NETR_OWF_PASSWORD_SZ); 5155331Samw 5168334SJose.Borrego@Sun.COM if (ndr_rpc_call(netr_handle, opnum, &arg) != 0) 5178334SJose.Borrego@Sun.COM return (-1); 5188334SJose.Borrego@Sun.COM 5198334SJose.Borrego@Sun.COM if (arg.status != 0) { 5208334SJose.Borrego@Sun.COM ndr_rpc_status(netr_handle, opnum, arg.status); 5218334SJose.Borrego@Sun.COM ndr_rpc_release(netr_handle); 5225331Samw return (-1); 5235331Samw } 5245331Samw 5255331Samw /* 5265331Samw * Check the returned credentials. The server returns the new 5275331Samw * client credential rather than the new server credentiali, 5285331Samw * as documented elsewhere. 5295331Samw * 5305331Samw * Generate the new seed for the credential chain. Increment 5315331Samw * the timestamp and add it to the client challenge. Then we 5325331Samw * need to copy the challenge to the credential field in 5335331Samw * preparation for the next cycle. 5345331Samw */ 5355331Samw if (netr_validate_chain(netr_info, &arg.auth) == 0) { 5365331Samw /* 5375331Samw * Save the new password. 5385331Samw */ 5395331Samw (void) memcpy(netr_info->password, new_password, 5405331Samw NETR_OWF_PASSWORD_SZ); 5415331Samw } 5425331Samw 5438334SJose.Borrego@Sun.COM ndr_rpc_release(netr_handle); 5445331Samw return (0); 5455331Samw } 5465331Samw 5475331Samw /* 5485331Samw * netr_gen_password 5495331Samw * 5505331Samw * Generate a new pasword from the old password and the session key. 5515331Samw * The algorithm is a two stage hash. The session key is used in the 5525331Samw * first hash but only part of the session key is used in the second 5535331Samw * hash. 5545331Samw * 5555331Samw * If any difficulties occur using the cryptographic framework, the 5565331Samw * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is 5575331Samw * returned. 5585331Samw */ 5595331Samw static int 5605331Samw netr_gen_password(BYTE *session_key, BYTE *old_password, BYTE *new_password) 5615331Samw { 5625331Samw int rv; 5635331Samw 5647052Samw rv = smb_auth_DES(new_password, 8, session_key, NETR_DESKEY_LEN, 5657052Samw old_password, 8); 5665331Samw if (rv != SMBAUTH_SUCCESS) 5675331Samw return (rv); 5685331Samw 5697052Samw rv = smb_auth_DES(&new_password[8], 8, &session_key[NETR_DESKEY_LEN], 5707052Samw NETR_DESKEY_LEN, &old_password[8], 8); 5715331Samw return (rv); 5725331Samw } 573