problems getting caller's identity
Hi,
I'm building a COM service that runs as Local System. I have experience
with in-proc servers, but this is all new to me, and I've been having a
really hard time with all of the security related stuff... because I'm
providing system-level access to unprivileged users, I would like to get the
caller's identity and deny access to anyone who is not a member of the
administrator's group... (simply allowing admin group only is not an option
due to other constraints)
I don't know that I am doing any of this correctly... I have been doing
trial and error until I got it working at all... so it could be all wrong
and I welcome any comments or corrections...
In my service module's InitializeSecurity method, I have:
HRESULT InitializeSecurity() throw()
{
CSecurityDesc secdesc;
CSid sidSys(Sids:: System());
CSid sidAdmins(Sids:: Admins());
CDacl dacl;
HRESULT hr;
if(!dacl.AddAllowedAce(sidSys, COM_RIGHTS_EXECUTE |
COM_RIGHTS_EXECUTE_LOCAL | COM_RIGHTS_ACTIVATE_LOCAL))
return E_FAIL;
if(!dacl.AddAllowedAce(sidAdmins, COM_RIGHTS_EXECUTE |
COM_RIGHTS_EXECUTE_LOCAL | COM_RIGHTS_ACTIVATE_LOCAL))
return E_FAIL;
if(!dacl.AddAllowedAce(Sids:: AuthenticatedUser(), COM_RIGHTS_EXECUTE |
COM_RIGHTS_EXECUTE_LOCAL | COM_RIGHTS_ACTIVATE_LOCAL))
return E_FAIL;
secdesc.SetGroup(sidAdmins);
secdesc.SetOwner(sidSys);
secdesc.SetDacl(dacl);
hr =
::CoInitializeSecurity(const_cast<SECURITY_DESCRIPTOR*>(secdesc.GetPSECURITY_DESCRIPTOR()),
-1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IDENTIFY,
NULL, EOAC_NO_CUSTOM_MARSHAL, NULL);
return hr;
}
I honestly don't understand much of this, other than the basic idea that I
am saying that any authenticated user has the right to attempt to create a
COM object provided by my service (I think)... oh, and... I thought that
this says that I will require the ability to identify any caller... but
that's where I'm currently pulling my hair out...
In my application's WinMain, among other initialization code, I have:
{
CSecurityDesc secdesc;
CSid sidSys(Sids:: System());
CSid sidMe(Sids:: Self());
CSid sidAuth(Sids:: AuthenticatedUser());
CDacl dacl;
HRESULT hr;
dacl.AddAllowedAce(sidSys, COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL
| COM_RIGHTS_ACTIVATE_LOCAL);
dacl.AddAllowedAce(sidMe, COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL |
COM_RIGHTS_ACTIVATE_LOCAL);
dacl.AddAllowedAce(sidAuth, COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL
| COM_RIGHTS_ACTIVATE_LOCAL);
secdesc.SetGroup(sidAuth);
secdesc.SetOwner(sidMe);
secdesc.SetDacl(dacl);
hr =
::CoInitializeSecurity(const_cast<SECURITY_DESCRIPTOR*>(secdesc.GetPSECURITY_DESCRIPTOR()),
-1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IDENTIFY,
NULL, EOAC_DYNAMIC_CLOAKING, NULL);
}
which I think gives the system the ability to use callback interfaces if
necessary... like I said, I really don't understand... but, again, I thought
that this says that when I call out, the service has the ability to identify
me...
but lastly (at least, I think it ought to be the last piece to the puzzle),
in a derived class factory that all of my externally creatable objects will
be using, I have:
STDMETHODIMP
CAdminOnlyCF:: CreateInstance(LPUNKNOWN pUnkOuter, const IID &riid, void
**ppvObj)
{
CAccessToken token;
bool isAdmin;
if(!token.OpenThreadToken(TOKEN_QUERY, false, false,
SecurityIdentification))
return E_FAIL;
if(!token.CheckTokenMembership(Sids::Admins(), &isAdmin))
return E_FAIL;
if(isAdmin)
return __super:: CreateInstance(pUnkOuter, riid, ppvObj);
return E_ACCESSDENIED;
}
but the call to OpenThreadToken always fails... walking into the code, I
find that the failure occurs in the call to the OpenThreadToken API, with
the error:
0x00000542 Either a required impersonation level was not provided, or the
provided impersonation level is invalid.
if RPC_C_IMP_LEVEL_IDENTIFY is used in both calls to CoInitializeSecurity,
and I am passing SecurityIdentification into OpenThreadToken, then why is my
impersonation level invalid? What am I missing?
I have searched the groups for related threads, but I can't seem to find a
working solution... Any help is greatly appreciated...
Thanks in advance,
Chris