IIS Client Certificate Mapping Authentication

1

I am trying to programmatically add onetoone client certificate authentication to the applicationhost.config file.

After referring to these two documents(thread1, thread2), I am sure that it is possible to implement it with different languages. And for some kind of reason I have to develop it with C++. While translating the code sample in thread1,

Below is the code snippet FYI.

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <ahadmin.h>
#include <crtdbg.h>
#include <string>

using namespace std;

void PrintPropertiesOfElement(IAppHostElement *pElement)
{
HRESULT hr = S_OK;

IAppHostPropertyCollection *pProperties = NULL;
IAppHostProperty *pProperty = NULL;

hr = pElement->get_Properties(&pProperties);

DWORD properties_count = 0;
hr = pProperties->get_Count(&properties_count);

VARIANT vtIndex;
vtIndex.vt = VT_INT;
for(DWORD i=0; i<properties_count; ++i)
{
    vtIndex.intVal = i;
    hr = pProperties->get_Item(vtIndex, &pProperty);

    BSTR strName;
    BSTR strValue;
    hr = pProperty->get_Name(&strName);
    hr = pProperty->get_StringValue(&strValue);
    _tprintf(_T("name : %s,  value: %s\n"), strName, strValue);
}
}


void PrintElementsOfCollection(IAppHostChildElementCollection *pCollection)
{
HRESULT hr = S_OK;

IAppHostElement *pElement = NULL;

DWORD elements_count = 0;
hr = pCollection->get_Count(&elements_count);

VARIANT vtIndex;
vtIndex.vt = VT_INT;
for(DWORD i=0; i<elements_count; ++i)
{
    vtIndex.intVal = i;
    hr = pCollection->get_Item(vtIndex, &pElement);

    BSTR strName;
    hr = pElement->get_Name(&strName);
    _tprintf(_T("element : %s\n"), strName);
}
}

void PrintElementsOfCollection(IAppHostElementCollection *pCollection)
{
HRESULT hr = S_OK;

IAppHostElement *pElement = NULL;

DWORD elements_count = 0;
hr = pCollection->get_Count(&elements_count);

VARIANT vtIndex;
vtIndex.vt = VT_INT;
for(DWORD i=0; i<elements_count; ++i)
{
    vtIndex.intVal = i;
    hr = pCollection->get_Item(vtIndex, &pElement);

    BSTR strName;
    hr = pElement->get_Name(&strName);
    _tprintf(_T("element : %s\n"), strName);

    //PrintPropertiesOfElement(pElement);
}
}

struct UserCertification
{
VARIANT username;
VARIANT password;
VARIANT certification;

public:
    UserCertification(wstring name, wstring pwd, wstring cert)
    {
    username.vt = VT_BSTR;
    username.bstrVal = SysAllocString(name.c_str());

    password.vt = VT_BSTR;
    password.bstrVal = SysAllocString(pwd.c_str());

    certification.vt = VT_BSTR;
    certification.bstrVal = SysAllocString(cert.c_str());
}
};

HRESULT SetHostElementProperty(IAppHostElement *pElement, UserCertification *pUserCert)
{
HRESULT hr = S_OK;

IAppHostProperty *pProperty = NULL;

BSTR name = SysAllocString(L"userName");
BSTR password = SysAllocString(L"password");
BSTR certification = SysAllocString(L"certificate");

//name
hr = pElement->GetPropertyByName(name, &pProperty);
pProperty->put_Value(pUserCert->username);

//password
hr = pElement->GetPropertyByName(password, &pProperty);
pProperty->put_Value(pUserCert->password);

//certification
hr = pElement->GetPropertyByName(certification, &pProperty);
pProperty->put_Value(pUserCert->certification);

return hr;
}

UserCertification* GenerateUserCertification()
{
wstring username = L"jinqiu.tao@emacle.com";
wstring password = L"123456";
wstring certificate = L"xxxxxxxx";

return new UserCertification(username, password, certificate);
}

int _tmain(int argc, _TCHAR* argv[])
{
HRESULT                               hr          = S_OK;

IAppHostWritableAdminManager        * pWMgr       = NULL;
IAppHostConfigManager               * pCfgMgr     = NULL;
IAppHostConfigFile                  * pCfgFile    = NULL;
IAppHostConfigLocationCollection * pLocations  = NULL;

IAppHostElement *pAdminSection = NULL;
IAppHostElementCollection *pElementCollection = NULL;
IAppHostChildElementCollection *pChildElements = NULL;
IAppHostElement *pElement = NULL;
IAppHostElement *pNewElement = NULL;

BSTR bstrConfigCommitPath = SysAllocString(L"MACHINE/WEBROOT/APPHOST/Default Web Site");
BSTR bstrSectionName = SysAllocString(L"system.webServer/security/authentication/iisClientCertificateMappingAuthentication");
BSTR bstrOneToOne = SysAllocString(L"oneToOneMappings");
BSTR bstrElementName = SysAllocString(L"add");

// Initialize
hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );

// Create
hr = CoCreateInstance( __uuidof( AppHostWritableAdminManager ), NULL,
    CLSCTX_INPROC_SERVER,
    __uuidof( IAppHostWritableAdminManager ), (void**) &pWMgr );

pWMgr -> put_CommitPath ( bstrConfigCommitPath );

hr = pWMgr->GetAdminSection(bstrSectionName, bstrConfigCommitPath, &pAdminSection);

hr = pAdminSection->get_ChildElements(&pChildElements);

PrintElementsOfCollection(pChildElements);

hr = pAdminSection->GetElementByName(bstrOneToOne, &pElement);

hr = pElement->get_Collection(&pElementCollection);

//PrintElementsOfCollection(pElementCollection);

hr = pElementCollection->CreateNewElement(bstrElementName, &pNewElement);

//PrintPropertiesOfElement(pNewElement);

hr = SetHostElementProperty(pNewElement, GenerateUserCertification());

    //got and error saying that another process is accesssing the data
hr = pElementCollection->AddElement(pNewElement);  //got an error code 0x80070021 here |||||||||||||||||

PrintElementsOfCollection(pElementCollection);

// Commit the changes to the configuration system
pWMgr->CommitChanges ( );
return 0;
}

As you see, I can create a new element, but not able to add it to the element collection.

What I want to do is just add a record to the onetoonemappings part.

<location path="Default Web Site">
        <system.webServer>
            <security>
                <access sslFlags="None" />
                <authentication>
                    <anonymousAuthentication enabled="true" />
                    <iisClientCertificateMappingAuthentication enabled="true" oneToOneCertificateMappingsEnabled="true">
                        <oneToOneMappings>
                            <add userName="yonggui.yu@emacle.com" password="[enc:AesProvider:4QEVwn3c530VH5sdwCl+Sm8G2eJesNEs4SaL6U5LrXg=:enc]" certificate="MIIFOjCCBCKgAwIBAgIKOAV" />
                            <add userName="yuyonggui@tbp.com" password="[enc:AesProvider:iBqmPwvbefiuiUZ03AyPD/0AxzD0HIb4SlJXKQGr9Ug=:enc]" certificate="MIIEjzCCA3egAwIBAgIKGgSFpwAAAA" />
                            <add userName="yonggui.yu@emacle.com" password="[enc:AesProvider:DogNZMKGrLa9ih2IO9PiMNUz9Ucggu9icKD7o8+U8dQ=:enc]" certificate="MIIFZzCCBE+gAwIBAgIHGAOD3e2==" />
                        </oneToOneMappings>
                    </iisClientCertificateMappingAuthentication>
                </authentication>
        </security>
    </system.webServer>

I hope that I have made it clear enough. If you guys need any kind of additional information, please do not hesitate to inform me.

Looking forward for your help.

Best Regards,

Jordan

c++
windows
iis
windows-server-2008
asked on Stack Overflow Dec 13, 2013 by user3069571 • edited Dec 13, 2013 by user3069571

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0