Partager via


Exemple : utilisation de l’encodage d’authentification SSPI avec BITS

Vous pouvez utiliser l’authentification SSPI (Security Support Provider Interface) et les méthodes BITS (Background Intelligent Transfer Service) pour obtenir les informations d’identification d’un utilisateur, encoder les informations d’identification et définir les informations d’identification codées sur un travail de transfert BITS. L’encodage est nécessaire pour convertir la structure des informations d’identification en chaînes qui peuvent être passées à un travail de transfert BITS.

Pour plus d’informations sur l’authentification et les méthodes SSPI, consultez SSPI.

La procédure suivante demande des informations d’identification de l’utilisateur à l’aide du package de sécurité Negotiate. Le programme crée une structure d’identité d’authentification et remplit la structure avec les chaînes encodées qui représentent le nom d’utilisateur, le domaine et le mot de passe de l’utilisateur. Ensuite, le programme crée un travail de téléchargement BITS et définit le nom d’utilisateur et le mot de passe codés comme informations d’identification pour le travail. Le programme libère la structure d’identité d’authentification une fois qu’elle n’est plus nécessaire.

Cet exemple utilise l’en-tête et l’implémentation définis dans Exemple : Classes communes.

Pour utiliser l’encodage d’authentification SSPI avec les travaux de transfert BITS

  1. Initialisez les paramètres COM en appelant la fonction CCoInitializer. Pour plus d’informations sur la fonction CCoInitializer, consultez Exemple : classes communes.
  2. Obtenez des pointeurs pour les interfaces IBackgroundCopyManager, IBackgroundCopyJob et IBackgroundCopyJob2 . Cet exemple utilise la classe CComPtr pour gérer les pointeurs d’interface COM.
  3. Créez une structure CREDUI_INFO qui contient des informations pour personnaliser l’apparence de la boîte de dialogue pour la fonction SspiPromptForCredentials. Invitez ensuite les informations d’identification de l’utilisateur. Pour plus d’informations, consultez la fonction SspiPromptForCredentials.
  4. Encoder la structure des informations d’identification sous forme de chaînes qui peuvent être passées à un travail de transfert BITS à l’aide de la fonction SspiEncodeAuthIdentityAsStrings .
  5. Préparez une structure BG_AUTH_CREDENTIALS .
  6. Initialisez la sécurité des processus COM en appelant CoInitializeSecurity. BITS nécessite au moins le niveau d’emprunt d’identité IMPERSONATE. BITS échoue avec E_ACCESSDENIED si le niveau d’emprunt d’identité correct n’est pas défini.
  7. Obtenez le localisateur initial sur BITS en appelant la fonction CoCreateInstance .
  8. Créez un travail de transfert BITS en appelant la méthode IBackgroundCopyManager::CreateJob .
  9. Obtenez l’identificateur de l’interface IBackgroundCopyJob2 et appelez la méthode IBackgroundCopyJob::QueryInterface .
  10. Remplissez la structure BG_AUTH_CREDENTIALS avec les chaînes de nom d’utilisateur et de mot de passe encodées, puis définissez le schéma d’authentification sur Negotiate (BG_AUTH_SCHEME_NEGOTIATE).
  11. Utilisez le pointeur IBackgroundCopyJob2 pour effectuer des requêtes à BITS. Ce programme utilise la méthode IBackgroundCopyJob2::SetCredentials pour définir les informations d’identification du travail de transfert BITS.
  12. Ajoutez des fichiers, modifiez des propriétés ou reprenez le travail de transfert BITS.
  13. Une fois le travail de transfert BITS terminé, supprimez le travail de la file d’attente en appelant IBackgroundCopyJob::Complete.
  14. Enfin, libérez la structure d’identité d’authentification en appelant la fonction SspiFreeAuthIdentity .

L’exemple de code suivant montre comment utiliser l’encodage d’authentification SSPI avec les travaux de transfert BITS.

#define SECURITY_WIN32
#define _SEC_WINNT_AUTH_TYPES

#include <windows.h>
#include <ntsecapi.h>
#include <bits.h>
#include <sspi.h>
#include <wincred.h>
#include <iostream>
#include <atlbase.h>
#include "CommonCode.h"

void PromptForCredentials(PWSTR pwTargetName)
{
    HRESULT hr;
    
    // If CoInitializeEx fails, the exception is unhandled and the program terminates
    CCoInitializer coInitializer(COINIT_APARTMENTTHREADED);
    
    CComPtr<IBackgroundCopyManager> pQueueMgr;
    CComPtr<IBackgroundCopyJob> pJob;
    CComPtr<IBackgroundCopyJob2> pJob2;

    PSEC_WINNT_AUTH_IDENTITY_OPAQUE pAuthIdentityEx2 = NULL;
    DWORD dwFlags = 0;
    BOOL fSave = FALSE;
    BOOL bReturn = TRUE;

    CREDUI_INFO creduiInfo = { 0 };
    creduiInfo.cbSize = sizeof(creduiInfo);
    // Change the message text and caption to the actual text for your dialog.
    creduiInfo.pszMessageText = pwTargetName;
    creduiInfo.pszCaptionText = L"SSPIPFC title for the dialog box";

    try {
        // Prompt for credentials from user using Negotiate security package.
        DWORD dwRet = SspiPromptForCredentials(
            pwTargetName,
            &creduiInfo,
            0,
            L"Negotiate", 
            NULL,
            &pAuthIdentityEx2,
            &fSave,
            dwFlags
            );

        if (SEC_E_OK != dwRet) 
        {
            // Prompt for credentials failed.
            throw MyException(dwRet, L"SspiPromptForCredentials");
        }

        if (NULL != pAuthIdentityEx2) 
        {
            GUID guidJob;
            BG_AUTH_CREDENTIALS authCreds;

            PCWSTR pwUserName = NULL;
            PCWSTR pwDomainName = NULL;
            PCWSTR pwPassword = NULL;

            // Encode credential structure as strings that can
            // be passed to a BITS job.
            SECURITY_STATUS secStatus = SspiEncodeAuthIdentityAsStrings(
                pAuthIdentityEx2,
                &pwUserName,
                &pwDomainName,
                &pwPassword
                );

            if(SEC_E_OK != secStatus) 
            {
                // Encode authentication identity as strings.
                throw MyException(secStatus, L"SspiEncodeAuthIdentityAsStrings");   
            }

            // Show the encoded user name and domain name.
            wprintf(
                L"User Name: %s\nDomain Name: %s",
                pwUserName,
                pwDomainName
                );

            //The impersonation level must be at least RPC_C_IMP_LEVEL_IMPERSONATE.
            HRESULT hr = CoInitializeSecurity(
                NULL,
                -1,
                NULL,
                NULL,
                RPC_C_AUTHN_LEVEL_CONNECT,
                RPC_C_IMP_LEVEL_IMPERSONATE,
                NULL,
                EOAC_DYNAMIC_CLOAKING,
                0
                );
            
            if (FAILED(hr))
            {
                throw MyException(hr, L"CoInitializeSecurity");
            }

            // Connect to BITS.
            hr = CoCreateInstance(__uuidof(BackgroundCopyManager), NULL,
                CLSCTX_LOCAL_SERVER,
                __uuidof(IBackgroundCopyManager),
                (void**) &pQueueMgr);

            if (FAILED(hr))
            {
                // Failed to connect.
                throw MyException(hr, L"CoCreateInstance");
            }

            // Create a job.
            hr = pQueueMgr->CreateJob(
                L"EncodeSample", 
                BG_JOB_TYPE_DOWNLOAD, 
                &guidJob, 
                &pJob
                );

            if(FAILED(hr))
            {   
                // Failed to create a BITS job.
                throw MyException(hr, L"CreateJob");
            }

            // Get IBackgroundCopyJob2 interface.
            hr = pJob->QueryInterface(__uuidof(IBackgroundCopyJob2), (void**)&pJob2);
            if (FAILED(hr)) 
            {
                // Failed to get a reference to the IBackgroundCopyJob2 interface.
                throw MyException(hr, L"QueryInterface(IBackgroundCopyJob2)");
            }

            // Create a BITS authentication structure from the encoded strings.
            authCreds.Target = BG_AUTH_TARGET_SERVER;
            authCreds.Scheme = BG_AUTH_SCHEME_NEGOTIATE;
            authCreds.Credentials.Basic.UserName = (LPWSTR)pwUserName;
            authCreds.Credentials.Basic.Password = (LPWSTR)pwPassword;

            // Set the credentials for the job.
            hr = pJob2->SetCredentials(&authCreds);
            if (FAILED(hr)) 
            {
                // Failed to set credentials.
                throw MyException(hr, L"SetCredentials");
            }

            // Modify the job's property values.
            // Add files to the job.
            // Activate (resume) the job in the transfer queue.

            // Remove the job from the transfer queue.
            hr = pJob->Complete();
            if (FAILED(hr)) 
            {
                // Failed to complete the job.
                throw MyException(hr, L"Complete");
            }
        }
    }
    catch(std::bad_alloc &)
    {
        wprintf(L"Memory allocation failed");
        if (pJob != NULL)
        {
            pJob->Cancel();
        }
    }
    catch(MyException &ex)
    {
        wprintf(L"Error %x occurred during operation", ex.Error);
        if (pJob != NULL)
        {
            pJob->Cancel();
        }
    }

    // Free the auth identity structure.
    if (NULL != pAuthIdentityEx2)
    {
        SspiFreeAuthIdentity(pAuthIdentityEx2);
        pAuthIdentityEx2 = NULL;
    }

    return;
}

void _cdecl _tmain(int argc, LPWSTR* argv)
{
    PromptForCredentials(L"Target");
}

SSPI

IBackgroundCopyManager

IBackgroundCopyJob

IBackgroundCopyJob2

Exemple : Classes courantes