Example #1
0
void
LsaFreeSMBCreds(
    IN OUT PLSA_CREDS_FREE_INFO* ppFreeInfo
    )
{
    PLSA_CREDS_FREE_INFO pFreeInfo = *ppFreeInfo;

    if (!pFreeInfo)
    {
        goto cleanup;
    }

    LwIoSetThreadCreds(pFreeInfo->pRestoreCreds);
    if (pFreeInfo->pRestoreCreds != NULL)
    {
        LwIoDeleteCreds(pFreeInfo->pRestoreCreds);
    }
    
    if (pFreeInfo->bKrbCreds)
    {
        LwKrb5SetThreadDefaultCachePath(
                      pFreeInfo->pszRestoreCache,
                      NULL);
        LW_SAFE_FREE_STRING(pFreeInfo->pszRestoreCache);

        if (pFreeInfo->ctx != NULL)
        {
            if (pFreeInfo->cc != NULL)
            {
                krb5_cc_destroy(pFreeInfo->ctx, pFreeInfo->cc);
            }
            krb5_free_context(pFreeInfo->ctx);
        }
    }

    LwFreeMemory(pFreeInfo);

    *ppFreeInfo = NULL;

cleanup:
    return;
}
Example #2
0
static
DWORD
AD_GetComputerDn(
    IN OPTIONAL PCSTR pszDnsDomainName,
    OUT PSTR* ppszComputerDn
    )
{
    DWORD dwError = 0;
    PSTR pszComputerDn = NULL;
    PLSA_MACHINE_PASSWORD_INFO_A pPasswordInfo = NULL;
    PSTR pszUserPrincipalName = NULL;
    PCSTR pszKrb5CachePath = "MEMORY:lsass_get_computer_dn";
    PSTR pszPreviousKrb5CachePath = NULL;
    HANDLE hDirectory = NULL;
    // Lock to protect the cache:
    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    BOOLEAN isLocked = FALSE;
    BOOLEAN needDestroyCache = FALSE;

    //
    // In the future, if we have cached DN information in the domain state,
    // we will use that.  However, since that does not currently exist,
    // we will fetch it directly.
    //
    // Since this code should work regardless of the internal state,
    // we will need to use a private memory cache to establish credentials.
    //

    dwError = AD_GetMachinePasswordInfoA(pszDnsDomainName, &pPasswordInfo);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwAllocateStringPrintf(
                    &pszUserPrincipalName,
                    "%s@%s",
                    pPasswordInfo->Account.SamAccountName,
                    pPasswordInfo->Account.DnsDomainName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwMapErrnoToLwError(pthread_mutex_lock(&mutex));
    BAIL_ON_LSA_ERROR(dwError);
    isLocked = TRUE;

    dwError = LwKrb5InitializeCredentials(
                    pszUserPrincipalName,
                    pPasswordInfo->Password,
                    pszKrb5CachePath,
                    NULL);
    BAIL_ON_LSA_ERROR(dwError);
    needDestroyCache = TRUE;

    dwError = LwKrb5SetThreadDefaultCachePath(pszKrb5CachePath, &pszPreviousKrb5CachePath);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaLdapOpenDirectoryDomain(
                    pPasswordInfo->Account.DnsDomainName,
                    NULL,
                    0,
                    &hDirectory);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = AD_RawFindComputerDn(
                    hDirectory,
                    pPasswordInfo->Account.DnsDomainName,
                    pPasswordInfo->Account.SamAccountName,
                    &pszComputerDn);
    BAIL_ON_LSA_ERROR(dwError);

error:
    if (dwError)
    {
        LW_SAFE_FREE_STRING(pszComputerDn);
    }

    if (needDestroyCache)
    {
        LwKrb5DestroyCache(pszKrb5CachePath);
    }

    if (pszPreviousKrb5CachePath)
    {
        LwKrb5SetThreadDefaultCachePath(pszPreviousKrb5CachePath, NULL);
    }

    if (isLocked)
    {
        int localError = pthread_mutex_unlock(&mutex);
        LSA_ASSERT(!localError);
    }

    LsaSrvFreeMachinePasswordInfoA(pPasswordInfo);
    LW_SAFE_FREE_STRING(pszUserPrincipalName);
    LW_SAFE_FREE_STRING(pszPreviousKrb5CachePath);

    if (hDirectory)
    {
        LwLdapCloseDirectory(hDirectory);
    }

    *ppszComputerDn = pszComputerDn;

    return dwError;
}
Example #3
0
DWORD
IDMLdapSaslBind(
    LDAP*        pLd                       /* IN     */
    )
{
    DWORD dwError = 0;
    DWORD dwCleanupError = 0;
    BOOLEAN bLocked = FALSE;
    PSTR  pszCachePath = NULL;

    if (!pLd)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_ERROR(dwError);
    }

    switch (IDMKrbGetState(pgIdmKrbContext))
    {
        case IDM_KRB_CONTEXT_STATE_INITIAL:

            dwError = IDMKrbDetermineJoinState(pgIdmKrbContext);
            BAIL_ON_ERROR(dwError);

        case IDM_KRB_CONTEXT_STATE_JOINED:

            dwError = IDMKrbRenewCredentials(pgIdmKrbContext);
            if (dwError)
            {
               // Refreshing credentials might fail if the system left
               // the domain or there were issues reaching the domain
               // controller.
               IDMKrbSetState(pgIdmKrbContext, IDM_KRB_CONTEXT_STATE_INITIAL);
            }
            BAIL_ON_ERROR(dwError);

            IDM_RWMUTEX_LOCK_SHARED(
                &pgIdmKrbContext->mutex_rw,
                bLocked,
                dwError);
            BAIL_ON_ERROR(dwError);

            dwError = LwKrb5SetThreadDefaultCachePath(
                            pgIdmKrbContext->pszCachePath,
                            &pszCachePath);
            BAIL_ON_ERROR(dwError);

            dwError = LwMapLdapErrorToLwError(
                        ldap_sasl_interactive_bind_s(
                            pLd,
                            NULL,
                            "GSSAPI",
                            NULL,
                            NULL,
                            LDAP_SASL_QUIET,
                            &IDMSASLInteraction,
                            NULL));
            BAIL_ON_ERROR(dwError);

            break;

        default:

            dwError = ERROR_INVALID_STATE;
            BAIL_ON_ERROR(dwError);

            break;
    }

cleanup:

    if (pszCachePath)
    {
        LwKrb5SetThreadDefaultCachePath(pszCachePath, NULL);

        LwFreeMemory(pszCachePath);
    }

    IDM_RWMUTEX_UNLOCK(&pgIdmKrbContext->mutex_rw, bLocked, dwCleanupError);
    if(!dwError)
    {
        dwError = dwCleanupError;
    }
    return dwError;

error:

    goto cleanup;
}
Example #4
0
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;
}