/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * * -*- mode: c, c-basic-offset: 4 -*- */ /* * Copyright Likewise Software 2004-2008 * All rights reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Copyright (C) Likewise Software. All rights reserved. * * Module Name: * * provider-main.c * * Abstract: * * Likewise Password Storage (LWPS) * * API to support TDB Password Storage * * Authors: Gerald Carter * */ #include "util_tdbkey.h" #include "util_sid.h" /************************************************************* ************************************************************/ static DWORD KeyCreate( PCSTR pszPrefix, PCSTR pszData, PSTR *pszKey ) { DWORD dwError = LWPS_ERROR_INTERNAL; DWORD dwLen = 0; PVOID pBuffer = NULL; dwLen = strlen(pszPrefix) + strlen(pszData) + 1; dwError = LwpsAllocateMemory(dwLen, &pBuffer); BAIL_ON_LWPS_ERROR(dwError); snprintf((PSTR)pBuffer, dwLen, "%s%s", pszPrefix, pszData); *pszKey = (PSTR)pBuffer; dwError = LWPS_ERROR_SUCCESS; error: return dwError; } /************************************************************* ************************************************************/ DWORD KeyMachinePassword( PCSTR pszDomain, PSTR *pszKey ) { DWORD dwError = LWPS_ERROR_INTERNAL; PCSTR pszKeyPrefix = "SECRETS/MACHINE_PASSWORD/"; BAIL_ON_INVALID_POINTER(pszDomain); dwError = KeyCreate(pszKeyPrefix, pszDomain, pszKey); BAIL_ON_LWPS_ERROR(dwError); StrUpper(*pszKey); error: return dwError; } /************************************************************* ************************************************************/ DWORD KeyDomainSid( PCSTR pszDomain, PSTR *pszKey ) { DWORD dwError = LWPS_ERROR_INTERNAL; PCSTR pszKeyPrefix = "SECRETS/SID/"; BAIL_ON_INVALID_POINTER(pszDomain); dwError = KeyCreate(pszKeyPrefix, pszDomain, pszKey); BAIL_ON_LWPS_ERROR(dwError); StrUpper(*pszKey); error: return dwError; } /************************************************************* ************************************************************/ DWORD KeyPasswordLastChangeTime( PCSTR pszDomain, PSTR *pszKey ) { DWORD dwError = LWPS_ERROR_INTERNAL; PCSTR pszKeyPrefix = "SECRETS/MACHINE_LAST_CHANGE_TIME/"; BAIL_ON_INVALID_POINTER(pszDomain); dwError = KeyCreate(pszKeyPrefix, pszDomain, pszKey); BAIL_ON_LWPS_ERROR(dwError); StrUpper(*pszKey); error: return dwError; } /************************************************************* ************************************************************/ DWORD KeySecureChannelType( PCSTR pszDomain, PSTR *pszKey ) { DWORD dwError = LWPS_ERROR_INTERNAL; PCSTR pszKeyPrefix = "SECRETS/MACHINE_SEC_CHANNEL_TYPE/"; BAIL_ON_INVALID_POINTER(pszDomain); dwError = KeyCreate(pszKeyPrefix, pszDomain, pszKey); BAIL_ON_LWPS_ERROR(dwError); StrUpper(*pszKey); error: return dwError; } /************************************************************* ************************************************************/ TDB_DATA TdbDataBlob( PBYTE Data, size_t Len ) { TDB_DATA Blob; Blob.dptr = Data; Blob.dsize = Len; return Blob; } /************************************************************* ************************************************************/ static DWORD TdbStore( PTDB_PROVIDER_CONTEXT pCtx, PSTR pszKey, TDB_DATA Data ) { DWORD dwError = LWPS_ERROR_INTERNAL; int ret; TDB_DATA TdbKey; TdbKey = TdbDataBlob((PBYTE)pszKey, strlen(pszKey)); if ((ret = tdb_transaction_start(pCtx->pTdb)) != 0) { dwError = LWPS_ERROR_UNEXPECTED_DB_RESULT; BAIL_ON_LWPS_ERROR(dwError); } if ((ret = tdb_store(pCtx->pTdb, TdbKey, Data, TDB_REPLACE)) != 0) { tdb_transaction_cancel(pCtx->pTdb); dwError = LWPS_ERROR_DATA_ERROR; BAIL_ON_LWPS_ERROR(dwError); } if ((ret = tdb_transaction_commit(pCtx->pTdb)) != 0) { dwError = LWPS_ERROR_UNEXPECTED_DB_RESULT; BAIL_ON_LWPS_ERROR(dwError); } dwError = LWPS_ERROR_SUCCESS; error: return dwError; } /************************************************************* ************************************************************/ static DWORD TdbFetch( PTDB_PROVIDER_CONTEXT pCtx, PSTR pszKey, TDB_DATA *pData ) { DWORD dwError = LWPS_ERROR_INTERNAL; TDB_DATA TdbRec; TDB_DATA TdbKey; TdbKey = TdbDataBlob((PBYTE)pszKey, strlen(pszKey)); TdbRec = tdb_fetch(pCtx->pTdb, TdbKey); if (TdbRec.dsize == 0) { dwError = LWPS_ERROR_DB_RECORD_NOT_FOUND; BAIL_ON_LWPS_ERROR(dwError); } pData->dptr = TdbRec.dptr; pData->dsize = TdbRec.dsize; dwError = LWPS_ERROR_SUCCESS; error: return dwError; } /************************************************************* ************************************************************/ #if 0 static DWORD TdbDelete( PTDB_PROVIDER_CONTEXT pCtx, PSTR pszKey ) { DWORD dwError = LWPS_ERROR_INTERNAL; TDB_DATA TdbKey; int ret; TdbKey = TdbDataBlob((PBYTE)pszKey, strlen(pszKey)); if ((ret = tdb_transaction_start(pCtx->pTdb)) != 0) { dwError = LWPS_ERROR_UNEXPECTED_DB_RESULT; BAIL_ON_LWPS_ERROR(dwError); } if ((ret = tdb_delete(pCtx->pTdb, TdbKey)) != 0) { tdb_transaction_cancel(pCtx->pTdb); dwError = LWPS_ERROR_DATA_ERROR; BAIL_ON_LWPS_ERROR(dwError); } if ((ret = tdb_transaction_commit(pCtx->pTdb)) != 0) { dwError = LWPS_ERROR_UNEXPECTED_DB_RESULT; BAIL_ON_LWPS_ERROR(dwError); } dwError = LWPS_ERROR_SUCCESS; error: return dwError; } #endif /************************************************************* ************************************************************/ DWORD TdbStoreMachineAccountInfo( PTDB_PROVIDER_CONTEXT pCtx, PCSTR pszDomain, PMACHINE_ACCT_INFO pAcctInfo ) { DWORD dwError = LWPS_ERROR_INTERNAL; TDB_DATA data; PSTR pszKeyMachPw = NULL; PSTR pszKeySid = NULL; PSTR pszKeyLCT = NULL; PSTR pszKeySchannel = NULL; DOMAIN_SID Sid = {0}; DWORD dwSchannelType = 0; DWORD dwLCT = 0; /* Machine Password */ dwError = KeyMachinePassword(pszDomain, &pszKeyMachPw); BAIL_ON_LWPS_ERROR(dwError); data = TdbDataBlob((PBYTE)pAcctInfo->pszMachineAccountPassword, (size_t)strlen(pAcctInfo->pszMachineAccountPassword)+1); dwError = TdbStore(pCtx, pszKeyMachPw, data); BAIL_ON_LWPS_ERROR(dwError); /* Domain SID */ dwError = StringToSid(pAcctInfo->pszDomainSID, &Sid); BAIL_ON_LWPS_ERROR(dwError); dwError = KeyDomainSid(pszDomain, &pszKeySid); BAIL_ON_LWPS_ERROR(dwError); data = TdbDataBlob((PBYTE)&Sid, sizeof(Sid)); dwError = TdbStore(pCtx, pszKeySid, data); BAIL_ON_LWPS_ERROR(dwError); /* Schannel Type */ dwError = KeySecureChannelType(pszDomain, &pszKeySchannel); BAIL_ON_LWPS_ERROR(dwError); dwSchannelType = LW_HTOL32(pAcctInfo->dwSchannelType); data = TdbDataBlob((PBYTE)&dwSchannelType, sizeof(DWORD)); dwError = TdbStore(pCtx, pszKeySchannel, data); BAIL_ON_LWPS_ERROR(dwError); /* Last Change Time */ dwError = KeyPasswordLastChangeTime(pszDomain, &pszKeyLCT); BAIL_ON_LWPS_ERROR(dwError); dwLCT = LW_HTOL32(pAcctInfo->tPwdClientModifyTimestamp); data = TdbDataBlob((PBYTE)&dwLCT, sizeof(DWORD)); dwError = TdbStore(pCtx, pszKeyLCT, data); BAIL_ON_LWPS_ERROR(dwError); error: LWPS_SAFE_FREE_STRING(pszKeyMachPw); LWPS_SAFE_FREE_STRING(pszKeyLCT); LWPS_SAFE_FREE_STRING(pszKeySchannel); LWPS_SAFE_FREE_STRING(pszKeySid); return dwError; } /************************************************************* ************************************************************/ DWORD TdbFetchMachineAccountInfo( PTDB_PROVIDER_CONTEXT pCtx, PCSTR pszDomain, PMACHINE_ACCT_INFO *ppAcctInfo ) { DWORD dwError = LWPS_ERROR_INTERNAL; TDB_DATA data = { NULL, 0 }; PSTR pszKeyMachPw = NULL; PSTR pszKeySid = NULL; PSTR pszKeySchannel = NULL; PSTR pszKeyLCT = NULL; PMACHINE_ACCT_INFO pAcctInfo = NULL; dwError = LwpsAllocateMemory(sizeof(*pAcctInfo), (PVOID*)&pAcctInfo); BAIL_ON_LWPS_ERROR(dwError); /* Machine Password Fetch the record early so we can go ahead and bail if it is not there */ dwError = KeyMachinePassword(pszDomain, &pszKeyMachPw); BAIL_ON_LWPS_ERROR(dwError); dwError = TdbFetch(pCtx, pszKeyMachPw, &data); BAIL_ON_LWPS_ERROR(dwError); dwError = LwpsAllocateString((PCSTR)data.dptr, &pAcctInfo->pszMachineAccountPassword); BAIL_ON_LWPS_ERROR(dwError); if (data.dptr) { free(data.dptr); memset(&data, 0x0, sizeof(data)); } /* Copy short domain name */ dwError = LwpsAllocateString(pszDomain, &pAcctInfo->pszDomainName); BAIL_ON_LWPS_ERROR(dwError); /* Domain Sid */ dwError = KeyDomainSid(pszDomain, &pszKeySid); BAIL_ON_LWPS_ERROR(dwError); dwError = TdbFetch(pCtx, pszKeySid, &data); BAIL_ON_LWPS_ERROR(dwError); dwError = SidToString((PDOMAIN_SID)data.dptr, &pAcctInfo->pszDomainSID); BAIL_ON_LWPS_ERROR(dwError); if (data.dptr) { free(data.dptr); memset(&data, 0x0, sizeof(data)); } /* LCT */ dwError = KeyPasswordLastChangeTime(pszDomain, &pszKeyLCT); BAIL_ON_LWPS_ERROR(dwError); dwError = TdbFetch(pCtx, pszKeyLCT, &data); BAIL_ON_LWPS_ERROR(dwError); pAcctInfo->tPwdClientModifyTimestamp = LW_HTOL32(*data.dptr); if (data.dptr) { free(data.dptr); memset(&data, 0x0, sizeof(data)); } /* Schannel Type */ dwError = KeySecureChannelType(pszDomain, &pszKeySchannel); BAIL_ON_LWPS_ERROR(dwError); dwError = TdbFetch(pCtx, pszKeySchannel, &data); BAIL_ON_LWPS_ERROR(dwError); pAcctInfo->dwSchannelType = LW_HTOL32(*data.dptr); if (data.dptr) { free(data.dptr); memset(&data, 0x0, sizeof(data)); } cleanup: LWPS_SAFE_FREE_STRING(pszKeyMachPw); LWPS_SAFE_FREE_STRING(pszKeyLCT); LWPS_SAFE_FREE_STRING(pszKeySchannel); LWPS_SAFE_FREE_STRING(pszKeySid); if (data.dptr) { free(data.dptr); } *ppAcctInfo = pAcctInfo; return dwError; error: if (pAcctInfo) { TDB_FreeMachineAccountInfo(pAcctInfo); pAcctInfo = NULL; } goto cleanup; } /************************************************************* ************************************************************/ DWORD TdbDeleteMachineAccountInfo( PTDB_PROVIDER_CONTEXT pCtx, PCSTR pszDomain ) { DWORD dwError = LWPS_ERROR_INTERNAL; return dwError; } /* local variables: mode: c c-basic-offset: 4 indent-tabs-mode: nil tab-width: 4 end: */