In my application I need to know if the computer is the primary domain controller of a domain, so I need to know the domain of the computer to call NetGetDCName function.
Thanks.
EDIT: The problem is related with the DCOM authentication so I need to know the domain to use the DOMAIN\USERNAME in case of a PDC or COMPUTER\USERNAME if I need to use the local authentication database of the computer.
The NetWkstaGetInfo() function returns either the domain name or the workgroup of the computer, and is therefore not a reliable way to determine if the computer is a member of a domain.
The GetComputerNameEx() function will help, used with the ComputerNameDnsDomain parameter, as shown below. This will return an empty string if the computer is in a workgroup, or the DNS name of the domain:
DWORD bufSize = MAX_PATH;
TCHAR domainNameBuf[ MAX_PATH ];
GetComputerNameEx( ComputerNameDnsDomain, domainNameBuf, &bufSize );
I would consider using NetWkstaGetInfo() and pass the local computer name is that first parameter.
#include <Lmwksta.h>
#include <StrSafe.h>
WCHAR domain_name[256];
WKSTA_INFO_100 info = {0};
if (NERR_Success == NetWkstaGetInfo(L"THIS-COMPUTER", 100, &info) &&
SUCCEEDED(StringCchCopy(domain_name, ARRAYSIZE(domain_name), info.wki100_langroup))) {
// use domain_name here...
}
You can use the NetWkstaGetInfo Function do this.
If you pass in null for the computer name it returns info about the local computer.
It will return a WKSTA_INFO_100 instance, which includes the domain name.
If you just want to know if the machine the code is running is the primary domain controller I think your best option is NetServerGetInfo. If you pass 101 as the level parameter it returns an SERVER_INFO_101 structure. Then look for its sv101_type member:
sv101_type
The type of software the computer is running. This member can be one of the following values.
(...)
SV_TYPE_DOMAIN_CTRL: A primary domain controller.
There is a specific function to determine the join status of a Workstation.
https://learn.microsoft.com/en-gb/windows/desktop/api/lmjoin/nf-lmjoin-netgetjoininformation
THere can be 3 statussus, 'Joined' to a workgroup (The good old Windows 3.0 networking) status == NetSetupWorkgroupName, or joined to a domain status == NetSetupDomainName
or unjoined (standalone) status == NetSetupUnjoined
So if you know this, you can call the respective required functions in a reliable way.
Finally I have used this code. It works in local machine, executed remotely nStatus gives a ACCESS_DENIED error.
NET_API_STATUS nStatus;
TOleString oleServerName=strServerName.c_str();
DWORD dwLevel=101;
LPSERVER_INFO_101 pBufServer=NULL;
LPWKSTA_INFO_100 pBufWksta = NULL;
nStatus=NetServerGetInfo(oleServerName, dwLevel,
(LPBYTE*)&pBufServer);
if(nStatus==NERR_Success &&
(pBufServer->sv101_type & SV_TYPE_DOMAIN_CTRL))
{
dwLevel=100;
nStatus=NetWkstaGetInfo(oleServerName, 100,
(LPBYTE*)&pBufWksta);
if(nStatus==NERR_Success)
{
AnsiString strDomain(pBufWksta->wki100_langroup);
m_pgServerConnection->SetDomain(strDomain);
}
}
Thanks to all :)
Related
I've started to investigate how credential providers work, but due to poor documentation I got stuck in couple of places.
I have console application(sort of like ssh server) when I connect remotly to this application and authenticate(none is logged on), I want it to be able to forward those credentials to credential provider and I want CP to login user(create session).
I've also noticed that In documentation it says that SetSerialization method always gets called after SetusageScenario. But I've added logs and SetSerialization never gets called after SetusageScenario.
As I know SetSerialization is called when credential is provided by application. I can't understand what does it mean to provide credential through application? It seems like this is what I need, to forward credentials from application to credential provider, but How can I do that? Are there some functions that I could call from credential provider dll to provoke login?
Is there any way I can achieve this? I've read that when remote login is done, UpdateRemoteCredential is called, But As I understand(correct me if I'm wrong) in remote login it means RDP but my application is simple, it just listens to some port and gets username and password and then uses Logonuser function.
A program named MxLogon2 implements this scheme. A remote server with MxLogon2 installed can authenticate a USB key(But I want username/password) connected to the client side in a remote desktop session.
Any suggestion that would direct me to right way would be greatly appriciated.
P.S
I'm using pGina as my credential provider.
I wouldn't mind too much of SetSerialization in your case. This is used for pre-initializing tile.
One example would be, with RDP connection, you can store certificates of credentials on your system. This function is used to pre-inquire tiles with those credentials (not the only solution though).
Make it return E_NOTIMPL in your case.
The main purpose of the provider is to initialize Credentials and tiles :
Credentials initialization
is done through SetUsageScenario function (automatically called after Provider construction).
In there, you can customize the behavior depending on scenario you are in. Most basic one being CPUS_LOGON.
It shall look like this (this is only a preview)
HRESULT Provider::SetUsageScenario(
__in CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
__in DWORD dwFlags
)
{
HRESULT hr;
switch(cpus)
{
case CPUS_UNLOCK_WORKSTATION:
case CPUS_LOGON:
hr = this->_InitCredential();
break;
default:
hr = E_INVALIDARG;
break;
}
return hr;
}
Tiles initialization
begins in GetCredentialCount function. It allows you to define how many tiles you gonna show (pdwCount out parameter), as well as the one to be used as the default tile (pdwDefault).
Auto-Logon is also handle in here (through pbAutoLogonWithDefault).
Tiles Enumeration is then beginning in GetCredentialAt function.
Passing credentials for authentication is done in the credential you're using through the GetSerialization function.
Examples of implementation can be found here.
I hardly insist on example as it easily divert depending on what you are trying to achieve. This is very flexible and you'd better understand the purpose of any function / parameter to fit your goals.
EDIT - cf comments :
#define IDCredential 0x1
Credential::Credential(Provider* parent)
{
//Do ssh connection or whatever
if(success)
{
parent->login = retrievedLogin;
parent->pwd = retrievedPwd;
parent->CredentialUsed = IDCredential;
parent->autoLogin = true;
parent->ProviderEvents->CredentialsChanged(AdviseContext);
}
}
HRESULT Provider::GetCredentialCount(
__out DWORD* pdwCount,
__out_range(<,*pdwCount) DWORD* pdwDefault,
__out BOOL* pbAutoLogonWithDefault
)
{
if(this->autoLogin && this->CredentialUsed)
{
*pbAutoLogonWithDefault = true; // --> Instant call to GetSerialization
*pdwDefault = this->CredentialUsed; //index of the tile
}
else
{
*pbAutoLogonWithDefault = false;
*pdwDefault = IDCredential;
}
return S_OK;
}
I am trying to connect to a mobile network via a modem and a sim card. Every time I try to set the APN String and User Credentials in a Context via SetProvisionedContext() I get the E_INVALIDARG HRESULT.
As Parameters I used an Instance of MBN_CONTEXT, a wchar_t* in form of &std::vector<wchar_t>[0], and a ULONG*.
MBN_CONTEXT context;
std::vector<WCHAR> apnVector;
inParamAPN.GetCString(apnVector);
std::vector<WCHAR> userNameVec;
inParamUsername.GetCString(userNameVec);
std::vector<WCHAR> passwordVector;
inParamPassword.GetCString(passwordVector);
context.contextID = MBN_CONTEXT_ID_APPEND;
context.contextType = MBN_CONTEXT_TYPE_INTERNET;
context.accessString = &apnVector[0];
context.userName = &userNameVec[0];
context.password = &passwordVector[0];
context.compression = MBN_COMPRESSION_NONE;
context.authType = MBN_AUTH_PROTOCOL_PAP;
and later when I have the IMbnConnectionContext:
std::vector<WCHAR> providerVector;
InParamProvider.GetCString(providerVector);
ULONG requestID;
contextInterface->SetProvisionedContext(context, &providerVector[0], &requestID);
So my Question is: Which Parameter does the WinAPI have a Problem with, and how can I fix it?
Also any Tips of additional Sources for Information are appriciated.
All I have so far are the official MSDN and the Code Example contained in the Windows 7 SDK. Are there any further sources of Information I am not aware of? A google search didn't yield the hoped for results.
In the end I did not get it working as it should. I used the second way of connecting to a custom APN, by making a new connection profile. For this I used a XML filled with the Values I needed.
Along the way I encountered another problem with an unforseen Error Code which I described here.
Best regards,
Stefan
I've been tasked with determining whether a particular DLL from a third party company has been tampered with, after installation on a user's system. I've never done anything related to digital signing before. I'm trying to set up a test on my own system using WinVerifyTrust.
{
WINTRUST_FILE_INFO wtfi;
wtfi.cbStruct = sizeof(WINTRUST_FILE_INFO);
wtfi.pcwszFilePath = TEXT("*****.dll");
//wtfi.hFile = DllHandle;
wtfi.pgKnownSubject = NULL;
GUID wtvPolicyGUID = DRIVER_ACTION_VERIFY;
WINTRUST_DATA wtd;
wtd.cbStruct = sizeof(WINTRUST_DATA);
wtd.pPolicyCallbackData = NULL;
wtd.pSIPClientData = NULL;
wtd.dwUIChoice = WTD_UI_NONE;
wtd.fdwRevocationChecks = WTD_REVOKE_NONE;
wtd.dwUnionChoice = WTD_CHOICE_FILE;
wtd.pFile = &wtfi;
wtd.dwStateAction = WTD_STATEACTION_IGNORE;
wtd.pwszURLReference = NULL;
wtd.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
//wtd.pSignatureSettings = NULL; // Win8 and Server2012 only?
LONG result = WinVerifyTrust( NULL, &wtvPolicyGUID, &wtd);
debugf(TEXT("Validation result: 0x%08x"), result);
}
This is returning 0x57. From what I've gathered from MSDN, errors come from a supplied trust provider. I don't really know what the trust provider is or what error messages it can return.
I've linked in WinTrust.dll and WinTrust.lib, so I presume that means I'm using Microsoft's "Software Publisher Trust Provider". Is this recommended, or are there better ones out there? Should you be using one specific to / provided by the software publisher whose product you're analyzing?
SoftPub.h contains the GUID input value, but does not seem to provide output error codes. Any help in tracking down their response code list is appreciated.
Thanks in advance.
EDIT: I have since figured out that this library uses error codes provided by winerror.h. 0x57 is "ERROR_INVALID_PARAMETER", so I'm reviewing what it could be complaining about. I also tried switching the Policy GUID to WINTRUST_ACTION_GENERIC_VERIFY_V2, which returned error TRUST_E_SUBJECT_FORM_UNKNOWN. Neither error code is particularly illuminating about what the ultimate issue is.
EDIT 2: I also ran Microsoft's SignTool.exe on the dll in question, and got the following output:
SignTool Error: A certificate chain processed, but terminated in a root
certificate which is not trusted by the trust provider.
Number of errors: 1
So it seems like I need to change the trust provider I'm using. After discussing with the software manufacturer, the task is being dropped in favor of another approach.
According to MSDN it seems that you should set
dwStateAction = WTD_STATEACTION_VERIFY;
Also I would try setting
wtfi.hFile = NULL;
or when giving the file handle setting
wtfi.pcwszFilePath = NULL;
(It's not quite clear to me if you are providing hFile or not. And I would not set both hFile and pcwszFilePath to valid values.)
Another point to check: if you are compiling for Windows 8 or Windows Server 2012 you will have the struct member pSignatureSettings and will need to initialize it. Take care to set cbStruct so that pSignatureSettings is not included or to properly initialize pSignatureSettings.
i am using ldap functions to get user attributes value using win32 api.
the user name is arun.
in ldap_functions like init,set_options,connect,bind is succeed.but ldap search function is returned error code 10.
here my code
errorCode = ldap_search_s(
pLdapConnection, // Session handle
pMyDN, // DN to start search
LDAP_SCOPE_SUBTREE, // Scope LDAP_SCOPE_BASE LDAP_SCOPE_SUBTREE
pMyFilter, // Filter
NULL, // Retrieve list of attributes
0, // Get both attributes and values
&pSearchResult);
in pMyDN specified `"DC=SANJU,DC=CO,DC=IN"...
the return code 10 gives error is LDAP_REFERRAL.but i cant get it.
But i put pMyDN value into "OU=Marketing,DC=SANJU,DC=CO,DC=IN"
Now,search function succeed,So what is the problem?
i need this function without using OU,
can anyone help?
LDAP_REFERRAL: sent by Directory Server if the given base DN is an entry not handled by the current server and if the referral URL identifies a different server to handle the entry.
whether DNS and AD in different URL(IP) without trusted rule,this problem will occured.
LDAP response do not use error codes, they use result codes - so called because non-zero responses aren't necessarily errors. 10 is a case in point, it's a referral. The referral will contain information about the server which can process the request. If a directory proxy server is not in place to follow the referral, the LDAP client must follow the referral for itself.
Compare operation responses also use result codes to transmit the result of a compare.
I'm running the following piece of code from a local service application. The purpose is to obtain the path to a user's profile before calling LoadUserProfile() to load that user's profile before calling CreateProcessAsUser() to run a user-mode process on behalf of that user.
Note that this question is not about LoadUserProfile(), or CreateProcessAsUser().
What happens is this. When the code below is run on Windows XP w/SP3 that is a part of the Active Directory domain, with a single user logged in via a local console (that user's session ID is used below) the NetUserGetInfo() API fails. Also note that it works fine in any other circumstance:
//'dwSessID' = session ID of the user to retrieve a user profile path for
LPTSTR pUserName = NULL;
DWORD dwcbSzUserName = 0;
if(!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwSessID, WTSUserName, &pUserName, &dwcbSzUserName))
{
//Error
return false;
}
USER_INFO_4* pUI4 = NULL;
DWORD dwNetStatus;
if((dwNetStatus = NetUserGetInfo(NULL, pUserName, 4, (BYTE**)&pUI4)) == NERR_Success)
{
PROFILEINFO pfi = {0};
pfi.dwSize = sizeof(pfi);
pfi.lpUserName = pUserName;
pfi.dwFlags = PI_NOUI;
pfi.lpProfilePath = pUI4->usri4_profile;
LoadUserProfile(hToken, &pfi);
//And so on
}
else
{
//On that specific machine I get here with 'dwNetStatus' = 2221,
//or NERR_UserNotFound, that according to MSDN is
//"The user name could not be found."
//Also note that GetLastError is not used for this API.
}
Can some suggest why can NetUserGetInfo() fail on that particular machine, and how to fix this code?
PS. I know that MSDN for NetUserGetInfo states that there might be issues with a ACL on Active Directory domain, but it doesn't specify how to set one...
If I read the documentation for NetUserGetInfo, for the information level of the data you code 4 . It's written Level 4 Return detailed information and additional attributes about the user account. This level is valid only on servers. As far as I understand it's not your case. Do you verify the value of pUserName returned by WTSQuerySessionInformation.
As JPBlanc stated NetUserGetInfo with level 4 is valid only on servers.
Another problem is that you retrieve the name of the logged on user, but not the domain the user belongs to.
Noticed you are calling NetUserGetInfo with pUserName the type of LPTSTR.
Sometimes it won't work (if you will compile your project to use ANSII strings by default).
Consider changing you string types to LPWSTR.