Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Credential Provider Filter not working

1,736 views
Skip to first unread message

sushi_cw

unread,
Feb 4, 2008, 2:48:08 PM2/4/08
to
Hello,

I've implemented a Credential Provider based on the MS samples, and I would
like it to filter out the default MS password provider. To keep things
simple, I decided to implement the ICredentialProviderFilter interface on my
main Credential Provider class (which works fine). To do that, I updated the
class to implement ICredentialProviderFilter, implemented the Filter and
UpdateRemoteCredential methods, and registered the assembly in the registry
as a Credential Provider filter.

Unfortunately, something isn't working. As far as I can tell the Filter
method is never getting called, and I'm wondering what I've missed. I've
included the relevant sections of code (and registry entries):


--CLMSProvider.h--

class CLMSProvider : public ICredentialProvider, public
ICredentialProviderFilter
{

//***SNIP***

public:

//***SNIP: ICredentialProvider methods ***

IFACEMETHODIMP Filter(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, DWORD
dwFlags, GUID* rgclsidProviders, BOOL* rgbAllow, DWORD cProviders);

IFACEMETHODIMP UpdateRemoteCredential(const
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcsIn,
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcsOut);

//***SNIP***

};
--------------------

--CLMSProvider.cpp--

//***SNIP***

//Function to filter out other credential providers
HRESULT CLMSProvider::Filter(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, DWORD
dwFlags, GUID* rgclsidProviders, BOOL* rgbAllow, DWORD cProviders)
{
//DEBUG
MessageBox(NULL, "Filter!", "Trace", NULL);

switch (cpus)
{
case CPUS_LOGON:
case CPUS_UNLOCK_WORKSTATION:
//Filters out the default Windows provider (only for Logon and
Unlock scenarios)
//TODO: This isn't working
for (int i = 0; i < cProviders; i++)
{
if (IsEqualGUID(rgclsidProviders[i], CLSID_PasswordCredentialProvider))
rgbAllow[i] = FALSE;
}
return S_OK;

case CPUS_CREDUI:
case CPUS_CHANGE_PASSWORD:
return E_NOTIMPL;

default:
return E_INVALIDARG;
}
}

//Used for remote sessions, not implemented here
HRESULT CLMSProvider::UpdateRemoteCredential(const
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcsIn,
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcsOut)
{
return E_NOTIMPL;
}

//***SNIP***
-------------------

--Register.reg--

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{3E340420-5103-11DC-99F1-DB9156D89593}]
@="LMSCredentialProvider"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters\{3E340420-5103-11DC-99F1-DB9156D89593}]
@="LMSCredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{3E340420-5103-11DC-99F1-DB9156D89593}]
@="LMSCredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{3E340420-5103-11DC-99F1-DB9156D89593}\InprocServer32]
@="LMSCredentialProvider.dll"
"ThreadingModel"="Apartment"

-------------------

So, what did I miss? Any help would be appreciated. Thanks!

sushi_cw

unread,
Feb 13, 2008, 11:10:00 AM2/13/08
to
I managed to solve this elsewhere: see
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2775055&SiteID=1 for
the whole conversation.

Short version: once I moved the filter to its own class (instead of putting
ICredentialProvider and ICredentialProviderFilter on the same class)
everything worked fine.

dmm

unread,
Apr 8, 2008, 3:24:01 PM4/8/08
to
Hi sushi_cw

I followed the message trail and implemented my filter as you suggested. In
the tests that I executed below, any actual filtration was disabled in method
"Filter" for simplicity. I am not an experienced COM programmer which is
likely why my implementation failed.

At first, I instantiated my filter from the constructor in CMyProvider
(based on the MS example "CSampleProvider"). Methods "Filter" and
"UpdateRemoteCredential" are never invoked in my filter. Next I instantiated
my filter in the same manner as CMyProvider via the class factory, etc. This
was worse in that no tiles appeared (pretty effective filtering!).

How did you instantiate your filter object and from where?

Thanks
dmm

sushi_cw

unread,
Apr 9, 2008, 10:21:02 AM4/9/08
to
You shouldn't need to manually instantiate the filter. You just register it,
and code enough of the COM boilerplate that when Windows asks your DLL for an
instance, it can be generated. From your post, I'm not sure if you're doing
that or not, so I'll go ahead and post some code samples for you and anyone
else who comes looking.

Here's a snippet from my "register.reg":

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{<LMSCredentialProvider GUID Snipped>}]
@="LMSCredentialProvider"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters\{<LMSCredentialProvider GUID Snipped>}]
@="LMSCredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{<LMSCredentialProvider GUID Snipped>}]
@="LMSCredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{<LMSCredentialProvider GUID
Snipped>}\InprocServer32]


@="LMSCredentialProvider.dll"
"ThreadingModel"="Apartment"

As mentioned in the other thread, I have a separate class for the filter in
the same DLL.

Here is CLMSFilter.h:

#pragma once
#include "credentialprovider.h"
#include <windows.h>
#include <strsafe.h>
#include "dll.h"

//This class implements ICredentialProviderFilter, which is responsible for
filtering out other credential providers.
//The LMS Credential Provider uses this to mask out the default Windows
provider.
class CLMSFilter : public ICredentialProviderFilter
{
public:
//This section contains some COM boilerplate code

// IUnknown
STDMETHOD_(ULONG, AddRef)()
{
return _cRef++;
}

STDMETHOD_(ULONG, Release)()
{
LONG cRef = _cRef--;
if (!cRef)
{
delete this;
}
return cRef;
}

STDMETHOD (QueryInterface)(REFIID riid, void** ppv)
{
HRESULT hr;
if (IID_IUnknown == riid ||
IID_ICredentialProviderFilter == riid)
{
*ppv = this;
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
hr = S_OK;
}
else
{
*ppv = NULL;
hr = E_NOINTERFACE;
}
return hr;
}

public:
friend HRESULT CLMSFilter_CreateInstance(REFIID riid, __deref_out void**
ppv);

//Implementation of ICredentialProviderFilter


IFACEMETHODIMP Filter(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, DWORD
dwFlags, GUID* rgclsidProviders, BOOL* rgbAllow, DWORD cProviders);
IFACEMETHODIMP UpdateRemoteCredential(const
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcsIn,
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcsOut);

protected:
CLMSFilter();
__override ~CLMSFilter();

private:
LONG _cRef;
};

You shouldn't need to do anything special with your CredentialProvider class.

You will also need to modify dll.cpp to know about your Credential Provider
filter class. I believe the only changes I made to the basic MS sample were:
1. add "extern HRESULT CLMSFilter_CreateInstance(REFIID riid, void** ppv);"
towards the top of the file.
2. Modify the function with signature "STDMETHOD (CreateInstance)(IUnknown*
pUnkOuter, REFIID riid, void** ppv)" to be as follows:
STDMETHOD (CreateInstance)(IUnknown* pUnkOuter, REFIID riid, void** ppv)
{
HRESULT hr;
if (!pUnkOuter)
{
if (IID_ICredentialProvider == riid)
hr = CLMSProvider_CreateInstance(riid, ppv);
else if (IID_ICredentialProviderFilter == riid)
hr = CLMSFilter_CreateInstance(riid, ppv);
}
else
{
hr = CLASS_E_NOAGGREGATION;
}
return hr;
}

I think that's everything. Go ahead and check your code against what I've
posted: hopefully, there's something there that will help you out.

dmm

unread,
Apr 9, 2008, 2:51:01 PM4/9/08
to
Hi sushi_cw

After examining your reply, I realized that I had missed step 2. After
inserting the code in my CClassFactory implementation, my filter is filtering
and my credential provider is looking good!

Many thanks for your help once again!

dmm

zakjamieson

unread,
Dec 22, 2009, 9:50:22 PM12/22/09
to
Hello,

I have a working Credential Provider where I wanted to introduce filtering. So I followed all of your steps (thanks for posting btw) but when I compile I run into an error:

2. Modify the function with signature "STDMETHOD (CreateInstance)(IUnknown*
pUnkOuter, REFIID riid, void** ppv)" to be as follows:
STDMETHOD (CreateInstance)(IUnknown* pUnkOuter, REFIID riid, void** ppv)
{
HRESULT hr;
if (!pUnkOuter)
{
if (IID_ICredentialProvider == riid)
hr = CLMSProvider_CreateInstance(riid, ppv);
else if (IID_ICredentialProviderFilter == riid)
hr = CLMSFilter_CreateInstance(riid, ppv);
}
else
{
hr = CLASS_E_NOAGGREGATION;
}
return hr;
}


This is the error message, what am I missing?

1>.\Dll.cpp(51) : error C2065: 'IID_ICredentialProvider' : undeclared identifier
1>.\Dll.cpp(53) : error C2065: 'IID_ICredentialProviderFilter' : undeclared identifier

thanks
zak

sushic wrote:

You shouldn't need to manually instantiate the filter.

09-Apr-08

You shouldn't need to manually instantiate the filter. You just register it,
and code enough of the COM boilerplate that when Windows asks your DLL for an
instance, it can be generated. From your post, I'm not sure if you're doing
that or not, so I'll go ahead and post some code samples for you and anyone
else who comes looking.

Here's a snippet from my "register.reg":

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{<LMSCredentialProvider GUID Snipped>}]
@="LMSCredentialProvider"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters\{<LMSCredentialProvider GUID Snipped>}]
@="LMSCredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{<LMSCredentialProvider GUID Snipped>}]
@="LMSCredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{<LMSCredentialProvider GUID
Snipped>}\InprocServer32]
@="LMSCredentialProvider.dll"
"ThreadingModel"="Apartment"

As mentioned in the other thread, I have a separate class for the filter in
the same DLL.

Here is CLMSFilter.h:


protected:
CLMSFilter();
__override ~CLMSFilter();

private:
LONG _cRef;
};


"dmm" wrote:

Previous Posts In This Thread:

On Monday, February 04, 2008 2:48 PM
sushic wrote:

Credential Provider Filter not working
Hello,

I've implemented a Credential Provider based on the MS samples, and I would
like it to filter out the default MS password provider. To keep things
simple, I decided to implement the ICredentialProviderFilter interface on my
main Credential Provider class (which works fine). To do that, I updated the
class to implement ICredentialProviderFilter, implemented the Filter and
UpdateRemoteCredential methods, and registered the assembly in the registry
as a Credential Provider filter.

Unfortunately, something isn't working. As far as I can tell the Filter
method is never getting called, and I'm wondering what I've missed. I've
included the relevant sections of code (and registry entries):


--CLMSProvider.h--

class CLMSProvider : public ICredentialProvider, public
ICredentialProviderFilter
{

//***SNIP***

public:

//***SNIP: ICredentialProvider methods ***

IFACEMETHODIMP Filter(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, DWORD

dwFlags, GUID* rgclsidProviders, BOOL* rgbAllow, DWORD cProviders);

IFACEMETHODIMP UpdateRemoteCredential(const
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcsIn,
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcsOut);

//***SNIP***

};
--------------------

--CLMSProvider.cpp--

//***SNIP***

//Function to filter out other credential providers

HRESULT CLMSProvider::Filter(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, DWORD

dwFlags, GUID* rgclsidProviders, BOOL* rgbAllow, DWORD cProviders)

{
//DEBUG
MessageBox(NULL, "Filter!", "Trace", NULL);

switch (cpus)
{
case CPUS_LOGON:
case CPUS_UNLOCK_WORKSTATION:
//Filters out the default Windows provider (only for Logon and
Unlock scenarios)
//TODO: This isn't working
for (int i = 0; i < cProviders; i++)
{
if (IsEqualGUID(rgclsidProviders[i], CLSID_PasswordCredentialProvider))
rgbAllow[i] = FALSE;
}
return S_OK;

case CPUS_CREDUI:
case CPUS_CHANGE_PASSWORD:
return E_NOTIMPL;

default:
return E_INVALIDARG;
}
}

//Used for remote sessions, not implemented here

HRESULT CLMSProvider::UpdateRemoteCredential(const
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcsIn,
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcsOut)
{
return E_NOTIMPL;
}

//***SNIP***
-------------------

--Register.reg--

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{3E340420-5103-11DC-99F1-DB9156D89593}]
@="LMSCredentialProvider"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters\{3E340420-5103-11DC-99F1-DB9156D89593}]
@="LMSCredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{3E340420-5103-11DC-99F1-DB9156D89593}]
@="LMSCredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{3E340420-5103-11DC-99F1-DB9156D89593}\InprocServer32]


@="LMSCredentialProvider.dll"
"ThreadingModel"="Apartment"

-------------------



So, what did I miss? Any help would be appreciated. Thanks!

On Wednesday, February 13, 2008 11:10 AM
sushic wrote:

RE: Credential Provider Filter not working


I managed to solve this elsewhere: see
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2775055&SiteID=1 for
the whole conversation.

Short version: once I moved the filter to its own class (instead of putting
ICredentialProvider and ICredentialProviderFilter on the same class)
everything worked fine.

"sushi_cw" wrote:

On Tuesday, April 08, 2008 3:24 PM
dm wrote:

Hi sushi_cwI followed the message trail and implemented my filter as you
Hi sushi_cw

I followed the message trail and implemented my filter as you suggested. In
the tests that I executed below, any actual filtration was disabled in method
"Filter" for simplicity. I am not an experienced COM programmer which is
likely why my implementation failed.

At first, I instantiated my filter from the constructor in CMyProvider
(based on the MS example "CSampleProvider"). Methods "Filter" and
"UpdateRemoteCredential" are never invoked in my filter. Next I instantiated
my filter in the same manner as CMyProvider via the class factory, etc. This
was worse in that no tiles appeared (pretty effective filtering!).

How did you instantiate your filter object and from where?

Thanks
dmm


"sushi_cw" wrote:

On Wednesday, April 09, 2008 10:21 AM
sushic wrote:

You shouldn't need to manually instantiate the filter.
You shouldn't need to manually instantiate the filter. You just register it,
and code enough of the COM boilerplate that when Windows asks your DLL for an
instance, it can be generated. From your post, I'm not sure if you're doing
that or not, so I'll go ahead and post some code samples for you and anyone
else who comes looking.

Here's a snippet from my "register.reg":

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{<LMSCredentialProvider GUID Snipped>}]
@="LMSCredentialProvider"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters\{<LMSCredentialProvider GUID Snipped>}]
@="LMSCredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{<LMSCredentialProvider GUID Snipped>}]
@="LMSCredentialProvider"

[HKEY_CLASSES_ROOT\CLSID\{<LMSCredentialProvider GUID
Snipped>}\InprocServer32]
@="LMSCredentialProvider.dll"
"ThreadingModel"="Apartment"

As mentioned in the other thread, I have a separate class for the filter in
the same DLL.

Here is CLMSFilter.h:


protected:
CLMSFilter();
__override ~CLMSFilter();

private:
LONG _cRef;
};


"dmm" wrote:

On Wednesday, April 09, 2008 2:51 PM
dm wrote:

Hi sushi_cwAfter examining your reply, I realized that I had missed step 2.
Hi sushi_cw

After examining your reply, I realized that I had missed step 2. After
inserting the code in my CClassFactory implementation, my filter is filtering
and my credential provider is looking good!

Many thanks for your help once again!

dmm

"sushi_cw" wrote:


Submitted via EggHeadCafe - Software Developer Portal of Choice
Multi-Dimensional Arrays In ASP
http://www.eggheadcafe.com/tutorials/aspnet/7c9eb19a-2ee5-42c0-8e59-3dae1c6edc36/multidimensional-arrays.aspx

0 new messages