1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21148c5f43SAlan Wright 22da6c28aaSamw /* 23148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24*b3700b07SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 25da6c28aaSamw */ 26da6c28aaSamw 27da6c28aaSamw /* 28da6c28aaSamw * NETR challenge/response client functions. 29da6c28aaSamw * 30da6c28aaSamw * NT_STATUS_INVALID_PARAMETER 31da6c28aaSamw * NT_STATUS_NO_TRUST_SAM_ACCOUNT 32da6c28aaSamw * NT_STATUS_ACCESS_DENIED 33da6c28aaSamw */ 34da6c28aaSamw 35da6c28aaSamw #include <stdio.h> 36da6c28aaSamw #include <stdlib.h> 37da6c28aaSamw #include <strings.h> 38da6c28aaSamw #include <unistd.h> 39da6c28aaSamw #include <ctype.h> 403db3f65cSamw #include <security/cryptoki.h> 413db3f65cSamw #include <security/pkcs11.h> 42da6c28aaSamw 43da6c28aaSamw #include <smbsrv/libsmb.h> 446537f381Sas200622 #include <smbsrv/libsmbns.h> 458d7e4166Sjose borrego #include <smbsrv/libmlsvc.h> 46da6c28aaSamw #include <smbsrv/ndl/netlogon.ndl> 47da6c28aaSamw #include <smbsrv/smbinfo.h> 48da6c28aaSamw #include <smbsrv/netrauth.h> 49da6c28aaSamw 503db3f65cSamw #define NETR_SESSKEY_ZEROBUF_SZ 4 512c1b14e5Sjose borrego /* The DES algorithm uses a 56-bit encryption key. */ 523db3f65cSamw #define NETR_DESKEY_LEN 7 533db3f65cSamw 54da6c28aaSamw int netr_setup_authenticator(netr_info_t *, struct netr_authenticator *, 55da6c28aaSamw struct netr_authenticator *); 56da6c28aaSamw DWORD netr_validate_chain(netr_info_t *, struct netr_authenticator *); 57da6c28aaSamw 58da6c28aaSamw static int netr_server_req_challenge(mlsvc_handle_t *, netr_info_t *); 59da6c28aaSamw static int netr_server_authenticate2(mlsvc_handle_t *, netr_info_t *); 60da6c28aaSamw static int netr_gen_password(BYTE *, BYTE *, BYTE *); 61da6c28aaSamw 62da6c28aaSamw /* 63da6c28aaSamw * Shared with netr_logon.c 64da6c28aaSamw */ 65da6c28aaSamw netr_info_t netr_global_info; 66da6c28aaSamw 67da6c28aaSamw /* 68da6c28aaSamw * netlogon_auth 69da6c28aaSamw * 70da6c28aaSamw * This is the core of the NETLOGON authentication protocol. 71da6c28aaSamw * Do the challenge response authentication. 72da6c28aaSamw * 73da6c28aaSamw * Prior to calling this function, an anonymous session to the NETLOGON 74da6c28aaSamw * pipe on a domain controller(server) should have already been opened. 75faa1795aSjb150015 * 76faa1795aSjb150015 * Upon a successful NETLOGON credential chain establishment, the 77faa1795aSjb150015 * netlogon sequence number will be set to match the kpasswd sequence 78faa1795aSjb150015 * number. 79faa1795aSjb150015 * 80da6c28aaSamw */ 81da6c28aaSamw DWORD 82da6c28aaSamw netlogon_auth(char *server, mlsvc_handle_t *netr_handle, DWORD flags) 83da6c28aaSamw { 84da6c28aaSamw netr_info_t *netr_info; 85da6c28aaSamw int rc; 8655bf511dSas200622 DWORD leout_rc[2]; 87da6c28aaSamw 88da6c28aaSamw netr_info = &netr_global_info; 89da6c28aaSamw bzero(netr_info, sizeof (netr_info_t)); 90da6c28aaSamw 91da6c28aaSamw netr_info->flags |= flags; 92da6c28aaSamw 93b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = smb_getnetbiosname(netr_info->hostname, NETBIOS_NAME_SZ); 94da6c28aaSamw if (rc != 0) 95da6c28aaSamw return (NT_STATUS_UNSUCCESSFUL); 96da6c28aaSamw 97*b3700b07SGordon Ross /* server is our DC. Note: normally an FQDN. */ 98da6c28aaSamw (void) snprintf(netr_info->server, sizeof (netr_info->server), 99da6c28aaSamw "\\\\%s", server); 100da6c28aaSamw 10155bf511dSas200622 LE_OUT32(&leout_rc[0], random()); 10255bf511dSas200622 LE_OUT32(&leout_rc[1], random()); 10355bf511dSas200622 (void) memcpy(&netr_info->client_challenge, leout_rc, 104da6c28aaSamw sizeof (struct netr_credential)); 105da6c28aaSamw 106da6c28aaSamw if ((rc = netr_server_req_challenge(netr_handle, netr_info)) == 0) { 107da6c28aaSamw rc = netr_server_authenticate2(netr_handle, netr_info); 108faa1795aSjb150015 if (rc == 0) { 1091ed6b69aSGordon Ross /* 1101ed6b69aSGordon Ross * TODO: (later) When joining a domain using a 1111ed6b69aSGordon Ross * pre-created machine account, should do: 1121ed6b69aSGordon Ross * netr_server_password_set(&netr_handle, netr_info); 1131ed6b69aSGordon Ross * Nexenta issue 11960 1141ed6b69aSGordon Ross */ 115faa1795aSjb150015 smb_update_netlogon_seqnum(); 116da6c28aaSamw netr_info->flags |= NETR_FLG_VALID; 117faa1795aSjb150015 118faa1795aSjb150015 } 119da6c28aaSamw } 120da6c28aaSamw 121da6c28aaSamw return ((rc) ? NT_STATUS_UNSUCCESSFUL : NT_STATUS_SUCCESS); 122da6c28aaSamw } 123da6c28aaSamw 124da6c28aaSamw /* 125da6c28aaSamw * netr_open 126da6c28aaSamw * 1271fcced4cSJordan Brown * Open an anonymous session to the NETLOGON pipe on a domain controller 1281fcced4cSJordan Brown * and bind to the NETR RPC interface. 1291fcced4cSJordan Brown * 1301fcced4cSJordan Brown * We store the remote server information, which is used to drive Windows 1311fcced4cSJordan Brown * version specific behavior. 132*b3700b07SGordon Ross * 133*b3700b07SGordon Ross * Returns 0 or NT status 134da6c28aaSamw */ 135*b3700b07SGordon Ross DWORD 136da6c28aaSamw netr_open(char *server, char *domain, mlsvc_handle_t *netr_handle) 137da6c28aaSamw { 138a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN]; 139*b3700b07SGordon Ross DWORD status; 140da6c28aaSamw 141a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); 1421fcced4cSJordan Brown 143*b3700b07SGordon Ross status = ndr_rpc_bind(netr_handle, server, domain, user, "NETR"); 144da6c28aaSamw 145*b3700b07SGordon Ross return (status); 146da6c28aaSamw } 147da6c28aaSamw 148da6c28aaSamw /* 149da6c28aaSamw * netr_close 150da6c28aaSamw * 151da6c28aaSamw * Close a NETLOGON pipe and free the RPC context. 152da6c28aaSamw */ 153da6c28aaSamw int 154da6c28aaSamw netr_close(mlsvc_handle_t *netr_handle) 155da6c28aaSamw { 1568d7e4166Sjose borrego ndr_rpc_unbind(netr_handle); 157da6c28aaSamw return (0); 158da6c28aaSamw } 159da6c28aaSamw 160da6c28aaSamw /* 161da6c28aaSamw * netr_server_req_challenge 162da6c28aaSamw */ 163da6c28aaSamw static int 164da6c28aaSamw netr_server_req_challenge(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) 165da6c28aaSamw { 166da6c28aaSamw struct netr_ServerReqChallenge arg; 167da6c28aaSamw int opnum; 168da6c28aaSamw 169da6c28aaSamw bzero(&arg, sizeof (struct netr_ServerReqChallenge)); 170da6c28aaSamw opnum = NETR_OPNUM_ServerReqChallenge; 171da6c28aaSamw 172da6c28aaSamw arg.servername = (unsigned char *)netr_info->server; 173da6c28aaSamw arg.hostname = (unsigned char *)netr_info->hostname; 174da6c28aaSamw 175da6c28aaSamw (void) memcpy(&arg.client_challenge, &netr_info->client_challenge, 176da6c28aaSamw sizeof (struct netr_credential)); 177da6c28aaSamw 1788d7e4166Sjose borrego if (ndr_rpc_call(netr_handle, opnum, &arg) != 0) 1798d7e4166Sjose borrego return (-1); 1808d7e4166Sjose borrego 181da6c28aaSamw if (arg.status != 0) { 1828d7e4166Sjose borrego ndr_rpc_status(netr_handle, opnum, arg.status); 1838d7e4166Sjose borrego ndr_rpc_release(netr_handle); 1848d7e4166Sjose borrego return (-1); 185da6c28aaSamw } 186da6c28aaSamw 1878d7e4166Sjose borrego (void) memcpy(&netr_info->server_challenge, &arg.server_challenge, 1888d7e4166Sjose borrego sizeof (struct netr_credential)); 1898d7e4166Sjose borrego 1908d7e4166Sjose borrego ndr_rpc_release(netr_handle); 1918d7e4166Sjose borrego return (0); 192da6c28aaSamw } 193da6c28aaSamw 194da6c28aaSamw /* 195da6c28aaSamw * netr_server_authenticate2 196da6c28aaSamw */ 197da6c28aaSamw static int 198da6c28aaSamw netr_server_authenticate2(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) 199da6c28aaSamw { 200da6c28aaSamw struct netr_ServerAuthenticate2 arg; 201*b3700b07SGordon Ross /* sizeof netr_info->hostname, + 1 for the '$' */ 202*b3700b07SGordon Ross char account_name[(NETBIOS_NAME_SZ * 2) + 1]; 203da6c28aaSamw int opnum; 204da6c28aaSamw int rc; 205da6c28aaSamw 206da6c28aaSamw bzero(&arg, sizeof (struct netr_ServerAuthenticate2)); 207da6c28aaSamw opnum = NETR_OPNUM_ServerAuthenticate2; 208da6c28aaSamw 209da6c28aaSamw (void) snprintf(account_name, sizeof (account_name), "%s$", 210da6c28aaSamw netr_info->hostname); 211da6c28aaSamw 2122c1b14e5Sjose borrego smb_tracef("server=[%s] account_name=[%s] hostname=[%s]\n", 2132c1b14e5Sjose borrego netr_info->server, account_name, netr_info->hostname); 2142c1b14e5Sjose borrego 215da6c28aaSamw arg.servername = (unsigned char *)netr_info->server; 216da6c28aaSamw arg.account_name = (unsigned char *)account_name; 217da6c28aaSamw arg.account_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE; 218da6c28aaSamw arg.hostname = (unsigned char *)netr_info->hostname; 2192c1b14e5Sjose borrego arg.negotiate_flags = NETR_NEGOTIATE_BASE_FLAGS; 220da6c28aaSamw 221a0aa776eSAlan Wright if (ndr_rpc_server_os(netr_handle) == NATIVE_OS_WIN2000) { 2222c1b14e5Sjose borrego arg.negotiate_flags |= NETR_NEGOTIATE_STRONGKEY_FLAG; 2232c1b14e5Sjose borrego if (netr_gen_skey128(netr_info) != SMBAUTH_SUCCESS) 224da6c28aaSamw return (-1); 2252c1b14e5Sjose borrego } else { 2262c1b14e5Sjose borrego if (netr_gen_skey64(netr_info) != SMBAUTH_SUCCESS) 2272c1b14e5Sjose borrego return (-1); 2282c1b14e5Sjose borrego } 229da6c28aaSamw 2302c1b14e5Sjose borrego if (netr_gen_credentials(netr_info->session_key.key, 2312c1b14e5Sjose borrego &netr_info->client_challenge, 0, 232da6c28aaSamw &netr_info->client_credential) != SMBAUTH_SUCCESS) { 233da6c28aaSamw return (-1); 234da6c28aaSamw } 235da6c28aaSamw 2362c1b14e5Sjose borrego if (netr_gen_credentials(netr_info->session_key.key, 2372c1b14e5Sjose borrego &netr_info->server_challenge, 0, 238da6c28aaSamw &netr_info->server_credential) != SMBAUTH_SUCCESS) { 239da6c28aaSamw return (-1); 240da6c28aaSamw } 241da6c28aaSamw 242da6c28aaSamw (void) memcpy(&arg.client_credential, &netr_info->client_credential, 243da6c28aaSamw sizeof (struct netr_credential)); 244da6c28aaSamw 2458d7e4166Sjose borrego if (ndr_rpc_call(netr_handle, opnum, &arg) != 0) 2468d7e4166Sjose borrego return (-1); 247da6c28aaSamw 248da6c28aaSamw if (arg.status != 0) { 2498d7e4166Sjose borrego ndr_rpc_status(netr_handle, opnum, arg.status); 2508d7e4166Sjose borrego ndr_rpc_release(netr_handle); 2518d7e4166Sjose borrego return (-1); 252da6c28aaSamw } 253da6c28aaSamw 2548d7e4166Sjose borrego rc = memcmp(&netr_info->server_credential, &arg.server_credential, 2558d7e4166Sjose borrego sizeof (struct netr_credential)); 2568d7e4166Sjose borrego 2578d7e4166Sjose borrego ndr_rpc_release(netr_handle); 258da6c28aaSamw return (rc); 259da6c28aaSamw } 260da6c28aaSamw 261da6c28aaSamw /* 2622c1b14e5Sjose borrego * netr_gen_skey128 263da6c28aaSamw * 2642c1b14e5Sjose borrego * Generate a 128-bit session key from the client and server challenges. 2652c1b14e5Sjose borrego * See "Session-Key Computation" section of MS-NRPC document. 266da6c28aaSamw */ 2673db3f65cSamw int 2682c1b14e5Sjose borrego netr_gen_skey128(netr_info_t *netr_info) 2693db3f65cSamw { 2703db3f65cSamw unsigned char ntlmhash[SMBAUTH_HASH_SZ]; 2713db3f65cSamw int rc = SMBAUTH_FAILURE; 2723db3f65cSamw CK_RV rv; 2733db3f65cSamw CK_MECHANISM mechanism; 2743db3f65cSamw CK_SESSION_HANDLE hSession; 2753db3f65cSamw CK_ULONG diglen = MD_DIGEST_LEN; 2763db3f65cSamw unsigned char md5digest[MD_DIGEST_LEN]; 2773db3f65cSamw unsigned char zerobuf[NETR_SESSKEY_ZEROBUF_SZ]; 2783db3f65cSamw 2793db3f65cSamw bzero(ntlmhash, SMBAUTH_HASH_SZ); 2803db3f65cSamw /* 2813db3f65cSamw * We should check (netr_info->flags & NETR_FLG_INIT) and use 2823db3f65cSamw * the appropriate password but it isn't working yet. So we 2833db3f65cSamw * always use the default one for now. 2843db3f65cSamw */ 2853db3f65cSamw bzero(netr_info->password, sizeof (netr_info->password)); 2863db3f65cSamw rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, 2873db3f65cSamw (char *)netr_info->password, sizeof (netr_info->password)); 2883db3f65cSamw 2893db3f65cSamw if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') { 2903db3f65cSamw return (SMBAUTH_FAILURE); 2913db3f65cSamw } 2923db3f65cSamw 2933db3f65cSamw rc = smb_auth_ntlm_hash((char *)netr_info->password, ntlmhash); 2943db3f65cSamw if (rc != SMBAUTH_SUCCESS) 2953db3f65cSamw return (SMBAUTH_FAILURE); 2963db3f65cSamw 2973db3f65cSamw bzero(zerobuf, NETR_SESSKEY_ZEROBUF_SZ); 2983db3f65cSamw 2993db3f65cSamw mechanism.mechanism = CKM_MD5; 3003db3f65cSamw mechanism.pParameter = 0; 3013db3f65cSamw mechanism.ulParameterLen = 0; 3023db3f65cSamw 3033db3f65cSamw rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession); 3043db3f65cSamw if (rv != CKR_OK) 3053db3f65cSamw return (SMBAUTH_FAILURE); 3063db3f65cSamw 3073db3f65cSamw rv = C_DigestInit(hSession, &mechanism); 3083db3f65cSamw if (rv != CKR_OK) 3093db3f65cSamw goto cleanup; 3103db3f65cSamw 3113db3f65cSamw rv = C_DigestUpdate(hSession, (CK_BYTE_PTR)zerobuf, 3123db3f65cSamw NETR_SESSKEY_ZEROBUF_SZ); 3133db3f65cSamw if (rv != CKR_OK) 3143db3f65cSamw goto cleanup; 3153db3f65cSamw 3163db3f65cSamw rv = C_DigestUpdate(hSession, 3173db3f65cSamw (CK_BYTE_PTR)netr_info->client_challenge.data, NETR_CRED_DATA_SZ); 3183db3f65cSamw if (rv != CKR_OK) 3193db3f65cSamw goto cleanup; 3203db3f65cSamw 3213db3f65cSamw rv = C_DigestUpdate(hSession, 3223db3f65cSamw (CK_BYTE_PTR)netr_info->server_challenge.data, NETR_CRED_DATA_SZ); 3233db3f65cSamw if (rv != CKR_OK) 3243db3f65cSamw goto cleanup; 3253db3f65cSamw 3263db3f65cSamw rv = C_DigestFinal(hSession, (CK_BYTE_PTR)md5digest, &diglen); 3273db3f65cSamw if (rv != CKR_OK) 3283db3f65cSamw goto cleanup; 3293db3f65cSamw 3303db3f65cSamw rc = smb_auth_hmac_md5(md5digest, diglen, ntlmhash, SMBAUTH_HASH_SZ, 3312c1b14e5Sjose borrego netr_info->session_key.key); 3323db3f65cSamw 3332c1b14e5Sjose borrego netr_info->session_key.len = NETR_SESSKEY128_SZ; 3343db3f65cSamw cleanup: 3353db3f65cSamw (void) C_CloseSession(hSession); 3363db3f65cSamw return (rc); 3373db3f65cSamw 3383db3f65cSamw } 3392c1b14e5Sjose borrego /* 3402c1b14e5Sjose borrego * netr_gen_skey64 3412c1b14e5Sjose borrego * 3422c1b14e5Sjose borrego * Generate a 64-bit session key from the client and server challenges. 3432c1b14e5Sjose borrego * See "Session-Key Computation" section of MS-NRPC document. 3442c1b14e5Sjose borrego * 3452c1b14e5Sjose borrego * The algorithm is a two stage hash. For the first hash, the input is 3462c1b14e5Sjose borrego * the combination of the client and server challenges, the key is 3472c1b14e5Sjose borrego * the first 7 bytes of the password. The initial password is formed 3482c1b14e5Sjose borrego * using the NT password hash on the local hostname in lower case. 3492c1b14e5Sjose borrego * The result is stored in a temporary buffer. 3502c1b14e5Sjose borrego * 3512c1b14e5Sjose borrego * input: challenge 3522c1b14e5Sjose borrego * key: passwd lower 7 bytes 3532c1b14e5Sjose borrego * output: intermediate result 3542c1b14e5Sjose borrego * 3552c1b14e5Sjose borrego * For the second hash, the input is the result of the first hash and 3562c1b14e5Sjose borrego * the key is the last 7 bytes of the password. 3572c1b14e5Sjose borrego * 3582c1b14e5Sjose borrego * input: result of first hash 3592c1b14e5Sjose borrego * key: passwd upper 7 bytes 3602c1b14e5Sjose borrego * output: session_key 3612c1b14e5Sjose borrego * 3622c1b14e5Sjose borrego * The final output should be the session key. 3632c1b14e5Sjose borrego * 3642c1b14e5Sjose borrego * FYI: smb_auth_DES(output, key, input) 3652c1b14e5Sjose borrego * 3662c1b14e5Sjose borrego * If any difficulties occur using the cryptographic framework, the 3672c1b14e5Sjose borrego * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is 3682c1b14e5Sjose borrego * returned. 3692c1b14e5Sjose borrego */ 370da6c28aaSamw int 3712c1b14e5Sjose borrego netr_gen_skey64(netr_info_t *netr_info) 372da6c28aaSamw { 373da6c28aaSamw unsigned char md4hash[32]; 374da6c28aaSamw unsigned char buffer[8]; 375da6c28aaSamw DWORD data[2]; 376da6c28aaSamw DWORD *client_challenge; 377da6c28aaSamw DWORD *server_challenge; 378da6c28aaSamw int rc; 37955bf511dSas200622 DWORD le_data[2]; 380da6c28aaSamw 381da6c28aaSamw client_challenge = (DWORD *)(uintptr_t)&netr_info->client_challenge; 382da6c28aaSamw server_challenge = (DWORD *)(uintptr_t)&netr_info->server_challenge; 383da6c28aaSamw bzero(md4hash, 32); 384da6c28aaSamw 385da6c28aaSamw /* 386da6c28aaSamw * We should check (netr_info->flags & NETR_FLG_INIT) and use 387da6c28aaSamw * the appropriate password but it isn't working yet. So we 388da6c28aaSamw * always use the default one for now. 389da6c28aaSamw */ 390dc20a302Sas200622 bzero(netr_info->password, sizeof (netr_info->password)); 391dc20a302Sas200622 rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, 392dc20a302Sas200622 (char *)netr_info->password, sizeof (netr_info->password)); 393da6c28aaSamw 394dc20a302Sas200622 if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') { 3953db3f65cSamw return (SMBAUTH_FAILURE); 396da6c28aaSamw } 397da6c28aaSamw 398dc20a302Sas200622 rc = smb_auth_ntlm_hash((char *)netr_info->password, md4hash); 399da6c28aaSamw 400da6c28aaSamw if (rc != SMBAUTH_SUCCESS) 401da6c28aaSamw return (SMBAUTH_FAILURE); 402da6c28aaSamw 403da6c28aaSamw data[0] = LE_IN32(&client_challenge[0]) + LE_IN32(&server_challenge[0]); 404da6c28aaSamw data[1] = LE_IN32(&client_challenge[1]) + LE_IN32(&server_challenge[1]); 40555bf511dSas200622 LE_OUT32(&le_data[0], data[0]); 40655bf511dSas200622 LE_OUT32(&le_data[1], data[1]); 4072c1b14e5Sjose borrego rc = smb_auth_DES(buffer, 8, md4hash, NETR_DESKEY_LEN, 4082c1b14e5Sjose borrego (unsigned char *)le_data, 8); 409da6c28aaSamw 410da6c28aaSamw if (rc != SMBAUTH_SUCCESS) 411da6c28aaSamw return (rc); 412da6c28aaSamw 4132c1b14e5Sjose borrego netr_info->session_key.len = NETR_SESSKEY64_SZ; 4142c1b14e5Sjose borrego rc = smb_auth_DES(netr_info->session_key.key, 4152c1b14e5Sjose borrego netr_info->session_key.len, &md4hash[9], NETR_DESKEY_LEN, buffer, 4162c1b14e5Sjose borrego 8); 4172c1b14e5Sjose borrego 418da6c28aaSamw return (rc); 419da6c28aaSamw } 420da6c28aaSamw 421da6c28aaSamw /* 422da6c28aaSamw * netr_gen_credentials 423da6c28aaSamw * 424da6c28aaSamw * Generate a set of credentials from a challenge and a session key. 425da6c28aaSamw * The algorithm is a two stage hash. For the first hash, the 426da6c28aaSamw * timestamp is added to the challenge and the result is stored in a 427da6c28aaSamw * temporary buffer: 428da6c28aaSamw * 429da6c28aaSamw * input: challenge (including timestamp) 430da6c28aaSamw * key: session_key 431da6c28aaSamw * output: intermediate result 432da6c28aaSamw * 433da6c28aaSamw * For the second hash, the input is the result of the first hash and 434da6c28aaSamw * a strange partial key is used: 435da6c28aaSamw * 436da6c28aaSamw * input: result of first hash 437da6c28aaSamw * key: funny partial key 438da6c28aaSamw * output: credentiails 439da6c28aaSamw * 440da6c28aaSamw * The final output should be an encrypted set of credentials. 441da6c28aaSamw * 442da6c28aaSamw * FYI: smb_auth_DES(output, key, input) 443da6c28aaSamw * 444da6c28aaSamw * If any difficulties occur using the cryptographic framework, the 445da6c28aaSamw * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is 446da6c28aaSamw * returned. 447da6c28aaSamw */ 448da6c28aaSamw int 449da6c28aaSamw netr_gen_credentials(BYTE *session_key, netr_cred_t *challenge, 450da6c28aaSamw DWORD timestamp, netr_cred_t *out_cred) 451da6c28aaSamw { 452da6c28aaSamw unsigned char buffer[8]; 453da6c28aaSamw DWORD data[2]; 45455bf511dSas200622 DWORD le_data[2]; 455da6c28aaSamw DWORD *p; 456da6c28aaSamw int rc; 457da6c28aaSamw 458da6c28aaSamw p = (DWORD *)(uintptr_t)challenge; 45955bf511dSas200622 data[0] = LE_IN32(&p[0]) + timestamp; 46055bf511dSas200622 data[1] = LE_IN32(&p[1]); 46155bf511dSas200622 46255bf511dSas200622 LE_OUT32(&le_data[0], data[0]); 46355bf511dSas200622 LE_OUT32(&le_data[1], data[1]); 464da6c28aaSamw 4653db3f65cSamw if (smb_auth_DES(buffer, 8, session_key, NETR_DESKEY_LEN, 46655bf511dSas200622 (unsigned char *)le_data, 8) != SMBAUTH_SUCCESS) 467da6c28aaSamw return (SMBAUTH_FAILURE); 468da6c28aaSamw 4693db3f65cSamw rc = smb_auth_DES(out_cred->data, 8, &session_key[NETR_DESKEY_LEN], 4703db3f65cSamw NETR_DESKEY_LEN, buffer, 8); 471da6c28aaSamw 472da6c28aaSamw return (rc); 473da6c28aaSamw } 474da6c28aaSamw 475da6c28aaSamw /* 476da6c28aaSamw * netr_server_password_set 477da6c28aaSamw * 478da6c28aaSamw * Attempt to change the trust account password for this system. 479da6c28aaSamw * 480da6c28aaSamw * Note that this call may legitimately fail if the registry on the 481da6c28aaSamw * domain controller has been setup to deny attempts to change the 482da6c28aaSamw * trust account password. In this case we should just continue to 483da6c28aaSamw * use the original password. 484da6c28aaSamw * 485da6c28aaSamw * Possible status values: 486da6c28aaSamw * NT_STATUS_ACCESS_DENIED 487da6c28aaSamw */ 488da6c28aaSamw int 489da6c28aaSamw netr_server_password_set(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) 490da6c28aaSamw { 491da6c28aaSamw struct netr_PasswordSet arg; 492da6c28aaSamw int opnum; 493da6c28aaSamw BYTE new_password[NETR_OWF_PASSWORD_SZ]; 494b89a8333Snatalie li - Sun Microsystems - Irvine United States char account_name[NETBIOS_NAME_SZ * 2]; 495da6c28aaSamw 496da6c28aaSamw bzero(&arg, sizeof (struct netr_PasswordSet)); 497da6c28aaSamw opnum = NETR_OPNUM_ServerPasswordSet; 498da6c28aaSamw 499da6c28aaSamw (void) snprintf(account_name, sizeof (account_name), "%s$", 500da6c28aaSamw netr_info->hostname); 501da6c28aaSamw 502da6c28aaSamw arg.servername = (unsigned char *)netr_info->server; 503da6c28aaSamw arg.account_name = (unsigned char *)account_name; 5041ed6b69aSGordon Ross arg.sec_chan_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE; 505da6c28aaSamw arg.hostname = (unsigned char *)netr_info->hostname; 506da6c28aaSamw 507da6c28aaSamw /* 508da6c28aaSamw * Set up the client side authenticator. 509da6c28aaSamw */ 510da6c28aaSamw if (netr_setup_authenticator(netr_info, &arg.auth, 0) != 511da6c28aaSamw SMBAUTH_SUCCESS) { 512da6c28aaSamw return (-1); 513da6c28aaSamw } 514da6c28aaSamw 515da6c28aaSamw /* 516da6c28aaSamw * Generate a new password from the old password. 517da6c28aaSamw */ 5182c1b14e5Sjose borrego if (netr_gen_password(netr_info->session_key.key, 519da6c28aaSamw netr_info->password, new_password) == SMBAUTH_FAILURE) { 520da6c28aaSamw return (-1); 521da6c28aaSamw } 522da6c28aaSamw 5231ed6b69aSGordon Ross (void) memcpy(&arg.owf_password, &new_password, 524da6c28aaSamw NETR_OWF_PASSWORD_SZ); 525da6c28aaSamw 5268d7e4166Sjose borrego if (ndr_rpc_call(netr_handle, opnum, &arg) != 0) 5278d7e4166Sjose borrego return (-1); 5288d7e4166Sjose borrego 5298d7e4166Sjose borrego if (arg.status != 0) { 5308d7e4166Sjose borrego ndr_rpc_status(netr_handle, opnum, arg.status); 5318d7e4166Sjose borrego ndr_rpc_release(netr_handle); 532da6c28aaSamw return (-1); 533da6c28aaSamw } 534da6c28aaSamw 535da6c28aaSamw /* 536da6c28aaSamw * Check the returned credentials. The server returns the new 537da6c28aaSamw * client credential rather than the new server credentiali, 538da6c28aaSamw * as documented elsewhere. 539da6c28aaSamw * 540da6c28aaSamw * Generate the new seed for the credential chain. Increment 541da6c28aaSamw * the timestamp and add it to the client challenge. Then we 542da6c28aaSamw * need to copy the challenge to the credential field in 543da6c28aaSamw * preparation for the next cycle. 544da6c28aaSamw */ 545da6c28aaSamw if (netr_validate_chain(netr_info, &arg.auth) == 0) { 546da6c28aaSamw /* 547da6c28aaSamw * Save the new password. 548da6c28aaSamw */ 549da6c28aaSamw (void) memcpy(netr_info->password, new_password, 550da6c28aaSamw NETR_OWF_PASSWORD_SZ); 551da6c28aaSamw } 552da6c28aaSamw 5538d7e4166Sjose borrego ndr_rpc_release(netr_handle); 554da6c28aaSamw return (0); 555da6c28aaSamw } 556da6c28aaSamw 557da6c28aaSamw /* 558da6c28aaSamw * netr_gen_password 559da6c28aaSamw * 560da6c28aaSamw * Generate a new pasword from the old password and the session key. 561da6c28aaSamw * The algorithm is a two stage hash. The session key is used in the 562da6c28aaSamw * first hash but only part of the session key is used in the second 563da6c28aaSamw * hash. 564da6c28aaSamw * 565da6c28aaSamw * If any difficulties occur using the cryptographic framework, the 566da6c28aaSamw * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is 567da6c28aaSamw * returned. 568da6c28aaSamw */ 569da6c28aaSamw static int 570da6c28aaSamw netr_gen_password(BYTE *session_key, BYTE *old_password, BYTE *new_password) 571da6c28aaSamw { 572da6c28aaSamw int rv; 573da6c28aaSamw 5743db3f65cSamw rv = smb_auth_DES(new_password, 8, session_key, NETR_DESKEY_LEN, 5753db3f65cSamw old_password, 8); 576da6c28aaSamw if (rv != SMBAUTH_SUCCESS) 577da6c28aaSamw return (rv); 578da6c28aaSamw 5793db3f65cSamw rv = smb_auth_DES(&new_password[8], 8, &session_key[NETR_DESKEY_LEN], 5803db3f65cSamw NETR_DESKEY_LEN, &old_password[8], 8); 581da6c28aaSamw return (rv); 582da6c28aaSamw } 5831ed6b69aSGordon Ross 5841ed6b69aSGordon Ross /* 5851ed6b69aSGordon Ross * Todo: need netr_server_password_set2() 5861ed6b69aSGordon Ross * used by "unsecure join". (NX 11960) 5871ed6b69aSGordon Ross */ 588