全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2187
推到 Plurk!
推到 Facebook!

Windows Management Instrumentation

 
axsoft
版主


發表:681
回覆:1056
積分:969
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-02-25 16:28:50 IP:61.218.xxx.xxx 未訂閱
Windows Management Instrumentation     [資料來源: MSDN Executing Privileged Operations Using C Special client applications might invoke privileged operations. For example, an application could allow a manager to reboot an unresponsive office computer. With WMI, you can execute a privileged operation by calling the WMI provider for the privileged operation. To call a provider for a privileged operation Gain permissions for the client process to execute the privileged operation. Normally, an administrator sets these permissions using system administrative tools prior to running the process. Gain permission for the provider process to enable the privileged operation. You can normally set provider permissions with a call to the AdjustTokenPrivileges function. Gain permission for the client process to enable the privileged operation. This step is necessary only if the provider is local to the client. If the client and provider exist on the same computer, the client must specifically enable the privileged operation using one of the following techniques: If the client owns the process, the client can use AdjustTokenPrivileges to adjust the process token before calling WMI. In this case, you do not need to code any further. If the client is running on Windows 2000 or later and cannot access the client token, the client can use the following procedure to create a thread token and use AdjustTokenPrivileges on that token. Create a copy of the process token by calling ImpersonateSelf. Retrieve the newly-created thread token by calling GetThreadToken. Enable the privileged operation with a call to AdjustTokenPrivileges on the new token. Obtain a pointer to IWbemServices. Cloak the pointer to IWbemServices with a call to CoSetProxyBlanket. Repeat the previous five steps on any call to WMI. You must repeat the five steps because COM caches tokens incorrectly. The following code example shows how to enable privileges on a local machine:

// Get the privileges
//    The token has been obtained elsewhere
// ================== 
DWORD dwLen;
TOKEN_USER tu;    bRes = GetTokenInformation(
  hToken, 
  TokenPrivileges, 
  &tu, 
  0,
  &dwLen
); 
memset(&tu,0,sizeof(TOKEN_PRIVILEGE));
BYTE* pBuffer = new BYTE[dwLen];
if(pBuffer == NULL)
{
  CloseHandle(hToken);
  return WBEM_E_OUT_OF_MEMORY;
} 
bRes = GetTokenInformation(
  hToken, 
  TokenPrivileges, 
  pBuffer, 
  dwLen,
  &dwLen
);
if (!bRes)
{
  CloseHandle(hToken);
  delete [] pBuffer;
  return WBEM_E_ACCESS_DENIED;
}     // Iterate through all the privileges and enable them all
// ====================================================== 
TOKEN_PRIVILEGES* pPrivs = (TOKEN_PRIVILEGES*)pBuffer;
for (DWORD i = 0; i < pPrivs->PrivilegeCount; i  )
{
  pPrivs->Privileges[i].Attributes |= SE_PRIVILEGE_ENABLED;
} 
// Store the information back in the token
// ========================================= 
bRes = AdjustTokenPrivileges(
  hToken, 
  FALSE, 
  pPrivs, 
  0, NULL, NULL
);    delete [] pBuffer;
CloseHandle(hToken);     if (!bRes)
  return WBEM_E_ACCESS_DENIED;
else
  return WBEM_S_NO_ERROR;
Setting Authentication Using C One of the main tasks of ConnectServer for WMI is returning a pointer to an IWbemServices proxy. Through the IWbemServices proxy, you can access the capabilities of the WMI infrastructure. However, the pointer to the IWbemServices proxy has the identity of the client application process and not the identity of the IWbemServices process. Therefore, if you attempt to access IWbemServices with the pointer, you may receive an access-denied code such as E_ACCESSDENIED. To avoid the access-denied error, you must set the identity of the new pointer with a call to the CoSetProxyBlanket interface. If a client needs support for multiple Microsoft platforms, the best approach is merely to "echo back" the proxy security. By using this approach, you avoid having to write platform-specific code.

HRESULT hr = NULL;
DWORD dwAuthLevel;
hr = CoQueryProxyBlanket(pEnum, 
                         NULL,
                         NULL,
                         NULL,
                         &dwAuthLevel,
                         NULL,
                         NULL,
                         NULL
);
if (FAILED(hr))  // -- query failed
{
   cout << "Count not query proxy blanket. Error code = 0x"
        << hex << hr << endl;
   return 1;
}    hr = CoSetProxyBlanket(pEnum,
                       RPC_C_AUTHN_DEFAULT,
                       RPC_C_AUTHZ_NONE,
                       NULL,
                       dwAuthLevel,
                       RPC_C_IMP_LEVEL_IMPERSONATE,
                       NULL,
                       EOAC_NONE
);
if (FAILED(hr))
{
   cout << "Count not set proxy blanket. Error code = 0x"
        << hex << hr << endl;
   pEnum->Release();
   CoUninitialize();
   return 2;
}
After you set the security for your pointer, you can access WMI through the pointer. The previous code example works for most simple WMI client applications. However, you may need to change some of the security settings to a pointer during the life of an application. One of the changes you are most likely to make to the security for an out-of-process pointer is to the authentication credentials. Using the pAuthInfo parameter, you can define the authentication credentials in a call to CoSetProxyBlanket. The pAuthInfo parameter receives a SEC_WINNT_AUTH_IDENTIFY_W structure for NTLM or Kerberos authentication. The following code example shows how to set authentication credentials using CoSetProxyBlanket:

SEC_WINNT_AUTH_IDENTITY_W* pAuthIdentity = new WINNT_AUTH_IDENTITY_W;
ZeroMemory(pAuthIdentity, sizeof(SEC_WINNT_AUTH_IDENTITY_W));    pAuthIdentity->User = new WCHAR[32];
wcscpy(pAuthIdentity->User , L"MyUser");
pAuthIdentity->UserLength = wcslen(pAuthIdentity->User);    pAuthIdentity->Domain = new WCHAR[32];
wcscpy(pAuthIdentity-> Domain, L"MyDomain");
pAuthIdentity->Domain Length = wcslen(pAuthIdentity->Domain);    pAuthIdentity->Password = new WCHAR[32];
pAuthIdentity->Password[0] = NULL;
pAuthIdentity->PasswordLength = wcslen(pAuthIdentity->Password);    pAuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;    hr = CoSetProxyBlanket(pWbemServices, 
                       RPC_C_AUTHN_WINNT, 
                       RPC_C_AUTHZ_NONE, 
                       NULL, 
                       RPC_C_AUTHN_LEVEL_DEFAULT, 
                       RPC_C_IMP_LEVEL_IMPERSONATE, 
                       pAuthIdentity, 
                       EOAC_NONE
);
if (FAILED(hr))
{
   cout << "Count not set proxy blanket. Error code = 0x"
        << hex << hr << endl;
   pWbemServices->Release();
   delete [] pAuthIdentity->User;
   delete [] pAuthIdentity->Domain;
   delete [] pAuthIdentity->Password;
   delete pAuthIdentity;
   CoUninitialize();
   return 1;
}    //
// Perform a bunch of operations
//    // Cleanup
pWbemServices->Release();    delete [] pAuthIdentity->User;
delete [] pAuthIdentity->Domain;
delete [] pAuthIdentity->Password;    delete pAuthIdentity;
 
COM uses the authentication credentials contained within the SEC_WINNT_AUTH_IDENTIFY_W throughout the life of the proxy. Specifically, COM returns a pointer to SEC_WINNT_AUTH_IDENTIFY_W in calls to CoQueryProxyBlanket. In addition, the WMI Refresher calls CoSetProxyBlanket on the IWbemServices pointer passed into the AddObjectByPath, AddObjectByTemplate, and AddEnum methods. This is so that WMI can use the new authentication settings during calls to the Refresher. Therefore, do not delete SEC_WINNT_AUTH_IDENTIFY_W unless you change the values in the structure or until you free the proxy. Normally, you will have no reason to change the impersonation settings from what you set them to be in CoInitializeSecurity. Windows provides authentication services in one of three different security packages: NTLM, Kerberos, and Negotiate. For more information on these packages, see Microsoft Provided SSPS in the Security section of the Platform SDK. Normally, WMI and COM negotiate the correct authentication service during the connection process. However, there are some circumstances in which you may need to specify an authentication service: To specify Kerberos security to use delegation. To specify NTLM security on a Windows 2000 or later computer running in a Windows NT domain. To connect to a share-level Windows 95/98Me computer There is no simple way to specify an authentication service in a call to CoInitializeSecurity. Instead, you must use CoSetProxyBlanket to declare your desired authentication service. The following code example shows how to call CoSetProxyBlanket with an alternative authentication service:

hr = CoSetProxyBlanket(pProxy,
                       RPC_C_AUTHN_GSS_KERBEROS,     // Kerberos authentication service
                       RPC_C_AUTHN_DEFAULT,          // default authorization service
                       COLE_DEFAULT_PRINCIPAL,       // default server principal
                       RPC_C_AUTHN_LEVEL_CONNECT,    // authentication level
                       RPC_C_IMP_LEVEL_DELEGATE,     // impersonation level
                       NULL,                         // use current token
                       EOAC_NONE                     // no special capabilities
);
if (FAILED(hr))
{
   cout << "Count not set proxy blanket. Error code = 0x"
        << hex << hr << endl;
   pProxy->Release();
   return 1;
}
The CoSetProxyBlanket function allows you to specify an authorization service in the dwAuthzSvc parameter. However, neither NTLM nor Kerberos uses an authorization service. Therefore, set dwAuthzSvc to RPC_C_AUTHZ_DEFAULT or RPC_C_AUTHZ_NONE. If you use Windows 2000 to connect to a local WMI process, you cannot use RPC_C_AUTHN_GSS_KERBEROS. Instead, you must use RPC_C_AUTHN_GSS_NEGOTIATE. Using the Negotiate service, you receive Kerberos if a Kerberos service is available. Setting Security on a Remote IUnknown Interface In some situations, you may need more access to a server than just a pointer to a proxy. At times, you may need to gain a secure connection to the IUnknown interface of the proxy. Using IUnknown, you can query the remote system for interfaces and other necessary techniques. When a proxy is located on a remote computer, the server delegates all calls to the IUnknown interface of the proxy to the IRemUnknown interface. For example, if you call QueryInterface on a proxy and the requested interface was not part of the proxy, the proxy sends the call to the remote server. In turn, the remote server checks for the appropriate interface support. If the server does support the interface, COM marshals a new proxy back to the client so that the application can use the new interface. Problems arise if the client does not have access permissions to the remote server, yet is using the credentials of a user that does. In this situation, any attempt to access QueryInterface on the remote server fails. The final release on the proxy fails as well, because the current user does not have access to the remote server. A symptom of this is a one or two second lag before the client application fails the final proxy release. The failure occurs because COM attempted to access the remote server using the default security settings of the current user, which do not include the modified credentials that allowed access to the server in the first place. To avoid the failed connection, use CoSetProxyBlanket to explicitly set the security authentication on the pointer returned from IUnknown. Using CoSetProxyBlanket, you can make sure that the remote server receives the correct authentication identity. The following code describes how to use CoSetProxyBlanket to access a remote IUnknown interface.

SEC_WINNT_AUTH_IDENTITY_W* pAuthIdentity = 
   new SEC_WINNT_AUTH_IDENTITY_W;
ZeroMemory(pAuthIdentity, sizeof(SEC_WINNT_AUTH_IDENTITY_W));    pAuthIdentity->User = new WCHAR[32];
wcscpy(pAuthIdentity->User , L"MyUser" );
pAuthIdentity->UserLength = wcslen(pAuthIdentity->User);    pAuthIdentity->Domain = new WCHAR[32];
wcscpy(pAuthIdentity->Domain, L"MyDomain" );
pAuthIdentity->Domain Length = wcslen( pAuthIdentity->Domain);    pAuthIdentity->Password = new WCHAR[32];
pAuthIdentity->Password[0] = NULL;
pAuthIdentity->PasswordLength = wcslen( pAuthIdentity->Password);    pAuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;    // Set proxy security
hr = CoSetProxyBlanket(pWbemServices, 
                       RPC_C_AUTHN_WINNT, 
                       RPC_C_AUTHZ_NONE, 
                       NULL, 
                       RPC_C_AUTHN_LEVEL_DEFAULT, 
                       RPC_C_IMP_LEVEL_IMPERSONATE, 
                       pAuthIdentity, 
                       EOAC_NONE 
);
if (FAILED(hr))
{
   cout << "Count not set proxy blanket. Error code = 0x"
        << hex << hr << endl;
   pWbemServices->Release();
   return 1;
}    // Set IUnknown security
IUnknown*    pUnk = NULL;
pWbemServices->QueryInterface(IID_IUnknown, (void**) &pUnk);    hr = CoSetProxyBlanket(pUnk, 
                       RPC_C_AUTHN_WINNT, 
                       RPC_C_AUTHZ_NONE, 
                       NULL, 
                       RPC_C_AUTHN_LEVEL_DEFAULT, 
                       RPC_C_IMP_LEVEL_IMPERSONATE, 
                       pAuthIdentity, 
                       EOAC_NONE 
);
if (FAILED(hr))
{
   cout << "Count not set proxy blanket. Error code = 0x"
        << hex << hr << endl;
   pUnk->Release();
   pWbemServices->Release();
   delete [] pAuthIdentity->User;
   delete [] pAuthIdentity->Domain;
   delete [] pAuthIdentity->Password;
   delete pAuthIdentity;   
   return 1;
}    // cleanup IUnknown
pUnk->Release();    //
// Perform a bunch of operations
//    // Cleanup
pWbemServices->Release();    delete [] pAuthIdentity->User;
delete [] pAuthIdentity->Domain;
delete [] pAuthIdentity->Password;    delete pAuthIdentity;
Note When you set security on the IUnknown interface of a proxy, COM creates a copy of the proxy that may not be released until you call CoUninitialize. Setting the Security on an Out-of-Process Pointer You can set the authentication service, such as Kerberos, for calls to Windows® Management Instrumentation (WMI), or remote computers, such as shut-down commands. Setting the authentication level sets the security on any pointer that attempts to access information outside the process of the client application. A client application connects to an out-of-process server using an identity. An identity is a data object that consists of a user name, password, and authority settings. For a WMI client application, the call to the IWbemLocator::ConnectServer interface creates the initial identity. The ConnectServer method takes the identity in a set of three parameters, which you can set to NULL to indicate the current user. You can also specify a non-NULL parameter to indicate a specific user and domain. If the call is successful, ConnectServer returns a pointer through which you can access a variety of remote processes, such as a WMI service or the Windows operating system—directly. Like many COM interfaces, ConnectServer returns a pointer to a proxy. A proxy is a data object that represents a remote process, such as WMI or a remote provider. COM uses a proxy to allow developers access to remote data as though the data were local. The following list identifies which WMI interfaces use proxies: IWbemServices(SWbemServices scripting object) IEnumWbemClassObject IWbemCallResult IWbemRefresher (SWbemRefresher scripting object) For more information, see Accessing Performance Data from a High-performance Provider. Note The WMI Refresher is a special case because it is passed an IWbemServices pointer, whose security settings must be properly set. After you receive a pointer to a remote process, you can do one of two things. If you know what the process does, you can choose to set the security on the pointer and access the process normally. This is the case with most pointers to a WMI service. For more information, see Setting the Security Levels on a WMI Connection. Alternately, you can choose to access a different COM interface on the proxy through a call to the IUnknown interface on the proxy. For more information, see Setting Security on a Remote IUnknown Interface. Defaults and Recommendations The distributed version of the Component Object Model (DCOM) negotiates the default authentication service, and you cannot specify the default authentication service using CoInitializeSecurity(). For remote connections, when the client and server are both at least Windows 2000, the default service is Negotiate, which is the recommended service for applications functioning in both Kerberos and non-Kerberos domains. For local connections, the default authentication service is NT LAN Manager (NTLM). However, the client does have control of the service selected for a specific proxy, through CoSetProxyBlanket. It is recommended that DCOM select the default principal. If you are connected to a local WMI process, RPC_C_AUTHN_GSS_KERBEROS cannot be used. Using Default allows DCOM to select the most suitable service. The following C example shows the recommended defaults in the CoSetProxyBlanket call.

HRESULT hr = CoSetProxyBlanket(pWbemServices,                //Proxy
                               RPC_C_AUTHN_DEFAULT,          //Authentication service 
                               RPC_C_AUTHZ_DEFAULT,          //Authorization service 
                               COLE_DEFAULT_PRINCIPAL,       //Server principal name used by authentication service
                               RPC_C_AUTHN_LEVEL_DEFAULT,    //Authentication level
                               RPC_C_IMP_LEVEL_IMPERSONATE,  //Impersonation level
                               0COLE_DEFAULT_AUTHINFO,       //Client identity
                               EOAC_DEFAULT                  //Capability flags
              );
For scripting, it is recommended that you use the defaults that DCOM selects for remote calls. On the local machine you cannot specify an authentication service for calls to WMI. For more information, see Setting the Authentication Service Using VBScript and Constructing a Moniker String. 聯盟----Visita網站http://www.vista.org.tw ---[ 發問前請先找找舊文章 ]--- 發表人 - axsoft 於 2003/02/25 16:35:04
系統時間:2024-07-01 21:42:54
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!