/* 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 "lwps-utils.h"
#include "lwps/lwps.h"
#include "lwps-provider.h"
#include "provider-main_p.h"
#include "util_str.h"
#include "param.h"
#include "util_tdbkey.h"
#define TDB_CTX_HANDLE_MAGIC 0x38A2AD8E
#define CFG_PROVIDER_NAME "tdb"
#define BAIL_ON_INVALID_TDB_CTX(hParam) \
if (!hParam || (hParam->magic != TDB_CTX_HANDLE_MAGIC)) { \
dwError = LWPS_ERROR_INVALID_HANDLE; \
BAIL_ON_LWPS_ERROR(dwError); \
}
static PCSTR gpszTDBProviderName = "likewise-tdb-password-provider";
LWPS_PROVIDER_FUNC_TABLE gTDBProviderAPITable;
/************************************************************
************************************************************/
VOID
TDB_FreeMachineAccountInfo(
PMACHINE_ACCT_INFO pAcctInfo
)
{
if (!pAcctInfo)
return;
LWPS_SAFE_FREE_STRING(pAcctInfo->pszDomainName);
LWPS_SAFE_FREE_STRING(pAcctInfo->pszDomainDnsName);
LWPS_SAFE_FREE_STRING(pAcctInfo->pszHostName);
LWPS_SAFE_FREE_STRING(pAcctInfo->pszDomainSID);
LWPS_SAFE_FREE_STRING(pAcctInfo->pszMachineAccountName);
LWPS_SAFE_FREE_STRING(pAcctInfo->pszMachineAccountPassword);
LwpsFreeMemory(pAcctInfo);
return;
}
/************************************************************
************************************************************/
static VOID
FreePasswordInfoStruct(
PLWPS_PASSWORD_INFO pInfo
)
{
if (!pInfo)
return;
LWPS_SAFE_FREE_MEMORY(pInfo->pwszDomainName);
LWPS_SAFE_FREE_MEMORY(pInfo->pwszDnsDomainName);
LWPS_SAFE_FREE_MEMORY(pInfo->pwszHostname);
LWPS_SAFE_FREE_MEMORY(pInfo->pwszHostDnsDomain);
LWPS_SAFE_FREE_MEMORY(pInfo->pwszSID);
LWPS_SAFE_FREE_MEMORY(pInfo->pwszMachineAccount);
LWPS_SAFE_FREE_MEMORY(pInfo->pwszMachinePassword);
LwpsFreeMemory(pInfo);
return;
}
/************************************************************
************************************************************/
static DWORD
ConvertPasswordInfoFromMb(
PMACHINE_ACCT_INFO pAcctInfo,
PLWPS_PASSWORD_INFO *ppInfo
)
{
DWORD dwError = LWPS_ERROR_INTERNAL;
PLWPS_PASSWORD_INFO pInfo = NULL;
/* Sanity checks */
BAIL_ON_INVALID_POINTER(pAcctInfo);
BAIL_ON_INVALID_POINTER(ppInfo);
/* Allocate and convert */
dwError = LwpsAllocateMemory(sizeof(LWPS_PASSWORD_INFO),
(PVOID*)&pInfo);
BAIL_ON_LWPS_ERROR(dwError);
if (pAcctInfo->pszDomainName) {
dwError = LwpsMbsToWc16s(pAcctInfo->pszDomainName,
&pInfo->pwszDomainName);
BAIL_ON_LWPS_ERROR(dwError);
}
if (pAcctInfo->pszMachineAccountPassword) {
dwError = LwpsMbsToWc16s(pAcctInfo->pszMachineAccountPassword,
&pInfo->pwszMachinePassword);
BAIL_ON_LWPS_ERROR(dwError);
}
if (pAcctInfo->pszDomainDnsName) {
dwError = LwpsMbsToWc16s(pAcctInfo->pszDomainDnsName,
&pInfo->pwszDnsDomainName);
BAIL_ON_LWPS_ERROR(dwError);
}
if (pAcctInfo->pszDomainSID) {
dwError = LwpsMbsToWc16s(pAcctInfo->pszDomainSID,
&pInfo->pwszSID);
BAIL_ON_LWPS_ERROR(dwError);
}
if (pAcctInfo->pszHostName) {
dwError = LwpsMbsToWc16s(pAcctInfo->pszHostName,
&pInfo->pwszHostname);
BAIL_ON_LWPS_ERROR(dwError);
}
if (pAcctInfo->pszMachineAccountName) {
dwError = LwpsMbsToWc16s(pAcctInfo->pszMachineAccountName,
&pInfo->pwszMachineAccount);
BAIL_ON_LWPS_ERROR(dwError);
}
pInfo->last_change_time = pAcctInfo->tPwdClientModifyTimestamp;
pInfo->dwSchannelType = pAcctInfo->dwSchannelType;
/* Done */
dwError = LWPS_ERROR_SUCCESS;
cleanup:
*ppInfo = pInfo;
return dwError;
error:
if (pInfo) {
FreePasswordInfoStruct(pInfo);
pInfo = NULL;
}
goto cleanup;
}
/************************************************************
************************************************************/
static DWORD
ConvertPasswordInfoToMb(
PLWPS_PASSWORD_INFO pInfo,
PMACHINE_ACCT_INFO *ppAcctInfo
)
{
DWORD dwError = LWPS_ERROR_INTERNAL;
PMACHINE_ACCT_INFO pAcct = NULL;
/* Sanity checks */
BAIL_ON_INVALID_POINTER(pInfo);
BAIL_ON_INVALID_POINTER(ppAcctInfo);
/* Allocate and convert */
dwError = LwpsAllocateMemory(sizeof(MACHINE_ACCT_INFO),
(PVOID*)&pAcct);
BAIL_ON_LWPS_ERROR(dwError);
if (pInfo->pwszDomainName) {
dwError = LwpsWc16sToMbs(pInfo->pwszDomainName,
&pAcct->pszDomainName);
BAIL_ON_LWPS_ERROR(dwError);
}
if (pInfo->pwszMachinePassword) {
dwError = LwpsWc16sToMbs(pInfo->pwszMachinePassword,
&pAcct->pszMachineAccountPassword);
BAIL_ON_LWPS_ERROR(dwError);
}
if (pInfo->pwszDnsDomainName) {
dwError = LwpsWc16sToMbs(pInfo->pwszDnsDomainName,
&pAcct->pszDomainDnsName);
BAIL_ON_LWPS_ERROR(dwError);
}
if (pInfo->pwszSID) {
dwError = LwpsWc16sToMbs(pInfo->pwszSID,
&pAcct->pszDomainSID);
BAIL_ON_LWPS_ERROR(dwError);
}
if (pInfo->pwszHostname) {
dwError = LwpsWc16sToMbs(pInfo->pwszHostname,
&pAcct->pszHostName);
BAIL_ON_LWPS_ERROR(dwError);
}
if (pInfo->pwszMachineAccount) {
dwError = LwpsWc16sToMbs(pInfo->pwszMachineAccount,
&pAcct->pszMachineAccountName);
BAIL_ON_LWPS_ERROR(dwError);
}
pAcct->tPwdClientModifyTimestamp = pInfo->last_change_time;
pAcct->dwSchannelType = pInfo->dwSchannelType;
/* Done */
*ppAcctInfo = pAcct;
dwError = LWPS_ERROR_SUCCESS;
cleanup:
return dwError;
error:
if (pAcct) {
TDB_FreeMachineAccountInfo(pAcct);
}
goto cleanup;
}
/************************************************************
************************************************************/
static DWORD
Tdb_ConfigStartSection(
PCSTR pszSectionName,
PVOID pData,
PBOOLEAN pbSkipSection,
PBOOLEAN pbContinue
)
{
DWORD dwError = 0;
PCSTR pszProviderName = NULL;
BOOLEAN bContinue = TRUE;
BOOLEAN bSkipSection = FALSE;
if (!StrnEqual(pszSectionName, LWPS_CFG_PROVIDER_TAG,
strlen(LWPS_CFG_PROVIDER_TAG)))
{
bSkipSection = TRUE;
goto cleanup;
}
pszProviderName = pszSectionName + strlen(LWPS_CFG_PROVIDER_TAG);
if (!StrEqual(pszProviderName, CFG_PROVIDER_NAME)) {
bSkipSection = TRUE;
goto cleanup;
}
*pbSkipSection = bSkipSection;
*pbContinue = bContinue;
cleanup:
return dwError;
}
/************************************************************
************************************************************/
DWORD
Tdb_ConfigNameValuePair(
PCSTR pszName,
PCSTR pszValue,
PVOID pData,
PBOOLEAN pbContinue
)
{
DWORD dwError = LWPS_ERROR_INTERNAL;
BOOLEAN bContinue = FALSE;
BAIL_ON_INVALID_POINTER(pszName);
BAIL_ON_INVALID_POINTER(pszValue);
/* Path to secrets.tdb */
if (StrEqual(pszName, "db path")) {
dwError = TdbSetDbPath(pszValue);
BAIL_ON_LWPS_ERROR(dwError);
}
bContinue = TRUE;
dwError = LWPS_ERROR_SUCCESS;
error:
*pbContinue = bContinue;
return dwError;
}
/************************************************************
************************************************************/
DWORD
LWPS_INITIALIZE_PROVIDER(tdb)(
PCSTR pszConfigFilePath,
PSTR* ppszName,
PLWPS_PROVIDER_FUNC_TABLE* ppFnTable
)
{
DWORD dwError = LWPS_ERROR_INTERNAL;
BAIL_IF_NOT_SUPERUSER(geteuid());
dwError = TdbInitProviderParams();
BAIL_ON_LWPS_ERROR(dwError);
if (!IsNullOrEmptyString(pszConfigFilePath)) {
dwError = LwpsParseConfigFile(
pszConfigFilePath,
LWPS_CFG_OPTION_STRIP_ALL,
&Tdb_ConfigStartSection,
NULL,
&Tdb_ConfigNameValuePair,
NULL,
NULL);
BAIL_ON_LWPS_ERROR(dwError);
}
*ppszName = (PSTR)gpszTDBProviderName;
*ppFnTable = &gTDBProviderAPITable;
cleanup:
return dwError;
error:
*ppszName = NULL;
*ppFnTable = NULL;
goto cleanup;
}
/************************************************************
************************************************************/
DWORD
TDB_OpenProvider(
PHANDLE phProvider
)
{
DWORD dwError = LWPS_ERROR_INTERNAL;
PTDB_PROVIDER_CONTEXT pContext = NULL;
PSTR pszDbPath = NULL;
BAIL_IF_NOT_SUPERUSER(geteuid());
BAIL_ON_INVALID_POINTER(phProvider);
dwError = LwpsAllocateMemory(
sizeof(TDB_PROVIDER_CONTEXT),
(PVOID*)&pContext);
BAIL_ON_LWPS_ERROR(dwError);
pContext->magic = TDB_CTX_HANDLE_MAGIC;
dwError = TdbGetDbPath(&pszDbPath);
BAIL_ON_LWPS_ERROR(dwError);
pContext->pTdb = tdb_open(pszDbPath,
0,
TDB_DEFAULT,
O_RDWR|O_CREAT,
0600);
if (pContext->pTdb == NULL) {
dwError = LWPS_ERROR_UNEXPECTED_DB_RESULT;
BAIL_ON_LWPS_ERROR(dwError);
}
*phProvider = (HANDLE)pContext;
dwError = LWPS_ERROR_SUCCESS;
cleanup:
return dwError;
error:
if (pContext) {
if (pContext->pTdb) {
tdb_close(pContext->pTdb);
pContext->pTdb = NULL;
}
LwpsFreeMemory(pContext);
}
*phProvider = (HANDLE)NULL;
goto cleanup;
}
/************************************************************
************************************************************/
DWORD
TDB_ReadPasswordByDomain(
HANDLE hProvider,
PCSTR pszDomain,
PLWPS_PASSWORD_INFO* ppInfo
)
{
DWORD dwError = LWPS_ERROR_INTERNAL;
PTDB_PROVIDER_CONTEXT pContext = (PTDB_PROVIDER_CONTEXT)hProvider;
PMACHINE_ACCT_INFO pAcctInfo = NULL;
PLWPS_PASSWORD_INFO pPasswordInfo = NULL;
BAIL_IF_NOT_SUPERUSER(geteuid());
BAIL_ON_INVALID_POINTER(ppInfo);
BAIL_ON_INVALID_TDB_CTX(pContext);
dwError = TdbFetchMachineAccountInfo(pContext,
pszDomain,
&pAcctInfo);
BAIL_ON_LWPS_ERROR(dwError);
dwError = ConvertPasswordInfoFromMb(pAcctInfo,
&pPasswordInfo);
BAIL_ON_LWPS_ERROR(dwError);
cleanup:
if (pAcctInfo)
{
TDB_FreeMachineAccountInfo(pAcctInfo);
pAcctInfo = NULL;
}
*ppInfo = pPasswordInfo;
return dwError;
error:
if (pPasswordInfo)
{
FreePasswordInfoStruct(pPasswordInfo);
pPasswordInfo = NULL;
}
goto cleanup;
}
/************************************************************
************************************************************/
DWORD
TDB_ReadPasswordByHostName(
HANDLE hProvider,
PCSTR pszDomainName,
PLWPS_PASSWORD_INFO* ppInfo
)
{
DWORD dwError = LWPS_ERROR_NOT_IMPLEMENTED;
PTDB_PROVIDER_CONTEXT pContext = (PTDB_PROVIDER_CONTEXT)hProvider;
BAIL_IF_NOT_SUPERUSER(geteuid());
BAIL_ON_INVALID_POINTER(ppInfo);
BAIL_ON_INVALID_TDB_CTX(pContext);
error:
return dwError;
}
/************************************************************
************************************************************/
DWORD
TDB_WritePassword(
HANDLE hProvider,
PLWPS_PASSWORD_INFO pInfo
)
{
DWORD dwError = LWPS_ERROR_NOT_IMPLEMENTED;
PTDB_PROVIDER_CONTEXT pContext = (PTDB_PROVIDER_CONTEXT)hProvider;
PMACHINE_ACCT_INFO pAcctInfo = NULL;
BAIL_IF_NOT_SUPERUSER(geteuid());
BAIL_ON_INVALID_POINTER(pInfo);
BAIL_ON_INVALID_TDB_CTX(pContext);
dwError = ConvertPasswordInfoToMb(pInfo, &pAcctInfo);
BAIL_ON_LWPS_ERROR(dwError);
dwError = TdbStoreMachineAccountInfo(pContext,
pAcctInfo->pszDomainName,
pAcctInfo);
BAIL_ON_LWPS_ERROR(dwError);
cleanup:
if (pAcctInfo) {
TDB_FreeMachineAccountInfo(pAcctInfo);
}
return dwError;
error:
goto cleanup;
}
/************************************************************
************************************************************/
DWORD
TDB_DeleteAllEntries(
HANDLE hProvider
)
{
DWORD dwError = LWPS_ERROR_NOT_IMPLEMENTED;
PTDB_PROVIDER_CONTEXT pContext = (PTDB_PROVIDER_CONTEXT)hProvider;
BAIL_IF_NOT_SUPERUSER(geteuid());
BAIL_ON_INVALID_TDB_CTX(pContext);
/* This will have to be a TDB traversal but I'm leaving it
blank for now. --jerry */
cleanup:
return dwError;
error:
goto cleanup;
}
/************************************************************
************************************************************/
VOID
TDB_FreePassword(
PLWPS_PASSWORD_INFO pInfo
)
{
FreePasswordInfoStruct(pInfo);
}
/************************************************************
************************************************************/
DWORD
TDB_CloseProvider(
HANDLE hProvider
)
{
DWORD dwError = LWPS_ERROR_NOT_IMPLEMENTED;
PTDB_PROVIDER_CONTEXT pContext = (PTDB_PROVIDER_CONTEXT)hProvider;
BAIL_IF_NOT_SUPERUSER(geteuid());
BAIL_ON_INVALID_TDB_CTX(pContext);
if (pContext->pTdb) {
tdb_close(pContext->pTdb);
pContext->pTdb = NULL;
}
/* Make sure there is no valid info in the handle
so it cannot be reused accidentally */
memset(pContext, 0x0, sizeof(TDB_PROVIDER_CONTEXT));
LwpsFreeMemory(pContext);
dwError = LWPS_ERROR_SUCCESS;
cleanup:
return dwError;
error:
goto cleanup;
}
/************************************************************
************************************************************/
DWORD
LWPS_SHUTDOWN_PROVIDER(tdb)(
PSTR pszName,
PLWPS_PROVIDER_FUNC_TABLE pFnTable
)
{
DWORD dwError = LWPS_ERROR_NOT_IMPLEMENTED;
BAIL_IF_NOT_SUPERUSER(geteuid());
dwError = TdbReleaseProviderParams();
BAIL_ON_LWPS_ERROR(dwError);
cleanup:
return dwError;
error:
goto cleanup;
}
/************************************************************
************************************************************/
static DWORD
TDB_StoreHostListByDomainName(
HANDLE hProvider,
PCSTR pszDomainName,
PSTR **pppszHostnames,
DWORD *pdwHostname
)
{
return LWPS_ERROR_NOT_IMPLEMENTED;
}
/************************************************************
************************************************************/
static DWORD
TDB_DeleteHostEntry(
HANDLE hProvider,
PCSTR pszHostname
)
{
return LWPS_ERROR_NOT_IMPLEMENTED;
}
/************************************************************
Provider dispatch table
************************************************************/
LWPS_PROVIDER_FUNC_TABLE gTDBProviderAPITable = {
.pFnOpenProvider = &TDB_OpenProvider,
.pFnReadPasswordByHostName = &TDB_ReadPasswordByHostName,
.pFnReadPasswordByDomainName = &TDB_ReadPasswordByDomain,
.pFnReadHostListByDomainName = &TDB_StoreHostListByDomainName,
.pFnWritePassword = &TDB_WritePassword,
.pFnDeleteAllEntries = &TDB_DeleteAllEntries,
.pFnDeleteHostEntry = &TDB_DeleteHostEntry,
.pfnFreePassword = &TDB_FreePassword,
.pFnCloseProvider = &TDB_CloseProvider
};
/*
local variables:
mode: c
c-basic-offset: 4
indent-tabs-mode: nil
tab-width: 4
end:
*/