We call DirectoryEntry.Invoke("SetPassword",newpwd) to change the password of a local user, but the new password is not being used immediately when doing Windows Authentication to a remote SQL server. It does get used after a reboot, but that's not really an option for me here. How can I make it take effect without rebooting? I need currently running processes on the client to begin using the new password immediately.
The environment is two Windows 7 Embedded systems, call them 'server' and 'client', and there is no domain, but they are both in the same workgroup. We use the same username on both systems. There are multiple servers out there with different passwords (computed based on various things). When we need to switch to use a different server, we change the password locally. The change itself is successful, but SQL accesses from client to server fail with
SSPI handshake failed with error code 0x8009030c, state 14 while establishing a connection with integrated security; the connection has been closed. Reason: AcceptSecurityContext failed. The Windows error code indicates the cause of failure.
and
Login failed. The login is from an untrusted domain and cannot be used with Windows authentication.
But as soon as client reboots it can access server's database successfully.
SQL Express 2008 on both systems, configured to use only Windows Authentication.
Wireshark shows me the SMB2 NTLMSSP_AUTH packet with what looks like the usual info although I don't know how to decode the security blob. Otherwise it matches the packet from a successful session. In the failure case this packet is followed by an SMB2 response with STATUS_LOGON_FAILURE and a missing security blob. I can only think that the client presents some kind of hash of the password in that security blob and the server is finding that it doesn't match its own password hash - or something like that.
Changing the environment ('Use Active Directory', 'Use Kerberos', etc.) is unfortunately not an option for me here. Also, these are consumer touch-screen kiosks, where no human ever knows the password, and wouldn't have a keyboard to enter it anyway.
ADD: FYI, The changing of the password is done thus:
DirectoryEntry directoryEntry = new DirectoryEntry(string.Format("WinNT://localhost/{0}", username));
directoryEntry.Invoke("SetPassword", newPassword);
ADD: Made that parameter new object[] {newPassword}, and called .CommitChanges(), because those look like correct things to do. No change in behavior.
Related
In Azure DevOps services, when you connect an agent to the server, you have different types of ways to authenticate to the server. You can see here for example, about connecting a Linux agent, that you have these 4 types:
Alternate (Basic authentication)
PAT
Negotiate - Connect as a user other than the signed-in user via a scheme such as Kerberos or NTLM.
Integrated - Not supported in Linux
The integrated type is mentioned in the page about connecting a Windows agent as "Windows default credentials"
Bare with me please.
In my organization, we have a Active Directory domain with a Single-Sign-On, I suppose it uses Kerberos as the authentication protocol. Sometimes I use Powershell scripts to access the API of our internal Azure DevOps Server, and I use the -UseDefaultCredentials flag so the user won't have to enter username and password - it will just authenticate based on the logged-in user.
That got me thinking that the -UseDefaultCredentials flag is using Kerberos to authenticate.
But from the above, it seems that Integrated is using "Default credentials", which is something else than "Negotiate" which uses Kerberos.
Can someone help me understand this?
The UseDefaultCredentials flag tells the underlying system to try and use the caller's SSO credentials, which in most cases is the credential used to log into the system interactively or otherwise.
Strictly speaking it does not indicate which protocol to use. What it's actually saying is "dear system internals: please figure it out for me". The way this works is by selecting the negotiate protocol, which as it's name suggests negotiates the use of specific authentication protocols based on the client credentials as well as information from the server. This is called the SPNEGO protocol. It is transparent to the caller.
SPNEGO is fairly simple in nature. The client has a list of known authentication protocols (Kerberos, NTLM, etc.) and will send that list to the server saying 'pick one please'. The server can select any of them and respond telling them what to use, and the client then goes and uses it. Fin.
SPNEGO is also relatively smart because it can reasonably predict what it thinks the server will accept and will attempt to optimistically provide a token up front using the first protocol in the list. So if it thinks it needs Kerberos it'll go and get a Kerberos ticket up front and send it first. The server might think that's fine, or it might fail and return a response saying
"no, I really need NTLM", and so the client tries again with NTLM.
I have an application which has been successfully logging into our database for years without issue.
The password hasn't changed and i can manually login.
I enabled the audit trail in the database and can see the failed login attempt and return code of 1017 indicating invalid username and password combination.
The password being entered in the application is correct but is still being rejected by the database. I confirmed the user and pass combination by logging in with SQL Developer.
Is there any way for the audit trail to show the password being received so that i can find out how the password is being altered between the app and the db.
Are there any other causes to 1017 than an invalid user/pass?
No, the audit trail does not show the passwords of failed log in attempts. Using the audit trail you can determine things such as the machine name and OS user that is attempting to log in, but it will not capture the password that was used.
Since this application has been logging into the database for years, I am guessing that the database itself has been updated a number of times, correct? If so, is it possible that you are running into password case sensitivity issues as a result of an older client being used on the application side? If the application is connecting from a machine using an older client, you may want to check out this question: ORA-01017 Invalid Username/Password when connecting to 11g database from 9i client
To test this hypothesis, you could try logging in from the application side by using quotes to pass the credentials. From the question above:
oracle9i defaults to uppercase as it didn't cater for case
sensitivity. instead of changing the database to insensitive, you can
connect by pasting your password in double quotes eg `sqlplus
youruser/"Password"#db to pass mixed case.
If that is not the case, and you want to determine what password is being passed from the application to rule out that avenue, you could use a tool like Wireshark to listen to the traffic and see if you can sniff out what credentials they're using, assuming they aren't using an encrypted connection. Please only explore this if you have complete control over the network or the permission from the appropriate powers that be, as it could be illegal or against your organizations policy to use a tool like Wireshark without permission.
I work as a student web developer for my computer science department and I've been asked to look into a modification of our password reset procedure for linux accounts. Currently users will log in with their university credentials (via Active Directory) and after being authenticated they get a temporary password through email which they are forced to change as soon as they log in. This way eben if the temporary password it intercepted there is a very short time span in which it could even be used.
Now the idea has been posed that instead of using a temporary password that we might allow the user to pick a new permanent password and set it directly through the web utility. It is my understanding that https is more of "the best we have" than "a great way to secure information". Are there any other avenues I can explore for securing the new password so that we can feel comfortable implementing such a system?
Basically, if you communicate with a server over HTTPS and the private key of the server isn't exposed to someone else, you can be sure that anything you transfer (e.g. the new password) can only be decrypted by the server. Additionally the server certificate assures, that the server you are communicating with, really is the server you want to communicate with.
So, using HTTPS provides authentication and prevents eavesdropping.
If you are working with Active Directory, it is my understanding that the Password Modify Extended Operation (which requires the existing password) is not supported. Therefore, the password must be changed with the LDAP modify request. One solution would be to use the UnboundID LDAP SDK with a web application to execute the LDAP modify with the new password. The modify request should be transmitted over a secure connection, or a non-secure connection promoted to a secure connection using the StartTLS extended operation.
see also
AD password change
Using ldapmodify - this article is about the command line utility ldapmodify but the concepts are useful.
I'm currently attempting to debug a solution that I've picked up as a side project but I'm not having much luck. The solution depends on data (user IDs, page content, etc) stored on an MSSQL server on my local network, but when I execute the solution in VS2012 debug mode the connection fails. The error I'm getting says that the connection failed, and that the user was rejected.
When I log into the SQL server and check the event logs I can see where the login ID was rejected, but it was rejected because it wasn't the login ID that I specified in the connection string. It seems to be trying to use my windows authentication instead (which in windows 8 is a live ID) which won't work because my windows ID doesn't (and shouldn't) have access to the server.
Some basic connection string info (all data changed to protect the innocent... aka my poor server)
Data Source=myServer; Initial Catalog=myDB; User ID=myUsername; Password=myPassword; Integrated Security=false;
Has anyone run into this issue?
Do a search in the entire solution for myServer. This should shed light on the issue, given the connection string is defined somewhere else and it connects to the same server.
I have a DCOM client and server applications which use OLE automation marshaller. They work fine when run on the same PC but when the server is on a different PC not in the same domain I get E_ACCESSDENIED (0x80070005).
Server PC is configured with dcomcnfg to give all access to any DCOM object to the user whose login and password I specify on the client. ServerApp and its type library are registered on the server pc.
Type library is also registered on the client PC. I specify server name directly in the ClientApp so no dcomcnfg configuration is needed on the Client PC as far as I understand.
CreateInstanceEx() with server name, login, domain and password works fine. It returns IUnknown and at the same time starts ServerApp on server PC.
But when I try to QueryInterface() for the interface which server supports, I get E_ACCESSDENIED.
Analyzing the Security Event Log, I have two records there:
First, a successful network login by the user whose credentials I specify in ClientApp. This happens when I call CreateInstanceEx().
Next, a failed login attempt by the user under which I'm logged in on a client PC. Since two PCs are not in a domain, this user is unknown to server PC.
Now, why the heck would THIS user be logging into server, especially when I call QueryInterface of all things?
Studying CreateInterfaceEx params, it appears there's some kind of impersonation mechanism going on. But it's unclear who impersonates who. There are THREE user credentials involved:
User under which ServerApp runs on the server PC (as configured in dcomcnfg).
User whose credentials ClientApp specifies when connecting.
User under whose credentials ClientApp runs on client PC.
No matter how you look at it, if #3 is involved it's one user too much. If DCOM is going to identify/impersonate #3 on server PC anyway, why do I need to specify #2's credentials? To what point?
It would have seem logical for DCOM to impersonate #2 because this is what I have explicitly specified as my credentials. But why the second login attempt then?
Can someone please explain how exactly the impersonation works, and also if there's a way to just ignore it and run as user which is specified in dcomcnfg?
Answering my own question. After much exploration it became apparent that DCOM has TWO different identification cases:
Authorization for object creation (CoCreateInstanceEx)
Authorization for method calls.
For reasons unknown, #2 doesn't inherit #1 settings. By default it uses the credentials of the client process, hence strange logins.
There are two ways to specify credentials for #2. First one is CoSetProxyBlanket. It sets credentials for a specified proxy (marshaller-unmarshaller) only:
CoCreateInstanceEx(IID_IObject1, /*login, pass*/, obj1); //Success!
//Logged in and recevied IObject1 proxy in obj1
obj1->DoSomething();
//IObject1 proxy in obj1 now tries to login under process credentials.
//Failure! E_ACCESSDENIED
CoSetProxyBlanket(obj1, /*login, pass*/); //Success!
//IObject1 proxy is now authorized.
obj1->DoSomething(); //Success!
obj1->QueryInterface(IID_IObject2, obj2); //Success!
obj2->DoSomethingElse(); //Failure!
//This different proxy for IObject2 have not yet been authorized.
CoSetProxyBlanket(obj2, /*login, pass*/);
//etc.
It's important to note that while CoCreateInstanceEx requires impersonation level to be at least IMPERSONATE, CoSetProxyBlanket doesn't seem to work on anything except IDENTIFY.
Another option is to use CoInitializeSecurity to set default credentials for the whole process. Then you don't have to call CoSetProxyBlanket on every proxy:
CoInitializeSecurity(/* login, pass */);
CoCreateInstanceEx(IID_IUnknown, /*login, pass*/, obj); //Success!
obj->DoSomething(); //Success!
When using CoInitializeSecurity on the client you have to specify asAuthSvc too, even though MSDN says you don't.
The drawback of this method is obviously that if you have several DCOM objects from different PCs you're going to have to specify all the credentials in this call and those are probably going to be tried against every computer every time you open a different proxy.
It also is not reliable when you're running from a DLL (what if a process has different default security?). So, it's probably better to implement a QueryInterface wrapper which CoSetsProxyBlanket before returning from every call.
For those who are working in Delphi there is one little note that can save a lot of your time. After you did obj as ISomeInterface operation, you have to call CoSetProxyBlanket for the new instance. This could be not very obvious, but all we know that as operator calls QueryInterface method, and it can return new instance.