manual netlogon - c++

Anyone know how I would do a manual netlogon or any other way to authenticate a user on a remote domain? I need to test authentication.
Right now we're using impersonation and calling an arbitrary function. The problem is that arbitrary winapi function that will login. The problem is that some domains allow that function to be called by null session thus causing false positives.
The only goal of this is to get reliable, fast authentication against a remote domain that the local computer is not added to so I wouldn't deny another approach.
This is the solution that we got from filing a MSDN ticket.
if(!LogonUser(username.c_str(), domain.c_str(), password.c_str(), LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, &token))
{
debug->DebugMessage(Error::GetErrorMessageW(GetLastError()));
CloseHandle(token);
RevertToSelf();
return false;
}
if(!ImpersonateLoggedOnUser(token))
{
debug->DebugMessage(Error::GetErrorMessageW(GetLastError()));
CloseHandle(token);
RevertToSelf();
return false;
}
...
int err = NetUserModalsGet ....
if (err != ERROR_SUCCESS) logged_on = false;
RevertToSelf();

If all you want to do is answer the question "are these credentials valid for a given domain which I may not be a member of?" then you might see some millage in existing things that do this. A number of Linux/UNIX applications offer NTLM authentication against an arbitrary domain without domain membership. Most use winbindd, which I suspect running on a Windows system would be asking for trouble.
Notably though there's an apache module for this, which can run without any external dependencies. You might have some luck looking through their sources, in particular mod_ntlm.c and seeing how they craft the request packets for the domain controller and parse the responses.

Not sure if you've considered the fact that there are many infrastructure configuration concerns associated with using Windows integrated security on remote domains. Are the trust policies appropriately in place? Which SSPI are you using NTLM, Kerberos, PKU2U, DPA, etc?
Have these been appropriately configured for your usage scenario?
Ok... After hearing more about your scenario, have you considered leveraging a custom GINA?
http://msdn.microsoft.com/en-us/library/aa380543(v=VS.85).aspx

Related

TLS Upgradation

public bool CheckValidationResult(ServicePoint sp,
System.Security.Cryptography.X509Certificates.X509Certificate cert, WebRequest req, int problem)
{
return true;
}
Here , I am in the position to access the web service using Tls 1.2 alone from the web service.
So , after adding the below lines before the return true in the method. ,
Then ,I can be able to access the service and also able to get the response.
Is it the correct way to handle these or any other way is there ? ? ?
Please help anyone who has experience on this .
Thanks in Advance.
//Here given protocol version with or operator accepting tls 1.1 ,1.2 and 1.0 along with ssl3
sp.Expect100Continue = true;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls | SecurityProtocolType.Tls12;
No, that is not the correct way! Although I am aware that 100's of developers do this (return true for certificate validation), however their communication is no longer secure and is now subject to middleman and replay attacks, which are the most-common SSL attacks known to man.
The truth is you need provide a "comprehensive implementation" for certificate validation, which is based-on several RFCs (search for: X.509 Certificate validation). At a minimum you need to check the certificates validity (dates), validate subject signature hash using CA's public key and validate CA's CRL revocations (ensure server certficate has not been revoked). However ...
To keep things simple, without degrading TLS's integrity, you could simply check the "problem" (int problem), then return true or false, based on the value of problem. The OS should set the problem value, based-on internal OS security policy. Personally, I still would prefer "comprehensive implementation", because OS security policy can be weak, inundated or corrupt (hacked). Let me know if you need more details on "comprehensive implementation"

Verify Active Directory domain trust relationship of the local machine

I have to find out if the local machine is still joined to a domain, or if another computer has used the computer account or, if the computer account has been reset.
In other words, i need to verify the trust relationship between the local machine and the domain
NLTest /SC_VERIFY:{Domain} does the job pretty well.
Are there any API functions that i can use to detect whether the local machine has lost the trust relationship to a domain? I don't like to call external executables from my program.
What i tried so far:
NetGetJoinInformation(): It doesn't realize it.
DsBind*(): It doesn't realize it. Also tried to call it under the local system account.
Any ideas?
Okay. After a lot of digging, i finally found a solution: I_NetLogonControl2
NETLOGON_INFO_2* buffer=NULL;
LPBYTE domainName = (LPBYTE) L"eng";
int ret = I_NetLogonControl2(NULL, NETLOGON_CONTROL_TC_VERIFY, 2, (LPBYTE) &domainName, (LPBYTE*)&buffer);
wprintf( L"I_NetLogonControl2() returned %i\n", ret);
if (ret==0)
{
wprintf( L"PdcConenctionStatus: %i\n", buffer->netlog2_pdc_connection_status);
if (buffer->netlog2_pdc_connection_status==0)
wprintf(L"Trust relationship verified.\n");
else
wprintf(L"Trust relationship FAILED.\n");
wprintf( L"TcConenctionStatus: %i\n", buffer->netlog2_tc_connection_status);
wprintf( L"Flags: %i\n", buffer->netlog2_flags);
}
return 0;
So the magic thing is hidden in NETLOGON_INFO_2::netlog2_pdc_connection_status.If this value is 86 (ERROR_INVALID_PASSWORD) or 5 (ERROR_ACCESS_DENIED) the computer account has been changed (or reset).
If the computer account has been deleted, the value is 1787 (ERROR_NO_TRUST_SAM_ACCOUNT)
Hope this helps others!
Unfortunately, the MSDN documentation is not precise. When you are specifying "NETLOGON_CONTROL_TC_VERIFY", the data argument (LPBYTE) must point to (LPWSTR*)!
you can try LogonUser function to perform network login (LOGON32_LOGON_NETWORK).
If workstation has broken trust with domain, it will not be able to verify your credentials.
You will need some domain credentials which can perform network logon of course, not local.
Your other option is to use local account which has granted network service logon and try to access other domain workstation resource.You can receive access denied error or trust relation failed depends on which resource on which server.
Finally, you can still search system event log for event ID signaling trust failure.
but we don't have any well known accounts that we can use for this
You can not check for workstation account status on domain site (in AD) until you authenticate somehow, just local status.
NetLogon_Control2 is for BDC to PDC communications; does not work for my tests in Win 7
Microsoft page --
Remarks
This function can be used to request that a BDC ensure that its copy of the SAM database is brought up-to-date. It can also be used to determine if a BDC currently has a secure channel open to the PDC.

How to impersonate another domain user as i have the administrator account of this AD domain?

i'm working on a windows software which can display all the users, groups and shared folders info in a domain when you input the domain administrator account. I have some trouble fetching some shared folders info because these folders even did not grant share permissions to domain admins(remove the Everyone in the share tab). The GetFileSecurity or the GetNamedSecurityInfo returns error code 5). But as a domain administrator, i think i could have the access to the permission information of the shared folders(just ACLs, no need to full access permission) in my domain computers.
I learnt about the impersonate method to log on to be another user, and if i log on as a domain user who is granted read permission in the share tab of the shared folder, i could get the ACLs successfully. But the problem here is that i do not know the password of a domain user in a practical environment even though i know their usernames and can change their passwords.
So how to get a domain user' access token to impersonate when i already have the domain admin account, or is there any way else?
I develop it using C++ and ADSI.
Here's the log on and get NTFS security desciption methods:
BOOL ADDirectorySearch::logOnByUserPassword(CString strDomainName, CString strUserName, CString strPassword)
{
CString strFullUserName = strDomainName + _T("\\") + strUserName;
HANDLE hToken;
BOOL bResult;
bResult = LogonUser(strFullUserName, strDomainName, strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, &hToken);
if (bResult == FALSE)
{
MyMessageBox_Error(_T("logOnByUserPassword Error."), _T("Error"));
return FALSE;
}
else
{
bResult = ImpersonateLoggedOnUser(hToken);
if (bResult == FALSE)
{
MyMessageBox_Error(_T("logOnByUserPassword Error."), _T("Error"));
return FALSE;
}
else
{
return TRUE;
}
}
}
PSECURITY_DESCRIPTOR ADDirectorySearch::getNTFSSecDescriptor2(CString strFileName, CString strServerName, CString strServerIP)
{
//CString strServerNameWithSlash = _T("\\\\") + strServerName;//"\\\\veotax3";
CString strFilePathName = _T("\\\\") + strServerName + _T("\\") + strFileName;//"\\\\veotax3\\nrdc1001";
CString strFilePathName2 = _T("\\\\") + strServerIP + _T("\\") + strFileName;//"\\\\192.168.1.7\\nrdc1001";
_bstr_t bstrFilePathName = strFilePathName;
BOOL bSuccess = FALSE;
PSECURITY_DESCRIPTOR pSecDescriptorBuf = NULL;
DWORD dwSizeNeeded = 0;label2:;
bSuccess = GetNamedSecurityInfoW(bstrFilePathName, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSecDescriptorBuf);
//bSuccess = GetFileSecurityW(bstrFilePathName, DACL_SECURITY_INFORMATION, NULL, 0, &dwSizeNeeded);
if (ERROR_SUCCESS != bSuccess)
{
if (strFilePathName != strFilePathName2)
{
strFilePathName = strFilePathName2;
bstrFilePathName = strFilePathName2;
goto label2;
}
else
{
MyMessageBox_Error(_T("getNTFSSecDescriptor2 Error."), _T("Error"));
return NULL;
}
}
else
{
return pSecDescriptorBuf;
}
}
I read another question from you. I think I understand what you try to do. In order to acheive your goal, you need to have an access token with impersonation level "Impersonate" or "Delegate". You can get it by different ways. Providing the password is the most straight forward approach. Another approach is to setup a machine to do Protocol Transition.
My personal suggestion is to avoid doing impersonation. Just make sure all shared folders have domain administrator granted to have read access. As I showed in another question, this is not a security compromise at all. Domain administrator can always have a way to read the folder anyway if they want to.
Also, fyi, there are some existing tools avaliable from SysInternals doing similar things.
Check out AccessChk.exe and AccessEnum.exe from SysInternals
They both suffer from the same permission problem as what you are facing now.
It is common mistake to forget granting admin access to shares containing profiles or home drives at the time of their creation. Permissions are usually driven through CREATOR OWNER and inheritance is broken in such shares. Only way for admins to get inside is to take ownership. Taking ownership will of course cause issues for end users. In some cases, where it is clear who is the owner of particular folder (eg. folder name is equal to user account name) you can use script which will take ownership-> set admin permission->set permission back to user account name gathered from folder name.
If you are still interested, I can post the code here
You can't and should not "impersonate" any account you don't have the password - and thereby no permission to use - because you're not meant to do anything on his or her behalf even if you're an administrator and can change his or her password - unless explicitly authorized for. Nor you should modify permissions on any folder you are not the owner of - unless authorized. Being an "administrator" doesn't mean you're a god-like creature and you're exempt from company policies.
It is all about "accountability" - accounts are not only to permit or deny access, but to record and audit also who made what, and thereby accountable for. There are legal requirements that can ask to identify and control whoever has access to some kind of sensitive informations - and restrict the number of people who can access them. Windows have facilities to audit users actions - including file accesses.
That's why Windows doesn't let you act on behalf of any users unless explicity allowed to - even if your're an administrator.
There are good reason also to remove access by administrators from folders - the fact that an administrator could always gain access to something doesn't mean he or she is allowed to do that - and doing without permission could put you in trouble. Removing permission from (some) administrators means you can't "by mistake" access files you're not explicitly allowed to access.
In properly setup systems, also logs are shipped to different machines where most administrators but highly privileged ones have no access - to ensure company policies about data protection are enforced and audited, without administrators being able to clear the logs to hide their tracks.

Exchange Web Services, try to use ExchangeImpersonationType

I am trying to use EWS, first time trying to use the ExchangeServiceBinding. The code I am using is below:
_service = new ExchangeServiceBinding();
//_service.Credentials = new NetworkCredential(userName, userPassword, this.Domain);
_service.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
_service.Url = this.ServiceURL;
ExchangeImpersonationType ei = new ExchangeImpersonationType();
ConnectingSIDType sid = new ConnectingSIDType();
sid.PrimarySmtpAddress = this.ExchangeAccount;
ei.ConnectingSID = sid;
_service.ExchangeImpersonation = ei;
The application is an aspnet 3.5 trying to create a task using EWS. I have tried to use impersonation because I will not know the logon user's domain password, so I thought impersonation would be the best fit. Any thoughts on how I can utilize impersonation? Am I setting this correctly, I get an error while trying to run my application. I also tried without impersonation just to try to see if I can create a task, no luck either. Any help would be appreciated. Thanks.
Without broader context of your code snip, I can't tell for sure what's wrong, but here are a few things you might find useful...
You mention you had trouble connecting without impersonation.
I'm assuming you are using Exchange Server 2007 SP1, yes?
Do you have a mailbox for which you do know the username and password? If so, consider trying to connect to that mailbox, just to see if you can send an email or query for inbox count. That will help verify your connection at least.
As to exchange impersonation,
have the permissions been set on the Client Access Server (CAS) to enable impersonation?
Have the permissions been set on either the mailbox or mailbox database (containing the mailbox you are attempting to access)?
are you in a cross-forest scenario that requires additional trust relationships?
If not, that might explain why you cannot connect.
Some links you might find useful
Configuring (http://msdn.microsoft.com/en-us/library/bb204095.aspx)
Using Exchange impersonation (http://msdn.microsoft.com/en-us/library/bb204088.aspx)
Access multiple resource mailboxes (http://msexchangeteam.com/archive/2007/12/13/447731.aspx)

Remote installing of windows service

I need to remotely install windows service on number of computers, so I use CreateService() and other service functions from winapi. I know admin password and user name for machines that I need access to. In order to gain access to remote machine I impersonate calling process with help of LogonUser like this:
//all variables are initialized correctly
int status = 0;
status = LogonUser(lpwUsername,
lpwDomain,
lpwPassword,
LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_DEFAULT,
&hToken);
if (status == 0)
{
//here comes a error
}
status = ImpersonateLoggedOnUser(hToken);
if (status == 0)
{
//once again a error
}
//ok, now we are impersonated, do all service work there
So, I gain access to machine in a domain, but some of computers are out of domain. On machines that are out of domain this code doesn't work. Is there any way to access service manager on machine out of domain?
You can do it , the account needs to exist on the remote machine and you need to use the machine name for the domain name in the LogonUser call.
Rather than rolling your own, why not just use the SC built-in command?
OK, problem resolved (not really very good, but rather OK). I used WNetAddConnection() to ipc$ on remote machine.