static OSStatus AuthMechanismDestroy( IN AuthorizationMechanismRef pMechanismRef ) { PLW_AUTH_MECHANISM_INSTANCE pMechanismInstance = pMechanismRef; OSStatus osStatus = noErr; if (pMechanismInstance == NULL) { LSA_LOG_DEBUG( "Likewise auth plugin called with NULL mechanism instance"); goto error; } if (pMechanismInstance->pAuthMechanism == NULL) { LSA_LOG_DEBUG( "Likewise auth plugin called with NULL mechanism pointer"); goto error; } LSA_LOG_DEBUG( "Destroying auth mechanism Likewise:%s", pMechanismInstance->pAuthMechanism->name); if (pMechanismInstance->pAuthMechanism->Destroy != NULL && pMechanismInstance->pAuthMechanism->Destroy( pMechanismInstance) != noErr) { LSA_LOG_DEBUG( "Destroying auth mechanism Likewise:%s failed", pMechanismInstance->pAuthMechanism->name); goto error; } cleanup: return osStatus; error: /* * The documentation says all errors should return * errAuthorizationInternal. */ osStatus = errAuthorizationInternal; goto cleanup; }
static DWORD LsaAdBatchGatherNonSchemaModeGroup( IN OUT PLSA_AD_BATCH_ITEM pItem, IN DWORD dwKeywordValuesCount, IN PSTR* ppszKeywordValues ) { DWORD dwError = 0; DWORD dwValue = 0; dwError = ADNonSchemaKeywordGetUInt32( ppszKeywordValues, dwKeywordValuesCount, AD_LDAP_GID_TAG, &dwValue); if (LW_ERROR_INVALID_LDAP_ATTR_VALUE == dwError) { SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_DISABLED); dwError = LW_ERROR_SUCCESS; } BAIL_ON_LSA_ERROR(dwError); if (IsSetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_DISABLED)) { goto cleanup; } if (!dwValue) { LSA_LOG_DEBUG("gid must be non-zero for SID '%s'", pItem->pszSid); // SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_SKIP); dwError = LW_ERROR_DATA_ERROR; BAIL_ON_LSA_ERROR(dwError); } pItem->GroupInfo.gid = (gid_t)dwValue; dwError = ADNonSchemaKeywordGetString( ppszKeywordValues, dwKeywordValuesCount, AD_LDAP_DISPLAY_NAME_TAG, &pItem->GroupInfo.pszAlias); BAIL_ON_LSA_ERROR(dwError); dwError = ADNonSchemaKeywordGetString( ppszKeywordValues, dwKeywordValuesCount, AD_LDAP_PASSWD_TAG, &pItem->GroupInfo.pszPasswd); BAIL_ON_LSA_ERROR(dwError); cleanup: return dwError; error: goto cleanup; }
DWORD LsaSrvInitAuthProvider( IN PLSA_AUTH_PROVIDER pProvider, IN OPTIONAL PLSA_STATIC_PROVIDER pStaticProviders ) { DWORD dwError = 0; PFNINITIALIZEPROVIDER pfnInitProvider = NULL; PCSTR pszError = NULL; PSTR pszProviderLibpath = NULL; int i = 0; if (pStaticProviders) { /* First look for a static provider entry with the given name */ for (i = 0; pStaticProviders[i].pszId; i++) { if (!strcmp(pStaticProviders[i].pszId, pProvider->pszId)) { pfnInitProvider = pStaticProviders[i].pInitialize; LSA_LOG_DEBUG("Provider %s loaded from static list", pProvider->pszId); break; } } } if (!pfnInitProvider) { /* Try to load the provider dynamically */ if (LW_IS_NULL_OR_EMPTY_STR(pProvider->pszProviderLibpath)) { dwError = LW_ERROR_INVALID_AUTH_PROVIDER; BAIL_ON_LSA_ERROR(dwError); } pszProviderLibpath = pProvider->pszProviderLibpath; dlerror(); pProvider->pLibHandle = dlopen(pszProviderLibpath, RTLD_NOW | RTLD_LOCAL); if (!pProvider->pLibHandle) { LSA_LOG_ERROR("Failed to open auth provider at path '%s'", pszProviderLibpath); pszError = dlerror(); if (!LW_IS_NULL_OR_EMPTY_STR(pszError)) { LSA_LOG_ERROR("%s", pszError); } dwError = LW_ERROR_INVALID_AUTH_PROVIDER; BAIL_ON_LSA_ERROR(dwError); } dlerror(); pfnInitProvider = (PFNINITIALIZEPROVIDER) dlsym( pProvider->pLibHandle, LSA_SYMBOL_NAME_INITIALIZE_PROVIDER); if (!pfnInitProvider) { LSA_LOG_ERROR("Ignoring invalid auth provider at path '%s'", pszProviderLibpath); pszError = dlerror(); if (!LW_IS_NULL_OR_EMPTY_STR(pszError)) { LSA_LOG_ERROR("%s", pszError); } dwError = LW_ERROR_INVALID_AUTH_PROVIDER; BAIL_ON_LSA_ERROR(dwError); } } dwError = pfnInitProvider( &pProvider->pszName, &pProvider->pFnTable); BAIL_ON_LSA_ERROR(dwError); dwError = LsaSrvValidateProvider(pProvider); BAIL_ON_LSA_ERROR(dwError); cleanup: return dwError; error: goto cleanup; }
DWORD LsaReadVersionFile( PLSA_VERSION pVersion ) { DWORD dwError = 0; DWORD dwMajor = 0; DWORD dwMinor = 0; DWORD dwBuild = 0; DWORD dwRevision = 0; int versionFile = -1; // A typical version file is 40 bytes long. The whole file can be read into // a static buffer, because if the file is too long, then it is invalid. char szFileBuffer[200]; ssize_t dwCount = 0; // Do not free PSTR pszPos = szFileBuffer; #ifdef MINIMAL_LSASS versionFile = open(LOCALSTATEDIR "/VERSION", O_RDONLY, 0); #else versionFile = open(PREFIXDIR "/data/ENTERPRISE_VERSION", O_RDONLY, 0); if (versionFile < 0 && errno == ENOENT) { versionFile = open(PREFIXDIR "/data/VERSION", O_RDONLY, 0); } #endif if (versionFile < 0) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(dwError); } dwCount = read(versionFile, szFileBuffer, sizeof(szFileBuffer)); if (dwCount < 0) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(dwError); } if (dwCount == sizeof(szFileBuffer)) { dwError = LW_ERROR_INVALID_AGENT_VERSION; BAIL_ON_LSA_ERROR(dwError); } szFileBuffer[dwCount] = 0; while (*pszPos) { LwStripWhitespace(pszPos, TRUE, TRUE); if (!strncmp(pszPos, "VERSION=", sizeof("VERSION=") - 1)) { pszPos += sizeof("VERSION=") - 1; errno = 0; dwMajor = strtoul(pszPos, &pszPos, 10); dwError = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(dwError); if (pszPos[0] != '.') { dwError = LW_ERROR_INVALID_AGENT_VERSION; BAIL_ON_LSA_ERROR(dwError); } pszPos++; dwMinor = strtoul(pszPos, &pszPos, 10); dwError = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(dwError); } else if (!strncmp(pszPos, "BUILD=", sizeof("BUILD=") - 1)) { pszPos += sizeof("BUILD=") - 1; errno = 0; dwBuild = strtoul(pszPos, &pszPos, 10); dwError = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(dwError); } else if (!strncmp(pszPos, "REVISION=", sizeof("REVISION=") - 1)) { pszPos += sizeof("REVISION=") - 1; errno = 0; dwRevision = strtoul(pszPos, &pszPos, 10); dwError = LwMapErrnoToLwError(errno); if (dwError != 0) { LSA_LOG_DEBUG("Unable to parse revision due to error %u", dwError); dwRevision = 0; dwError = 0; } } pszPos = strchr(pszPos, '\n'); if (!pszPos) { break; } // Skip the \n pszPos++; if (*pszPos == '\r') { pszPos++; } } pVersion->dwMajor = dwMajor; pVersion->dwMinor = dwMinor; pVersion->dwBuild = dwBuild; pVersion->dwRevision = dwRevision; cleanup: if (versionFile != -1) { close(versionFile); } return dwError; error: memset(pVersion, 0, sizeof(*pVersion)); goto cleanup; }
DWORD AD_GroupExpansionDataGetNextGroupToExpand( IN PLSA_AD_GROUP_EXPANSION_DATA pExpansionData, OUT PLSA_SECURITY_OBJECT* ppGroupToExpand, OUT PDWORD pdwGroupToExpandDepth ) { DWORD dwError = 0; PLSA_SECURITY_OBJECT pGroupToExpand = NULL; DWORD dwGroupToExpandDepth = 0; const LW_HASH_ENTRY* pHashEntry = NULL; dwError = pExpansionData->dwLastError; BAIL_ON_LSA_ERROR(dwError); if (pExpansionData->pGroupsToExpand->sCount < 1) { // Nothing to return goto cleanup; } if (pExpansionData->bIsIteratorInitialized) { pHashEntry = LwHashNext(&pExpansionData->GroupsToExpandIterator); } if (!pHashEntry) { // Either the iterator is not initialized or we // reached the end of the hash table and need to start over. dwError = LwHashGetIterator( pExpansionData->pGroupsToExpand, &pExpansionData->GroupsToExpandIterator); BAIL_ON_LSA_ERROR(dwError); pExpansionData->bIsIteratorInitialized = TRUE; pHashEntry = LwHashNext(&pExpansionData->GroupsToExpandIterator); if (!pHashEntry) { dwError = LW_ERROR_INTERNAL; BAIL_ON_LSA_ERROR(dwError); } } pGroupToExpand = (PLSA_SECURITY_OBJECT) pHashEntry->pKey; dwGroupToExpandDepth = (size_t) pHashEntry->pValue; dwGroupToExpandDepth++; // Move the object to the expanded list. Note that the object is // not necessarily expanded yet, but we must remove it from // the "to expand" list. It does not hurt to track it in the // "expanded" list. dwError = LwHashSetValue(pExpansionData->pExpandedGroups, pGroupToExpand, (PVOID)(size_t)dwGroupToExpandDepth); BAIL_ON_LSA_ERROR(dwError); dwError = LwHashRemoveKey(pExpansionData->pGroupsToExpand, pGroupToExpand); if (dwError) { LSA_LOG_DEBUG("ASSERT: cannot fail"); } BAIL_ON_LSA_ERROR(dwError); cleanup: *ppGroupToExpand = pGroupToExpand; *pdwGroupToExpandDepth = dwGroupToExpandDepth; return dwError; error: ADCacheSafeFreeObject(&pGroupToExpand); dwGroupToExpandDepth = 0; if (dwError && !pExpansionData->dwLastError) { pExpansionData->dwLastError = dwError; } goto cleanup; }
DWORD LsaSetSMBCreds( IN PCSTR pszUserPrincipalName, IN PCSTR pszPassword, IN BOOLEAN bSetDefaultCachePath, OUT PLSA_CREDS_FREE_INFO* ppFreeInfo ) { DWORD dwError = 0; krb5_error_code ret = 0; PSTR pszNewCachePath = NULL; PCSTR pszCacheName = NULL; PCSTR pszCacheType = NULL; krb5_context ctx = 0; krb5_ccache cc = 0; LW_PIO_CREDS pNewCreds = NULL; LW_PIO_CREDS pOldCreds = NULL; PLSA_CREDS_FREE_INFO pFreeInfo = NULL; PSTR pszOldCachePath = NULL; BOOLEAN bSwitchedPath = FALSE; BAIL_ON_INVALID_POINTER(ppFreeInfo); BAIL_ON_INVALID_STRING(pszUserPrincipalName); ret = krb5_init_context(&ctx); BAIL_ON_KRB_ERROR(ctx, ret); /* Generates a new filed based credentials cache in /tmp. The file will * be owned by root and only accessible by root. */ ret = krb5_cc_new_unique( ctx, "FILE", "hint", &cc); BAIL_ON_KRB_ERROR(ctx, ret); pszCacheType = krb5_cc_get_type(ctx, cc); pszCacheName = krb5_cc_get_name(ctx, cc); dwError = LwAllocateStringPrintf(&pszNewCachePath, "%s:%s", pszCacheType, pszCacheName); BAIL_ON_LSA_ERROR(dwError); dwError = LwKrb5GetTgt( pszUserPrincipalName, pszPassword, pszNewCachePath, NULL); BAIL_ON_LSA_ERROR(dwError); if (bSetDefaultCachePath) { LSA_LOG_DEBUG("Switching default credentials path for new access token"); dwError = LwKrb5SetThreadDefaultCachePath( pszNewCachePath, &pszOldCachePath); BAIL_ON_LSA_ERROR(dwError); bSwitchedPath = TRUE; } dwError = LwIoCreateKrb5CredsA( pszUserPrincipalName, pszNewCachePath, &pNewCreds); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateMemory(sizeof(*pFreeInfo), (PVOID*)&pFreeInfo); BAIL_ON_LSA_ERROR(dwError); dwError = LwIoGetThreadCreds(&pOldCreds); BAIL_ON_LSA_ERROR(dwError); dwError = LwIoSetThreadCreds(pNewCreds); BAIL_ON_LSA_ERROR(dwError); pFreeInfo->ctx = ctx; pFreeInfo->cc = cc; pFreeInfo->pRestoreCreds = pOldCreds; pFreeInfo->pszRestoreCache = pszOldCachePath; pFreeInfo->bKrbCreds = TRUE; pOldCreds = NULL; cleanup: *ppFreeInfo = pFreeInfo; if (pOldCreds != NULL) { LwIoDeleteCreds(pOldCreds); } if (pNewCreds != NULL) { LwIoDeleteCreds(pNewCreds); } LW_SAFE_FREE_STRING(pszNewCachePath); return dwError; error: if (ctx != NULL) { if (cc != NULL) { krb5_cc_destroy(ctx, cc); } krb5_free_context(ctx); } if (pFreeInfo) { LwFreeMemory(pFreeInfo); pFreeInfo = NULL; } if (bSwitchedPath) { LwKrb5SetThreadDefaultCachePath( pszOldCachePath, NULL); LW_SAFE_FREE_STRING(pszOldCachePath); } goto cleanup; }
DWORD SELinuxCreate( PSELINUX *ppSELinux ) { DWORD dwError = 0; PSELINUX pSELinux = NULL; dwError = LwAllocateMemory(sizeof(SELINUX), (PVOID*)&pSELinux); BAIL_ON_LSA_ERROR(dwError); pSELinux->bEnabled = FALSE; #if ENABLE_SELINUX BOOLEAN bFileExists = FALSE; dwError = LsaCheckFileExists(LIBSELINUX, &bFileExists); BAIL_ON_LSA_ERROR(dwError); if (bFileExists == FALSE) { LSA_LOG_DEBUG("Could not find %s", LIBSELINUX); goto error; } pSELinux->dlhandle = dlopen(LIBSELINUX, RTLD_LAZY | RTLD_LOCAL); if (pSELinux->dlhandle == NULL) { LSA_LOG_ERROR("Could not load " LIBSELINUX ": %s", dlerror()); goto cleanup; } else { pSELinux->is_selinux_enabled = dlsym(pSELinux->dlhandle, "is_selinux_enabled"); pSELinux->matchpathcon_init = dlsym(pSELinux->dlhandle, "matchpathcon_init"); pSELinux->matchpathcon_fini = dlsym(pSELinux->dlhandle, "matchpathcon_fini"); pSELinux->matchpathcon = dlsym(pSELinux->dlhandle, "matchpathcon"); pSELinux->setfilecon= dlsym(pSELinux->dlhandle, "setfilecon"); pSELinux->freecon = dlsym(pSELinux->dlhandle, "freecon"); if (!pSELinux->is_selinux_enabled || !pSELinux->matchpathcon || !pSELinux->setfilecon || !pSELinux->freecon) { LSA_LOG_ERROR("Could not find symbol in " LIBSELINUX); dwError = LW_ERROR_LOOKUP_SYMBOL_FAILED; BAIL_ON_LSA_ERROR(dwError); } if (pSELinux->is_selinux_enabled() == 1) { LSA_LOG_DEBUG("SELinux is enabled."); if(pSELinux->matchpathcon_init != NULL) { pSELinux->matchpathcon_init(NULL); } pSELinux->bEnabled = TRUE; } } #endif *ppSELinux = pSELinux; cleanup: return dwError; error: LW_SAFE_FREE_MEMORY(pSELinux); goto cleanup; }
DWORD LsaSetSystemTime( time_t ttCurTime ) { DWORD dwError = 0; BOOLEAN bTimeset = FALSE; DWORD dwCount = 0; // The aix implementation of clock_settime segfaults #ifdef __LWI_AIX__ #undef HAVE_CLOCK_SETTIME #endif #if !defined(HAVE_CLOCK_SETTIME) && !defined(HAVE_SETTIMEOFDAY) #error Either clock_settime or settimeofday is needed #endif #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) struct timespec systemspec; #endif #if HAVE_SETTIMEOFDAY || HAVE_GETTIMEOFDAY struct timeval systemval; #endif long long readTime = -1; #ifdef HAVE_CLOCK_SETTIME memset(&systemspec, 0, sizeof(systemspec)); systemspec.tv_sec = ttCurTime; #endif #if HAVE_SETTIMEOFDAY memset(&systemval, 0, sizeof(systemval)); systemval.tv_sec = ttCurTime; #endif #ifdef HAVE_CLOCK_SETTIME if (!bTimeset) { if (clock_settime(CLOCK_REALTIME, &systemspec) == -1) { LSA_LOG_VERBOSE("Setting time with clock_settime failed %d", errno); } else { LSA_LOG_VERBOSE("Setting time with clock_settime worked"); bTimeset = TRUE; } } #endif #ifdef HAVE_SETTIMEOFDAY if (!bTimeset) { if (settimeofday(&systemval, NULL) == -1) { LSA_LOG_VERBOSE("Setting time with settimeofday failed %d", errno); } else { LSA_LOG_VERBOSE("Setting time with settimeofday worked"); bTimeset = TRUE; } } #endif if (!bTimeset) { dwError = LW_ERROR_FAILED_TO_SET_TIME; BAIL_ON_LSA_ERROR(dwError); } //Verify the clock got set bTimeset = FALSE; #ifdef HAVE_CLOCK_GETTIME if (!bTimeset && clock_gettime(CLOCK_REALTIME, &systemspec) >= 0) { bTimeset = TRUE; readTime = systemspec.tv_sec; } #endif #ifdef HAVE_GETTIMEOFDAY if (!bTimeset && gettimeofday(&systemval, NULL) >= 0) { bTimeset = TRUE; readTime = systemval.tv_sec; } #endif if (!bTimeset) { dwError = LW_ERROR_FAILED_TO_SET_TIME; BAIL_ON_LSA_ERROR(dwError); } //Make sure the time is now within 5 seconds of what we set if (labs(readTime - ttCurTime) > 5) { LSA_LOG_ERROR("Attempted to set time to %ld, but it is now %ld.", ttCurTime, readTime); dwError = LW_ERROR_FAILED_TO_SET_TIME; BAIL_ON_LSA_ERROR(dwError); } //Make sure the time reported by time() is now within 5 seconds of //what we set. On virtual systems it may be slow to update. for ( dwCount = 0 ; dwCount < 5 ; dwCount++ ) { readTime = time(NULL); if (labs(readTime - ttCurTime) > 5) { LSA_LOG_DEBUG("Time is slow to update...waiting"); sleep(1); } else { break; } } cleanup: return dwError; error: goto cleanup; }
static DWORD LsaAdBatchGatherNonSchemaModeUser( IN OUT PLSA_AD_BATCH_ITEM pItem, IN DWORD dwKeywordValuesCount, IN PSTR* ppszKeywordValues ) { DWORD dwError = 0; DWORD dwValue = 0; dwError = ADNonSchemaKeywordGetUInt32( ppszKeywordValues, dwKeywordValuesCount, AD_LDAP_UID_TAG, &dwValue); if (LW_ERROR_INVALID_LDAP_ATTR_VALUE == dwError) { SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_DISABLED); dwError = LW_ERROR_SUCCESS; } BAIL_ON_LSA_ERROR(dwError); if (IsSetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_DISABLED)) { goto cleanup; } if (!dwValue) { LSA_LOG_DEBUG("uid must be non-zero for SID '%s'", pItem->pszSid); // SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_SKIP); dwError = LW_ERROR_DATA_ERROR; BAIL_ON_LSA_ERROR(dwError); } pItem->UserInfo.uid = (uid_t)dwValue; dwError = ADNonSchemaKeywordGetUInt32( ppszKeywordValues, dwKeywordValuesCount, AD_LDAP_GID_TAG, &dwValue); BAIL_ON_LSA_ERROR(dwError); if (!dwValue) { LSA_LOG_DEBUG("gid must be non-zero for SID '%s'", pItem->pszSid); // SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_SKIP); dwError = LW_ERROR_DATA_ERROR; BAIL_ON_LSA_ERROR(dwError); } pItem->UserInfo.gid = (gid_t)dwValue; dwError = ADNonSchemaKeywordGetString( ppszKeywordValues, dwKeywordValuesCount, AD_LDAP_ALIAS_TAG, &pItem->UserInfo.pszAlias); BAIL_ON_LSA_ERROR(dwError); dwError = ADNonSchemaKeywordGetString( ppszKeywordValues, dwKeywordValuesCount, AD_LDAP_PASSWD_TAG, &pItem->UserInfo.pszPasswd); BAIL_ON_LSA_ERROR(dwError); dwError = ADNonSchemaKeywordGetString( ppszKeywordValues, dwKeywordValuesCount, AD_LDAP_GECOS_TAG, &pItem->UserInfo.pszGecos); BAIL_ON_LSA_ERROR(dwError); dwError = ADNonSchemaKeywordGetString( ppszKeywordValues, dwKeywordValuesCount, AD_LDAP_HOMEDIR_TAG, &pItem->UserInfo.pszHomeDirectory); BAIL_ON_LSA_ERROR(dwError); dwError = ADNonSchemaKeywordGetString( ppszKeywordValues, dwKeywordValuesCount, AD_LDAP_SHELL_TAG, &pItem->UserInfo.pszShell); BAIL_ON_LSA_ERROR(dwError); dwError = ADNonSchemaKeywordGetString( ppszKeywordValues, dwKeywordValuesCount, AD_LDAP_LOCALWINDOWSHOMEFOLDER_TAG, &pItem->UserInfo.pszLocalWindowsHomeFolder); BAIL_ON_LSA_ERROR(dwError); cleanup: return dwError; error: goto cleanup; }
DWORD LsaSrvGetLsassVersion( PLSA_VERSION pVersion ) { DWORD dwError = 0; PSTR pszVersion = NULL; DWORD iVerComp = 0; PSTR pszToken = NULL; PSTR pszTokenState = NULL; DWORD dwMajor = 0; DWORD dwMinor = 0; DWORD dwBuild = 0; DWORD dwRevision = 0; if (LW_IS_NULL_OR_EMPTY_STR(COMPONENT_VERSION)) { dwError = LW_ERROR_INVALID_AGENT_VERSION; BAIL_ON_LSA_ERROR(dwError); } dwError = LwAllocateString( COMPONENT_VERSION, &pszVersion); BAIL_ON_LSA_ERROR(dwError); pszToken = strtok_r(pszVersion, ".", &pszTokenState); while (!LW_IS_NULL_OR_EMPTY_STR(pszVersion) && (iVerComp < 4)) { int i = 0; for (; i < strlen(pszVersion); i++) { if (!isdigit((int)pszVersion[i])) { dwError = LW_ERROR_INVALID_AGENT_VERSION; BAIL_ON_LSA_ERROR(dwError); } } switch (iVerComp++) { case 0: dwMajor = atoi(pszToken); break; case 1: dwMinor = atoi(pszToken); break; case 2: dwBuild = atoi(pszToken); break; case 3: errno = 0; dwRevision = strtoul(pszToken, NULL, 10); dwError = LwMapErrnoToLwError(errno); if (dwError != 0) { LSA_LOG_DEBUG("Unable to parse revision due to error %u", dwError); dwRevision = 0; dwError = 0; } break; default: dwError = LW_ERROR_INTERNAL; BAIL_ON_LSA_ERROR(dwError); } pszToken = strtok_r(NULL, ".", &pszTokenState); } if (iVerComp < 4) { dwError = LW_ERROR_INVALID_AGENT_VERSION; BAIL_ON_LSA_ERROR(dwError); } pVersion->dwMajor = dwMajor; pVersion->dwMinor = dwMinor; pVersion->dwBuild = dwBuild; pVersion->dwRevision = dwRevision; cleanup: LW_SAFE_FREE_MEMORY(pszVersion); return dwError; error: memset(pVersion, 0, sizeof(*pVersion)); goto cleanup; }
static OSStatus AuthMechanismCreate( IN AuthorizationPluginRef pPluginRef, IN AuthorizationEngineRef pEngineRef, IN AuthorizationMechanismId mechanismId, OUT AuthorizationMechanismRef *ppMechanismRef ) { PLW_AUTH_MECHANISM pAuthMechanism = NULL; PLW_AUTH_MECHANISM_INSTANCE pMechanismInstance = NULL; OSStatus osStatus = noErr; DWORD dwError = LW_ERROR_SUCCESS; LSA_LOG_DEBUG("Creating auth mechanism Likewise:%s", mechanismId); for (pAuthMechanism = gpAuthMechanisms; pAuthMechanism != NULL; pAuthMechanism = pAuthMechanism->pNext) { if (!strcmp(pAuthMechanism->name, mechanismId)) { break; } } if (pAuthMechanism == NULL) { LSA_LOG_DEBUG("Auth mechanism Likewise:%s not found", mechanismId); goto error; } dwError = AUTH_PLUGIN_ALLOCATE(pMechanismInstance); BAIL_ON_LSA_ERROR(dwError); pMechanismInstance->pAuthPlugin = pPluginRef; pMechanismInstance->pAuthEngine = pEngineRef; pMechanismInstance->pAuthMechanism = pAuthMechanism; pMechanismInstance->pMechanismData = NULL; if (pAuthMechanism->Create) { if (pAuthMechanism->Create(pMechanismInstance) != noErr) { goto error; } } cleanup: *ppMechanismRef = pMechanismInstance; return osStatus; error: if (pMechanismInstance) { if (pMechanismInstance->pAuthMechanism && pMechanismInstance->pAuthMechanism->Destroy) { pMechanismInstance->pAuthMechanism->Destroy(pMechanismInstance); } LwFreeMemory(pMechanismInstance); } /* * The documentation says all errors should return * errAuthorizationInternal. */ osStatus = errAuthorizationInternal; goto cleanup; }
int main(int argc, const char **argv) { poptContext poptContext; int poptResult; uid_t uid; int kq; HANDLE lsaConnection = (HANDLE) NULL; PVOID pUserInfo = NULL; struct kevent event = { 0 }; int numChanges = 1; krb5_context krb5Context = NULL; char krb5FileCachePath[PATH_MAX]; krb5_ccache krb5FileCache = NULL; krb5_ccache krb5MemoryCache = NULL; krb5_cc_cursor krb5Cursor = NULL; krb5_creds krb5Credentials = { 0 }; krb5_principal krb5Principal = NULL; krb5_error_code krb5Error; int exitStatus = 0; DWORD dwError = LW_ERROR_SUCCESS; poptContext = poptGetContext(NULL, argc, argv, Options, 0); while ((poptResult = poptGetNextOpt(poptContext)) >= 0) { /* All options are processed automatically. */ } if (poptResult < -1) { fprintf(stderr, "%s: %s: %s\n", getprogname(), poptBadOption(poptContext, POPT_BADOPTION_NOALIAS), poptStrerror(poptResult)); exitStatus = 1; goto error; } uid = getuid(); /* Make sure we're running as an AD user. */ dwError = LsaOpenServer(&lsaConnection); BAIL_ON_LSA_ERROR(dwError); dwError = LsaFindUserById( lsaConnection, uid, 0, &pUserInfo); if (dwError == LW_ERROR_NO_SUCH_USER) { /* * Running as a non-AD user; exit 0 so launchd doesn't restart * the ticketcopy program (see com.beyondtrust.pbis.ticketcopy.plist). */ LSA_LOG_DEBUG( "uid %lu is not an AD user; exiting", (unsigned long) uid); dwError = LW_ERROR_SUCCESS; goto cleanup; } BAIL_ON_LSA_ERROR(dwError); kq = kqueue(); BAIL_ON_UNIX_ERROR(kq == -1); krb5Error = krb5_init_context(&krb5Context); BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); krb5Error = krb5_cc_default(krb5Context, &krb5MemoryCache); BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); snprintf( krb5FileCachePath, sizeof(krb5FileCachePath), "FILE:/tmp/krb5cc_%lu", (unsigned long) uid); while (1) /* Forever (or until an error occurs) */ { while ((event.ident = open(krb5FileCachePath + 5, O_RDONLY)) == -1) { sleep(5); } event.filter = EVFILT_VNODE; event.flags = EV_ADD | EV_ENABLE | EV_CLEAR; event.fflags = NOTE_DELETE | NOTE_WRITE; numChanges = 1; krb5Error = krb5_cc_resolve( krb5Context, krb5FileCachePath, &krb5FileCache); BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); while (1) /* While the file continues to exist. */ { /* * Turn off KRB5_TC_OPENCLOSE so the file will be opened once * and kept open. This causes it to actually attempt to open * the file, so this is where we check for the file not * existing and retry after sleeping a bit. */ krb5Error = krb5_cc_set_flags(krb5Context, krb5FileCache, 0); if (krb5Error == KRB5_FCC_NOFILE) { break; } BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); /* Copy all credentials from the file to the memory cache. */ krb5Error = krb5_cc_start_seq_get( krb5Context, krb5FileCache, &krb5Cursor); BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); while ((krb5Error = krb5_cc_next_cred( krb5Context, krb5FileCache, &krb5Cursor, &krb5Credentials)) == 0) { krb5Error = krb5_cc_store_cred( krb5Context, krb5MemoryCache, &krb5Credentials); if (krb5Error == KRB5_FCC_NOFILE) { krb5Error = krb5_cc_get_principal( krb5Context, krb5FileCache, &krb5Principal); BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); /* The memory cache was destroyed; re-create it. */ krb5Error = krb5_cc_initialize( krb5Context, krb5MemoryCache, krb5Principal); BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); krb5_free_principal(krb5Context, krb5Principal); krb5Principal = NULL; krb5Error = krb5_cc_store_cred( krb5Context, krb5MemoryCache, &krb5Credentials); } BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); krb5_free_cred_contents(krb5Context, &krb5Credentials); } if (krb5Error != KRB5_CC_END) { BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); } krb5Error = krb5_cc_end_seq_get( krb5Context, krb5FileCache, &krb5Cursor); krb5Cursor = NULL; BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); /* * Turn KRB5_TC_OPENCLOSE back on; this will cause * the file to be closed and any locks to be * released. */ krb5Error = krb5_cc_set_flags( krb5Context, krb5FileCache, KRB5_TC_OPENCLOSE); BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); /* * Wait for the file to be modified or deleted. The first * time this is called after the file is opened, numChanges * will be 1, which will install the fd into the event * list. After that numChanges is changed to 0, so it will * just report events from the existing list. */ if (kevent(kq, &event, numChanges, &event, 1, NULL) != 1) { fprintf(stderr, "kevent failed\n"); exitStatus = 1; goto cleanup; } if (event.fflags & NOTE_DELETE) { break; } numChanges = 0; } krb5Error = krb5_cc_close(krb5Context, krb5FileCache); BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError); krb5FileCache = NULL; close(event.ident); event.ident = -1; /* * The cache file is usually removed as part of a * rename(2) system call, so only wait a short * time before the first attempt to re-open it. */ usleep(100000); } error: cleanup: krb5_free_cred_contents(krb5Context, &krb5Credentials); if (krb5Cursor) { krb5_cc_end_seq_get(krb5Context, krb5FileCache, &krb5Cursor); } if (krb5FileCache) { krb5_cc_close(krb5Context, krb5FileCache); } if (krb5Principal) { krb5_free_principal(krb5Context, krb5Principal); } if (krb5Context) { krb5_free_context(krb5Context); } if (event.ident != -1) { close(event.ident); } if (pUserInfo) { LsaFreeUserInfo(0, pUserInfo); } if (lsaConnection != (HANDLE) NULL) { LsaCloseServer(lsaConnection); } if (dwError) { exitStatus = 1; } return exitStatus; }