예제 #1
0
파일: config.c 프로젝트: borland667/pbis
DWORD
UmnSrvReadConfig(
    PUMN_SRV_API_CONFIG *ppConfig
    )
{
    DWORD dwError = 0;
    PUMN_SRV_API_CONFIG pConfig = NULL;

    dwError = UmnSrvInitConfig(&pConfig);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = UmnSrvReadAllocatedConfig(pConfig);
    BAIL_ON_UMN_ERROR(dwError);
    
    UMN_LOG_VERBOSE("CheckInterval = %d seconds\n",
            pConfig->CheckInterval);
    UMN_LOG_VERBOSE("SkipNoLogin = %d\n",
            pConfig->SkipNoLogin);

    *ppConfig = pConfig;

cleanup:

    return dwError;

error:
    UmnSrvFreeConfig(pConfig);
    *ppConfig = NULL;

    goto cleanup;
}
예제 #2
0
DWORD
UmnSrvPollerRefresh(
    VOID
    )
{
    DWORD dwError = 0;

    if (gbPollerThreadRunning)
    {
        gbPollerRefresh = TRUE;
        dwError = pthread_cond_signal(
                        &gSignalPoller);
        BAIL_ON_UMN_ERROR(dwError);
    }
    else
    {
        dwError = ESRCH;
        BAIL_ON_UMN_ERROR(dwError);
    }

cleanup:
    return dwError;

error:
    goto cleanup;
}
예제 #3
0
NTSTATUS
SvcmStart(
    PLW_SVCM_INSTANCE pInstance,
    ULONG ArgCount,
    PWSTR* ppArgs,
    ULONG FdCount,
    int* pFds
)
{
    DWORD dwError = 0;

    dwError = pthread_rwlock_init(&gUmnConfigLock, NULL);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = UmnSrvInitConfig(&gpAPIConfig);
    BAIL_ON_UMN_ERROR(dwError);

    // This function creates threads, so signals must be blocked first
    dwError = UmnSrvRefreshConfiguration();
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LWNetExtendEnvironmentForKrb5Affinity(TRUE);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = UmnSrvStartPollerThread();
    BAIL_ON_UMN_ERROR(dwError);

error:
    return dwError;
}
예제 #4
0
static
DWORD
UmnSrvWriteADGroupValues(
    HANDLE hReg,
    HKEY hGroup,
    PLSA_SECURITY_OBJECT pGroup
    )
{
    DWORD dwError = 0;
    DWORD dword = 0;
    PCSTR pString = NULL;

    dwError = RegSetValueExA(
                    hReg,
                    hGroup,
                    "gr_name",
                    0,
                    REG_SZ,
                    (PBYTE)pGroup->groupInfo.pszUnixName,
                    strlen(pGroup->groupInfo.pszUnixName) + 1);
    BAIL_ON_UMN_ERROR(dwError);

    pString = pGroup->groupInfo.pszPasswd;
    if (!pString)
    {
        pString = "x";
    }
    dwError = RegSetValueExA(
                    hReg,
                    hGroup,
                    "gr_passwd",
                    0,
                    REG_SZ,
                    (PBYTE)pString,
                    strlen(pString) + 1);
    BAIL_ON_UMN_ERROR(dwError);

    dword = pGroup->groupInfo.gid;
    dwError = RegSetValueExA(
                    hReg,
                    hGroup,
                    "gr_gid",
                    0,
                    REG_DWORD,
                    (PBYTE)&dword,
                    sizeof(dword));
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    return dwError;

error:
    goto cleanup;
}
예제 #5
0
DWORD
UmnSrvStartPollerThread(
    VOID
    )
{
    DWORD dwError = 0;
    BOOLEAN bDestroyOnError = FALSE;

    if (gbPollerThreadRunning)
    {
        dwError = EEXIST;
        BAIL_ON_UMN_ERROR(dwError);
    }

    bDestroyOnError = TRUE;

    dwError = pthread_cond_init(
                    &gSignalPoller,
                    NULL);
    BAIL_ON_UMN_ERROR(dwError);
    gbSignalPollerCreated = TRUE;
                    
    dwError = pthread_mutex_init(
                    &gSignalPollerMutex,
                    NULL);
    BAIL_ON_UMN_ERROR(dwError);
    gbSignalPollerMutexCreated = TRUE;

    gbPollerThreadShouldExit = FALSE;

    dwError = pthread_create(
                    &gPollerThread,
                    NULL,
                    UmnSrvPollerThreadRoutine,
                    NULL);
    BAIL_ON_UMN_ERROR(dwError);
    gbPollerThreadRunning = TRUE;

cleanup:
    return dwError;

error:
    if (bDestroyOnError)
    {
        UmnSrvStopPollerThread();
    }
    goto cleanup;
}
예제 #6
0
파일: config.c 프로젝트: borland667/pbis
DWORD
UmnSrvInitConfig(
    PUMN_SRV_API_CONFIG *ppConfig
    )
{
    PUMN_SRV_API_CONFIG pConfig = NULL;
    DWORD dwError = 0;

    dwError = RTL_ALLOCATE(
                    &pConfig,
                    UMN_SRV_API_CONFIG,
                    sizeof(*pConfig));
    BAIL_ON_UMN_ERROR(dwError);

    pConfig->CheckInterval = 60 * 30;
    pConfig->SkipNoLogin = FALSE;

    *ppConfig = pConfig;

cleanup:
    return dwError;

error:
    *ppConfig = NULL;
    UmnSrvFreeConfig(pConfig);
    goto cleanup;
}
예제 #7
0
DWORD
UmnSrvStopPollerThread(
    VOID
    )
{
    DWORD dwError = 0;

    gbPollerThreadShouldExit = TRUE;
    if (gbPollerThreadRunning)
    {
        dwError = pthread_cond_signal(
                        &gSignalPoller);
        BAIL_ON_UMN_ERROR(dwError);

        dwError = pthread_join(
                        gPollerThread,
                        NULL);
        BAIL_ON_UMN_ERROR(dwError);

        gbPollerThreadRunning = FALSE;
    }

    if (gbSignalPollerCreated)
    {
        dwError = pthread_cond_destroy(&gSignalPoller);
        BAIL_ON_UMN_ERROR(dwError);
        gbSignalPollerCreated = FALSE;
    }
                    
    if (gbSignalPollerMutexCreated)
    {
        dwError = pthread_mutex_destroy(&gSignalPollerMutex);
        BAIL_ON_UMN_ERROR(dwError);
    }

cleanup:
    return dwError;

error:
    goto cleanup;
}
예제 #8
0
파일: config.c 프로젝트: borland667/pbis
DWORD
UmnSrvRefreshConfiguration(
    )
{
    DWORD dwError = 0;
    BOOLEAN bUnlockConfigLock = FALSE;
    PUMN_SRV_API_CONFIG pAPIConfig = NULL;

    dwError = UmnSrvReadConfig(&pAPIConfig);
    BAIL_ON_UMN_ERROR(dwError);

    pthread_rwlock_wrlock(&gUmnConfigLock);
    bUnlockConfigLock = TRUE;

    UmnSrvFreeConfig(gpAPIConfig);
    gpAPIConfig = pAPIConfig;
    pAPIConfig = NULL;

    dwError = UmnSrvPollerRefresh();
    if (dwError == ESRCH)
    {
        // The thread may not be running yet
        dwError = 0;
    }
    BAIL_ON_UMN_ERROR(dwError);

cleanup:

    UmnSrvFreeConfig(pAPIConfig);

    if (bUnlockConfigLock)
    {
        pthread_rwlock_unlock(&gUmnConfigLock);
    }

    return(dwError);

error:
    goto cleanup;
}
예제 #9
0
/**
 * @brief Populate the timespec & timeval with the current time
 *
 * @param pDestTimespec
 * @param pDestTimeval
 *
 * @return 0 for success, or errno error code
 */
DWORD
static
UmnSrvNow(
    OUT struct timespec * const pDestTimespec,
    OUT struct timeval * const pDestTimeval
    )
{
    DWORD dwError = 0;

    dwError = gettimeofday(pDestTimeval, NULL);
    BAIL_ON_UMN_ERROR(dwError);

    UmnSrvTimevalToTimespec(
                pDestTimespec,
                pDestTimeval);

error:
    return dwError;
}
예제 #10
0
파일: config.c 프로젝트: borland667/pbis
DWORD
UmnSrvReadAllocatedConfig(
    PUMN_SRV_API_CONFIG pConfig
    )
{
    DWORD dwError = 0;

    LWREG_CONFIG_ITEM ConfigDescription[] =
    {
        {
            "CheckInterval",
            TRUE,
            LwRegTypeDword,
            0,
            -1,
            NULL,
            &pConfig->CheckInterval,
            NULL
        },
        {
            "SkipNoLogin",
            TRUE,
            LwRegTypeDword,
            0,
            -1,
            NULL,
            &pConfig->SkipNoLogin,
            NULL
        },
    };

    UMN_LOG_INFO("Read user monitor configuration settings");

    dwError = LwRegProcessConfig(
                "Services\\" SERVICE_NAME "\\Parameters",
                "Policy\\Services\\" SERVICE_NAME "\\Parameters",
                ConfigDescription,
                sizeof(ConfigDescription)/sizeof(ConfigDescription[0]));
    BAIL_ON_UMN_ERROR(dwError);

error:
    return dwError;
}
예제 #11
0
/**
 * @brief Set pElapsed to TRUE if pTimespec has elapsed.
 *
 * @param pTimespec
 * @param pElapsed set to TRUE if pTimespec is <= 'now',
 *  FALSE otherwise, always FALSE on error
 * @return 0 for success, or errno error code
 */
DWORD
static UmnSrvTimespecElapsed(
    IN struct timespec const * const pTimespec,
    OUT BOOLEAN * const pElapsed
    )
{
    DWORD dwError = ERROR_SUCCESS;
    struct timeval now = {0};
    struct timespec nowSpec = {0};

    *pElapsed = FALSE;

    dwError = UmnSrvNow(&nowSpec, &now);
    BAIL_ON_UMN_ERROR(dwError);

    *pElapsed = (nowSpec.tv_sec > pTimespec->tv_sec
                || (nowSpec.tv_sec == pTimespec->tv_sec
                    && nowSpec.tv_nsec >= pTimespec->tv_nsec))
        ? TRUE
        : FALSE;

error:
    return dwError;
}
예제 #12
0
파일: users.c 프로젝트: borland667/pbis
static
DWORD
UmnSrvWriteUserEvent(
    PLW_EVENTLOG_CONNECTION pEventlog,
    long long PreviousRun,
    PUSER_MONITOR_PASSWD pOld,
    long long Now,
    struct passwd *pNew
    )
{
    DWORD dwError = 0;
    // Do not free. The field values are borrowed from other structures.
    USER_CHANGE change = { { 0 } };
    LW_EVENTLOG_RECORD record = { 0 };
    char oldTimeBuf[128] = { 0 };
    char newTimeBuf[128] = { 0 };
    struct tm oldTmBuf = { 0 };
    struct tm newTmBuf = { 0 };
    time_t temp = 0;
    PCSTR pOperation = NULL;

    if (PreviousRun)
    {
        temp = PreviousRun;
        localtime_r(&temp, &oldTmBuf);
        strftime(
                oldTimeBuf,
                sizeof(oldTimeBuf),
                "%Y/%m/%d %H:%M:%S",
                &oldTmBuf);
    }
    else
    {
        strcpy(oldTimeBuf, "unknown");
    }
    temp = Now;
    localtime_r(&temp, &newTmBuf);

    strftime(
            newTimeBuf,
            sizeof(newTimeBuf),
            "%Y/%m/%d %H:%M:%S",
            &newTmBuf);

    if (pOld)
    {
        memcpy(&change.OldValue, pOld, sizeof(change.OldValue));
    }

    if (pNew)
    {
        change.NewValue.pw_name = pNew->pw_name;
        change.NewValue.pw_passwd = pNew->pw_passwd;
        change.NewValue.pw_uid = pNew->pw_uid;
        change.NewValue.pw_gid = pNew->pw_gid;
        change.NewValue.pw_gecos = pNew->pw_gecos;
        change.NewValue.pw_dir = pNew->pw_dir;
        change.NewValue.pw_shell = pNew->pw_shell;
        change.NewValue.LastUpdated = Now;
    }

    dwError = LwMbsToWc16s(
                    "Application",
                    &record.pLogname);
    BAIL_ON_UMN_ERROR(dwError);

    if (!PreviousRun)
    {
        dwError = LwMbsToWc16s(
                        "Success Audit",
                        &record.pEventType);
    }
    else
    {
        dwError = LwMbsToWc16s(
                        "Information",
                        &record.pEventType);
    }
    BAIL_ON_UMN_ERROR(dwError);

    record.EventDateTime = Now;

    dwError = LwMbsToWc16s(
                    "User Monitor",
                    &record.pEventSource);
    BAIL_ON_UMN_ERROR(dwError);

    if (pOld != NULL && pNew != NULL)
    {
        pOperation = "changed";
    }
    else if (pOld != NULL && pNew == NULL)
    {
        pOperation = "deleted";
    }
    else if (pOld == NULL && pNew != NULL)
    {
        pOperation = "added";
    }
    else
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_UMN_ERROR(dwError);
    }

    dwError = LwAllocateWc16sPrintfW(
                    &record.pEventCategory,
                    L"User %hhs",
                    pOperation);
    BAIL_ON_UMN_ERROR(dwError);

    if (pNew != NULL)
    {
        record.EventSourceId = pNew->pw_uid;

        dwError = LwMbsToWc16s(
                        pNew->pw_name,
                        &record.pUser);
        BAIL_ON_UMN_ERROR(dwError);
    }
    else
    {
        record.EventSourceId = pOld->pw_uid;

        dwError = LwMbsToWc16s(
                        pOld->pw_name,
                        &record.pUser);
        BAIL_ON_UMN_ERROR(dwError);
    }

    // Leave computer NULL so it is filled in by the eventlog

    dwError = LwAllocateWc16sPrintfW(
                    &record.pDescription,
                    L"Between %hhs and %hhs, user '%hhs' was %hhs.\n"
                    L"Passwd (from passwd struct)\n"
                    L"\tOld: %hhs\n"
                    L"\tNew: %hhs\n"
                    L"Uid\n"
                    L"\tOld: %d\n"
                    L"\tNew: %d\n"
                    L"Primary group id\n"
                    L"\tOld: %d\n"
                    L"\tNew: %d\n"
                    L"Gecos\n"
                    L"\tOld: %hhs\n"
                    L"\tNew: %hhs\n"
                    L"Home directory\n"
                    L"\tOld: %hhs\n"
                    L"\tNew: %hhs\n"
                    L"Shell\n"
                    L"\tOld: %hhs\n"
                    L"\tNew: %hhs",
                    oldTimeBuf,
                    newTimeBuf,
                    pOld ? pOld->pw_name : pNew->pw_name,
                    pOperation,
                    pOld ? pOld->pw_passwd : "",
                    pNew ? pNew->pw_passwd : "",
                    pOld ? pOld->pw_uid : -1,
                    pNew ? pNew->pw_uid : -1,
                    pOld ? pOld->pw_gid : -1,
                    pNew ? pNew->pw_gid : -1,
                    pOld ? pOld->pw_gecos : "",
                    pNew ? pNew->pw_gecos : "",
                    pOld ? pOld->pw_dir : "",
                    pNew ? pNew->pw_dir : "",
                    pOld ? pOld->pw_shell : "",
                    pNew ? pNew->pw_shell : "");
    BAIL_ON_UMN_ERROR(dwError);

    dwError = EncodeUserChange(
                    &change,
                    &record.DataLen,
                    (PVOID*)&record.pData);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwEvtWriteRecords(
                    pEventlog,
                    1,
                    &record);
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    LW_SAFE_FREE_MEMORY(record.pLogname);
    LW_SAFE_FREE_MEMORY(record.pEventType);
    LW_SAFE_FREE_MEMORY(record.pEventSource);
    LW_SAFE_FREE_MEMORY(record.pEventCategory);
    LW_SAFE_FREE_MEMORY(record.pUser);
    LW_SAFE_FREE_MEMORY(record.pDescription);
    LW_SAFE_FREE_MEMORY(record.pData);
    return dwError;

error:
    goto cleanup;
}
예제 #13
0
파일: users.c 프로젝트: borland667/pbis
DWORD
UmnSrvFindDeletedUsers(
    PLW_EVENTLOG_CONNECTION pEventlog,
    HANDLE hReg,
    PCSTR pUserKeyName,
    HKEY hUsers,
    long long Now
    )
{
    DWORD dwError = 0;
    DWORD subKeyCount = 0;
    DWORD maxSubKeyLen = 0;
    DWORD subKeyLen = 0;
    DWORD i = 0;
    PSTR pKeyName = NULL;
    DWORD lastUpdated = 0;
    DWORD lastUpdatedLen = 0;
    USER_MONITOR_PASSWD old = { 0 };

    dwError = RegQueryInfoKeyA(
                    hReg,
                    hUsers,
                    NULL,
                    NULL,
                    NULL,
                    &subKeyCount,
                    &maxSubKeyLen,
                    NULL,
                    NULL,
                    NULL,
                    NULL,
                    NULL,
                    NULL);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwAllocateMemory(
                    maxSubKeyLen + 1,
                    (PVOID *)&pKeyName);

    for (i = 0; i < subKeyCount; i++)
    {
        if (gbPollerThreadShouldExit)
        {
            dwError = ERROR_CANCELLED;
            BAIL_ON_UMN_ERROR(dwError);
        }
        subKeyLen = maxSubKeyLen;

        dwError = RegEnumKeyExA(
                        hReg,
                        hUsers,
                        i,
                        pKeyName,
                        &subKeyLen,
                        NULL,
                        NULL,
                        NULL,
                        NULL);
        BAIL_ON_UMN_ERROR(dwError);

        pKeyName[subKeyLen] = 0;

        lastUpdatedLen = sizeof(lastUpdated);
        dwError = RegGetValueA(
                        hReg,
                        hUsers,
                        pKeyName,
                        "LastUpdated",
                        0,
                        NULL,
                        (PBYTE)&lastUpdated,
                        &lastUpdatedLen);
        if (dwError == LWREG_ERROR_NO_SUCH_KEY_OR_VALUE)
        {
            UMN_LOG_WARNING("User %s not completely written. The user monitor service may have previously terminated ungracefully.",
                        LW_SAFE_LOG_STRING(pKeyName));
            lastUpdated = 0;
            dwError = 0;
        }
        else
        {
            BAIL_ON_UMN_ERROR(dwError);
        }

        if (lastUpdated < Now)
        {
            UmnSrvFreeUserContents(&old);
            dwError = UmnSrvReadUser(
                            pUserKeyName,
                            pKeyName,
                            &old);
            BAIL_ON_UMN_ERROR(dwError);

            UMN_LOG_INFO("User '%s' deleted",
                            old.pw_name);

            dwError = RegDeleteKeyA(
                            hReg,
                            hUsers,
                            pKeyName);
            BAIL_ON_UMN_ERROR(dwError);

            if (!strcmp(pUserKeyName, "Users"))
            {
                dwError = UmnSrvWriteUserEvent(
                                pEventlog,
                                old.LastUpdated,
                                &old,
                                Now,
                                NULL);
                BAIL_ON_UMN_ERROR(dwError);
            }
            else
            {
                dwError = UmnSrvWriteADUserEvent(
                                pEventlog,
                                old.LastUpdated,
                                &old,
                                Now,
                                NULL);
                BAIL_ON_UMN_ERROR(dwError);
            }

            // Make sure we don't skip the next key since this one was deleted
            i--;
            subKeyCount--;
        }
    }

cleanup:
    UmnSrvFreeUserContents(&old);

    LW_SAFE_FREE_STRING(pKeyName);
    return dwError;

error:
    goto cleanup;
}
예제 #14
0
파일: users.c 프로젝트: borland667/pbis
static
DWORD
UmnSrvUpdateUser(
    PLW_EVENTLOG_CONNECTION pEventlog,
    HANDLE hReg,
    HKEY hUsers,
    long long PreviousRun,
    long long Now,
    struct passwd *pUser
    )
{
    DWORD dwError = 0;
    HKEY hKey = NULL;
    USER_MONITOR_PASSWD old = { 0 };
    DWORD dwNow = Now;
    PSTR pEncodedUser = NULL;

    dwError = LwURLEncodeString(
                    pUser->pw_name,
                    &pEncodedUser);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegOpenKeyExA(
                    hReg,
                    hUsers,
                    pEncodedUser,
                    0,
                    KEY_ALL_ACCESS,
                    &hKey);
    if (dwError == LWREG_ERROR_NO_SUCH_KEY_OR_VALUE)
    {
        UMN_LOG_INFO("Adding user '%s' (uid %d)",
                        pUser->pw_name, pUser->pw_uid);

        dwError = RegCreateKeyExA(
                        hReg,
                        hUsers,
                        pEncodedUser,
                        0,
                        NULL,
                        0,
                        KEY_ALL_ACCESS,
                        NULL,
                        &hKey,
                        NULL);
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvWriteUserValues(
                        hReg,
                        hKey,
                        pUser);
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvWriteUserEvent(
                        pEventlog,
                        PreviousRun,
                        NULL,
                        Now,
                        pUser);
        BAIL_ON_UMN_ERROR(dwError);
    }
    else
    {
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvReadUser(
                        "Users",
                        pEncodedUser,
                        &old);
        BAIL_ON_UMN_ERROR(dwError);

        if (strcmp(pUser->pw_name, old.pw_name) ||
                strcmp(pUser->pw_passwd, old.pw_passwd) ||
                pUser->pw_uid != old.pw_uid ||
                pUser->pw_gid != old.pw_gid ||
                strcmp(pUser->pw_gecos, old.pw_gecos) ||
                strcmp(pUser->pw_dir, old.pw_dir) ||
                strcmp(pUser->pw_shell, old.pw_shell))
        {
            UMN_LOG_INFO("User '%s' (uid %d) changed",
                            pUser->pw_name, pUser->pw_uid);
            dwError = UmnSrvWriteUserValues(
                            hReg,
                            hKey,
                            pUser);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = UmnSrvWriteUserEvent(
                            pEventlog,
                            PreviousRun,
                            &old,
                            Now,
                            pUser);
            BAIL_ON_UMN_ERROR(dwError);
        }
    }

    dwError = RegSetValueExA(
                    hReg,
                    hKey,
                    "LastUpdated",
                    0,
                    REG_DWORD,
                    (PBYTE)&dwNow,
                    sizeof(dwNow));
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    LW_SAFE_FREE_STRING(pEncodedUser);
    UmnSrvFreeUserContents(&old);
    if (hKey)
    {
        RegCloseKey(
                hReg,
                hKey);
    }
    return dwError;
    
error:
    goto cleanup;
}
예제 #15
0
파일: users.c 프로젝트: borland667/pbis
DWORD
UmnSrvReadUser(
    PCSTR pParentKey,
    PCSTR pName,
    PUSER_MONITOR_PASSWD pResult
    )
{
    DWORD dwError = 0;
    PSTR pUserPath = NULL;
    LWREG_CONFIG_ITEM userLayout[] =
    {
        {
            "pw_name",
            FALSE,
            LwRegTypeString,
            0,
            -1,
            NULL,
            &pResult->pw_name,
            NULL
        },
        {
            "pw_passwd",
            FALSE,
            LwRegTypeString,
            0,
            -1,
            NULL,
            &pResult->pw_passwd,
            NULL
        },
        {
            "pw_uid",
            FALSE,
            LwRegTypeDword,
            0,
            -1,
            NULL,
            &pResult->pw_uid,
            NULL
        },
        {
            "pw_gid",
            FALSE,
            LwRegTypeDword,
            0,
            -1,
            NULL,
            &pResult->pw_gid,
            NULL
        },
        {
            "pw_gecos",
            FALSE,
            LwRegTypeString,
            0,
            -1,
            NULL,
            &pResult->pw_gecos,
            NULL
        },
        {
            "pw_dir",
            FALSE,
            LwRegTypeString,
            0,
            -1,
            NULL,
            &pResult->pw_dir,
            NULL
        },
        {
            "pw_shell",
            FALSE,
            LwRegTypeString,
            0,
            -1,
            NULL,
            &pResult->pw_shell,
            NULL
        },
        {
            "pDisplayName",
            FALSE,
            LwRegTypeString,
            0,
            -1,
            NULL,
            &pResult->pDisplayName,
            NULL
        },
        {
            "LastUpdated",
            FALSE,
            LwRegTypeDword,
            0,
            -1,
            NULL,
            &pResult->LastUpdated,
            NULL
        },
    };

    UMN_LOG_VERBOSE("Reading previous values for user '%s'",
                    pName);

    dwError = LwAllocateStringPrintf(
                    &pUserPath,
                    "Services\\" SERVICE_NAME "\\Parameters\\%s\\%s",
                    pParentKey,
                    pName);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwRegProcessConfig(
                pUserPath,
                NULL,
                userLayout,
                sizeof(userLayout)/sizeof(userLayout[0]));
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    LW_SAFE_FREE_STRING(pUserPath);
    return dwError;
    
error:
    goto cleanup;
}
예제 #16
0
파일: users.c 프로젝트: borland667/pbis
static
DWORD
UmnSrvWriteUserValues(
    HANDLE hReg,
    HKEY hUser,
    struct passwd *pUser
    )
{
    DWORD dwError = 0;
    DWORD dword = 0;

    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_name",
                    0,
                    REG_SZ,
                    (PBYTE) pUser->pw_name,
                    strlen(pUser->pw_name) + 1);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_passwd",
                    0,
                    REG_SZ,
                    (PBYTE) pUser->pw_passwd,
                    strlen(pUser->pw_passwd) + 1);
    BAIL_ON_UMN_ERROR(dwError);

    dword = pUser->pw_uid;
    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_uid",
                    0,
                    REG_DWORD,
                    (PBYTE)&dword,
                    sizeof(dword));
    BAIL_ON_UMN_ERROR(dwError);

    dword = pUser->pw_gid;
    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_gid",
                    0,
                    REG_DWORD,
                    (PBYTE)&dword,
                    sizeof(dword));
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_gecos",
                    0,
                    REG_SZ,
                    (PBYTE) pUser->pw_gecos,
                    strlen(pUser->pw_gecos) + 1);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_dir",
                    0,
                    REG_SZ,
                    (PBYTE) pUser->pw_dir,
                    strlen(pUser->pw_dir) + 1);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_shell",
                    0,
                    REG_SZ,
                    (PBYTE) pUser->pw_shell,
                    strlen(pUser->pw_shell) + 1);
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    return dwError;

error:
    goto cleanup;
}
예제 #17
0
파일: ad_users.c 프로젝트: borland667/pbis
static
DWORD
UmnSrvUpdateADAccountsByHash(
    HANDLE hLsass,
    PLW_EVENTLOG_CONNECTION pEventlog,
    HANDLE hReg,
    HKEY hParameters,
    PLW_HASH_TABLE pUsers,
    long long PreviousRun,
    long long Now
    )
{
    DWORD dwError = 0;
    HKEY hUsers = NULL;
    HKEY hGroups = NULL;
    LW_HASH_ITERATOR usersIterator = { 0 };
    LW_HASH_ENTRY* pEntry = NULL;
    DWORD groupSidCount = 0;
    PSTR* ppGroupSids = NULL;
    DWORD lookupGroupSidCount = 0;
    DWORD lookupGroupSidCapacity = 0;
    // Only free the first level of this array, do not free the strings it
    // points to.
    PSTR* ppLookupGroupSids = NULL;
    LSA_QUERY_LIST list = { 0 };
    PLSA_SECURITY_OBJECT *ppLookedupGroups = NULL;
    PLW_HASH_TABLE pGroups = NULL;
    PLW_HASH_TABLE pNameToUser = NULL;
    PLW_HASH_TABLE pNameToGroup = NULL;
    DWORD i = 0;
    // Do not free
    PLSA_SECURITY_OBJECT pGroup = NULL;
    // Do not free
    PLSA_SECURITY_OBJECT pExisting = NULL;
    PSTR pNewName = NULL;

    dwError = LwHashCreate(
                    100,
                    LwHashStringCompare,
                    LwHashStringHash,
                    UmnSrvHashFreeObjectValue,
                    NULL,
                    &pGroups);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwHashCreate(
                    100,
                    LwHashStringCompare,
                    LwHashStringHash,
                    NULL,
                    NULL,
                    &pNameToGroup);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwHashCreate(
                    pUsers->sCount * 2,
                    LwHashStringCompare,
                    LwHashStringHash,
                    NULL,
                    NULL,
                    &pNameToUser);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegOpenKeyExA(
                hReg,
                hParameters,
                "AD Users",
                0,
                KEY_ALL_ACCESS,
                &hUsers);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegOpenKeyExA(
                hReg,
                hParameters,
                "AD Groups",
                0,
                KEY_ALL_ACCESS,
                &hGroups);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwHashGetIterator(
                    pUsers,
                    &usersIterator);
    BAIL_ON_UMN_ERROR(dwError);

    while((pEntry = LwHashNext(&usersIterator)) != NULL)
    {
        PLSA_SECURITY_OBJECT pUser = (PLSA_SECURITY_OBJECT)pEntry->pValue;

        if (gbPollerThreadShouldExit)
        {
            dwError = ERROR_CANCELLED;
            BAIL_ON_UMN_ERROR(dwError);
        }

        dwError = LwHashGetValue(
                        pNameToUser,
                        pUser->userInfo.pszUnixName,
                        (PVOID*)&pExisting);
        if (dwError != ERROR_NOT_FOUND)
        {
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateStringPrintf(
                            &pNewName,
                            "%s\\%s",
                            pUser->pszNetbiosDomainName,
                            pUser->pszSamAccountName);
            BAIL_ON_UMN_ERROR(dwError);

            UMN_LOG_ERROR("Found conflict on user name '%hhs'. Sid %hhs will now be reported as name '%s' instead because its alias conflicts with sid %hhs.",
                                    pUser->userInfo.pszUnixName,
                                    pUser->pszObjectSid,
                                    pNewName,
                                    pExisting->pszObjectSid);
            BAIL_ON_UMN_ERROR(dwError);

            LW_SAFE_FREE_STRING(pUser->userInfo.pszUnixName);
            pUser->userInfo.pszUnixName = pNewName;
            pNewName = NULL;
        }

        dwError = LwHashSetValue(
                        pNameToUser,
                        pUser->userInfo.pszUnixName,
                        pUser);
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvUpdateADUser(
                        pEventlog,
                        hReg,
                        hUsers,
                        PreviousRun,
                        Now,
                        pUser);
        if (dwError == ERROR_NO_UNICODE_TRANSLATION)
        {
            // Error message already logged
            dwError = 0;
            continue;
        }
        BAIL_ON_UMN_ERROR(dwError);

        if (ppGroupSids)
        {
            LsaFreeSidList(
                    groupSidCount,
                    ppGroupSids);
        }
        dwError = LsaQueryMemberOf(
                        hLsass,
                        NULL,
                        0,
                        1,
                        &pUser->pszObjectSid,
                        &groupSidCount,
                        &ppGroupSids);
        BAIL_ON_UMN_ERROR(dwError);

        if (groupSidCount > lookupGroupSidCapacity)
        {
            LW_SAFE_FREE_MEMORY(ppLookupGroupSids);

            dwError = LwAllocateMemory(
                            groupSidCount * sizeof(ppLookupGroupSids[0]),
                            (PVOID*)&ppLookupGroupSids);
            BAIL_ON_UMN_ERROR(dwError);

            lookupGroupSidCapacity = groupSidCount;
        }

        lookupGroupSidCount = 0;

        for (i = 0; i < groupSidCount; i++)
        {
            dwError = LwHashGetValue(
                            pGroups,
                            ppGroupSids[i],
                            (PVOID*)&pGroup);
            if (dwError == ERROR_NOT_FOUND)
            {
                ppLookupGroupSids[lookupGroupSidCount++] = ppGroupSids[i];
            }
            else
            {
                BAIL_ON_UMN_ERROR(dwError);

                UMN_LOG_VERBOSE("Found AD user %s is a member of processed group %s",
                        pUser->userInfo.pszUnixName,
                        pGroup->groupInfo.pszUnixName);

                if (!pGroup->enabled)
                {
                    UMN_LOG_VERBOSE("Skipping unenabled group %s",
                        pGroup->groupInfo.pszUnixName);
                }
                else
                {
                    dwError = UmnSrvUpdateADGroupMember(
                                    pEventlog,
                                    hReg,
                                    hGroups,
                                    PreviousRun,
                                    Now,
                                    pGroup,
                                    pUser->userInfo.pszUnixName);
                    BAIL_ON_UMN_ERROR(dwError);
                }
            }
        }
        
        if (lookupGroupSidCount)
        {
            list.ppszStrings = (PCSTR *)ppLookupGroupSids;

            dwError = LsaFindObjects(
                            hLsass,
                            NULL,
                            0,
                            LSA_OBJECT_TYPE_GROUP,
                            LSA_QUERY_TYPE_BY_SID,
                            lookupGroupSidCount,
                            list,
                            &ppLookedupGroups);
            BAIL_ON_UMN_ERROR(dwError);

            for (i = 0; i < lookupGroupSidCount; i++)
            {
                if (gbPollerThreadShouldExit)
                {
                    dwError = ERROR_CANCELLED;
                    BAIL_ON_UMN_ERROR(dwError);
                }
                pGroup = ppLookedupGroups[i];

                if (!pGroup)
                {
                    UMN_LOG_ERROR("Unable to find group sid %s that user %s is a member of",
                            ppLookupGroupSids[i],
                            pUser->userInfo.pszUnixName);
                    continue;
                }

                UMN_LOG_VERBOSE("Found AD user %s is a member of unprocessed group %s",
                        pUser->userInfo.pszUnixName,
                        pGroup->groupInfo.pszUnixName);

                dwError = LwHashGetValue(
                                pNameToGroup,
                                pGroup->groupInfo.pszUnixName,
                                (PVOID*)&pExisting);
                if (dwError != ERROR_NOT_FOUND)
                {
                    BAIL_ON_UMN_ERROR(dwError);

                    dwError = LwAllocateStringPrintf(
                                    &pNewName,
                                    "%s\\%s",
                                    pGroup->pszNetbiosDomainName,
                                    pGroup->pszSamAccountName);
                    BAIL_ON_UMN_ERROR(dwError);

                    UMN_LOG_ERROR("Found conflict on group name '%hhs'. Sid %hhs will now be reported as name '%s' instead because its alias conflicts with sid %hhs.",
                                            pGroup->groupInfo.pszUnixName,
                                            pGroup->pszObjectSid,
                                            pNewName,
                                            pExisting->pszObjectSid);
                    BAIL_ON_UMN_ERROR(dwError);

                    LW_SAFE_FREE_STRING(pGroup->groupInfo.pszUnixName);
                    pGroup->groupInfo.pszUnixName = pNewName;
                    pNewName = NULL;
                }

                dwError = LwHashSetValue(
                                pNameToGroup,
                                pGroup->groupInfo.pszUnixName,
                                pGroup);
                BAIL_ON_UMN_ERROR(dwError);

                if (!pGroup->enabled)
                {
                    UMN_LOG_VERBOSE("Skipping unenabled group %s",
                        pGroup->groupInfo.pszUnixName);
                }
                else
                {
                    dwError = UmnSrvUpdateADGroup(
                                    pEventlog,
                                    hReg,
                                    hGroups,
                                    PreviousRun,
                                    Now,
                                    pGroup);
                    BAIL_ON_UMN_ERROR(dwError);

                    dwError = UmnSrvUpdateADGroupMember(
                                    pEventlog,
                                    hReg,
                                    hGroups,
                                    PreviousRun,
                                    Now,
                                    pGroup,
                                    pUser->userInfo.pszUnixName);
                    BAIL_ON_UMN_ERROR(dwError);
                }
                dwError = LwHashSetValue(
                                pGroups,
                                pGroup->pszObjectSid,
                                pGroup);
                BAIL_ON_UMN_ERROR(dwError);

                ppLookedupGroups[i] = NULL;
            }

            LsaFreeSecurityObjectList(
                lookupGroupSidCount,
                ppLookedupGroups);
            ppLookedupGroups = NULL;
        }
    }

    dwError = UmnSrvFindDeletedUsers(
                    pEventlog,
                    hReg,
                    "AD Users",
                    hUsers,
                    Now);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = UmnSrvFindDeletedGroups(
                    pEventlog,
                    hReg,
                    "AD Groups",
                    hGroups,
                    Now);
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    LW_SAFE_FREE_STRING(pNewName);
    LW_SAFE_FREE_MEMORY(ppLookupGroupSids);
    if (ppGroupSids)
    {
        LsaFreeSidList(
                groupSidCount,
                ppGroupSids);
    }
    if (ppLookedupGroups)
    {
        LsaFreeSecurityObjectList(
            lookupGroupSidCount,
            ppLookedupGroups);
    }
    if (hUsers)
    {
        RegCloseKey(hReg, hUsers);
    }
    if (hGroups)
    {
        RegCloseKey(hReg, hGroups);
    }
    LwHashSafeFree(&pGroups);
    LwHashSafeFree(&pNameToUser);
    LwHashSafeFree(&pNameToGroup);
    return dwError;
    
error:
    goto cleanup;
}
예제 #18
0
파일: ad_users.c 프로젝트: borland667/pbis
static
DWORD
UmnSrvUpdateADUser(
    PLW_EVENTLOG_CONNECTION pEventlog,
    HANDLE hReg,
    HKEY hUsers,
    long long PreviousRun,
    long long Now,
    PLSA_SECURITY_OBJECT pUser
    )
{
    DWORD dwError = 0;
    HKEY hKey = NULL;
    USER_MONITOR_PASSWD old = { 0 };
    DWORD dwNow = Now;
    PSTR pEncodedUser = NULL;

    dwError = LwURLEncodeString(
                    pUser->userInfo.pszUnixName,
                    &pEncodedUser);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegOpenKeyExA(
                    hReg,
                    hUsers,
                    pEncodedUser,
                    0,
                    KEY_ALL_ACCESS,
                    &hKey);
    if (dwError == LWREG_ERROR_NO_SUCH_KEY_OR_VALUE)
    {
        UMN_LOG_INFO("Adding user '%s' (uid %d)",
                        pUser->userInfo.pszUnixName, pUser->userInfo.uid);

        dwError = RegCreateKeyExA(
                        hReg,
                        hUsers,
                        pEncodedUser,
                        0,
                        NULL,
                        0,
                        KEY_ALL_ACCESS,
                        NULL,
                        &hKey,
                        NULL);
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvWriteADUserValues(
                        hReg,
                        hKey,
                        pUser);
        if (dwError == ERROR_NO_UNICODE_TRANSLATION)
        {
            UMN_LOG_ERROR("Ignoring user with URL encoding %s because one of their fields has no UCS-2 representation", pEncodedUser);

            // Delete the key so it does not show up with blank values next
            // time.
            dwError = RegCloseKey(
                    hReg,
                    hKey);
            BAIL_ON_UMN_ERROR(dwError);
            hKey = NULL;

            dwError = RegDeleteKeyA(
                            hReg,
                            hUsers,
                            pEncodedUser);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = ERROR_NO_UNICODE_TRANSLATION;
            BAIL_ON_UMN_ERROR(dwError);
        }
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvWriteADUserEvent(
                        pEventlog,
                        PreviousRun,
                        NULL,
                        Now,
                        pUser);
        BAIL_ON_UMN_ERROR(dwError);
    }
    else
    {
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvReadUser(
                        "AD Users",
                        pEncodedUser,
                        &old);
        BAIL_ON_UMN_ERROR(dwError);

        if (strcmp((pUser->userInfo.pszPasswd ?
                        pUser->userInfo.pszPasswd : "x"),
                    old.pw_passwd) ||
                pUser->userInfo.uid != old.pw_uid ||
                pUser->userInfo.gid != old.pw_gid ||
                !UmnSrvStringsEqual(pUser->userInfo.pszGecos, old.pw_gecos) ||
                !UmnSrvStringsEqual(pUser->userInfo.pszHomedir, old.pw_dir) ||
                !UmnSrvStringsEqual(pUser->userInfo.pszShell, old.pw_shell) ||
                !UmnSrvStringsEqual(pUser->userInfo.pszDisplayName,
                    old.pDisplayName))
        {
            UMN_LOG_INFO("User '%s' (uid %d) changed",
                            pUser->userInfo.pszUnixName, pUser->userInfo.uid);
            dwError = UmnSrvWriteADUserValues(
                            hReg,
                            hKey,
                            pUser);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = UmnSrvWriteADUserEvent(
                            pEventlog,
                            PreviousRun,
                            &old,
                            Now,
                            pUser);
            BAIL_ON_UMN_ERROR(dwError);
        }
    }

    dwError = RegSetValueExA(
                    hReg,
                    hKey,
                    "LastUpdated",
                    0,
                    REG_DWORD,
                    (PBYTE)&dwNow,
                    sizeof(dwNow));
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    LW_SAFE_FREE_STRING(pEncodedUser);
    UmnSrvFreeUserContents(&old);
    if (hKey)
    {
        RegCloseKey(
                hReg,
                hKey);
    }
    return dwError;
    
error:
    goto cleanup;
}
예제 #19
0
파일: ad_users.c 프로젝트: borland667/pbis
static
DWORD
UmnSrvAddUsersFromMembership(
    HANDLE hLsass,
    LW_HASH_TABLE *pUsers,
    PCSTR pLookup
    )
{
    DWORD dwError = 0;
    LSA_QUERY_LIST list;
    PLSA_SECURITY_OBJECT *ppObjects = NULL;
    PLSA_SECURITY_OBJECT *ppMembers = NULL;
    DWORD memberCount = 0;
    DWORD i = 0;

    list.ppszStrings = &pLookup;

    dwError = LsaFindObjects(
                    hLsass,
                    NULL,
                    0,
                    LSA_OBJECT_TYPE_UNDEFINED,
                    LSA_QUERY_TYPE_BY_NT4,
                    1,
                    list,
                    &ppObjects);
    switch(dwError)
    {
        // The string was not a valid NT4 name
        case LW_ERROR_INVALID_PARAMETER:
        // The user/group does not exist
        case LW_ERROR_NO_SUCH_OBJECT:
            goto cleanup;
        default:
            BAIL_ON_UMN_ERROR(dwError);
    }

    if (ppObjects[0] && ppObjects[0]->type == LSA_OBJECT_TYPE_USER)
    {
        if (ppObjects[0]->enabled &&
                !LwHashExists(pUsers, ppObjects[0]->pszObjectSid))
        {
            dwError = LwHashSetValue(
                            pUsers,
                            ppObjects[0]->pszObjectSid,
                            ppObjects[0]);
            BAIL_ON_UMN_ERROR(dwError);
            ppObjects[0] = NULL;
        }
    }
    else if (ppObjects[0] && ppObjects[0]->type == LSA_OBJECT_TYPE_GROUP)
    {
        dwError = LsaQueryExpandedGroupMembers(
                        hLsass,
                        NULL,
                        0,
                        LSA_OBJECT_TYPE_USER,
                        ppObjects[0]->pszObjectSid,
                        &memberCount,
                        &ppMembers);
        BAIL_ON_UMN_ERROR(dwError);

        for (i = 0; i < memberCount; i++)
        {
            if (ppMembers[i]->enabled &&
                    !LwHashExists(pUsers, ppMembers[i]->pszObjectSid))
            {
                UMN_LOG_VERBOSE("Found AD user %s that can login because of group %s",
                        ppMembers[i]->userInfo.pszUnixName, pLookup);

                dwError = LwHashSetValue(
                                pUsers,
                                ppMembers[i]->pszObjectSid,
                                ppMembers[i]);
                BAIL_ON_UMN_ERROR(dwError);
                ppMembers[i] = NULL;
            }
        }
    }

cleanup:
    if (ppObjects)
    {
        LsaFreeSecurityObjectList(
            1,
            ppObjects);
    }
    if (ppMembers)
    {
        LsaFreeSecurityObjectList(
            memberCount,
            ppMembers);
    }
    return dwError;

error:
    goto cleanup;
}
예제 #20
0
파일: ad_users.c 프로젝트: borland667/pbis
static
DWORD
UmnSrvWriteADUserValues(
    HANDLE hReg,
    HKEY hUser,
    PLSA_SECURITY_OBJECT pUser
    )
{
    DWORD dwError = 0;
    DWORD dword = 0;
    PCSTR pString = NULL;

    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_name",
                    0,
                    REG_SZ,
                    (PBYTE) pUser->userInfo.pszUnixName,
                    strlen(pUser->userInfo.pszUnixName) + 1);
    BAIL_ON_UMN_ERROR(dwError);

    pString = pUser->userInfo.pszPasswd;
    if (!pString)
    {
        pString = "x";
    }
    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_passwd",
                    0,
                    REG_SZ,
                    (PBYTE) pString,
                    strlen(pString) + 1);
    BAIL_ON_UMN_ERROR(dwError);

    dword = pUser->userInfo.uid;
    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_uid",
                    0,
                    REG_DWORD,
                    (PBYTE)&dword,
                    sizeof(dword));
    BAIL_ON_UMN_ERROR(dwError);

    dword = pUser->userInfo.gid;
    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_gid",
                    0,
                    REG_DWORD,
                    (PBYTE)&dword,
                    sizeof(dword));
    BAIL_ON_UMN_ERROR(dwError);

    pString = pUser->userInfo.pszGecos;
    if (!pString)
    {
        pString = "";
    }
    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_gecos",
                    0,
                    REG_SZ,
                    (PBYTE) pString,
                    strlen(pString) + 1);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_dir",
                    0,
                    REG_SZ,
                    (PBYTE) pUser->userInfo.pszHomedir,
                    strlen(pUser->userInfo.pszHomedir) + 1);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pw_shell",
                    0,
                    REG_SZ,
                    (PBYTE) pUser->userInfo.pszShell,
                    strlen(pUser->userInfo.pszShell) + 1);
    BAIL_ON_UMN_ERROR(dwError);

    pString = pUser->userInfo.pszDisplayName;
    if (!pString)
    {
        pString = "";
    }
    dwError = RegSetValueExA(
                    hReg,
                    hUser,
                    "pDisplayName",
                    0,
                    REG_SZ,
                    (PBYTE) pString,
                    strlen(pString) + 1);
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    return dwError;

error:
    goto cleanup;
}
예제 #21
0
파일: users.c 프로젝트: borland667/pbis
DWORD
UmnSrvUpdateUsers(
    HANDLE hLsass,
    PLW_EVENTLOG_CONNECTION pEventlog,
    HANDLE hReg,
    HKEY hParameters,
    long long PreviousRun,
    long long Now
    )
{
    DWORD uid = 0;
    DWORD dwError = 0;
    struct passwd *pUser = NULL;
    LSA_QUERY_LIST list = { 0 };
    PLSA_SECURITY_OBJECT* ppObjects = NULL;
    HKEY hUsers = NULL;
    BOOLEAN skipNoLogin = FALSE;

    dwError = UmnSrvGetSkipNoLogin(
                &skipNoLogin);
    BAIL_ON_UMN_ERROR(dwError);

    list.pdwIds = &uid;

    dwError = RegOpenKeyExA(
                hReg,
                hParameters,
                "Users",
                0,
                KEY_ALL_ACCESS,
                &hUsers);
    BAIL_ON_UMN_ERROR(dwError);

    while ((pUser = getpwent()) != NULL)
    {
        if (skipNoLogin && pUser->pw_shell &&
            (!strcmp(pUser->pw_shell, "/sbin/nologin") ||
            !strcmp(pUser->pw_shell, "/bin/nologin") ||
            !strcmp(pUser->pw_shell, "/usr/sbin/nologin") ||
            !strcmp(pUser->pw_shell, "/usr/bin/false") ||
            !strcmp(pUser->pw_shell, "/bin/false")))
        {
            UMN_LOG_VERBOSE("Skipping enumerated user '%s' (uid %d) because their shell prevents them from logging in.",
                    LW_SAFE_LOG_STRING(pUser->pw_name), uid);
            continue;
        }
        uid = pUser->pw_uid;

        dwError = LsaFindObjects(
                    hLsass,
                    NULL,
                    0,
                    LSA_OBJECT_TYPE_USER,
                    LSA_QUERY_TYPE_BY_UNIX_ID,
                    1,
                    list,
                    &ppObjects);

        if (dwError == ERROR_SUCCESS &&
                ppObjects && ppObjects[0] && ppObjects[0]->enabled &&
                ppObjects[0]->userInfo.pszUnixName && pUser->pw_name &&
                !strcmp(ppObjects[0]->userInfo.pszUnixName, pUser->pw_name))
        {
            UMN_LOG_VERBOSE("Skipping enumerated user '%s' (uid %d) because they came from lsass",
                    LW_SAFE_LOG_STRING(pUser->pw_name), uid);
        }
        else
        {
            dwError = UmnSrvUpdateUser(
                            pEventlog,
                            hReg,
                            hUsers,
                            PreviousRun,
                            Now,
                            pUser);
            BAIL_ON_UMN_ERROR(dwError);
        }

        if (ppObjects)
        {
            LsaFreeSecurityObjectList(1, ppObjects);
            ppObjects = NULL;
        }
    }

    dwError = UmnSrvFindDeletedUsers(
                    pEventlog,
                    hReg,
                    "Users",
                    hUsers,
                    Now);
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    if (ppObjects)
    {
        LsaFreeSecurityObjectList(1, ppObjects);
    }
    if (hUsers)
    {
        RegCloseKey(hReg, hUsers);
    }
    return dwError;
    
error:
    goto cleanup;
}
예제 #22
0
DWORD
UmnSrvUpdateADGroup(
    PLW_EVENTLOG_CONNECTION pEventlog,
    HANDLE hReg,
    HKEY hGroups,
    long long PreviousRun,
    long long Now,
    PLSA_SECURITY_OBJECT pGroup
    )
{
    DWORD dwError = 0;
    HKEY hKey = NULL;
    HKEY hMembers = NULL;
    USER_MONITOR_GROUP old = { 0 };
    DWORD dwNow = Now;
    old.gr_gid = -1;
    PSTR pEncodedGroup = NULL;

    dwError = LwURLEncodeString(
                    pGroup->groupInfo.pszUnixName,
                    &pEncodedGroup);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegOpenKeyExA(
                    hReg,
                    hGroups,
                    pEncodedGroup,
                    0,
                    KEY_ALL_ACCESS,
                    &hKey);
    if (dwError == LWREG_ERROR_NO_SUCH_KEY_OR_VALUE)
    {
        dwError = 0;
    }
    else
    {
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvReadGroup(
                        "AD Groups",
                        pEncodedGroup,
                        &old);
        BAIL_ON_UMN_ERROR(dwError);
    }
    // Check if the key does not exist yet, or it was not fully populated.
    if (old.LastUpdated == 0)
    {
        UMN_LOG_INFO("Adding group '%s' (gid %d)",
                        pGroup->groupInfo.pszUnixName, pGroup->groupInfo.gid);

        dwError = RegCreateKeyExA(
                        hReg,
                        hGroups,
                        pEncodedGroup,
                        0,
                        NULL,
                        0,
                        KEY_ALL_ACCESS,
                        NULL,
                        &hKey,
                        NULL);
        if (dwError == LWREG_ERROR_KEYNAME_EXIST)
        {
            // The key exists, but the values were not fully populated on a
            // previous run because the user monitor crashed or was killed. Use
            // the existing key and let the values get overwritten.
            dwError = 0;
        }
        BAIL_ON_UMN_ERROR(dwError);

        dwError = RegCreateKeyExA(
                        hReg,
                        hKey,
                        "Members",
                        0,
                        NULL,
                        0,
                        KEY_ALL_ACCESS,
                        NULL,
                        &hMembers,
                        NULL);
        if (dwError == LWREG_ERROR_KEYNAME_EXIST)
        {
            // The key exists, but the values were not fully populated on a
            // previous run because the user monitor crashed or was killed. Use
            // the existing key and let the values get overwritten.
            dwError = 0;
        }
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvWriteADGroupValues(
                        hReg,
                        hKey,
                        pGroup);
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvWriteADGroupEvent(
                        pEventlog,
                        PreviousRun,
                        NULL,
                        Now,
                        pGroup);
        BAIL_ON_UMN_ERROR(dwError);
    }
    else if (strcmp(pGroup->groupInfo.pszUnixName, old.gr_name))
    {
        // The group's name changed. This is too drastic of a change for a
        // change event. File a deletion and addition event.
        dwError = UmnSrvWriteADGroupEvent(
                        pEventlog,
                        PreviousRun,
                        &old,
                        Now,
                        NULL);
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvWriteADGroupEvent(
                        pEventlog,
                        PreviousRun,
                        NULL,
                        Now,
                        pGroup);
        BAIL_ON_UMN_ERROR(dwError);
    }
    else if (strcmp((pGroup->groupInfo.pszPasswd ?
                    pGroup->groupInfo.pszPasswd : "x"),
                old.gr_passwd) ||
            pGroup->groupInfo.gid != old.gr_gid)
    {
        UMN_LOG_INFO("Group '%s' (gid %d) changed",
                        pGroup->groupInfo.pszUnixName,
                        pGroup->groupInfo.gid);

        dwError = UmnSrvWriteADGroupValues(
                        hReg,
                        hKey,
                        pGroup);
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvWriteADGroupEvent(
                        pEventlog,
                        PreviousRun,
                        &old,
                        Now,
                        pGroup);
        BAIL_ON_UMN_ERROR(dwError);

        if (pGroup->groupInfo.gid != old.gr_gid)
        {
            // Send out membership deletion events for all members. They
            // will get readded through normal processing with the new gid
            dwError = RegOpenKeyExA(
                            hReg,
                            hKey,
                            "Members",
                            0,
                            KEY_ALL_ACCESS,
                            &hMembers);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = UmnSrvFindDeletedGroupMembers(
                            pEventlog,
                            hReg,
                            "AD Groups",
                            hMembers,
                            Now,
                            TRUE,
                            old.gr_gid,
                            old.gr_name);
            BAIL_ON_UMN_ERROR(dwError);
        }
    }

    dwError = RegSetValueExA(
                    hReg,
                    hKey,
                    "LastUpdated",
                    0,
                    REG_DWORD,
                    (PBYTE)&dwNow,
                    sizeof(dwNow));
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    LW_SAFE_FREE_STRING(pEncodedGroup);
    UmnSrvFreeGroupContents(&old);
    if (hKey)
    {
        RegCloseKey(
                hReg,
                hKey);
    }
    if (hMembers)
    {
        RegCloseKey(
                hReg,
                hMembers);
    }
    return dwError;
    
error:
    goto cleanup;
}
예제 #23
0
PVOID
UmnSrvPollerThreadRoutine(
    IN PVOID pUnused
    )
{
    DWORD dwError = 0;

    struct timeval now;
    struct timespec periodStart, periodUsed, nextWake, pushWait = {0};
    DWORD dwPeriodSecs = 0;
    
    char regErrMsg[256] = {0};
    char fqdn[1024] = {0};

    BOOLEAN bMutexLocked = FALSE;

    UMN_LOG_INFO("User poller thread started");
    dwError = pthread_mutex_lock(&gSignalPollerMutex);
    BAIL_ON_UMN_ERROR(dwError);
    bMutexLocked = TRUE;

    dwError = UmnSrvNow(&periodStart, &now);
    BAIL_ON_UMN_ERROR(dwError);

    while (!gbPollerThreadShouldExit)
    {
        dwError = UmnSrvGetCheckInterval(&dwPeriodSecs);
        BAIL_ON_UMN_ERROR(dwError);
        pushWait.tv_sec = dwPeriodSecs;

        UmnSrvTimespecAdd(
            &nextWake,
            &periodStart,
            &pushWait);

        UMN_LOG_INFO("User poller sleeping for %f seconds",
                pushWait.tv_sec + pushWait.tv_nsec /
                (double)NANOSECS_PER_SECOND);

        while (!gbPollerThreadShouldExit && !gbPollerRefresh)
        {
            BOOLEAN bWaitElapsed = FALSE;

            dwError = pthread_cond_timedwait(
                        &gSignalPoller,
                        &gSignalPollerMutex,
                        &nextWake);

            if (dwError == EINTR)
            {
                UMN_LOG_DEBUG("User poller cond wait interrupted; continuing.");
                continue;
            }

            if (dwError == ETIMEDOUT)
            {
                UMN_LOG_DEBUG("User poller cond wait completed.");
                dwError = 0;
                break;
            }

            if (dwError != 0) 
            {
                UMN_LOG_ERROR("Timed wait error: error %s (%d).", 
                      ErrnoToName(dwError), dwError);
                BAIL_ON_UMN_ERROR(dwError);
            }

            dwError = UmnSrvTimespecElapsed(&nextWake, &bWaitElapsed);
            if (dwError == 0 && bWaitElapsed == TRUE) 
            {
                break;
            }
        }

        gbPollerRefresh = FALSE;

        if (!gbPollerThreadShouldExit)
        {
            dwError = UmnSrvNow(&periodStart, &now);
            BAIL_ON_UMN_ERROR(dwError);

            // obtain the fully qualified domain name and use it throughout this iteration
            UmnEvtFreeEventComputerName();
            UmnEvtGetFQDN(fqdn, sizeof(fqdn));
            UmnEvtSetEventComputerName(fqdn);

            dwError = UmnSrvUpdateAccountInfo(now.tv_sec);
            if (dwError == ERROR_CANCELLED)
            {
                UMN_LOG_INFO("User poller cancelled iteration");
                dwError = 0;
                break;
            }

            // simply log other errors and attempt to continue
            if (dwError != LW_ERROR_SUCCESS) 
            {
                if (LwRegIsRegistrySpecificError(dwError))
                {
                    LwRegGetErrorString(dwError, regErrMsg, sizeof(regErrMsg) - 1);
                    UMN_LOG_ERROR("Failed updating account info, registry error = %d  %s. Continuing.",
                            dwError, regErrMsg);
                }
                else 
                {
                    UMN_LOG_ERROR("Failed updating account info, error = %d symbol = %s %s. Continuing.", 
                        dwError,
                        LwWin32ExtErrorToName(dwError), 
                        LwWin32ExtErrorToDescription(dwError));
                }
                dwError = 0;
            }

            // periodUsed = now - periodStart
            dwError = UmnSrvNow(&periodUsed, &now);
            BAIL_ON_UMN_ERROR(dwError);

            UmnSrvTimespecSubtract(
                &periodUsed,
                &periodUsed,
                &periodStart);

            UMN_LOG_DEBUG("Account activity update took %f seconds",
                    periodUsed.tv_sec + periodUsed.tv_nsec /
                    (double)NANOSECS_PER_SECOND);
        }
    }

    UMN_LOG_INFO("User poller thread stopped");

cleanup:
    if (bMutexLocked)
    {
        pthread_mutex_unlock(&gSignalPollerMutex);
    }

    if (dwError != 0)
    {
        UMN_LOG_ERROR(
                "User monitor polling thread exiting with code %d",
                dwError);
        kill(getpid(), SIGTERM);
    }

    return NULL;

error:
    goto cleanup;
}
예제 #24
0
static
DWORD
UmnSrvUpdateAccountInfo(
    long long Now
    )
{
    DWORD dwError = 0;
    HANDLE hLsass = NULL;
    HANDLE hReg = NULL;
    HKEY hParameters = NULL;
    BOOLEAN bLocalDBOpen = FALSE;

    // Do not free
    PSTR pDisableLsassEnum = NULL;
    DWORD lastUpdated = 0;
    DWORD lastUpdatedLen = sizeof(lastUpdated);
    PLW_EVENTLOG_CONNECTION pConn = NULL;

    dwError = LwEvtOpenEventlog(
                    NULL,
                    &pConn);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LsaOpenServer(&hLsass);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegOpenServer(&hReg);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegOpenKeyExA(
                hReg,
                NULL,
                HKEY_THIS_MACHINE "\\Services\\" SERVICE_NAME "\\Parameters",
                0,
                KEY_ALL_ACCESS,
                &hParameters);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegGetValueA(
                    hReg,
                    hParameters,
                    NULL,
                    "LastUpdated",
                    0,
                    NULL,
                    (PBYTE)&lastUpdated,
                    &lastUpdatedLen);
    if (dwError == LWREG_ERROR_NO_SUCH_KEY_OR_VALUE)
    {
        lastUpdated = 0;
        dwError = 0;
    }
    BAIL_ON_UMN_ERROR(dwError);

    /* processing local users/groups so disable AD user/group enumeration */
    pDisableLsassEnum = getenv("_DISABLE_LSASS_NSS_ENUMERATION");
    if (!pDisableLsassEnum || strcmp(pDisableLsassEnum, "1"))
    {
        /* Note, this code must leak memory.
         *
         * Putenv uses the memory passed to it, that it is it does not copy the
         * string. There is no Unix standard to unset an environment variable,
         * and the string passed to putenv must be accessible as long as the
         * program is running. A static string cannot be used because the
         * container could out live this service. There is no opportunity to
         * free the string before the program ends, because the variable must
         * be accessible for the duration of the program.
         */
        dwError = LwAllocateString(
                    "_DISABLE_LSASS_NSS_ENUMERATION=1",
                    &pDisableLsassEnum);
        BAIL_ON_UMN_ERROR(dwError);
        putenv(pDisableLsassEnum);
    }

    setpwent();
    setgrent();
    bLocalDBOpen = TRUE;

    dwError = UmnSrvUpdateUsers(
                    hLsass,
                    pConn,
                    hReg,
                    hParameters,
                    lastUpdated,
                    Now);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = UmnSrvUpdateGroups(
                    hLsass,
                    pConn,
                    hReg,
                    hParameters,
                    lastUpdated,
                    Now);
    BAIL_ON_UMN_ERROR(dwError);

    endpwent();
    endgrent();
    bLocalDBOpen = FALSE;

    dwError = UmnSrvUpdateADAccounts(
                    hLsass,
                    pConn,
                    hReg,
                    hParameters,
                    lastUpdated,
                    Now);
    BAIL_ON_UMN_ERROR(dwError);

    lastUpdated = Now;
    dwError = RegSetValueExA(
                    hReg,
                    hParameters,
                    "LastUpdated",
                    0,
                    REG_DWORD,
                    (PBYTE)&lastUpdated,
                    sizeof(lastUpdated));
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    if (bLocalDBOpen)
    {
        endpwent();
        endgrent();
    }
    if (hLsass)
    {
        LsaCloseServer(hLsass);
    }
    if (hReg)
    {
        RegCloseServer(hReg);
    }
    if (pConn)
    {
        LwEvtCloseEventlog(pConn);
    }
    return dwError;

error:
    goto cleanup;
}
예제 #25
0
DWORD
UmnSrvWriteADGroupEvent(
    PLW_EVENTLOG_CONNECTION pEventlog,
    long long PreviousRun,
    PUSER_MONITOR_GROUP pOld,
    long long Now,
    PLSA_SECURITY_OBJECT pNew
    )
{
    DWORD dwError = 0;
    // Do not free. The field values are borrowed from other structures.
    GROUP_CHANGE change = { { 0 } };
    LW_EVENTLOG_RECORD record = { 0 };
    char oldTimeBuf[128] = { 0 };
    char newTimeBuf[128] = { 0 };
    struct tm oldTmBuf = { 0 };
    struct tm newTmBuf = { 0 };
    time_t temp = 0;
    PCSTR pOperation = NULL;

    if (PreviousRun)
    {
        temp = PreviousRun;
        localtime_r(&temp, &oldTmBuf);
        strftime(
                oldTimeBuf,
                sizeof(oldTimeBuf),
                "%Y/%m/%d %H:%M:%S",
                &oldTmBuf);
    }
    else
    {
        strcpy(oldTimeBuf, "unknown");
    }
    temp = Now;
    localtime_r(&temp, &newTmBuf);

    strftime(
            newTimeBuf,
            sizeof(newTimeBuf),
            "%Y/%m/%d %H:%M:%S",
            &newTmBuf);

    if (pOld)
    {
        memcpy(&change.OldValue, pOld, sizeof(change.OldValue));
    }

    if (pNew)
    {
        change.NewValue.gr_name = pNew->groupInfo.pszUnixName;
        change.NewValue.gr_passwd = pNew->groupInfo.pszPasswd ?
                                        pNew->groupInfo.pszPasswd : "x";
        change.NewValue.gr_gid = pNew->groupInfo.gid;
        change.NewValue.LastUpdated = Now;
    }

    dwError = LwMbsToWc16s(
                    "Application",
                    &record.pLogname);
    BAIL_ON_UMN_ERROR(dwError);

    if (!PreviousRun)
    {
        dwError = LwMbsToWc16s(
                        "Success Audit",
                        &record.pEventType);
    }
    else
    {
        dwError = LwMbsToWc16s(
                        "Information",
                        &record.pEventType);
    }
    BAIL_ON_UMN_ERROR(dwError);

    record.EventDateTime = Now;

    dwError = LwMbsToWc16s(
                    "User Monitor",
                    &record.pEventSource);
    BAIL_ON_UMN_ERROR(dwError);

    if (pOld != NULL && pNew != NULL)
    {
        pOperation = "changed";
    }
    else if (pOld != NULL && pNew == NULL)
    {
        pOperation = "deleted";
    }
    else if (pOld == NULL && pNew != NULL)
    {
        pOperation = "added";
    }
    else
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_UMN_ERROR(dwError);
    }

    dwError = LwAllocateWc16sPrintfW(
                    &record.pEventCategory,
                    L"AD Group %hhs",
                    pOperation);
    BAIL_ON_UMN_ERROR(dwError);

    if (pNew != NULL)
    {
        record.EventSourceId = pNew->groupInfo.gid;

        dwError = LwMbsToWc16s(
                        pNew->groupInfo.pszUnixName,
                        &record.pUser);
        BAIL_ON_UMN_ERROR(dwError);
    }
    else
    {
        record.EventSourceId = pOld->gr_gid;

        dwError = LwMbsToWc16s(
                        pOld->gr_name,
                        &record.pUser);
        BAIL_ON_UMN_ERROR(dwError);
    }

    // Do not free. This value is borrowed from other structures.
    record.pComputer = (PWSTR)UmnEvtGetEventComputerName();

    dwError = LwAllocateWc16sPrintfW(
                    &record.pDescription,
                    L"Between %hhs and %hhs, group '%hhs' was %hhs.\n"
                    L"Passwd (from group struct)\n"
                    L"\tOld: %hhs\n"
                    L"\tNew: %hhs\n"
                    L"Gid\n"
                    L"\tOld: %d\n"
                    L"\tNew: %d",
                    oldTimeBuf,
                    newTimeBuf,
                    pOld ? pOld->gr_name : pNew->groupInfo.pszUnixName,
                    pOperation,
                    pOld ? pOld->gr_passwd : "",
                    pNew ? (pNew->groupInfo.pszPasswd ?
                                pNew->groupInfo.pszPasswd : "x") : "",
                    pOld ? pOld->gr_gid : -1,
                    pNew ? pNew->groupInfo.gid : -1);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = EncodeGroupChange(
                    &change,
                    &record.DataLen,
                    (PVOID*)&record.pData);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwEvtWriteRecords(
                    pEventlog,
                    1,
                    &record);
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    LW_SAFE_FREE_MEMORY(record.pLogname);
    LW_SAFE_FREE_MEMORY(record.pEventType);
    LW_SAFE_FREE_MEMORY(record.pEventSource);
    LW_SAFE_FREE_MEMORY(record.pEventCategory);
    LW_SAFE_FREE_MEMORY(record.pUser);
    LW_SAFE_FREE_MEMORY(record.pDescription);
    LW_SAFE_FREE_MEMORY(record.pData);
    return dwError;

error:
    goto cleanup;
}
예제 #26
0
파일: ad_users.c 프로젝트: borland667/pbis
DWORD
UmnSrvUpdateADAccounts(
    HANDLE hLsass,
    PLW_EVENTLOG_CONNECTION pEventlog,
    HANDLE hReg,
    HKEY hParameters,
    long long PreviousRun,
    long long Now
    )
{
    DWORD dwError = 0;
    PSTR pMemberList = NULL;
    PCSTR pIter = NULL;
    PSTR  pMember = NULL;
    PLW_HASH_TABLE pUsers = NULL;
    LWREG_CONFIG_ITEM ADConfigDescription[] =
    {
        {
            "RequireMembershipOf",
            TRUE,
            LwRegTypeMultiString,
            0,
            MAXDWORD,
            NULL,
            &pMemberList,
            NULL
        },
    };
    PLSASTATUS pLsaStatus = NULL;
    // Do not free
    PSTR pDomain = NULL;
    // Do not free
    PSTR pCell = NULL;
    PLSA_SECURITY_OBJECT pAllUsers = NULL;
    DWORD i = 0;

    dwError = LwHashCreate(
                    100,
                    LwHashStringCompare,
                    LwHashStringHash,
                    UmnSrvHashFreeObjectValue,
                    NULL,
                    &pUsers);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegProcessConfig(
                AD_PROVIDER_REGKEY,
                AD_PROVIDER_POLICY_REGKEY,
                ADConfigDescription,
                sizeof(ADConfigDescription)/sizeof(ADConfigDescription[0]));
    BAIL_ON_UMN_ERROR(dwError);

    if (pMemberList && pMemberList[0])
    {
        pIter = pMemberList;
        while (*pIter != 0)
        {
            dwError = LwStrDupOrNull(
                            pIter,
                            &pMember);
            BAIL_ON_UMN_ERROR(dwError);

            LwStripWhitespace(
                    pMember,
                    TRUE,
                    TRUE);

            dwError = UmnSrvAddUsersFromMembership(
                            hLsass,
                            pUsers,
                            pMember);
            BAIL_ON_UMN_ERROR(dwError);

            pIter += strlen(pIter) + 1;
        }
    }
    else
    {
        dwError = LsaGetStatus2(
                        hLsass,
                        NULL,
                        &pLsaStatus);
        BAIL_ON_UMN_ERROR(dwError);

        for (i = 0; i < pLsaStatus->dwCount; i++)
        {
            if (pLsaStatus->pAuthProviderStatusList[i].pszDomain)
            {
                pDomain = pLsaStatus->pAuthProviderStatusList[i].pszDomain;
            }
            if (pLsaStatus->pAuthProviderStatusList[i].pszCell)
            {
                pCell = pLsaStatus->pAuthProviderStatusList[i].pszCell;
            }
        }

        if (pDomain || pCell)
        {
            dwError = LwAllocateMemory(
                            sizeof(*pAllUsers),
                            (PVOID*)&pAllUsers);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "S-INVALID",
                            &pAllUsers->pszObjectSid);
            BAIL_ON_UMN_ERROR(dwError);

            pAllUsers->enabled = TRUE;
            pAllUsers->bIsLocal = FALSE;

            dwError = LwAllocateString(
                            "AllDomains",
                            &pAllUsers->pszNetbiosDomainName);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "AllUsers",
                            &pAllUsers->pszSamAccountName);
            BAIL_ON_UMN_ERROR(dwError);

            pAllUsers->type = LSA_OBJECT_TYPE_USER;

            dwError = LwAllocateString(
                            "S-INVALID",
                            &pAllUsers->userInfo.pszPrimaryGroupSid);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "All Users",
                            &pAllUsers->userInfo.pszUnixName);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "All Users",
                            &pAllUsers->userInfo.pszGecos);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "",
                            &pAllUsers->userInfo.pszShell);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "",
                            &pAllUsers->userInfo.pszHomedir);
            BAIL_ON_UMN_ERROR(dwError);

            if (pCell)
            {
                dwError = LwAllocateStringPrintf(
                                &pAllUsers->userInfo.pszDisplayName,
                                "All Users in cell %s",
                                pCell);
                BAIL_ON_UMN_ERROR(dwError);
            }
            else
            {
                dwError = LwAllocateStringPrintf(
                                &pAllUsers->userInfo.pszDisplayName,
                                "All Users accessible from domain %s",
                                pDomain);
                BAIL_ON_UMN_ERROR(dwError);
            }

            dwError = LwHashSetValue(
                            pUsers,
                            pAllUsers->pszObjectSid,
                            pAllUsers);
            BAIL_ON_UMN_ERROR(dwError);

            pAllUsers = NULL;
        }
    }

    dwError = UmnSrvUpdateADAccountsByHash(
                    hLsass,
                    pEventlog,
                    hReg,
                    hParameters,
                    pUsers,
                    PreviousRun,
                    Now);
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    if (pLsaStatus)
    {
        LsaFreeStatus(pLsaStatus);
    }
    LW_SAFE_FREE_STRING(pMemberList);
    LW_SAFE_FREE_STRING(pMember);
    LwHashSafeFree(&pUsers);
    if (pAllUsers)
    {
        LsaFreeSecurityObject(pAllUsers);
    }
    return dwError;

error:
    goto cleanup;
}
예제 #27
0
DWORD
UmnSrvUpdateADGroupMember(
    PLW_EVENTLOG_CONNECTION pEventlog,
    HANDLE hReg,
    HKEY hGroups,
    long long PreviousRun,
    long long Now,
    PLSA_SECURITY_OBJECT pGroup,
    PCSTR pMember
    )
{
    DWORD dwError = 0;
    HKEY hKey = NULL;
    HKEY hMembers = NULL;
    DWORD dwNow = Now;
    PSTR pEncodedMember = NULL;
    PSTR pKeyName = NULL;
    PSTR pEncodedGroup = NULL;
    PSTR pMembersKeyName = NULL;

    dwError = LwURLEncodeString(
                    pMember,
                    &pEncodedMember);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwURLEncodeString(
                    pGroup->groupInfo.pszUnixName,
                    &pEncodedGroup);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = LwAllocateStringPrintf(
                    &pKeyName,
                    "%s\\Members\\%s",
                    pEncodedGroup,
                    pEncodedMember);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegOpenKeyExA(
                    hReg,
                    hGroups,
                    pKeyName,
                    0,
                    KEY_ALL_ACCESS,
                    &hKey);
    if (dwError == LWREG_ERROR_NO_SUCH_KEY_OR_VALUE)
    {
        UMN_LOG_INFO("Adding user member '%s' to group '%s' (gid %d)",
                        pMember, pGroup->groupInfo.pszUnixName, pGroup->groupInfo.gid);

        dwError = LwAllocateStringPrintf(
                        &pMembersKeyName,
                        "%s\\Members",
                        pEncodedGroup);
        BAIL_ON_UMN_ERROR(dwError);

        dwError = RegOpenKeyExA(
                        hReg,
                        hGroups,
                        pMembersKeyName,
                        0,
                        KEY_ALL_ACCESS,
                        &hMembers);
        if (dwError == LWREG_ERROR_NO_SUCH_KEY_OR_VALUE)
        {
            // Previous run left registry in inconsistent state
            dwError = RegCreateKeyExA(
                            hReg,
                            hGroups,
                            pMembersKeyName,
                            0,
                            NULL,
                            0,
                            KEY_ALL_ACCESS,
                            NULL,
                            &hMembers,
                            NULL);
            BAIL_ON_UMN_ERROR(dwError);
        }
        BAIL_ON_UMN_ERROR(dwError);

        dwError = RegCreateKeyExA(
                        hReg,
                        hMembers,
                        pEncodedMember,
                        0,
                        NULL,
                        0,
                        KEY_ALL_ACCESS,
                        NULL,
                        &hKey,
                        NULL);
        BAIL_ON_UMN_ERROR(dwError);

        dwError = UmnSrvWriteGroupMemberEvent(
                        pEventlog,
                        Now,
                        "AD Groups",
                        PreviousRun,
                        TRUE, //Add member
                        FALSE, //Not gid change
                        pMember,
                        pGroup->groupInfo.gid,
                        pGroup->groupInfo.pszUnixName);
        BAIL_ON_UMN_ERROR(dwError);
    }

    dwError = RegSetValueExA(
                    hReg,
                    hKey,
                    "LastUpdated",
                    0,
                    REG_DWORD,
                    (PBYTE)&dwNow,
                    sizeof(dwNow));
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    LW_SAFE_FREE_STRING(pEncodedGroup);
    LW_SAFE_FREE_STRING(pKeyName);
    LW_SAFE_FREE_STRING(pMembersKeyName);
    LW_SAFE_FREE_STRING(pEncodedMember);
    if (hKey)
    {
        RegCloseKey(
                hReg,
                hKey);
    }
    if (hMembers)
    {
        RegCloseKey(
                hReg,
                hMembers);
    }
    return dwError;
    
error:
    goto cleanup;
}