|
|
//***************************************************************************
//
// WBEMSEC.CPP
//
// Purpose: Provides some security helper functions.
//
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
//#undef _WIN32_WINNT
//#define _WIN32_WINNT 0x0400
#include "precomp.h"
#include <wbemidl.h>
#include "wbemsec.h"
//***************************************************************************
//
// InitializeSecurity(DWORD dwAuthLevel, DWORD dwImpLevel)
//
// DESCRIPTION:
//
// Initialize DCOM security. The authentication level is typically
// RPC_C_AUTHN_LEVEL_CONNECT, and the impersonation level is typically
// RPC_C_IMP_LEVEL_IMPERSONATE. When using asynchronous call backs, an
// authentication level of RPC_C_AUTHN_LEVEL_NONE is useful
//
// RETURN VALUE:
//
// see description.
//
//***************************************************************************
HRESULT InitializeSecurity(DWORD dwAuthLevel, DWORD dwImpLevel) { // Initialize security
// ===================
return CoInitializeSecurity(NULL, -1, NULL, NULL, dwAuthLevel, dwImpLevel, NULL, EOAC_NONE, 0); }
//***************************************************************************
//
// bool bIsNT
//
// DESCRIPTION:
//
// Returns true if running windows NT.
//
// RETURN VALUE:
//
// see description.
//
//***************************************************************************
bool bIsNT(void) { OSVERSIONINFO os; os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if(!GetVersionEx(&os)) return FALSE; // should never happen
return os.dwPlatformId == VER_PLATFORM_WIN32_NT; }
//***************************************************************************
//
// SCODE ParseAuthorityUserArgs
//
// DESCRIPTION:
//
// Examines the Authority and User argument and determines the authentication
// type and possibly extracts the domain name from the user arugment in the
// NTLM case. For NTLM, the domain can be at the end of the authentication
// string, or in the front of the user name, ex; "redmond\a-davj"
//
// PARAMETERS:
//
// ConnType Returned with the connection type, ie wbem, ntlm
// AuthArg Output, contains the domain name
// UserArg Output, user name
// Authority Input
// User Input
//
// RETURN VALUE:
//
// S_OK all is well
// else error listed in WBEMSVC.H
//
//***************************************************************************
SCODE ParseAuthorityUserArgs(BSTR & AuthArg, BSTR & UserArg,BSTR & Authority,BSTR & User) {
// Determine the connection type by examining the Authority string
if(!(Authority == NULL || wcslen(Authority) == 0 || !_wcsnicmp(Authority, L"NTLMDOMAIN:",11))) return E_INVALIDARG;
// The ntlm case is more complex. There are four cases
// 1) Authority = NTLMDOMAIN:name" and User = "User"
// 2) Authority = NULL and User = "User"
// 3) Authority = "NTLMDOMAIN:" User = "domain\user"
// 4) Authority = NULL and User = "domain\user"
// first step is to determine if there is a backslash in the user name somewhere between the
// second and second to last character
WCHAR * pSlashInUser = NULL; if(User) { WCHAR * pEnd = User + wcslen(User) - 1; for(pSlashInUser = User; pSlashInUser <= pEnd; pSlashInUser++) if(*pSlashInUser == L'\\') // dont think forward slash is allowed!
break; if(pSlashInUser > pEnd) pSlashInUser = NULL; }
if(Authority && wcslen(Authority) > 11) { if(pSlashInUser) return E_INVALIDARG;
AuthArg = SysAllocString(Authority + 11); if(User) UserArg = SysAllocString(User); return S_OK; } else if(pSlashInUser) { INT_PTR iDomLen = min(MAX_PATH-1, pSlashInUser-User); WCHAR cTemp[MAX_PATH]; wcsncpy(cTemp, User, iDomLen); cTemp[iDomLen] = 0; AuthArg = SysAllocString(cTemp); if(wcslen(pSlashInUser+1)) UserArg = SysAllocString(pSlashInUser+1); } else if(User) UserArg = SysAllocString(User);
return S_OK; }
//***************************************************************************
//
// SCODE GetAuthImp
//
// DESCRIPTION:
//
// Gets the authentication and impersonation levels for a current interface.
//
// PARAMETERS:
//
// pFrom the interface to be tested.
// pdwAuthLevel Set to the authentication level
// pdwImpLevel Set to the impersonation level
// RETURN VALUE:
//
// S_OK all is well
// else error listed in WBEMSVC.H
//
//***************************************************************************
SCODE GetAuthImp(IUnknown * pFrom, DWORD * pdwAuthLevel, DWORD * pdwImpLevel) {
if(pFrom == NULL || pdwAuthLevel == NULL || pdwImpLevel == NULL) return WBEM_E_INVALID_PARAMETER;
IClientSecurity * pFromSec = NULL; SCODE sc = pFrom->QueryInterface(IID_IClientSecurity, (void **) &pFromSec); if(sc == S_OK) { DWORD dwAuthnSvc, dwAuthzSvc, dwCapabilities; sc = pFromSec->QueryBlanket(pFrom, &dwAuthnSvc, &dwAuthzSvc, NULL, pdwAuthLevel, pdwImpLevel, NULL, &dwCapabilities);
// Special case of going to a win9x share level box
if (sc == 0x800706d2) { *pdwAuthLevel = RPC_C_AUTHN_LEVEL_NONE; *pdwImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; sc = S_OK; } pFromSec->Release(); } return sc; } //***************************************************************************
//
// SCODE SetInterfaceSecurity
//
// DESCRIPTION:
//
// This routine is used by clients in order to set the identity to be used by a connection.
// NOTE that setting the security blanket on the interface is not recommended.
// The clients should typically just call CoInitializeSecurity( NULL, -1, NULL, NULL,
// RPC_C_AUTHN_LEVEL_DEFAULT,
// RPC_C_IMP_LEVEL_IMPERSONATE,
// NULL,
// EOAC_NONE,
// NULL );
// before calling out to WMI.
//
//
// PARAMETERS:
//
// pInterface Interface to be set
// pDomain Input, domain
// pUser Input, user name
// pPassword Input, password.
// pFrom Input, if not NULL, then the authentication level of this interface
// is used
// bAuthArg If pFrom is NULL, then this is the authentication level
// RETURN VALUE:
//
// S_OK all is well
// else error listed in WBEMSVC.H
//
//***************************************************************************
HRESULT SetInterfaceSecurity(IUnknown * pInterface, LPWSTR pAuthority, LPWSTR pUser, LPWSTR pPassword, DWORD dwAuthLevel, DWORD dwImpLevel) {
SCODE sc; if(pInterface == NULL) return E_INVALIDARG;
// If we are lowering the security, no need to deal with the identification info
if(dwAuthLevel == RPC_C_AUTHN_LEVEL_NONE) return CoSetProxyBlanket(pInterface, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
// If we are doing trivial case, just pass in a null authentication structure which is used
// if the current logged in user's credentials are OK.
if((pAuthority == NULL || wcslen(pAuthority) < 1) && (pUser == NULL || wcslen(pUser) < 1) && (pPassword == NULL || wcslen(pPassword) < 1)) return CoSetProxyBlanket(pInterface, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, dwAuthLevel, dwImpLevel, NULL, EOAC_NONE);
// If user, or Authority was passed in, the we need to create an authority argument for the login
COAUTHIDENTITY authident; BSTR AuthArg = NULL, UserArg = NULL; sc = ParseAuthorityUserArgs(AuthArg, UserArg, pAuthority, pUser); if(sc != S_OK) return sc;
memset((void *)&authident,0,sizeof(COAUTHIDENTITY)); if(bIsNT()) { if(UserArg) { authident.UserLength = (ULONG)wcslen(UserArg); authident.User = (LPWSTR)UserArg; } if(AuthArg) { authident.DomainLength = (ULONG)wcslen(AuthArg); authident.Domain = (LPWSTR)AuthArg; } if(pPassword) { authident.PasswordLength = (ULONG)wcslen(pPassword); authident.Password = (LPWSTR)pPassword; } authident.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; } else { char szUser[MAX_PATH], szAuthority[MAX_PATH], szPassword[MAX_PATH];
// Fill in the indentity structure
if(UserArg) { wcstombs(szUser, UserArg, MAX_PATH); authident.UserLength = (ULONG)strlen(szUser); authident.User = (LPWSTR)szUser; } if(AuthArg) { wcstombs(szAuthority, AuthArg, MAX_PATH); authident.DomainLength = (ULONG)strlen(szAuthority); authident.Domain = (LPWSTR)szAuthority; } if(pPassword) { wcstombs(szPassword, pPassword, MAX_PATH); authident.PasswordLength = (ULONG)strlen(szPassword); authident.Password = (LPWSTR)szPassword; } authident.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; } sc = CoSetProxyBlanket(pInterface, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, dwAuthLevel, dwImpLevel, &authident, EOAC_NONE);
if(UserArg) SysFreeString(UserArg); if(AuthArg) SysFreeString(AuthArg); return sc; }
|