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;
}
NTSTATUS
LsaSrvGetSystemCreds(
    OUT LW_PIO_CREDS *ppCreds
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    DWORD dwError = ERROR_SUCCESS;
    LW_PIO_CREDS pCreds = NULL;
    PSTR pszMachinePrincipal = NULL;
    PSTR pszCachePath = NULL;
    PLSA_MACHINE_ACCOUNT_INFO_A pAccountInfo = NULL;

    dwError = LsaSrvProviderGetMachineAccountInfoA(
                  LSA_PROVIDER_TAG_AD,
                  NULL,
                  &pAccountInfo);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwAllocateStringPrintf(
                    &pszMachinePrincipal,
                    "%s@%s",
                    pAccountInfo->SamAccountName,
                    pAccountInfo->DnsDomainName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwAllocateStringPrintf(
                    &pszCachePath,
                    "%s.%s",
                    LSASS_KRB5_CACHE_PATH,
                    pAccountInfo->DnsDomainName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwIoCreateKrb5CredsA(
                    pszMachinePrincipal,
                    pszCachePath,
                    &pCreds);
    BAIL_ON_LSA_ERROR(dwError);

    *ppCreds = pCreds;

cleanup:
    LW_SAFE_FREE_STRING(pszMachinePrincipal);
    LW_SAFE_FREE_STRING(pszCachePath);

    LsaSrvFreeMachineAccountInfoA(pAccountInfo);

    if (ntStatus == STATUS_SUCCESS &&
        dwError != ERROR_SUCCESS)
    {
        ntStatus = LwWin32ErrorToNtStatus(dwError);
    }

    return ntStatus;

error:
    if (pCreds)
    {
        LwIoDeleteCreds(pCreds);
    }

    *ppCreds = NULL;
    goto cleanup;
}
Exemple #3
0
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;
}