/* 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 program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program 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 General Public License * for more details. You should have received a copy of the GNU 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 * 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: * * lpcfg.c * * Abstract: * * Likewise Security and Authentication Subsystem (LSASS) * * Local Authentication Provider * * Wrappers for accessing global configuration variables * * Authors: Krishna Ganugapati (krishnag@likewisesoftware.com) * Sriram Nambakam (snambakam@likewisesoftware.com) * Brian Dunstan (bdunstan@likewisesoftware.com) */ #include "includes.h" static DWORD LocalCfgSetDefaultLoginShell( PLOCAL_CONFIG pConfig, PCSTR pszName, PCSTR pszValue ); static DWORD LocalCfgSetHomedirPrefix( PLOCAL_CONFIG pConfig, PCSTR pszName, PCSTR pszValue ); static DWORD LocalCfgSetHomedirUmask( PLOCAL_CONFIG pConfig, PCSTR pszName, PCSTR pszValue ); DWORD LocalCfgInitialize( PLOCAL_CONFIG pConfig ) { DWORD dwError = 0; PCSTR pszDefaultLoginShell = LOCAL_CFG_DEFAULT_LOGIN_SHELL; PCSTR pszDefaultHomedirPrefix = LOCAL_CFG_DEFAULT_HOMEDIR_PREFIX; PCSTR pszDefaultHomedirTemplate = LOCAL_CFG_DEFAULT_HOMEDIR_TEMPLATE; PCSTR pszDefaultSkelDirs = LOCAL_CFG_DEFAULT_SKELETON_DIRS; memset(pConfig, 0, sizeof(LOCAL_CONFIG)); pConfig->bEnableEventLog = FALSE; pConfig->dwMaxGroupNestingLevel = LOCAL_CFG_MAX_GROUP_NESTING_LEVEL_DEFAULT; dwError = LwAllocateString( pszDefaultLoginShell, &pConfig->pszLoginShell); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateString( pszDefaultHomedirPrefix, &pConfig->pszHomedirPrefix); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateString( pszDefaultHomedirTemplate, &pConfig->pszHomedirTemplate); BAIL_ON_LSA_ERROR(dwError); pConfig->bCreateHomedir = LOCAL_CFG_DEFAULT_CREATE_HOMEDIR; pConfig->bAcceptNTLMv1 = LOCAL_CFG_DEFAULT_ACCEPT_NTLMV1; pConfig->dwHomedirUMask = LOCAL_CFG_DEFAULT_HOMEDIR_UMASK; dwError = LwAllocateString( pszDefaultSkelDirs, &pConfig->pszSkelDirs); BAIL_ON_LSA_ERROR(dwError); error: return dwError; } DWORD LocalCfgTransferContents( PLOCAL_CONFIG pSrcConfig, PLOCAL_CONFIG pDstConfig ) { LocalCfgFreeContents(pDstConfig); *pDstConfig = *pSrcConfig; memset(pSrcConfig, 0, sizeof(LOCAL_CONFIG)); return 0; } DWORD LocalCfgGetMinPasswordAge( PLONG64 pllMinPwdAge ) { DWORD dwError = 0; LONG64 llMinPwdAge = 0; BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); llMinPwdAge = gLPGlobals.llMinPwdAge; LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); *pllMinPwdAge = llMinPwdAge; return dwError; } DWORD LocalCfgGetMaxPasswordAge( PLONG64 pllMaxPwdAge ) { DWORD dwError = 0; LONG64 llMaxPwdAge = 0; BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); llMaxPwdAge = gLPGlobals.llMaxPwdAge; LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); *pllMaxPwdAge = llMaxPwdAge; return dwError; } DWORD LocalCfgGetMinPwdLength( PDWORD pdwMinPwdLength ) { DWORD dwError = 0; DWORD dwMinPwdLength = 0; BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); dwMinPwdLength = gLPGlobals.dwMinPwdLength; LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); *pdwMinPwdLength = dwMinPwdLength; return dwError; } DWORD LocalCfgGetPasswordChangeWarningTime( PLONG64 pllPasswdChangeWarningTime ) { DWORD dwError = 0; LONG64 llPasswdChangeWarningTime = 0; BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); llPasswdChangeWarningTime = gLPGlobals.llPwdChangeTime; LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); *pllPasswdChangeWarningTime = llPasswdChangeWarningTime; return dwError; } DWORD LocalCfgIsEventlogEnabled( PBOOLEAN pbValue ) { DWORD dwError = 0; BOOLEAN bResult = FALSE; BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); bResult = gLPGlobals.cfg.bEnableEventLog; LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); *pbValue = bResult; return dwError; } DWORD LocalCfgGetMaxGroupNestingLevel( PDWORD pdwNestingLevel ) { DWORD dwError = 0; DWORD dwMaxGroupNestingLevel = LOCAL_CFG_MAX_GROUP_NESTING_LEVEL_DEFAULT; BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); dwMaxGroupNestingLevel = gLPGlobals.cfg.dwMaxGroupNestingLevel; LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); *pdwNestingLevel = dwMaxGroupNestingLevel; return dwError; } DWORD LocalCfgGetDefaultShell( PSTR* ppszLoginShell ) { DWORD dwError = 0; PSTR pszLoginShell = NULL; BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); dwError = LwAllocateString( gLPGlobals.cfg.pszLoginShell, &pszLoginShell); BAIL_ON_LSA_ERROR(dwError); *ppszLoginShell = pszLoginShell; cleanup: LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); return dwError; error: *ppszLoginShell = NULL; LW_SAFE_FREE_STRING(pszLoginShell); goto cleanup; } DWORD LocalCfgGetHomedirPrefix( PSTR* ppszHomedirPrefix ) { DWORD dwError = 0; PSTR pszHomedirPrefix = NULL; BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); dwError = LwAllocateString( gLPGlobals.cfg.pszHomedirPrefix, &pszHomedirPrefix); BAIL_ON_LSA_ERROR(dwError); *ppszHomedirPrefix = pszHomedirPrefix; cleanup: LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); return dwError; error: *ppszHomedirPrefix = NULL; LW_SAFE_FREE_STRING(pszHomedirPrefix); goto cleanup; } DWORD LocalCfgGetHomedirTemplate( PSTR* ppszHomedirTemplate ) { DWORD dwError = 0; PSTR pszHomedirTemplate = NULL; BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); dwError = LwAllocateString( gLPGlobals.cfg.pszHomedirTemplate, &pszHomedirTemplate); BAIL_ON_LSA_ERROR(dwError); *ppszHomedirTemplate = pszHomedirTemplate; cleanup: LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); return dwError; error: *ppszHomedirTemplate = NULL; LW_SAFE_FREE_STRING(pszHomedirTemplate); goto cleanup; } DWORD LocalCfgGetHomedirUmask( mode_t* pUmask ) { BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); *pUmask = gLPGlobals.cfg.dwHomedirUMask; LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); return 0; } DWORD LocalCfgMustCreateHomedir( PBOOLEAN pbCreateHomedir ) { BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); *pbCreateHomedir = gLPGlobals.cfg.bCreateHomedir; LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); return 0; } DWORD LocalCfgAcceptNTLMv1( PBOOLEAN pbResult ) { BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); *pbResult = gLPGlobals.cfg.bAcceptNTLMv1; LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); return 0; } DWORD LocalCfgGetSkeletonDirs( PSTR* ppszSkelDirs ) { DWORD dwError = 0; PSTR pszSkelDirs = NULL; BOOLEAN bInLock = FALSE; LOCAL_LOCK_MUTEX(bInLock, &gLPGlobals.mutex); dwError = LwAllocateString( gLPGlobals.cfg.pszSkelDirs, &pszSkelDirs); BAIL_ON_LSA_ERROR(dwError); *ppszSkelDirs = pszSkelDirs; cleanup: LOCAL_UNLOCK_MUTEX(bInLock, &gLPGlobals.mutex); return dwError; error: *ppszSkelDirs = NULL; LW_SAFE_FREE_STRING(pszSkelDirs); goto cleanup; } VOID LocalCfgFree( PLOCAL_CONFIG pConfig ) { LocalCfgFreeContents(pConfig); LwFreeMemory(pConfig); } VOID LocalCfgFreeContents( PLOCAL_CONFIG pConfig ) { LW_SAFE_FREE_STRING(pConfig->pszLoginShell); LW_SAFE_FREE_STRING(pConfig->pszHomedirPrefix); LW_SAFE_FREE_STRING(pConfig->pszHomedirTemplate); LW_SAFE_FREE_STRING(pConfig->pszSkelDirs); } DWORD LocalCfgReadRegistry( PLOCAL_CONFIG pConfig ) { DWORD dwError = LW_ERROR_SUCCESS; PSTR pszLoginShell = NULL; PSTR pszHomedirPrefix = NULL; PSTR pszUmask = NULL; LOCAL_CONFIG StagingConfig; LSA_CONFIG LpConfigDescription[] = { { "LoginShellTemplate", TRUE, LsaTypeString, 0, MAXDWORD, NULL, &pszLoginShell }, { "HomeDirPrefix", TRUE, LsaTypeString, 0, MAXDWORD, NULL, &pszHomedirPrefix }, { "HomeDirUmask", TRUE, LsaTypeString, 0, MAXDWORD, NULL, &pszUmask }, { "HomeDirTemplate", TRUE, LsaTypeString, 0, MAXDWORD, NULL, &StagingConfig.pszHomedirTemplate }, { "CreateHomeDir", TRUE, LsaTypeBoolean, 0, MAXDWORD, NULL, &StagingConfig.bCreateHomedir }, { "SkeletonDirs", TRUE, LsaTypeString, 0, MAXDWORD, NULL, &StagingConfig.pszSkelDirs }, { "AcceptNTLMv1", TRUE, LsaTypeBoolean, 0, MAXDWORD, NULL, &StagingConfig.bAcceptNTLMv1 }, }; LSA_CONFIG LsaConfigDescription[] = { { "EnableEventlog", TRUE, LsaTypeBoolean, 0, MAXDWORD, NULL, &StagingConfig.bEnableEventLog } }; dwError = LocalCfgInitialize(&StagingConfig); BAIL_ON_LSA_ERROR(dwError); dwError = LsaProcessConfig( "Services\\lsass\\Parameters\\Providers\\Local", "Policy\\Services\\lsass\\Parameters\\Providers\\Local", LpConfigDescription, sizeof(LpConfigDescription)/sizeof(LpConfigDescription[0])); BAIL_ON_LSA_ERROR(dwError); dwError = LsaProcessConfig( "Services\\lsass\\Parameters", "Policy\\Services\\lsass\\Parameters", LsaConfigDescription, sizeof(LsaConfigDescription)/sizeof(LsaConfigDescription[0])); BAIL_ON_LSA_ERROR(dwError); dwError = LocalCfgSetDefaultLoginShell( &StagingConfig, "LoginShellTemplate", pszLoginShell); BAIL_ON_LSA_ERROR(dwError); dwError = LocalCfgSetHomedirPrefix( &StagingConfig, "HomeDirPrefix", pszHomedirPrefix); BAIL_ON_LSA_ERROR(dwError); dwError = LocalCfgSetHomedirUmask( &StagingConfig, "HomeDirUmask", pszUmask); BAIL_ON_LSA_ERROR(dwError); LocalCfgTransferContents(&StagingConfig, pConfig); cleanup: LW_SAFE_FREE_STRING(pszLoginShell); LW_SAFE_FREE_STRING(pszHomedirPrefix); LW_SAFE_FREE_STRING(pszUmask); LocalCfgFreeContents(&StagingConfig); return dwError; error: LocalCfgFreeContents(pConfig); goto cleanup; } static DWORD LocalCfgSetDefaultLoginShell( PLOCAL_CONFIG pConfig, PCSTR pszName, PCSTR pszValue ) { DWORD dwError = 0; PSTR pszLoginShell = NULL; if (LW_IS_NULL_OR_EMPTY_STR(pszValue)) { goto error; } if (access(pszValue, X_OK) != 0) { LSA_LOG_ERROR("Invalid login shell [%s]", pszValue); goto error; } dwError = LwAllocateString(pszValue, &pszLoginShell); BAIL_ON_LSA_ERROR(dwError); LW_SAFE_FREE_STRING(pConfig->pszLoginShell); pConfig->pszLoginShell = pszLoginShell; pszLoginShell = NULL; cleanup: return dwError; error: LW_SAFE_FREE_STRING(pszLoginShell); goto cleanup; } static DWORD LocalCfgSetHomedirPrefix( PLOCAL_CONFIG pConfig, PCSTR pszName, PCSTR pszValue ) { DWORD dwError = 0; PSTR pszHomedirPrefix = NULL; if (LW_IS_NULL_OR_EMPTY_STR(pszValue)) { goto error; } dwError = LwAllocateString(pszValue, &pszHomedirPrefix); BAIL_ON_LSA_ERROR(dwError); LwStripWhitespace(pszHomedirPrefix, TRUE, TRUE); if (LW_IS_NULL_OR_EMPTY_STR(pszHomedirPrefix)) { goto error; } if (*pszHomedirPrefix != '/') { LSA_LOG_ERROR("Invalid home directory prefix [%s]", pszHomedirPrefix); goto error; } LW_SAFE_FREE_STRING(pConfig->pszHomedirPrefix); pConfig->pszHomedirPrefix = pszHomedirPrefix; pszHomedirPrefix = NULL; cleanup: return dwError; error: LW_SAFE_FREE_STRING(pszHomedirPrefix); goto cleanup; } static DWORD LocalCfgSetHomedirUmask( PLOCAL_CONFIG pConfig, PCSTR pszName, PCSTR pszValue ) { DWORD dwError = 0; PCSTR cp = NULL; DWORD dwOct = 0; DWORD dwVal = 0; DWORD dwCnt = 0; char cp2[2]; // Convert the umask octal string to a decimal number if (LW_IS_NULL_OR_EMPTY_STR(pszValue)) { goto error; } cp2[1] = 0; for ( cp = pszValue, dwCnt = 0 ; isdigit((int)*cp) ; cp++, dwCnt++ ) { dwOct *= 8; cp2[0] = *cp; dwVal = atoi(cp2); if ( dwVal > 7 ) { LSA_LOG_ERROR("Invalid Umask [%s]", pszValue); goto error; } dwOct += dwVal; } if ( dwCnt > 4 ) { LSA_LOG_ERROR("Invalid Umask [%s]", pszValue); goto error; } // Disallow 07xx since the user should always have // access to his home directory. if ( (dwOct & 0700) == 0700 ) { LSA_LOG_ERROR("Invalid Umask [%s]. User cannot access home directory.", pszValue); goto error; } else { pConfig->dwHomedirUMask = dwOct; } cleanup: return dwError; error: goto cleanup; }