static DWORD LsaAdBatchMarshalUserInfoFixShell( IN PLSA_AD_PROVIDER_STATE pState, IN OUT PSTR* ppszShell ) { DWORD dwError = 0; PSTR pszShell = *ppszShell; if (LW_IS_NULL_OR_EMPTY_STR(pszShell)) { dwError = AD_GetUnprovisionedModeShell( pState, &pszShell); BAIL_ON_LSA_ERROR(dwError); BAIL_ON_INVALID_STRING(pszShell); } cleanup: *ppszShell = pszShell; return dwError; error: goto cleanup; }
static DWORD AD_CheckList( PCSTR pszNeedle, PCSTR pszaHaystack, PBOOLEAN pbFoundIt ) { DWORD dwError = 0; BOOLEAN bFoundIt = FALSE; PCSTR pszCurrent = NULL; BAIL_ON_INVALID_STRING(pszNeedle); pszCurrent = pszaHaystack; if (pszCurrent) { while (*pszCurrent) { if (!strcasecmp(pszCurrent, pszNeedle)) { bFoundIt = TRUE; goto cleanup; } pszCurrent = pszCurrent + strlen(pszCurrent) + 1; } } cleanup: *pbFoundIt = bFoundIt; return dwError; error: goto cleanup; }
static DWORD SetMachineSid( PSTR pszSid ) { DWORD dwError = 0; HANDLE hLsaConnection = NULL; BAIL_ON_INVALID_STRING(pszSid); dwError = LsaOpenServer(&hLsaConnection); BAIL_ON_LSA_ERROR(dwError); dwError = LsaSetMachineSid(hLsaConnection, pszSid); BAIL_ON_LSA_ERROR(dwError); fprintf(stdout, "Successfully set machine SID to %s\n", pszSid); cleanup: if (hLsaConnection != (HANDLE)NULL) { LsaCloseServer(hLsaConnection); } return dwError; error: goto cleanup; }
static DWORD LsaAdBatchMarshalUserInfoFixHomeDirectory( IN PLSA_AD_PROVIDER_STATE pState, IN OUT PSTR* ppszHomeDirectory, IN PCSTR pszNetbiosDomainName, IN PCSTR pszSamAccountName ) { DWORD dwError = 0; PSTR pszHomeDirectory = *ppszHomeDirectory; PSTR pszNewHomeDirectory = NULL; if (LW_IS_NULL_OR_EMPTY_STR(pszHomeDirectory)) { dwError = AD_GetUnprovisionedModeHomedirTemplate( pState, &pszHomeDirectory); BAIL_ON_LSA_ERROR(dwError); BAIL_ON_INVALID_STRING(pszHomeDirectory); } if (strstr(pszHomeDirectory, "%")) { dwError = AD_BuildHomeDirFromTemplate( pState, pszHomeDirectory, pszNetbiosDomainName, pszSamAccountName, &pszNewHomeDirectory); if (dwError) { // If we encounter a problem with fixing up the shell, leave the user object with the actual // value stored in AD and log the problem. LSA_LOG_INFO("While processing information for user (%s), an invalid homedir value was detected (homedir: '%s')", LSA_SAFE_LOG_STRING(pszSamAccountName), LSA_SAFE_LOG_STRING(pszHomeDirectory)); dwError = 0; goto cleanup; } LW_SAFE_FREE_STRING(pszHomeDirectory); LSA_XFER_STRING(pszNewHomeDirectory, pszHomeDirectory); } LwStrCharReplace(pszHomeDirectory, ' ', '_'); cleanup: *ppszHomeDirectory = pszHomeDirectory; return dwError; error: goto cleanup; }
static DWORD LocalCfgSetHomedirPrefix( PLOCAL_CONFIG pConfig, PCSTR pszName, PCSTR pszValue ) { DWORD dwError = 0; PSTR pszHomedirPrefix = NULL; BAIL_ON_INVALID_STRING(pszValue); dwError = LwAllocateString( pszValue, &pszHomedirPrefix); BAIL_ON_UP_ERROR(dwError); LwStripWhitespace(pszHomedirPrefix, TRUE, TRUE); BAIL_ON_INVALID_STRING(pszHomedirPrefix); if (*pszHomedirPrefix != '/') { LOG_ERROR("Invalid home directory prefix [%s]", pszHomedirPrefix); goto error; } LW_SAFE_FREE_STRING(pConfig->pszHomedirPrefix); pConfig->pszHomedirPrefix = pszHomedirPrefix; cleanup: return 0; error: LW_SAFE_FREE_STRING(pszHomedirPrefix); goto cleanup; }
LSASS_API DWORD LsaDeleteGroupByName( HANDLE hLsaConnection, PCSTR pszName ) { DWORD dwError = 0; PVOID pGroupInfo = NULL; DWORD dwGroupInfoLevel = 0; if (geteuid() != 0) { dwError = LW_ERROR_ACCESS_DENIED; BAIL_ON_LSA_ERROR(dwError); } BAIL_ON_INVALID_HANDLE(hLsaConnection); BAIL_ON_INVALID_STRING(pszName); dwError = LsaValidateGroupName(pszName); BAIL_ON_LSA_ERROR(dwError); dwError = LsaFindGroupByName( hLsaConnection, pszName, 0, dwGroupInfoLevel, &pGroupInfo); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDeleteGroupById( hLsaConnection, ((PLSA_GROUP_INFO_0)pGroupInfo)->gid); BAIL_ON_LSA_ERROR(dwError); cleanup: if (pGroupInfo) { LsaFreeGroupInfo(dwGroupInfoLevel, pGroupInfo); } return dwError; error: goto cleanup; }
static DWORD ValidateParameters( PCSTR pszSid ) { DWORD dwError = 0; NTSTATUS ntStatus = STATUS_SUCCESS; PSID pSid = NULL; BAIL_ON_INVALID_STRING(pszSid); ntStatus = RtlAllocateSidFromCString(&pSid, pszSid); if (ntStatus != STATUS_SUCCESS) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } if (RtlValidSid(pSid) && pSid->SubAuthorityCount != 4) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } cleanup: if (pSid) { RTL_FREE(&pSid); } return dwError; error: goto cleanup; }
static DWORD LocalCfgSetDefaultLoginShell( PLOCAL_CONFIG pConfig, PCSTR pszName, PCSTR pszValue ) { DWORD dwError = 0; PSTR pszLoginShell = NULL; BAIL_ON_INVALID_STRING(pszValue); if (access(pszValue, X_OK) != 0) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_UP_ERROR(dwError); } dwError = LwAllocateString( pszValue, &pszLoginShell); BAIL_ON_UP_ERROR(dwError); LW_SAFE_FREE_STRING(pConfig->pszLoginShell); pConfig->pszLoginShell = pszLoginShell; cleanup: return dwError; error: LW_SAFE_FREE_STRING(pszLoginShell); goto cleanup; }
static DWORD ValidateParameters( PCSTR pszName ) { DWORD dwError = 0; BAIL_ON_INVALID_STRING(pszName); if (strlen(pszName) > 15) { fprintf(stdout, "Machine name can have up to 15 characters\n"); dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } cleanup: return dwError; error: goto cleanup; }
DWORD DefaultModeNonSchemaEnumNSSArtefacts( PLSA_DM_LDAP_CONNECTION pConn, PCSTR pszCellDN, PCSTR pszNetBIOSDomainName, PAD_ENUM_STATE pEnumState, DWORD dwMaxNumNSSArtefacts, PDWORD pdwNumNSSArtefactsFound, PVOID** pppNSSArtefactInfoList ) { DWORD dwError = 0; DWORD dwCount = 0; PCSTR pszQuery = "(&(objectClass=serviceConnectionPoint)(keywords=objectClass=centerisLikewiseMapEntry))"; PSTR pszDN = NULL; PSTR pszEscapedDN = NULL; PVOID* ppNSSArtefactInfoList = NULL; PVOID* ppNSSArtefactInfoList_accumulate = NULL; DWORD dwTotalNumNSSArtefactsFound = 0; DWORD dwNumNSSArtefactsFound = 0; DWORD dwNSSArtefactInfoLevel = 0; PSTR szAttributeList[] = { AD_LDAP_NAME_TAG, AD_LDAP_KEYWORDS_TAG, NULL }; LDAPMessage *pMessagePseudo = NULL; LDAP *pLd = NULL; HANDLE hDirectory = NULL; DWORD dwNumNSSArtefactsWanted = dwMaxNumNSSArtefacts; dwNSSArtefactInfoLevel = pEnumState->dwInfoLevel; BAIL_ON_INVALID_STRING(pEnumState->pszMapName); dwError = LwAllocateStringPrintf( &pszDN, "CN=%s,CN=Maps,%s", pEnumState->pszMapName, pszCellDN); BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapEscapeString( &pszEscapedDN, pszDN); BAIL_ON_LSA_ERROR(dwError); if (pEnumState->Cookie.bSearchFinished){ dwError = LW_ERROR_NO_MORE_NSS_ARTEFACTS; BAIL_ON_LSA_ERROR(dwError); } do { dwError = LsaDmLdapDirectoryOnePagedSearch( pConn, pszEscapedDN, pszQuery, szAttributeList, dwNumNSSArtefactsWanted, &pEnumState->Cookie, LDAP_SCOPE_ONELEVEL, &hDirectory, &pMessagePseudo); BAIL_ON_LSA_ERROR(dwError); pLd = LwLdapGetSession(hDirectory); dwCount = ldap_count_entries( pLd, pMessagePseudo); if (dwCount < 0) { dwError = LW_ERROR_LDAP_ERROR; } else if (dwCount == 0) { dwError = LW_ERROR_NO_MORE_NSS_ARTEFACTS; } BAIL_ON_LSA_ERROR(dwError); dwError = ADNonSchemaMarshalNSSArtefactInfoList( hDirectory, pszNetBIOSDomainName, pMessagePseudo, pEnumState->dwMapFlags, dwNSSArtefactInfoLevel, &ppNSSArtefactInfoList, &dwNumNSSArtefactsFound ); BAIL_ON_LSA_ERROR(dwError); dwNumNSSArtefactsWanted -= dwNumNSSArtefactsFound; dwError = LsaAppendAndFreePtrs( &dwTotalNumNSSArtefactsFound, &ppNSSArtefactInfoList_accumulate, &dwNumNSSArtefactsFound, &ppNSSArtefactInfoList); BAIL_ON_LSA_ERROR(dwError); if (pMessagePseudo) { ldap_msgfree(pMessagePseudo); pMessagePseudo = NULL; } } while (!pEnumState->Cookie.bSearchFinished && dwNumNSSArtefactsWanted); *pppNSSArtefactInfoList = ppNSSArtefactInfoList_accumulate; *pdwNumNSSArtefactsFound = dwTotalNumNSSArtefactsFound; cleanup: LW_SAFE_FREE_STRING(pszDN); LW_SAFE_FREE_STRING(pszEscapedDN); return dwError; error: *pppNSSArtefactInfoList = NULL; *pdwNumNSSArtefactsFound = 0; if (ppNSSArtefactInfoList) { LsaFreeNSSArtefactInfoList(dwNSSArtefactInfoLevel, ppNSSArtefactInfoList, dwNumNSSArtefactsFound); } if (ppNSSArtefactInfoList_accumulate) { LsaFreeNSSArtefactInfoList(dwNSSArtefactInfoLevel, ppNSSArtefactInfoList_accumulate, dwTotalNumNSSArtefactsFound); } if (dwError == LW_ERROR_LDAP_NO_SUCH_OBJECT) { dwError = LW_ERROR_NO_MORE_NSS_ARTEFACTS; } goto cleanup; }
DWORD DefaultModeNonSchemaFindNSSArtefactByKey( IN PLSA_DM_LDAP_CONNECTION pConn, PCSTR pszCellDN, PCSTR pszNetBIOSDomainName, PCSTR pszKeyName, PCSTR pszMapName, DWORD dwInfoLevel, LSA_NIS_MAP_QUERY_FLAGS dwFlags, PVOID* ppNSSArtefactInfo ) { DWORD dwError = 0; DWORD dwCount = 0; PSTR pszQuery = NULL; PSTR pszDN = NULL; PSTR pszEscapedDN = NULL; PSTR szAttributeList[] = { AD_LDAP_NAME_TAG, AD_LDAP_KEYWORDS_TAG, NULL }; LDAPMessage *pMessagePseudo = NULL; PVOID* ppArtefactInfos = NULL; DWORD dwNumInfos = 0; BOOLEAN bMapExists = FALSE; LDAP *pLd = NULL; HANDLE hDirectory = NULL; BAIL_ON_INVALID_STRING(pszMapName); BAIL_ON_INVALID_STRING(pszKeyName); dwError = LwAllocateStringPrintf( &pszDN, "CN=%s,CN=Maps,%s", pszMapName, pszCellDN); BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapEscapeString( &pszEscapedDN, pszDN); BAIL_ON_LSA_ERROR(dwError); dwError = ADLdap_IsValidDN( pConn, pszEscapedDN, &bMapExists); BAIL_ON_LSA_ERROR(dwError); if (!bMapExists) { dwError = LW_ERROR_NO_SUCH_NSS_MAP; BAIL_ON_LSA_ERROR(dwError); } dwError = LwAllocateStringPrintf( &pszQuery, "(&(objectClass=serviceConnectionPoint)(keywords=objectClass=centerisLikewiseMapEntry)(name=%s))", pszKeyName); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDmLdapDirectorySearch( pConn, pszEscapedDN, LDAP_SCOPE_ONELEVEL, pszQuery, szAttributeList, &hDirectory, &pMessagePseudo); BAIL_ON_LSA_ERROR(dwError); pLd = LwLdapGetSession(hDirectory); dwCount = ldap_count_entries( pLd, pMessagePseudo); if (dwCount < 0) { dwError = LW_ERROR_LDAP_ERROR; } else if (dwCount == 0) { dwError = LW_ERROR_NO_SUCH_NSS_KEY; } BAIL_ON_LSA_ERROR(dwError); dwError = ADNonSchemaMarshalNSSArtefactInfoList( hDirectory, pszNetBIOSDomainName, pMessagePseudo, dwFlags, dwInfoLevel, &ppArtefactInfos, &dwNumInfos); BAIL_ON_LSA_ERROR(dwError); *ppNSSArtefactInfo = *ppArtefactInfos; *ppArtefactInfos = NULL; cleanup: if (pMessagePseudo) { ldap_msgfree(pMessagePseudo); } if (ppArtefactInfos) { LsaFreeNSSArtefactInfoList(dwInfoLevel, ppArtefactInfos, dwNumInfos); } LW_SAFE_FREE_STRING(pszDN); LW_SAFE_FREE_STRING(pszEscapedDN); LW_SAFE_FREE_STRING(pszQuery); return dwError; error: *ppNSSArtefactInfo = NULL; if (dwError == LW_ERROR_LDAP_NO_SUCH_OBJECT) { dwError = LW_ERROR_NO_SUCH_NSS_KEY; } goto cleanup; }
DWORD AD_BuildHomeDirFromTemplate( PLSA_AD_PROVIDER_STATE pState, PCSTR pszHomedirTemplate, PCSTR pszNetBIOSDomainName, PCSTR pszSamAccountName, PSTR* ppszHomedir ) { DWORD dwError = 0; PSTR pszHomedirPrefix = NULL; PSTR pszHomedir = NULL; DWORD dwOffset = 0; PCSTR pszIterTemplate = pszHomedirTemplate; DWORD dwBytesAllocated = 0; DWORD dwNetBIOSDomainNameLength = 0; DWORD dwSamAccountNameLength = 0; DWORD dwHomedirPrefixLength = 0; PSTR pszHostName = NULL; DWORD dwHostNameLength = 0; CHAR szEscapedPercent[2] = "%"; DWORD dwEscapedPercentLength = 0; BAIL_ON_INVALID_STRING(pszHomedirTemplate); BAIL_ON_INVALID_STRING(pszNetBIOSDomainName); BAIL_ON_INVALID_STRING(pszSamAccountName); if (strstr(pszHomedirTemplate, "%H")) { dwError = AD_GetHomedirPrefixPath(pState, &pszHomedirPrefix); BAIL_ON_LSA_ERROR(dwError); BAIL_ON_INVALID_STRING(pszHomedirPrefix); dwHomedirPrefixLength = strlen(pszHomedirPrefix); } if (strstr(pszHomedirTemplate, "%L")) { dwError = LsaDnsGetHostInfo(&pszHostName); BAIL_ON_LSA_ERROR(dwError); BAIL_ON_INVALID_STRING(pszHostName); dwHostNameLength = strlen(pszHostName); } if (strstr(pszHomedirTemplate, "%%")) { dwEscapedPercentLength = strlen(szEscapedPercent); } dwNetBIOSDomainNameLength = strlen(pszNetBIOSDomainName); dwSamAccountNameLength = strlen(pszSamAccountName); // Handle common case where we might use all replacements. dwBytesAllocated = (strlen(pszHomedirTemplate) + dwNetBIOSDomainNameLength + dwSamAccountNameLength + dwHomedirPrefixLength + dwHostNameLength + dwEscapedPercentLength + 1); dwError = LwAllocateMemory( sizeof(CHAR) * dwBytesAllocated, (PVOID*)&pszHomedir); BAIL_ON_LSA_ERROR(dwError); while (pszIterTemplate[0]) { // Do not count the terminating NULL as "available". DWORD dwBytesRemaining = dwBytesAllocated - dwOffset - 1; PCSTR pszInsert = NULL; DWORD dwInsertLength = 0; BOOLEAN bNeedUpper = FALSE; BOOLEAN bNeedLower = FALSE; LSA_ASSERT(dwOffset < dwBytesAllocated); if (pszIterTemplate[0] == '%') { switch (pszIterTemplate[1]) { case 'D': pszInsert = pszNetBIOSDomainName; dwInsertLength = dwNetBIOSDomainNameLength; bNeedUpper = TRUE; break; case 'U': pszInsert = pszSamAccountName; dwInsertLength = dwSamAccountNameLength; bNeedLower = TRUE; break; case 'H': pszInsert = pszHomedirPrefix; dwInsertLength = dwHomedirPrefixLength; break; case 'L': pszInsert = pszHostName; dwInsertLength = dwHostNameLength; break; case '%': pszInsert = szEscapedPercent; dwInsertLength = dwEscapedPercentLength; break; default: dwError = LW_ERROR_INVALID_HOMEDIR_TEMPLATE; BAIL_ON_LSA_ERROR(dwError); } LSA_ASSERT(!(bNeedUpper && bNeedLower)); pszIterTemplate += 2; } else { PCSTR pszEnd = strchr(pszIterTemplate, '%'); if (!pszEnd) { dwInsertLength = strlen(pszIterTemplate); } else { dwInsertLength = pszEnd - pszIterTemplate; } pszInsert = pszIterTemplate; pszIterTemplate += dwInsertLength; } if (dwBytesRemaining < dwInsertLength) { // We will increment by at least a minimum amount. DWORD dwAllocate = LSA_MAX(dwInsertLength - dwBytesRemaining, 64); PSTR pszNewHomedir = NULL; dwError = LwReallocMemory( pszHomedir, (PVOID*)&pszNewHomedir, dwBytesAllocated + dwAllocate); BAIL_ON_LSA_ERROR(dwError); pszHomedir = pszNewHomedir; dwBytesAllocated += dwAllocate; } memcpy(pszHomedir + dwOffset, pszInsert, dwInsertLength); if (bNeedUpper) { LwStrnToUpper(pszHomedir + dwOffset, dwInsertLength); } else if (bNeedLower) { LwStrnToLower(pszHomedir + dwOffset, dwInsertLength); } dwOffset += dwInsertLength; } // We should still have enough room for NULL. LSA_ASSERT(dwOffset < dwBytesAllocated); pszHomedir[dwOffset] = 0; dwOffset++; *ppszHomedir = pszHomedir; cleanup: LW_SAFE_FREE_STRING(pszHomedirPrefix); LW_SAFE_FREE_STRING(pszHostName); return dwError; error: *ppszHomedir = NULL; LW_SAFE_FREE_MEMORY(pszHomedir); 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; }
//Convert to seconds string of form ##s, ##m, ##h, or ##d //where s,m,h,d = seconds, minutes, hours, days. DWORD LsaParseDateString( PCSTR pszTimeInterval, PDWORD pdwTimeInterval ) { DWORD dwError = 0; DWORD dwTimeInterval = 0; PSTR pszTimeIntervalLocal = 0; DWORD dwTimeIntervalLocalLen = 0; DWORD dwUnitMultiplier = 0; PSTR pszUnitCode = NULL; LwStripWhitespace(pszTimeIntervalLocal, TRUE, TRUE); BAIL_ON_INVALID_STRING(pszTimeInterval); dwError = LwAllocateString( pszTimeInterval, &pszTimeIntervalLocal ); BAIL_ON_LSA_ERROR(dwError); dwTimeIntervalLocalLen = strlen(pszTimeIntervalLocal); pszUnitCode = pszTimeIntervalLocal + dwTimeIntervalLocalLen - 1; if (isdigit((int)(*pszUnitCode))) { dwUnitMultiplier = 1; } else { switch(*pszUnitCode) { case 's': case 'S': dwUnitMultiplier = 1; break; case 'm': case 'M': dwUnitMultiplier = LSA_SECONDS_IN_MINUTE; break; case 'h': case 'H': dwUnitMultiplier = LSA_SECONDS_IN_HOUR; break; case 'd': case 'D': dwUnitMultiplier = LSA_SECONDS_IN_DAY; break; default: dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); break; } *pszUnitCode = ' '; } LwStripWhitespace(pszTimeIntervalLocal, TRUE, TRUE); dwTimeInterval = (DWORD) atoi(pszTimeIntervalLocal) * dwUnitMultiplier; *pdwTimeInterval = dwTimeInterval; cleanup: LW_SAFE_FREE_STRING(pszTimeIntervalLocal); return dwError; error: goto cleanup; }
DWORD LwTaskAcquireCredsA( PCSTR pszUsername, /* IN */ PCSTR pszPassword, /* IN */ PLW_TASK_CREDS* ppCreds /* IN OUT */ ) { DWORD dwError = 0; krb5_error_code ret = 0; PSTR pszNewCachePath = NULL; PLW_TASK_CREDS pCreds = NULL; BAIL_ON_INVALID_POINTER(ppCreds); BAIL_ON_INVALID_STRING(pszUsername); dwError = LwAllocateMemory(sizeof(*pCreds), (PVOID*)&pCreds); BAIL_ON_LW_TASK_ERROR(dwError); ret = krb5_init_context(&pCreds->ctx); BAIL_ON_KRB_ERROR(pCreds->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(pCreds->ctx, "FILE", "hint", &pCreds->cc); BAIL_ON_KRB_ERROR(pCreds->ctx, ret); dwError = LwAllocateStringPrintf( &pszNewCachePath, "%s:%s", krb5_cc_get_type(pCreds->ctx, pCreds->cc), krb5_cc_get_name(pCreds->ctx, pCreds->cc)); BAIL_ON_LW_TASK_ERROR(dwError); dwError = LwKrb5GetTgt(pszUsername, pszPassword, pszNewCachePath, NULL); BAIL_ON_LW_TASK_ERROR(dwError); dwError = LwKrb5SetDefaultCachePath( pszNewCachePath, &pCreds->pszRestoreCache); BAIL_ON_LW_TASK_ERROR(dwError); dwError = LwIoCreateKrb5CredsA( pszUsername, pszNewCachePath, &pCreds->pKrb5Creds); BAIL_ON_LW_TASK_ERROR(dwError); *ppCreds = pCreds; cleanup: LW_SAFE_FREE_STRING(pszNewCachePath); return dwError; error: *ppCreds = NULL; if (pCreds) { LwTaskFreeCreds(pCreds); } goto cleanup; }
LSASS_API DWORD LsaFindGroupByName( HANDLE hLsaConnection, PCSTR pszGroupName, LSA_FIND_FLAGS FindFlags, DWORD dwGroupInfoLevel, PVOID* ppGroupInfo ) { DWORD dwError = 0; PVOID pGroupInfo = NULL; LSA_QUERY_LIST QueryList; LSA_QUERY_ITEM QueryItem; DWORD dwObjectCount = 1; PLSA_SECURITY_OBJECT* ppObjects = NULL; PLSA_SECURITY_OBJECT pGroup = NULL; BAIL_ON_INVALID_HANDLE(hLsaConnection); BAIL_ON_INVALID_STRING(pszGroupName); dwError = LsaValidateGroupInfoLevel(dwGroupInfoLevel); BAIL_ON_LSA_ERROR(dwError); BAIL_ON_INVALID_POINTER(ppGroupInfo); switch (dwGroupInfoLevel) { case 1: /* Fast path */ QueryItem.pszString = pszGroupName; dwError = LsaFindGroupAndExpandedMembers( hLsaConnection, NULL, FindFlags, LSA_QUERY_TYPE_BY_NAME, QueryItem, &pGroup, &dwObjectCount, &ppObjects); BAIL_ON_LSA_ERROR(dwError); dwError = LsaMarshalGroupInfo1( hLsaConnection, FindFlags, pGroup, dwObjectCount, ppObjects, dwGroupInfoLevel, &pGroupInfo); BAIL_ON_LSA_ERROR(dwError); break; default: QueryList.ppszStrings = &pszGroupName; dwError = LsaFindObjects( hLsaConnection, NULL, 0, LSA_OBJECT_TYPE_GROUP, LSA_QUERY_TYPE_BY_NAME, 1, QueryList, &ppObjects); BAIL_ON_LSA_ERROR(dwError); if (ppObjects[0] == NULL) { dwError = LW_ERROR_NO_SUCH_GROUP; BAIL_ON_LSA_ERROR(dwError); } dwError = LsaMarshalGroupInfo( hLsaConnection, FindFlags, ppObjects[0], dwGroupInfoLevel, &pGroupInfo); BAIL_ON_LSA_ERROR(dwError); } error: if (ppGroupInfo) { *ppGroupInfo = pGroupInfo; } if (pGroup) { LsaFreeSecurityObject(pGroup); } if (ppObjects) { LsaFreeSecurityObjectList(dwObjectCount, ppObjects); } return dwError; }
// Give an attribute name "pszAttributeName" // Return all the values of the attribute for a given DN "pszDN" // The number of values can be more than 1500 since "ranging" is handled correctly in the routine // Now accept whether to do an extended DN search and whether to parse result to get Sids DWORD ADLdap_GetAttributeValuesList( IN PLSA_DM_LDAP_CONNECTION pConn, IN PCSTR pszDN, IN PCSTR pszAttributeName, IN BOOLEAN bDoExtDnSearch, IN BOOLEAN bDoSidParsing, OUT PDWORD pdwTotalCount, OUT PSTR** pppszValues ) { DWORD dwError = 0; // Do not free "szAttributeList" PSTR szAttributeList[2] = {NULL,NULL}; PSTR* ppszValuesTotal = NULL; PSTR* ppszValues = NULL; LDAPMessage* pMessage = NULL; DWORD dwCount = 0; DWORD dwTotalCount = 0; PLW_DLINKED_LIST pList = NULL; PLW_DLINKED_LIST pNode = NULL; PLSA_AD_QUERY_LISTS_ENTRY pEntry = NULL; PSTR pszRangeAttr = NULL; LDAP* pLd = NULL; BerElement* pBer = NULL; PSTR pszRetrievedAttr = NULL; //Do Not free "pszRetrievedRangeAttr" PSTR pszRetrievedRangeAttr = NULL; BOOLEAN bIsEnd = FALSE; DWORD iValues = 0; DWORD iValuesTotal = 0; PSTR pszAttributeRangedName = NULL; HANDLE hDirectory = NULL; BAIL_ON_INVALID_STRING(pszAttributeName); szAttributeList[0] = (PSTR)pszAttributeName; for (;;) { if (pMessage) { ldap_msgfree(pMessage); pMessage = NULL; } if (!bDoExtDnSearch && bDoSidParsing) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } if (bDoExtDnSearch) { dwError = LsaDmLdapDirectoryExtendedDNSearch( pConn, pszDN, "(objectClass=*)", szAttributeList, LDAP_SCOPE_BASE, &hDirectory, &pMessage); BAIL_ON_LSA_ERROR(dwError); } else { dwError = LsaDmLdapDirectorySearch( pConn, pszDN, LDAP_SCOPE_BASE, "(objectClass=*)", szAttributeList, &hDirectory, &pMessage); BAIL_ON_LSA_ERROR(dwError); } pLd = LwLdapGetSession(hDirectory); dwError = LwLdapGetStringsWithExtDnResult( hDirectory, pMessage, pszAttributeName, bDoSidParsing, &ppszValues, &dwCount); BAIL_ON_LSA_ERROR(dwError); if (ppszValues && dwCount) { if (pList) { // This is the case where we started out getting // ranged info but the info became non-ranged. // We might actually want to allow this to handle // a case where the membership list is trimmed // while we are enumerating. dwError = LW_ERROR_LDAP_ERROR; BAIL_ON_LSA_ERROR(dwError); } dwTotalCount = dwCount; ppszValuesTotal = ppszValues; dwCount = 0; ppszValues = NULL; break; } if (pszRetrievedAttr) { ldap_memfree(pszRetrievedAttr); pszRetrievedAttr = NULL; } if (pBer) { ber_free(pBer, 0); } LW_SAFE_FREE_STRING(pszAttributeRangedName); dwError = LwAllocateStringPrintf( &pszAttributeRangedName, "%s;Range=", pszAttributeName); BAIL_ON_LSA_ERROR(dwError); pszRetrievedAttr = ldap_first_attribute(pLd, pMessage, &pBer); while (pszRetrievedAttr) { if (!strncasecmp(pszRetrievedAttr, pszAttributeRangedName, strlen(pszAttributeRangedName))) { pszRetrievedRangeAttr = pszRetrievedAttr; break; } ldap_memfree(pszRetrievedAttr); pszRetrievedAttr = NULL; pszRetrievedAttr = ldap_next_attribute(pLd, pMessage, pBer); } if (!pszRetrievedRangeAttr) { // This happens when we have an group with no members, break; } if ('*' == pszRetrievedRangeAttr[strlen(pszRetrievedRangeAttr)-1]) { bIsEnd = TRUE; } dwError = LwLdapGetStringsWithExtDnResult( hDirectory, pMessage, pszRetrievedRangeAttr, bDoSidParsing, &ppszValues, &dwCount); BAIL_ON_LSA_ERROR(dwError); dwTotalCount += dwCount; dwError = CreateQueryListEntry( &pEntry, dwCount, ppszValues); BAIL_ON_LSA_ERROR(dwError); ppszValues = NULL; dwCount = 0; dwError = LwDLinkedListPrepend(&pList, pEntry); BAIL_ON_LSA_ERROR(dwError); pEntry = NULL; if (bIsEnd) { break; } LW_SAFE_FREE_STRING(pszRangeAttr); dwError = LwAllocateStringPrintf( &pszRangeAttr, "%s%u-*", pszAttributeRangedName, dwTotalCount); BAIL_ON_LSA_ERROR(dwError); szAttributeList[0] = pszRangeAttr; } if (pList && !ppszValuesTotal) { dwError = LwAllocateMemory( sizeof(*ppszValuesTotal) * dwTotalCount, (PVOID*)&ppszValuesTotal); BAIL_ON_LSA_ERROR(dwError); for (pNode = pList; pNode; pNode = pNode->pNext) { PLSA_AD_QUERY_LISTS_ENTRY pEntry = (PLSA_AD_QUERY_LISTS_ENTRY)pNode->pItem; for (iValues = 0; iValues < pEntry->dwQueryCount; iValues++) { ppszValuesTotal[iValuesTotal] = pEntry->ppszQueryValues[iValues]; pEntry->ppszQueryValues[iValues] = NULL; iValuesTotal++; } } } *pdwTotalCount = dwTotalCount; *pppszValues = ppszValuesTotal; cleanup: if (pMessage) { ldap_msgfree(pMessage); } if (pszRetrievedAttr) { ldap_memfree(pszRetrievedAttr); } if (pBer) { ber_free(pBer, 0); } LwFreeStringArray(ppszValues, dwCount); DestroyQueryListEntry(&pEntry); LW_SAFE_FREE_STRING(pszAttributeRangedName); LW_SAFE_FREE_STRING(pszRangeAttr); for (pNode = pList; pNode; pNode = pNode->pNext) { PLSA_AD_QUERY_LISTS_ENTRY pEntry = (PLSA_AD_QUERY_LISTS_ENTRY)pNode->pItem; DestroyQueryListEntry(&pEntry); } LwDLinkedListFree(pList); return dwError; error: LwFreeStringArray(ppszValuesTotal, iValuesTotal); *pdwTotalCount = 0; *pppszValues = NULL; goto cleanup; }
DWORD ADGuidStrToHex( PCSTR pszStr, PSTR* ppszHexStr) { DWORD dwError = 0; PSTR pszHexStr = NULL; PSTR pszUUIDStr = NULL; int iValue = 0, jValue = 0; uuid_t uuid= {0}; unsigned char temp; BAIL_ON_INVALID_STRING(pszStr); dwError = LwAllocateString( pszStr, &pszUUIDStr); BAIL_ON_LSA_ERROR(dwError); if (uuid_parse(pszUUIDStr, uuid) < 0) { dwError = LW_ERROR_INVALID_OBJECTGUID; BAIL_ON_LSA_ERROR(dwError); } for(iValue = 0; iValue < 2; iValue++){ temp = uuid[iValue]; uuid[iValue] = uuid[3-iValue]; uuid[3-iValue] = temp; } temp = uuid[4]; uuid[4] = uuid[5]; uuid[5] = temp; temp = uuid[6]; uuid[6] = uuid[7]; uuid[7] = temp; dwError = LwAllocateMemory( sizeof(CHAR)*(AD_GUID_SIZE*3+1), (PVOID*)&pszHexStr); BAIL_ON_LSA_ERROR(dwError); for (iValue = 0, jValue = 0; jValue < AD_GUID_SIZE; ){ if (iValue % 3 == 0){ *((char*)(pszHexStr+iValue++)) = '\\'; } else{ sprintf((char*)pszHexStr+iValue, "%.2X", uuid[jValue]); iValue += 2; jValue++; } } *ppszHexStr = pszHexStr; cleanup: LW_SAFE_FREE_STRING(pszUUIDStr); return dwError; error: *ppszHexStr = NULL; LW_SAFE_FREE_STRING(pszHexStr); goto cleanup; }
static DWORD ADUnprovPlugin_QueryByIdWithDomainName( IN PLSA_AD_PROVIDER_STATE pState, IN BOOLEAN bIsUser, IN DWORD dwId, IN PCSTR pszDnsDomainName, OUT PSTR* ppszSid, OUT PSTR* ppszAlias ) { DWORD dwError = 0; PSID pDomainSid = NULL; PSTR pszDomainSid = NULL; PSTR pszSid = NULL; PSTR pszAlias = NULL; // lsass unprovisioned mode converts a group/user uid/gid to objectSid/name with the same algorithm dwError = LsaDmQueryDomainInfo(pState->hDmState, pszDnsDomainName, NULL, NULL, &pDomainSid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (LW_ERROR_NO_SUCH_DOMAIN == dwError) { LSA_LOG_WARNING("Domain '%s' is unknown.", pszDnsDomainName); } BAIL_ON_LSA_ERROR(dwError); dwError = LsaAllocateCStringFromSid( &pszDomainSid, pDomainSid); BAIL_ON_LSA_ERROR(dwError); BAIL_ON_INVALID_STRING(pszDomainSid); dwError = UnprovisionedModeMakeLocalSID( pszDomainSid, dwId, &pszSid); BAIL_ON_LSA_ERROR(dwError); *ppszSid = pszSid; *ppszAlias = pszAlias; cleanup: LW_SAFE_FREE_MEMORY(pDomainSid); LW_SAFE_FREE_STRING(pszDomainSid); return dwError; error: LW_SAFE_FREE_STRING(pszSid); LW_SAFE_FREE_STRING(pszAlias); *ppszSid = NULL; *ppszAlias = NULL; goto cleanup; }
LSASS_API DWORD LsaGetGidsForUserByName( HANDLE hLsaConnection, PCSTR pszUserName, PDWORD pdwGroupFound, gid_t** ppGidResults ) { DWORD dwError = 0; PVOID pUserInfo = NULL; DWORD dwUserInfoLevel = 0; static const DWORD dwGroupInfoLevel = 0; DWORD dwGroupFound = 0; gid_t* pGidResult = NULL; PVOID* ppGroupInfoList = NULL; DWORD iGroup = 0; BAIL_ON_INVALID_HANDLE(hLsaConnection); BAIL_ON_INVALID_STRING(pszUserName); BAIL_ON_INVALID_POINTER(ppGidResults); dwError = LsaValidateUserName(pszUserName); BAIL_ON_LSA_ERROR(dwError); dwError = LsaFindUserByName( hLsaConnection, pszUserName, dwUserInfoLevel, &pUserInfo); BAIL_ON_LSA_ERROR(dwError); dwError = LsaGetGroupsForUserById( hLsaConnection, ((PLSA_USER_INFO_0)pUserInfo)->uid, LSA_FIND_FLAGS_NSS, dwGroupInfoLevel, &dwGroupFound, &ppGroupInfoList); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateMemory( sizeof(gid_t) * dwGroupFound, (PVOID*)&pGidResult); BAIL_ON_LSA_ERROR(dwError); for (iGroup = 0; iGroup < dwGroupFound; iGroup++) { *(pGidResult+iGroup) = ((PLSA_GROUP_INFO_0)(*(ppGroupInfoList+iGroup)))->gid; } *ppGidResults = pGidResult; *pdwGroupFound = dwGroupFound; cleanup: if (pUserInfo) { LsaFreeUserInfo(dwUserInfoLevel, pUserInfo); } if (ppGroupInfoList) { LsaFreeGroupInfoList(dwGroupInfoLevel, (PVOID*)ppGroupInfoList, dwGroupFound); } return dwError; error: *ppGidResults = NULL; *pdwGroupFound = 0; goto cleanup; }