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 /* 225772Sas200622 * Copyright 2008 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> 435521Sas200622 #include <smbsrv/libsmbrdr.h> 446432Sas200622 #include <smbsrv/libsmbns.h> 455331Samw #include <smbsrv/mlsvc_util.h> 465331Samw #include <smbsrv/ndl/netlogon.ndl> 475331Samw #include <smbsrv/ntstatus.h> 485331Samw #include <smbsrv/smbinfo.h> 495331Samw #include <smbsrv/mlsvc.h> 505331Samw #include <smbsrv/netrauth.h> 515331Samw 527052Samw #define NETR_SESSKEY_ZEROBUF_SZ 4 53*7619SJose.Borrego@Sun.COM /* The DES algorithm uses a 56-bit encryption key. */ 547052Samw #define NETR_DESKEY_LEN 7 557052Samw 565331Samw int netr_setup_authenticator(netr_info_t *, struct netr_authenticator *, 575331Samw struct netr_authenticator *); 585331Samw DWORD netr_validate_chain(netr_info_t *, struct netr_authenticator *); 595331Samw 605331Samw static int netr_server_req_challenge(mlsvc_handle_t *, netr_info_t *); 615331Samw static int netr_server_authenticate2(mlsvc_handle_t *, netr_info_t *); 625331Samw static int netr_gen_password(BYTE *, BYTE *, BYTE *); 635331Samw 645331Samw /* 655331Samw * Shared with netr_logon.c 665331Samw */ 675331Samw netr_info_t netr_global_info; 685331Samw 695331Samw /* 705331Samw * netlogon_auth 715331Samw * 725331Samw * This is the core of the NETLOGON authentication protocol. 735331Samw * Do the challenge response authentication. 745331Samw * 755331Samw * Prior to calling this function, an anonymous session to the NETLOGON 765331Samw * pipe on a domain controller(server) should have already been opened. 776139Sjb150015 * 786139Sjb150015 * Upon a successful NETLOGON credential chain establishment, the 796139Sjb150015 * netlogon sequence number will be set to match the kpasswd sequence 806139Sjb150015 * number. 816139Sjb150015 * 825331Samw */ 835331Samw DWORD 845331Samw netlogon_auth(char *server, mlsvc_handle_t *netr_handle, DWORD flags) 855331Samw { 865331Samw netr_info_t *netr_info; 875331Samw int rc; 885521Sas200622 DWORD leout_rc[2]; 895331Samw 905331Samw netr_info = &netr_global_info; 915331Samw bzero(netr_info, sizeof (netr_info_t)); 925331Samw 935331Samw netr_info->flags |= flags; 945331Samw 955331Samw rc = smb_getnetbiosname(netr_info->hostname, MLSVC_DOMAIN_NAME_MAX); 965331Samw if (rc != 0) 975331Samw return (NT_STATUS_UNSUCCESSFUL); 985331Samw 995331Samw (void) snprintf(netr_info->server, sizeof (netr_info->server), 1005331Samw "\\\\%s", server); 1015331Samw 1025521Sas200622 LE_OUT32(&leout_rc[0], random()); 1035521Sas200622 LE_OUT32(&leout_rc[1], random()); 1045521Sas200622 (void) memcpy(&netr_info->client_challenge, leout_rc, 1055331Samw sizeof (struct netr_credential)); 1065331Samw 1075331Samw if ((rc = netr_server_req_challenge(netr_handle, netr_info)) == 0) { 1085331Samw rc = netr_server_authenticate2(netr_handle, netr_info); 1096139Sjb150015 if (rc == 0) { 1106139Sjb150015 smb_update_netlogon_seqnum(); 1115331Samw netr_info->flags |= NETR_FLG_VALID; 1126139Sjb150015 1136139Sjb150015 } 1145331Samw } 1155331Samw 1166432Sas200622 /* 1176432Sas200622 * The NETLOGON credential chain establishment has unset 1186432Sas200622 * both ServerPrincipalName and dNSHostName attributes of the 1196432Sas200622 * workstation trust account. Those attributes will be updated 1206432Sas200622 * here to avoid any Kerberos authentication errors from happening. 1216432Sas200622 * 1226432Sas200622 * Later, when NT4 domain controller is supported, we need to 1236432Sas200622 * find a way to disable the following code. 1246432Sas200622 */ 1257052Samw if (smb_ads_update_attrs() == -1) 1266432Sas200622 syslog(LOG_DEBUG, "netlogon_auth: ServerPrincipalName" 1276432Sas200622 " and dNSHostName attributes might have been unset."); 1286432Sas200622 1295331Samw return ((rc) ? NT_STATUS_UNSUCCESSFUL : NT_STATUS_SUCCESS); 1305331Samw } 1315331Samw 1325331Samw /* 1335331Samw * netr_open 1345331Samw * 1355331Samw * Open an anonymous session to the NETLOGON pipe on a domain 1365331Samw * controller and bind to the NETR RPC interface. We store the 1375331Samw * remote server's native OS type - we may need it due to 1385331Samw * differences between versions of Windows. 1395331Samw */ 1405331Samw int 1415331Samw netr_open(char *server, char *domain, mlsvc_handle_t *netr_handle) 1425331Samw { 1435331Samw int fid; 1445331Samw int remote_os = 0; 1455331Samw int remote_lm = 0; 1465331Samw int server_pdc; 1475521Sas200622 char *user = smbrdr_ipc_get_user(); 1485331Samw 1495521Sas200622 if (mlsvc_logon(server, domain, user) != 0) 1505331Samw return (-1); 1515331Samw 1525521Sas200622 fid = mlsvc_open_pipe(server, domain, user, "\\NETLOGON"); 1535331Samw if (fid < 0) 1545331Samw return (-1); 1555331Samw 1565331Samw if (mlsvc_rpc_bind(netr_handle, fid, "NETR") < 0) { 1575331Samw (void) mlsvc_close_pipe(fid); 1585331Samw return (-1); 1595331Samw } 1605331Samw 1615331Samw (void) mlsvc_session_native_values(fid, &remote_os, &remote_lm, 1625331Samw &server_pdc); 1635331Samw netr_handle->context->server_os = remote_os; 1645331Samw netr_handle->context->server_pdc = server_pdc; 1655331Samw return (0); 1665331Samw } 1675331Samw 1685331Samw /* 1695331Samw * netr_close 1705331Samw * 1715331Samw * Close a NETLOGON pipe and free the RPC context. 1725331Samw */ 1735331Samw int 1745331Samw netr_close(mlsvc_handle_t *netr_handle) 1755331Samw { 1765331Samw (void) mlsvc_close_pipe(netr_handle->context->fid); 1775331Samw free(netr_handle->context); 1785331Samw return (0); 1795331Samw } 1805331Samw 1815331Samw /* 1825331Samw * netr_server_req_challenge 1835331Samw */ 1845331Samw static int 1855331Samw netr_server_req_challenge(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) 1865331Samw { 1875331Samw struct netr_ServerReqChallenge arg; 1885331Samw mlrpc_heapref_t heap; 1895331Samw int opnum; 1905331Samw int rc; 1915331Samw 1925331Samw bzero(&arg, sizeof (struct netr_ServerReqChallenge)); 1935331Samw opnum = NETR_OPNUM_ServerReqChallenge; 1945331Samw 1955331Samw arg.servername = (unsigned char *)netr_info->server; 1965331Samw arg.hostname = (unsigned char *)netr_info->hostname; 1975331Samw 1985331Samw (void) memcpy(&arg.client_challenge, &netr_info->client_challenge, 1995331Samw sizeof (struct netr_credential)); 2005331Samw 2015331Samw (void) mlsvc_rpc_init(&heap); 2025331Samw rc = mlsvc_rpc_call(netr_handle->context, opnum, &arg, &heap); 2035331Samw if (rc == 0) { 2045331Samw if (arg.status != 0) { 2055331Samw mlsvc_rpc_report_status(opnum, arg.status); 2065331Samw rc = -1; 2075331Samw } else { 2085331Samw (void) memcpy(&netr_info->server_challenge, 2095331Samw &arg.server_challenge, 2105331Samw sizeof (struct netr_credential)); 2115331Samw } 2125331Samw } 2135331Samw 2145331Samw mlsvc_rpc_free(netr_handle->context, &heap); 2155331Samw return (rc); 2165331Samw } 2175331Samw 2185331Samw /* 2195331Samw * netr_server_authenticate2 2205331Samw */ 2215331Samw static int 2225331Samw netr_server_authenticate2(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) 2235331Samw { 2245331Samw struct netr_ServerAuthenticate2 arg; 2255331Samw mlrpc_heapref_t heap; 2265331Samw int opnum; 2275331Samw int rc; 2285331Samw char account_name[MLSVC_DOMAIN_NAME_MAX * 2]; 2295331Samw 2305331Samw bzero(&arg, sizeof (struct netr_ServerAuthenticate2)); 2315331Samw opnum = NETR_OPNUM_ServerAuthenticate2; 2325331Samw 2335331Samw (void) snprintf(account_name, sizeof (account_name), "%s$", 2345331Samw netr_info->hostname); 2355331Samw 236*7619SJose.Borrego@Sun.COM smb_tracef("server=[%s] account_name=[%s] hostname=[%s]\n", 237*7619SJose.Borrego@Sun.COM netr_info->server, account_name, netr_info->hostname); 238*7619SJose.Borrego@Sun.COM 2395331Samw arg.servername = (unsigned char *)netr_info->server; 2405331Samw arg.account_name = (unsigned char *)account_name; 2415331Samw arg.account_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE; 2425331Samw arg.hostname = (unsigned char *)netr_info->hostname; 243*7619SJose.Borrego@Sun.COM arg.negotiate_flags = NETR_NEGOTIATE_BASE_FLAGS; 2445331Samw 245*7619SJose.Borrego@Sun.COM if (netr_handle->context->server_os != NATIVE_OS_WINNT) { 246*7619SJose.Borrego@Sun.COM arg.negotiate_flags |= NETR_NEGOTIATE_STRONGKEY_FLAG; 247*7619SJose.Borrego@Sun.COM if (netr_gen_skey128(netr_info) != SMBAUTH_SUCCESS) 248*7619SJose.Borrego@Sun.COM return (-1); 249*7619SJose.Borrego@Sun.COM } else { 250*7619SJose.Borrego@Sun.COM if (netr_gen_skey64(netr_info) != SMBAUTH_SUCCESS) 251*7619SJose.Borrego@Sun.COM return (-1); 252*7619SJose.Borrego@Sun.COM } 2535331Samw 254*7619SJose.Borrego@Sun.COM if (netr_gen_credentials(netr_info->session_key.key, 255*7619SJose.Borrego@Sun.COM &netr_info->client_challenge, 0, 2565331Samw &netr_info->client_credential) != SMBAUTH_SUCCESS) { 2575331Samw return (-1); 2585331Samw } 2595331Samw 260*7619SJose.Borrego@Sun.COM if (netr_gen_credentials(netr_info->session_key.key, 261*7619SJose.Borrego@Sun.COM &netr_info->server_challenge, 0, 2625331Samw &netr_info->server_credential) != SMBAUTH_SUCCESS) { 2635331Samw return (-1); 2645331Samw } 2655331Samw 2665331Samw (void) memcpy(&arg.client_credential, &netr_info->client_credential, 2675331Samw sizeof (struct netr_credential)); 2685331Samw 2695331Samw (void) mlsvc_rpc_init(&heap); 2705331Samw 2715331Samw rc = mlsvc_rpc_call(netr_handle->context, opnum, &arg, &heap); 2725331Samw if (rc == 0) { 2735331Samw if (arg.status != 0) { 2745331Samw mlsvc_rpc_report_status(opnum, arg.status); 2755331Samw rc = -1; 2765331Samw } else { 2775331Samw rc = memcmp(&netr_info->server_credential, 2785331Samw &arg.server_credential, 2795331Samw sizeof (struct netr_credential)); 2805331Samw } 2815331Samw } 2825331Samw 2835331Samw mlsvc_rpc_free(netr_handle->context, &heap); 2845331Samw return (rc); 2855331Samw } 2865331Samw 2875331Samw /* 288*7619SJose.Borrego@Sun.COM * netr_gen_skey128 2895331Samw * 290*7619SJose.Borrego@Sun.COM * Generate a 128-bit session key from the client and server challenges. 291*7619SJose.Borrego@Sun.COM * See "Session-Key Computation" section of MS-NRPC document. 2925331Samw */ 2937052Samw int 294*7619SJose.Borrego@Sun.COM netr_gen_skey128(netr_info_t *netr_info) 2957052Samw { 2967052Samw unsigned char ntlmhash[SMBAUTH_HASH_SZ]; 2977052Samw int rc = SMBAUTH_FAILURE; 2987052Samw CK_RV rv; 2997052Samw CK_MECHANISM mechanism; 3007052Samw CK_SESSION_HANDLE hSession; 3017052Samw CK_ULONG diglen = MD_DIGEST_LEN; 3027052Samw unsigned char md5digest[MD_DIGEST_LEN]; 3037052Samw unsigned char zerobuf[NETR_SESSKEY_ZEROBUF_SZ]; 3047052Samw 3057052Samw bzero(ntlmhash, SMBAUTH_HASH_SZ); 3067052Samw /* 3077052Samw * We should check (netr_info->flags & NETR_FLG_INIT) and use 3087052Samw * the appropriate password but it isn't working yet. So we 3097052Samw * always use the default one for now. 3107052Samw */ 3117052Samw bzero(netr_info->password, sizeof (netr_info->password)); 3127052Samw rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, 3137052Samw (char *)netr_info->password, sizeof (netr_info->password)); 3147052Samw 3157052Samw if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') { 3167052Samw return (SMBAUTH_FAILURE); 3177052Samw } 3187052Samw 3197052Samw rc = smb_auth_ntlm_hash((char *)netr_info->password, ntlmhash); 3207052Samw if (rc != SMBAUTH_SUCCESS) 3217052Samw return (SMBAUTH_FAILURE); 3227052Samw 3237052Samw bzero(zerobuf, NETR_SESSKEY_ZEROBUF_SZ); 3247052Samw 3257052Samw mechanism.mechanism = CKM_MD5; 3267052Samw mechanism.pParameter = 0; 3277052Samw mechanism.ulParameterLen = 0; 3287052Samw 3297052Samw rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession); 3307052Samw if (rv != CKR_OK) 3317052Samw return (SMBAUTH_FAILURE); 3327052Samw 3337052Samw rv = C_DigestInit(hSession, &mechanism); 3347052Samw if (rv != CKR_OK) 3357052Samw goto cleanup; 3367052Samw 3377052Samw rv = C_DigestUpdate(hSession, (CK_BYTE_PTR)zerobuf, 3387052Samw NETR_SESSKEY_ZEROBUF_SZ); 3397052Samw if (rv != CKR_OK) 3407052Samw goto cleanup; 3417052Samw 3427052Samw rv = C_DigestUpdate(hSession, 3437052Samw (CK_BYTE_PTR)netr_info->client_challenge.data, NETR_CRED_DATA_SZ); 3447052Samw if (rv != CKR_OK) 3457052Samw goto cleanup; 3467052Samw 3477052Samw rv = C_DigestUpdate(hSession, 3487052Samw (CK_BYTE_PTR)netr_info->server_challenge.data, NETR_CRED_DATA_SZ); 3497052Samw if (rv != CKR_OK) 3507052Samw goto cleanup; 3517052Samw 3527052Samw rv = C_DigestFinal(hSession, (CK_BYTE_PTR)md5digest, &diglen); 3537052Samw if (rv != CKR_OK) 3547052Samw goto cleanup; 3557052Samw 3567052Samw rc = smb_auth_hmac_md5(md5digest, diglen, ntlmhash, SMBAUTH_HASH_SZ, 357*7619SJose.Borrego@Sun.COM netr_info->session_key.key); 3587052Samw 359*7619SJose.Borrego@Sun.COM netr_info->session_key.len = NETR_SESSKEY128_SZ; 3607052Samw cleanup: 3617052Samw (void) C_CloseSession(hSession); 3627052Samw return (rc); 3637052Samw 3647052Samw } 365*7619SJose.Borrego@Sun.COM /* 366*7619SJose.Borrego@Sun.COM * netr_gen_skey64 367*7619SJose.Borrego@Sun.COM * 368*7619SJose.Borrego@Sun.COM * Generate a 64-bit session key from the client and server challenges. 369*7619SJose.Borrego@Sun.COM * See "Session-Key Computation" section of MS-NRPC document. 370*7619SJose.Borrego@Sun.COM * 371*7619SJose.Borrego@Sun.COM * The algorithm is a two stage hash. For the first hash, the input is 372*7619SJose.Borrego@Sun.COM * the combination of the client and server challenges, the key is 373*7619SJose.Borrego@Sun.COM * the first 7 bytes of the password. The initial password is formed 374*7619SJose.Borrego@Sun.COM * using the NT password hash on the local hostname in lower case. 375*7619SJose.Borrego@Sun.COM * The result is stored in a temporary buffer. 376*7619SJose.Borrego@Sun.COM * 377*7619SJose.Borrego@Sun.COM * input: challenge 378*7619SJose.Borrego@Sun.COM * key: passwd lower 7 bytes 379*7619SJose.Borrego@Sun.COM * output: intermediate result 380*7619SJose.Borrego@Sun.COM * 381*7619SJose.Borrego@Sun.COM * For the second hash, the input is the result of the first hash and 382*7619SJose.Borrego@Sun.COM * the key is the last 7 bytes of the password. 383*7619SJose.Borrego@Sun.COM * 384*7619SJose.Borrego@Sun.COM * input: result of first hash 385*7619SJose.Borrego@Sun.COM * key: passwd upper 7 bytes 386*7619SJose.Borrego@Sun.COM * output: session_key 387*7619SJose.Borrego@Sun.COM * 388*7619SJose.Borrego@Sun.COM * The final output should be the session key. 389*7619SJose.Borrego@Sun.COM * 390*7619SJose.Borrego@Sun.COM * FYI: smb_auth_DES(output, key, input) 391*7619SJose.Borrego@Sun.COM * 392*7619SJose.Borrego@Sun.COM * If any difficulties occur using the cryptographic framework, the 393*7619SJose.Borrego@Sun.COM * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is 394*7619SJose.Borrego@Sun.COM * returned. 395*7619SJose.Borrego@Sun.COM */ 3965331Samw int 397*7619SJose.Borrego@Sun.COM netr_gen_skey64(netr_info_t *netr_info) 3985331Samw { 3995331Samw unsigned char md4hash[32]; 4005331Samw unsigned char buffer[8]; 4015331Samw DWORD data[2]; 4025331Samw DWORD *client_challenge; 4035331Samw DWORD *server_challenge; 4045331Samw int rc; 4055521Sas200622 DWORD le_data[2]; 4065331Samw 4075331Samw client_challenge = (DWORD *)(uintptr_t)&netr_info->client_challenge; 4085331Samw server_challenge = (DWORD *)(uintptr_t)&netr_info->server_challenge; 4095331Samw bzero(md4hash, 32); 4105331Samw 4115331Samw /* 4125331Samw * We should check (netr_info->flags & NETR_FLG_INIT) and use 4135331Samw * the appropriate password but it isn't working yet. So we 4145331Samw * always use the default one for now. 4155331Samw */ 4165772Sas200622 bzero(netr_info->password, sizeof (netr_info->password)); 4175772Sas200622 rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, 4185772Sas200622 (char *)netr_info->password, sizeof (netr_info->password)); 4195331Samw 4205772Sas200622 if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') { 4217052Samw return (SMBAUTH_FAILURE); 4225331Samw } 4235331Samw 4245772Sas200622 rc = smb_auth_ntlm_hash((char *)netr_info->password, md4hash); 4255331Samw 4265331Samw if (rc != SMBAUTH_SUCCESS) 4275331Samw return (SMBAUTH_FAILURE); 4285331Samw 4295331Samw data[0] = LE_IN32(&client_challenge[0]) + LE_IN32(&server_challenge[0]); 4305331Samw data[1] = LE_IN32(&client_challenge[1]) + LE_IN32(&server_challenge[1]); 4315521Sas200622 LE_OUT32(&le_data[0], data[0]); 4325521Sas200622 LE_OUT32(&le_data[1], data[1]); 433*7619SJose.Borrego@Sun.COM rc = smb_auth_DES(buffer, 8, md4hash, NETR_DESKEY_LEN, 434*7619SJose.Borrego@Sun.COM (unsigned char *)le_data, 8); 4355331Samw 4365331Samw if (rc != SMBAUTH_SUCCESS) 4375331Samw return (rc); 4385331Samw 439*7619SJose.Borrego@Sun.COM netr_info->session_key.len = NETR_SESSKEY64_SZ; 440*7619SJose.Borrego@Sun.COM rc = smb_auth_DES(netr_info->session_key.key, 441*7619SJose.Borrego@Sun.COM netr_info->session_key.len, &md4hash[9], NETR_DESKEY_LEN, buffer, 442*7619SJose.Borrego@Sun.COM 8); 443*7619SJose.Borrego@Sun.COM 4445331Samw return (rc); 4455331Samw } 4465331Samw 4475331Samw /* 4485331Samw * netr_gen_credentials 4495331Samw * 4505331Samw * Generate a set of credentials from a challenge and a session key. 4515331Samw * The algorithm is a two stage hash. For the first hash, the 4525331Samw * timestamp is added to the challenge and the result is stored in a 4535331Samw * temporary buffer: 4545331Samw * 4555331Samw * input: challenge (including timestamp) 4565331Samw * key: session_key 4575331Samw * output: intermediate result 4585331Samw * 4595331Samw * For the second hash, the input is the result of the first hash and 4605331Samw * a strange partial key is used: 4615331Samw * 4625331Samw * input: result of first hash 4635331Samw * key: funny partial key 4645331Samw * output: credentiails 4655331Samw * 4665331Samw * The final output should be an encrypted set of credentials. 4675331Samw * 4685331Samw * FYI: smb_auth_DES(output, key, input) 4695331Samw * 4705331Samw * If any difficulties occur using the cryptographic framework, the 4715331Samw * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is 4725331Samw * returned. 4735331Samw */ 4745331Samw int 4755331Samw netr_gen_credentials(BYTE *session_key, netr_cred_t *challenge, 4765331Samw DWORD timestamp, netr_cred_t *out_cred) 4775331Samw { 4785331Samw unsigned char buffer[8]; 4795331Samw DWORD data[2]; 4805521Sas200622 DWORD le_data[2]; 4815331Samw DWORD *p; 4825331Samw int rc; 4835331Samw 4845331Samw p = (DWORD *)(uintptr_t)challenge; 4855521Sas200622 data[0] = LE_IN32(&p[0]) + timestamp; 4865521Sas200622 data[1] = LE_IN32(&p[1]); 4875521Sas200622 4885521Sas200622 LE_OUT32(&le_data[0], data[0]); 4895521Sas200622 LE_OUT32(&le_data[1], data[1]); 4905331Samw 4917052Samw if (smb_auth_DES(buffer, 8, session_key, NETR_DESKEY_LEN, 4925521Sas200622 (unsigned char *)le_data, 8) != SMBAUTH_SUCCESS) 4935331Samw return (SMBAUTH_FAILURE); 4945331Samw 4957052Samw rc = smb_auth_DES(out_cred->data, 8, &session_key[NETR_DESKEY_LEN], 4967052Samw NETR_DESKEY_LEN, buffer, 8); 4975331Samw 4985331Samw return (rc); 4995331Samw } 5005331Samw 5015331Samw /* 5025331Samw * netr_server_password_set 5035331Samw * 5045331Samw * Attempt to change the trust account password for this system. 5055331Samw * 5065331Samw * Note that this call may legitimately fail if the registry on the 5075331Samw * domain controller has been setup to deny attempts to change the 5085331Samw * trust account password. In this case we should just continue to 5095331Samw * use the original password. 5105331Samw * 5115331Samw * Possible status values: 5125331Samw * NT_STATUS_ACCESS_DENIED 5135331Samw */ 5145331Samw int 5155331Samw netr_server_password_set(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) 5165331Samw { 5175331Samw struct netr_PasswordSet arg; 5185331Samw mlrpc_heapref_t heap; 5195331Samw int opnum; 5205331Samw int rc; 5215331Samw BYTE new_password[NETR_OWF_PASSWORD_SZ]; 5225331Samw char account_name[MLSVC_DOMAIN_NAME_MAX * 2]; 5235331Samw 5245331Samw bzero(&arg, sizeof (struct netr_PasswordSet)); 5255331Samw opnum = NETR_OPNUM_ServerPasswordSet; 5265331Samw 5275331Samw (void) snprintf(account_name, sizeof (account_name), "%s$", 5285331Samw netr_info->hostname); 5295331Samw 5305331Samw arg.servername = (unsigned char *)netr_info->server; 5315331Samw arg.account_name = (unsigned char *)account_name; 5325331Samw arg.account_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE; 5335331Samw arg.hostname = (unsigned char *)netr_info->hostname; 5345331Samw 5355331Samw /* 5365331Samw * Set up the client side authenticator. 5375331Samw */ 5385331Samw if (netr_setup_authenticator(netr_info, &arg.auth, 0) != 5395331Samw SMBAUTH_SUCCESS) { 5405331Samw return (-1); 5415331Samw } 5425331Samw 5435331Samw /* 5445331Samw * Generate a new password from the old password. 5455331Samw */ 546*7619SJose.Borrego@Sun.COM if (netr_gen_password(netr_info->session_key.key, 5475331Samw netr_info->password, new_password) == SMBAUTH_FAILURE) { 5485331Samw return (-1); 5495331Samw } 5505331Samw 5515331Samw (void) memcpy(&arg.uas_new_password, &new_password, 5525331Samw NETR_OWF_PASSWORD_SZ); 5535331Samw 5545331Samw (void) mlsvc_rpc_init(&heap); 5555331Samw rc = mlsvc_rpc_call(netr_handle->context, opnum, &arg, &heap); 5565331Samw if ((rc != 0) || (arg.status != 0)) { 5575331Samw mlsvc_rpc_report_status(opnum, arg.status); 5585331Samw mlsvc_rpc_free(netr_handle->context, &heap); 5595331Samw return (-1); 5605331Samw } 5615331Samw 5625331Samw /* 5635331Samw * Check the returned credentials. The server returns the new 5645331Samw * client credential rather than the new server credentiali, 5655331Samw * as documented elsewhere. 5665331Samw * 5675331Samw * Generate the new seed for the credential chain. Increment 5685331Samw * the timestamp and add it to the client challenge. Then we 5695331Samw * need to copy the challenge to the credential field in 5705331Samw * preparation for the next cycle. 5715331Samw */ 5725331Samw if (netr_validate_chain(netr_info, &arg.auth) == 0) { 5735331Samw /* 5745331Samw * Save the new password. 5755331Samw */ 5765331Samw (void) memcpy(netr_info->password, new_password, 5775331Samw NETR_OWF_PASSWORD_SZ); 5785331Samw } 5795331Samw 5805331Samw mlsvc_rpc_free(netr_handle->context, &heap); 5815331Samw return (0); 5825331Samw } 5835331Samw 5845331Samw /* 5855331Samw * netr_gen_password 5865331Samw * 5875331Samw * Generate a new pasword from the old password and the session key. 5885331Samw * The algorithm is a two stage hash. The session key is used in the 5895331Samw * first hash but only part of the session key is used in the second 5905331Samw * hash. 5915331Samw * 5925331Samw * If any difficulties occur using the cryptographic framework, the 5935331Samw * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is 5945331Samw * returned. 5955331Samw */ 5965331Samw static int 5975331Samw netr_gen_password(BYTE *session_key, BYTE *old_password, BYTE *new_password) 5985331Samw { 5995331Samw int rv; 6005331Samw 6017052Samw rv = smb_auth_DES(new_password, 8, session_key, NETR_DESKEY_LEN, 6027052Samw old_password, 8); 6035331Samw if (rv != SMBAUTH_SUCCESS) 6045331Samw return (rv); 6055331Samw 6067052Samw rv = smb_auth_DES(&new_password[8], 8, &session_key[NETR_DESKEY_LEN], 6077052Samw NETR_DESKEY_LEN, &old_password[8], 8); 6085331Samw return (rv); 6095331Samw } 610