/* 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 */ #include "domainjoin.h" #include "djdaemonmgr.h" #include "ctstrutils.h" #include "djauthinfo.h" #include // aka: CENTERROR_LICENSE_INCORRECT static DWORD GPAGENT_LICENSE_ERROR = 0x00002001; // CENTERROR_LICENSE_EXPIRED static DWORD GPAGENT_LICENSE_EXPIRED_ERROR = 0x00002002; #define GCE(x) GOTO_CLEANUP_ON_CENTERROR((x)) #define PWGRD "/etc/rc.config.d/pwgr" static QueryResult QueryStopDaemons(const JoinProcessOptions *options, LWException **exc) { BOOLEAN running; QueryResult result = FullyConfigured; LWException *inner = NULL; /* Check for lwiauthd and likewise-open */ DJGetDaemonStatus("gpagentd", &running, &inner); if (!LW_IS_OK(inner) && inner->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON) { /* The gpagentd may not be installed so ignore */ LW_HANDLE(&inner); running = FALSE; } LW_CLEANUP(exc, inner); if(running) result = NotConfigured; DJGetDaemonStatus("lwmgmtd", &running, &inner); if (!LW_IS_OK(inner) && inner->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON) { /* The lwmgmtd may not be installed so ignore */ LW_HANDLE(&inner); running = FALSE; } LW_CLEANUP(exc, inner); if(running) result = NotConfigured; cleanup: LW_HANDLE(&inner); return result; } static void StopDaemons(JoinProcessOptions *options, LWException **exc) { LW_TRY(exc, DJManageDaemons(FALSE, &LW_EXC)); cleanup: ; } void DJManageDaemonsDescription( BOOLEAN bStart, PSTR *description, LWException **exc ); static PSTR GetStopDescription(const JoinProcessOptions *options, LWException **exc) { PSTR daemonsDescription = NULL; LW_TRY(exc, DJManageDaemonsDescription(FALSE, &daemonsDescription, &LW_EXC)); cleanup: return daemonsDescription; } const JoinModule DJDaemonStopModule = { TRUE, "stop", "stop daemons", QueryStopDaemons, StopDaemons, GetStopDescription }; static QueryResult QueryStartDaemons(const JoinProcessOptions *options, LWException **exc) { BOOLEAN running; QueryResult result = FullyConfigured; const ModuleState *stopState = DJGetModuleStateByName((JoinProcessOptions *)options, "stop"); LWException *inner = NULL; if(!options->joiningDomain) { result = NotApplicable; goto cleanup; } DJGetDaemonStatus("gpagentd", &running, &inner); if (!LW_IS_OK(inner) && inner->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON) { /* The gpagentd may not be installed so ignore */ LW_HANDLE(&inner); running = TRUE; } LW_CLEANUP(exc, inner); if(!running) result = NotConfigured; DJGetDaemonStatus("lwmgmtd", &running, &inner); if (!LW_IS_OK(inner) && inner->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON) { /* The lwmgmtd may not be installed so ignore */ LW_HANDLE(&inner); running = TRUE; } LW_CLEANUP(exc, inner); if(!running) result = NotConfigured; if(stopState != NULL && stopState->runModule) result = NotConfigured; cleanup: LW_HANDLE(&inner); return result; } static void StartDaemons(JoinProcessOptions *options, LWException **exc) { LW_TRY(exc, DJManageDaemons(TRUE, &LW_EXC)); cleanup: ; } static PSTR GetStartDescription(const JoinProcessOptions *options, LWException **exc) { PSTR daemonsDescription = NULL; PSTR ret = NULL; LW_TRY(exc, DJManageDaemonsDescription(TRUE, &daemonsDescription, &LW_EXC)); LW_CLEANUP_CTERR(exc, CTAllocateStringPrintf(&ret, "rm /var/lib/lwidentity/*_cache.tdb\n%s", daemonsDescription)); cleanup: CT_SAFE_FREE_STRING(daemonsDescription); return ret; } const JoinModule DJDaemonStartModule = { TRUE, "start", "start daemons", QueryStartDaemons, StartDaemons, GetStartDescription }; void DJRestartIfRunning(PCSTR daemon, LWException **exc) { BOOLEAN running; LWException *inner = NULL; DJGetDaemonStatus(daemon, &running, &inner); if(!LW_IS_OK(inner) && inner->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON) { //The daemon isn't installed LW_HANDLE(&inner); running = FALSE; } LW_CLEANUP(exc, inner); if(!running) goto cleanup; DJ_LOG_INFO("Restarting '%s'", daemon); LW_TRY(exc, DJStartStopDaemon(daemon, FALSE, &LW_EXC)); DJ_LOG_INFO("Starting '%s'", daemon); LW_TRY(exc, DJStartStopDaemon(daemon, TRUE, &LW_EXC)); cleanup: LW_HANDLE(&inner); } void DJManageDaemonsDescription( BOOLEAN bStart, PSTR *description, LWException **exc ) { BOOLEAN bFileExists = TRUE; LWException *innerExc = NULL; int daemonCount; int i; int j; StringBuffer buffer; PSTR daemonDescription = NULL; LW_CLEANUP_CTERR(exc, CTStringBufferConstruct(&buffer)); LW_CLEANUP_CTERR(exc, CTCheckFileExists(PWGRD, &bFileExists)); if(bFileExists && bStart) { LW_CLEANUP_CTERR(exc, CTStringBufferAppend(&buffer, "Shutdown pwgrd because it only handles usernames up to 8 characters long. This is done by running '/sbin/init.d/pwgr stop' and setting PWGR=0 in "PWGRD".")); } //Figure out how many daemons there are for(daemonCount = 0; daemonList[daemonCount].primaryName != NULL; daemonCount++); if(bStart) { //Start the daemons in ascending order i = 0; } else { i = daemonCount; } while(TRUE) { if(i >= daemonCount) break; if(i < 0) break; CT_SAFE_FREE_STRING(daemonDescription); DJManageDaemonDescription(daemonList[i].primaryName, bStart, daemonList[i].startPriority, daemonList[i].stopPriority, &daemonDescription, &innerExc); //Try the alternate daemon name if there is one for(j = 0; !LW_IS_OK(innerExc) && innerExc->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON && daemonList[i].alternativeNames[j] != NULL; j++) { LW_HANDLE(&innerExc); DJManageDaemonDescription(daemonList[i].alternativeNames[j], bStart, daemonList[i].startPriority, daemonList[i].stopPriority, &daemonDescription, &innerExc); if (!LW_IS_OK(innerExc) && innerExc->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON) { LW_HANDLE(&innerExc); } else break; } if (!LW_IS_OK(innerExc) && innerExc->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON && !daemonList[i].required) { LW_HANDLE(&innerExc); } LW_CLEANUP(exc, innerExc); if(daemonDescription != NULL) { LW_CLEANUP_CTERR(exc, CTStringBufferAppend(&buffer, daemonDescription)); } if(bStart) i++; else i--; } *description = CTStringBufferFreeze(&buffer); cleanup: CT_SAFE_FREE_STRING(daemonDescription); LW_HANDLE(&innerExc); CTStringBufferDestroy(&buffer); } void DJManageDaemons( BOOLEAN bStart, LWException **exc ) { BOOLEAN bFileExists = TRUE; FILE* fp = NULL; PSTR pszErrFilePath = "/var/cache/likewise/grouppolicy/gpagentd.err"; CHAR szBuf[256+1]; DWORD dwGPErrCode = 0; LWException *innerExc = NULL; int daemonCount; int i; int j; PLSA_LOG_INFO pLogInfo = NULL; BOOLEAN bLsassContacted = FALSE; DWORD dwError = 0; LW_HANDLE hLsa = NULL; LW_CLEANUP_CTERR(exc, CTCheckFileExists(PWGRD, &bFileExists)); if(bFileExists) { //Shutdown pwgr (a nscd-like daemon) on HP-UX because it only handles //usernames up to 8 characters in length. LW_TRY(exc, DJStartStopDaemon("pwgr", FALSE, &LW_EXC)); LW_CLEANUP_CTERR(exc, CTRunSedOnFile(PWGRD, PWGRD, FALSE, "s/=1/=0/")); } //Figure out how many daemons there are for(daemonCount = 0; daemonList[daemonCount].primaryName != NULL; daemonCount++); if(bStart) { //Start the daemons in ascending order for(i = 0; i < daemonCount; i++) { DJManageDaemon(daemonList[i].primaryName, bStart, daemonList[i].startPriority, daemonList[i].stopPriority, &innerExc); //Try the alternate daemon name if there is one for(j = 0; !LW_IS_OK(innerExc) && innerExc->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON && daemonList[i].alternativeNames[j] != NULL; j++) { LW_HANDLE(&innerExc); DJManageDaemon(daemonList[i].alternativeNames[j], bStart, daemonList[i].startPriority, daemonList[i].stopPriority, &innerExc); if (!LW_IS_OK(innerExc) && innerExc->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON) { LW_HANDLE(&innerExc); } else break; } if (!LW_IS_OK(innerExc) && innerExc->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON && !daemonList[i].required) { LW_HANDLE(&innerExc); } if (LW_IS_OK(innerExc) && !strcmp(daemonList[i].primaryName, "gpagentd")) { LW_CLEANUP_CTERR(exc, CTCheckFileExists(pszErrFilePath, &bFileExists)); if (bFileExists) { LW_HANDLE(&innerExc); fp = fopen(pszErrFilePath, "r"); if (fp != NULL) { if (fgets(szBuf, 256, fp) != NULL) { CTStripWhitespace(szBuf); dwGPErrCode = atoi(szBuf); if (dwGPErrCode == GPAGENT_LICENSE_ERROR || dwGPErrCode == GPAGENT_LICENSE_EXPIRED_ERROR) { LW_RAISE(exc, CENTERROR_DOMAINJOIN_LICENSE_ERROR); goto cleanup; } } } else { DJ_LOG_ERROR("Failed to open file [%s]", pszErrFilePath); } } } LW_CLEANUP(exc, innerExc); } // Make sure lsass is responding bLsassContacted = FALSE; for (i = 0; !bLsassContacted && i < 30; i++) { DJ_LOG_INFO("Trying to contact lsassd"); if (hLsa) { LsaCloseServer(hLsa); hLsa = NULL; } dwError = LsaOpenServer(&hLsa); if (dwError == ERROR_FILE_NOT_FOUND || dwError == LW_ERROR_ERRNO_ECONNREFUSED) { DJ_LOG_INFO("Failed with %d", dwError); dwError = 0; sleep(1); continue; } LW_CLEANUP_LSERR(exc, dwError); LW_CLEANUP_LSERR(exc, LsaGetLogInfo(hLsa, &pLogInfo)); bLsassContacted = TRUE; } if (!bLsassContacted) { LW_RAISE_EX(exc, CENTERROR_DOMAINJOIN_INCORRECT_STATUS, "Unable to reach lsassd", "The lsass daemon could not be reached for 30 seconds after trying to start it. Please verify it is running."); goto cleanup; } } else { //Stop the daemons in descending order for(i = daemonCount - 1; i >= 0; i--) { DJManageDaemon(daemonList[i].primaryName, bStart, daemonList[i].startPriority, daemonList[i].stopPriority, &innerExc); //Try the alternate daemon name if there is one for(j = 0; !LW_IS_OK(innerExc) && innerExc->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON && daemonList[i].alternativeNames[j] != NULL; j++) { LW_HANDLE(&innerExc); DJManageDaemon(daemonList[i].alternativeNames[j], bStart, daemonList[i].startPriority, daemonList[i].stopPriority, &innerExc); if (!LW_IS_OK(innerExc) && innerExc->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON) { LW_HANDLE(&innerExc); } else break; } if (!LW_IS_OK(innerExc) && innerExc->code == CENTERROR_DOMAINJOIN_MISSING_DAEMON && !daemonList[i].required) { LW_HANDLE(&innerExc); } LW_CLEANUP(exc, innerExc); } } cleanup: CTSafeCloseFile(&fp); if (pLogInfo) { LsaFreeLogInfo(pLogInfo); } if (hLsa) { LsaCloseServer(hLsa); } LW_HANDLE(&innerExc); }