How can I give SQL Server permission to read my SSL Key? - sql-server

I recently created a self-signed certificate and turned encryption on in SQL Server 2014:
The problem is that now the SQL Server service won't start:
This article from 2010 identifies the problem as a permissions issue: The SQL Server service does not have the necessary permission to read the SSL cert's private key.
The problem is that I am stuck on step 4 of the solution proposed in the article:
There is no group or user name matching the proposed format when I bring up the window shown in the article.
Is there another way I can determine the account that SQL Server service runs under, so that I can give it permissions to read the SSL cert?
An entirely different solution is welcome too.

If you specify the certificate, which should be used for TLS by SQL Server, then the SQL Server windows service have to read the certificate and the private key (the file from the folder %ProgramData%\Microsoft\Crypto\RSA\MachineKeys), which corresponds the certificate. The problem is: the SQL Server Configuration Manager in not comfortable and it makes not all the required work.
Thus first of all one should localize the Account used by SQL Server. One should start services.msc, find the account of SQL Server service. It's typically a build-in account like Local System, Network Service a local or domain account like .\SQLServer, DOMAIN\SQLServerAccount or an service account like NT Service\NT Service\MSSQL$SQL2012 on the picture below:
To grant permission on the private key to the account one can use Certificate Snap-In of mmc. One can start mmc.exe, choose "Add/Remove Snap-in" in the "File" menu, choose "Certificates" Snap-in and to choose "Computer account" of the Local computer. Then one should select the SSL certificate of Personal store and then use context menu "Manage Private Keys...".
and to add account like NT Service\NT Service\MSSQL$SQL2012, found above, and to set "Read" permission to the account on the private key:
If you would like to establish connection to the SQL server inside of the domain (both the client and the server have to belong to the same Active Directory or to the directories connected via the trust) then one should to create SPNs for the SQL server. If I correctly understand your requirements, you want to allow remove connection to SQL Server over HTTPS. One have to active mixed security to be able to connect to the server via SQL Server Authentication:
After creating SQL Login, making all above changed and restarting SQL Server service one will be able to establish TLS (encrypted) connection to the SQL server. In case of attempting to connect via Windows Account without creating SPN previously one get the error:
A connection was successfully established with the server, but then an
error occurred during the login process. (provider: SSL Provider,
error: 0 - The target principal name is incorrect.) (Microsoft SQL
Server, Error: -2146893022)
The target principal name is incorrect
If one forget to change Windows Authentication to Mixed authentication () then one will get the error like
Login failed for user 'OlegKi'. (Microsoft SQL Server, Error: 18456)
If all above steps done one can establish TLS connection using SQL Management Studio for example, but one still have to choose some options:
One should check "Encrypt connection"
and to set additional connection property TrustServerCertificate=true
Typically one use Encrypt=true;TrustServerCertificate=true; as the part of connection string in the application which establish the connection to SQL server. We set Encrypt=true property by the checkbox "Encrypt connection" describe above. More detailed about the meaning of the properties and different combinations of the options can be read in "Enabling Encryption" section of the MSDN article.
If one do all the above steps and check "Encrypt connection" without setting TrustServerCertificate=true property then one will get the error:
A connection was successfully established with the server, but then an
error occurred during the login process. (provider: SSL Provider,
error: 0 - The target principal name is incorrect.) (Microsoft SQL
Server, Error: -2146893022)
The target principal name is incorrect
which I already described above in a little another situation (connection with Windows account).
I described all above steps because configuration of TLS connection to the server is really not so easy and one can get strange errors, which direct description gives no direct tips how to fix the problem.

One other note: If you are entering the certificate thumbprint into the registry manually by copying and pasting from the certificate manager, you must remove the leading character. It is an invisible unicode character, but it will cause the SQL Server service to be unable to start if it is present. This is in addition to making it ALL CAPS, and removing all spaces.

I ran into this issue as well. What i was doing was:
Importing the certificate from the sql server protocol properties dialog, using the 'import' button. I imported the public key, then another open dialog opened to import the private keys. I then set the private key permission to the sql server service.
When importing a key pair directly, such as a .pfx bundle, the application crashed.
All permissions to MachineKeys were granted as well for the sql serive, but I could not find through process monitor any access denied for that path.
In order to solve my issue, i imported the pfx directly from the explorer. I first removed the key pair from the store, then I ran through the wizard to import the pfx in the local machine store, personal folder. I checked the permissions on the private key, they were still set for the sql service. I checked the protocol properties, the certificate was already selected. Only then the server started.

Related

SSL Certificate missing from dropdown in SQL Server Configuration Manager

I am trying to configure SQL Server 2014 so that I can connect to it remotely using SSL. A valid, wildcard cert is installed on the server, and the cert's domain name (example.com) matches the server's FQDN (test.windows-server-test.example.com).
The problem is that in SQL Server Configuration Manager, the certificate is not listed, so I cannot select it.
That is, I am stuck on step 2.e.2 from this MS tutorial.
After communication in comments I can suppose that your main problem is the CN part of the certificate which you use. To have successful TLS communication for IIS Server one have no such strong restrictions like SQL Server has.
Microsoft require (see here) that The name of the certificate must be the fully qualified domain name (FQDN) of the computer. It means that the Subject part of the certificate looks like CN = test.widows-server-test.example.com, where test.widows-server-test.example.com is the FQDN of your computer. It's not enough that you use for example CN = *.example.com and Subject Alternative Name, which contains DNS Name=*.example.com and DNS Name=test.widows-server-test.example.com, DNS Name=test1.widows-server-test.example.com, DNS Name=test.widows-server-test2.example.com and so on. Such certificate will be OK for TLS, but SQL Server will discard it. See the article, which describes close problems.
I recommend you to create self-signed certificate with CN equal to FQDN of the SQL Server and to verify that the certificate will be seen by SQL Server Configuration Manager.
UPDATED: I analysed the problem a little more with respect of Process Monitor and found out that two values in Registry are important for SQL Server Configuration Manager: the values Hostname and Domain under the key
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
If I change Domain and Hostname to the values which corresponds CN of the certificate then the certificate will be already displayed in the SQL Server Configuration Manager. It could be not all problems, but it shows that SQL Server required much more as a web server (IIS for example).
UPDATED 2: I examined the problem once more in details and I think I did found the way how one can configure common SSL certificate which you already have (for example free SSL certificated from Let's Encrypt, StartSSL or some other).
It's important to distinguished what do SQL Server Configuration Manager from the configuration required by SQL Server. The Certificate tab of the properties of the Configuration Manager have more hard restrictions as SQL Server. I describe above only the restrictions of SQL Server Configuration Manager, but one can make configuration directly in the Registry to use more common SSL/TLS Certificate by SQL Server. I describe below how one can do this.
What one need to do one can in the Registry under the key like HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL12.SQL2014\MSSQLServer\SuperSocketNetLib, where the part MSSQL12.SQL2014 can be a little different in your case. The SQL Server Configuration Manager help us to set two values in the registry: ForceEncryption and Certificate:
The Certificate value is SHA1 hash which can be found by examining the properties of the certificate:
or extended properties of the certificate, which you see by usage certutil.exe -store My:
One need just copy the "Cert Hash(sha1)" value, remove all spaces and to place as the value of Certificate value in the Registry. After making the settings and restarting SQL Server windows service one will see in file ERRORLOG in C:\Program Files\Microsoft SQL Server\...\MSSQL\Log directory the line like
2016-04-25 21:44:25.89 Server The certificate [Cert Hash(sha1)
"C261A7C38759A5AD96AC258B62A308A26DB525AA"] was successfully loaded
for encryption.
I want to add this for future folks that may stumble on a similar issue I encountered with SQL 2016 SP2 and failover cluster. The certificate thumbprint added to the registry had to be all upper case.
Hope this helps the next guy.
Once I followed steps in Updated 2 section of accepted answer, I can't start the SQL Server service, got those errors in Event Viewer:
Unable to load user-specified certificate [Cert Hash(sha1) "thumbprint of certificate"]. The server will not accept a connection. You should verify that the certificate is correctly installed. See "Configuring Certificate for Use by SSL" in Books Online.
TDSSNIClient initialization failed with error 0x80092004, status code 0x80. Reason: Unable to initialize SSL support. Cannot find object or property.
TDSSNIClient initialization failed with error 0x80092004, status code 0x1. Reason: Initialization failed with an infrastructure error. Check for previous errors. Cannot find object or property.
got error in SQL Server error log:
The server could not load the certificate it needs to initiate an SSL connection. It returned the following error: 0x8009030d. Check certificates to make sure they are valid.
googled it and found out a solution:
Make sure the windows account running SQL Server service (NT Service\MSSQLServer in my case) has full permissions to the following folders/register entry:
C:\Program Files\Microsoft SQL Server[Your Sql Server Instance]\MSSQL\
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
HKLM\System\CurrentControlSet\Services\WinSock2\Parameters
I checked No.1 NT Service\MSSQLSERVER has already had the permission.
I checked No.2, NT Service\MSSQLSERVER has no permission and I added the permission. It popped up an error saying one of files in that folder was denied the operation, but I just ignored it (nothing else I can do)
I didn't check No.3 and tried starting SQL Server, it worked!!
I faced similar issue in SSRS, wherein certificate issued by microsoft active directory CA was not visible in the dropdown in SSRS. After lot of searches, trial and error I could fix it by following this link.
https://learn.microsoft.com/en-us/archive/blogs/sqlserverfaq/can-tls-certificate-be-used-for-sql-server-encryption-on-the-wire
Brief of it is as below:
The Subject property of the certificate must indicate that the common name (CN) is the same as the host name or fully qualified domain name (FQDN) of the server computer.
So in our case we suggested to request the Certificate Authority to change the Subject name to ABC-SQLServer.abc.local (FQDN of SQL Server) instead of abc-corp.abc.com
Once this change was done, we loaded certificate again in MMC and now we could see the certificate loaded in SQL Server Configuration Manager!
Hope it helps someone facing same issue!
I was still having problems even after following the above. This is my fix:
in the certificates mmc right click the certificate All tasks->Manage Pricate Keys. Give the service account full control. In my case I am using NT Service\MSSQL$
SQL Server 2019
I found that the certificate thumbprint had to be entered into the certificate registry key in lower case for Configuration Manager to see it.
SQL Server will read the registry value and use it whether the registry key is in upper or lower case.
But configuration Manager will only display it if it is in lower case
I logged on to the server with SQL Server domain account( had to add the account to local admins temporarily) and imported the certificate in personal folder of the SQL Server service account. rebooted the server, and then SQL Server could see the certificate. Hope it helps someone.
An additional failure mode is key length - SQL requires a minimum keylength of 2048. With DH channel disabled.
I have also run into an issue copying out of the MMC as detailed in the article here. Using the certutil and copying that into the registry value worked perfectly.
My problem was that the Certificate Store was for WebHosting, but to see the certificate in SSRS it must be Personal.
USE UPPER CASE for Certificate in Registry editor LOL
Still not shown in config manager but TLS is working for SQL connections.

Configure SQL Server to allow LAN connection

I am trying to configure SQL Server to allow LAN connection but I do not seem to have any luck.
I am using the default server name and have created a new SQL Server user with a username and password.
I have also enabled Named Pipes and TCP\IP from SQL Server Configuration Manager and then reset the server.
I have tested the user on the local computer witch will act as the server
It seems that the client PC throws this error:
I usually get this error when I type the wrong server name this leads me to believe that I might need to add some additional configuration.
Can anyone point me the right direction on what I have to do next?

Trouble Connecting to sql server Login failed. "The login is from an untrusted domain and cannot be used with Windows authentication"

I am trying to host a SQL server database, but whenever I try to connect to it I get this error:
The login is from an untrusted domain and cannot be used with Windows
authentication
I am connecting through Matlab using the following command:
conn = database('Clinical_Data','DoyleLab07\Acc','','com.microsoft.sqlserver.jdbc.SQLServerDriver','jdbc:sqlserver://DOYLELAB07\SQLEXPRESS:54287;database=Clinical_Data;integratedSecurity=true;').
Connecting to the database using matlab worked fine as long as I was using matlab on the computer which I was using to host the server. However, when I use another computer and the same Matlab command I get the error I showed above.
When I look under control panel\system. I notice that no domain is listed on my host PC or the PC I am using to connect to the host, but both computers are in the same workgroup. Would I be able to fix my problem by creating a domain and adding the foreign PC and the host to that domain? If so, how can this be accomplished?
Any suggestions will be very much appreciated.
Thank you for reading my post.
Getting rid of Integrated Security=true worked for me.
In order to use Windows Authentication one of two things needs to be true:
You are executing from the same machine as the database server.
You have an Active Directory environment and the user the application is executing under (usually the logged in user) has rights to connect to that database.
If neither of those are true you have to do one of two things:
Establish a Windows Domain Controller, connect all of the relevant machines to that controller, then fix SQL server to use domain accounts; OR,
Change SQL server to use both Windows and SQL Server accounts.
By FAR the easiest way is to change SQL Server to use both Windows and SQL server accounts. Then you just need to create a sql server user on the DB server and change your connection string to do that.
Best case option 1 will take a full day of installation and configuration. Option 2 ought to take about 5 minutes.
If your SQL Server is on one domain controller and you are trying to connect to it from another domain controller then you will get this error when
IntegratedSecurity = true;
This will happen even if you include a valid SQL Server username and password in your connection string as they will automatically be over-written with your windows login and password. Integrated security means simply - use your windows credentials for login verification to SQL Server. So, if you are logged in to a different domain controller then it will fail. In the case where you are on two different domain controllers then you have no choice but to use
IntegratedSecurity = false;
Now, when Integrated security is false SQL Server will use the SQL Server login and password provided in your connection string. For this to work, the SQL Server instance has to have its authentication mode configured to mixed mode, being, SQL Server and Windows Authentication mode.
To verify or change this setting in SQL Server you can open the SQL Server Management Studio and right-click on your server name and then select Properties. On the pop-up that appears select Security and you will see where to alter this setting if you need to.
I've had this same issue when using DNS aliases and hosts files to connect to a machine using a different domain name.
Say you have a SQL server called sql1 on mydomain.com - which is an Active Directory domain - and you also have a DNS zone for mydomain.net, and - for consistency - you set up a DNS alias (CNAME) record for database.mydomain.net --> sql1.mydomain.com
You'll be able to connect to sql1.mydomain.com using Windows integrated security, but won't be able to connect to database.mydomain.net even though it's the same server because the domain name doesn't match your AD domain.
This error message can also occur if the account you are using to access the SQL server is locked out by the domain.
I was facing the issue while connecting to SQL Always On Listener. Disabling the loop back check resolved the issue.
Edit the registry using regedit. (Start –> Run > Regedit )
Navigate to: HKLM\System\CurrentControlSet\Control\LSA
Add a DWORD value called “DisableLoopbackCheck”
Set this value to 1
https://blog.sqlauthority.com/2017/04/18/sql-server-login-failed-login-untrusted-domain-cannot-used-windows-authentication/
Why not use a SQL Server account and pass both the user name and password?
Here is the reason why.
In short, it looks like you have an authentication issue.
The problem with workgroups is there is no common Access Control List like Active Directory (AD). If you are using ODBC or JDBC, the wrong credentials are passed.
Even if you create a local windows account (LWA) on the machine (SE) that has SQL Express installed (SE\LWA), the credentials that will be passed from your client machine (CM) will be CM\LWA.
As mentioned here, you might need to disable the loopback
Loopback check can be removed by adding a registry entry as follows:
Edit the registry using regedit. (Start –> Run > Regedit )
Navigate to: HKLM\System\CurrentControlSet\Control\LSA
Add a DWORD value called “DisableLoopbackCheck” Set this value to 1
If you using windows authentication make sure that password of the user hasn't expired. An expired password can explain this error. This was the problem in my case.
Same Error with Connection String in Visual Studio dev environment
Our development database server was recently given a self-signed certificate so it automatically became untrusted. This resulted in the login error cited above. I added TrustServerCertificate=True to my connection string and it works now.
"Server=TheServerAddress; Database=TheDataBase; User Id=TheUsername; Password=ThePassword; TrustServerCertificate=True"
NOTE: This certificate configuration is not recommended for production environments.
In my case the Aliases within SQL Native Client 11.0 Configuration were pointing to invalid server/IP. Once updated it worked correctly.
To check:
1. Start "SQL Server Configuration Manager"
2. Navigate to "SQL Native Client 11.0 Configuration" and then "Aliases"
3. Ensure "Alias Name" and "Server" match correctly for TCP/IP
Following worked for me to get access from another machine to SQL Server using Windows Authentication. This approach may be useful only in development/test environment. E.g. you need to update password manually once you change it on your working machine.
On machine with SQL Server go to Control Panel and add new Windows User with same username and password as is on your working machine. Then create SQL Server login for this user:
CREATE LOGIN [SQLSERVERHOST\myuser] FROM WINDOWS;
Now you can use this login for Windows Authentication.
If you receive error 'The login is from an untrusted domain', this may mean that you changed password on your working machine and now need to update password on SQL Server machine.
Just adding my suggestion for a resolution, I had a copy of a VM server for developing and testing, I created the database on that with 'sa' having ownership on the db.
I then restored the database onto the live VM server but I was getting the same error mentioned even though the data was still returning correctly. I looked up the 'sa' user mappings and could see it wasn't mapped to the database when I tried to apply the mapping I got a another error "Fix: Cannot use the special principal ‘sa’. Microsoft SQL Server, Error: 15405". so I ran this instead
ALTER AUTHORIZATION ON DATABASE::dbname TO sa
I rechecked the user mappings and it was now assigned to my db and it fixed a lot of access issues for me.
Joining a WORKGROUP then rejoining the domain fixed this issue for me.
I got this error while using Virtual Box VM's. The issue started to happen when I moved the VM files to a new drive location or computer.
Hope this helps the VM folks.
We now use a privileged account management solution that changes our passwords regularly. I ended up receiving this error after my password was changed. Closing and re-opening SSMS with the new password resolved my issue.
I started to get this error when i tried to login to SSMS using 'windows Authentication'. This started to happen after i renamed the Windows SQL server. I tried everything to resolve this error and in my particular case changing the machine names in the 'hosts' file to reflect the name SQL server name change resolved the issue. C:\Windows\System32\Drivers\etc\hosts
I had this problem because we where using a DNS name from an old server, ponting to a new server. Using the newserver\inst1 address, worked. both newserver\inst1 and oldserver\inst1 pointed to the same IP.
Yet another thing to check:We had our nightly QA restore job stop working all of a sudden after another developer remoted into the QA server and tried to start the restore job during the middle of the day, which subsequently failed with the "untrusted domain" message. Somehow the server pointed to be the job's maintenance plan was (changed?) using the ip address, instead of the local machine's name. Upon replacing with the machine name the issue was resolved.
TLDR: Changing the DNS server to the loop back address worked for me.
I am working in VirtualBox and had setup two Windows Server 2016 instances. Server A is configure as a Domain Controller and Server B as an SQL Server. After adding Server B to the domain I cold not connect to with Management Studio from Server A. I was getting the "The login is from an untrusted domain and cannot be used with Windows authentication".
My initial configuration had the server getting its IP from the VirtualBox DHCP server.
I changed this to use static IP and entered the 127.0.0.1 address in the Primary DNS and this worked for me.
Hope this helps someone passing by.
I enabled Trust Server Certificate in the Connection Properties and it worked for me
You might find out that you have more than one connection string, and you forgot to change the other one to Integrated Security to false. It happened to me. This answer might help someone.
I was focusing on the web config and the access rights, after a long hustle i remembered that I have another connection string in one of my classes for the emails, I had to change the connection string on the class to use the web config one.
i removed Integrated Security=true and Trusted_Connection=True both of them , worked for me..
In .net Core also you may get this error if Trusted_Connection=True;
Is set. Sample setting in appsettings.json
ConnectionStrings": {
"DefaultConnection": "Server=serverName; Database=DbName; uid=userId; pwd=password; MultipleActiveResultSets=true"
},
Sometime SSMS hang and close all of sudden ,then you get below error when you reconnect to SSMS
i) The Login is From an Untrusted Domain and Cannot be Used with Windows Authentication
OR
ii) The target principal name is incorrect .Cannot generate SSPI context.
In both cases RESTART YOUR MACHINE.
I also had a similar error but then I realised I just had changed the password for my system which caused this error.
To resolve it , I simply logged out of the current session and logged in again and this time
Please Use This Connection URL It's Work Fine
"Data Source=Your IP Address;Initial Catalog = DatabaseName;User ID =sa;Password =your PassWord;TrustServerCertificate=True"
Example : "Data Source=192.168.150.122;Initial Catalog=StudentDb;User ID=sa; PassWord=123;TrustServerCertificate=True"
If you have two servers on the same domain (eg. APP and DB), you can also use Windows Authentication between the app and MSSQL by setting up local users on both machines that match (same username and password). If you don't have the passwords matched up, it can throw this error.
Following was working for me. hope this helps you
<add name="getconn" connectionString="Data Source=servername;Initial Catalog=DBName;Persist Security Info=True;User ID=sa;Password=***" />

Error while trying to connect to SQL Server - localhost

I have checked the instance name, auto close is set to true, allow remote connections on the server is checked. The server is running when I open the SQL Server configuration manager. I have even rebooted. I have created this db the same way as all others. I use Entity Framework and have checked the names in the web.config and they match. This is the default connection string from the wizard - I use for testing before I deploy. I just can't think of anything else to check to figure out why it won't connect. Working inside SQL Server everything is fine.
Here is the general error.
A network-related or instance-specific error occurred while establishing a connection to SQL >Server. The server was not found or was not accessible. Verify that the instance name is >correct and that SQL Server is configured to allow remote connections. (provider: Shared >Memory Provider, error: 40 - Could not open a connection to SQL Server)
Config:
connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string='data source=.\SQL_1;attachdbfilename="C:\Program Files (x86)\Microsoft SQL Server\MSSQL10_50.SQL_1\MSSQL\DATA\A_db.mdf";integrated security=True;connect timeout=10;user instance=True;multipleactiveresultsets=True;App=EntityFramework'" providerName="System.Data.EntityClient" />
Thanks in advance.
Let me preface this answer by saying that proper setup of a SQL instance is not as easy as Microsoft would like you to think with the entity framework. It's a little bit involved and requires that you put your DBA hat on for a little bit.
The error you have indicates that the web instance is attempting to connect to the SQL server using Windows Integrated Security. This will work fine if (a) the windows user that the process is running as (which can be configured in IIS) is authorized to log on to the SQL server and has a valid login in the database and (b) if the SQL server is on the same machine or in the same domain as the IIS server.
In light of this, I recommend using SQL Server authentication. If you need to know how to do this, I recommend searching for "SQL Server Authentication setup" - here is an article that I found which might help you set this up.
http://msdn.microsoft.com/en-us/library/aa337562.aspx
In general, I recommend taking the following actions:
Connect to the sql server using MS SQL Management Studio.
Permanently attach your database, then use the Initial Catalog property on your connection string rather than AttachDbFileName
Then set up your login username and password on the SQL server, and create a login in the database for it.
Make sure your login can only execute the stored procedures you want it to execute. Deny it access to running sql statements.
You will also need to add the username and password to your connection string, and set IntegratedSecurity=false.
Let us know how things go once you get your SQL server set up properly.
This error means that your provider code cannot find the SQL Server. If you have checked the server instance name (it should be <yourLocalServer>\SQL_1), then it could be the attachdbfilename= parameter, as this is a really unreliable way to specify the database to connect to (you should be using the Database Name, not the file name), because there are about a hundred reasons that the file name could change that have nothing to do with your application.

Integrated Windows authentication in IIS causing ADO.NET failure

We have a .NET 3.5 Web Service (not WCF) running under IIS. It must use identity impersonate="true" and Integrated Windows authentication in order to authenticate to third-party software. In addition, it connects to a SQL Server database using ADO.NET and SQL Server Authentication (specifying a fixed User ID and Password in the connection string).
Everything worked fine until the database was moved from SQL Server A to SQL Server B. (Neither was the same as the web server.) Then the Web Service would throw the following exception:
A network-related or
instance-specific error occurred while
establishing a connection to SQL
Server. The server was not found or
was not accessible. Verify that the
instance name is correct and that SQL
Server is configured to allow remote
connections. (provider: Named Pipes
Provider, error: 40 - Could not open a
connection to SQL Server)
This error only occurs if identity impersonate is true in the Web.config.
Again, the connection string hasn't changed and it specifies the user. I have tested the connection string and it works, both under the impersonated account and under the service account (and from both the remote machine and the server).
What needs to be changed to get this to work with impersonation?
EDIT:
Remus Rusanu pointed us in the right direction. It came down to Kerberos - the SPNs weren't set up for the new server. See also asp.net via kerberos integrated windows authentication to sql server. Thank you!
When using impersonation and accessing a resource on a different host, delegation occurs (what the laymen call 'two hops'). Since delegation is restricted by default, authentication fails, unless constrained delegation is explicitly enabled.
But wait, you says, I use SQL Authentication and SQL authentication is not an NTLM/Kerberos 'resource'. True, says I, but you also use NAMED PIPES and named pipes are an NTLM/Kerberos resource, therefore delegation does occur.
See How to: Configure Client Protocols to make sure SQL Server is listening on TCP and Configuring Client Network Protocols for how to force the client to choose a specific protocol (ie. not try named pipe first). You can also force TCP by simply appending tcp: in front of the server name in the connection string.
are you using impersonation in the web service itself?
Impersonation in web services operates on a different layer than IIS does. To get from client to web service, you can have identity=impersonate off and get the user token from ServiceSecurityContext, even with Anonymous mode on.
To impersonate that token in the web service, get the WindowsCredential from ServiceSecurityContext and call the credential.Impersonate() method in a using statement, placing your connection to the database inside the using block.
public class HelloService : IHelloService
{
[OperationBehavior]
public string Hello(string message)
{
WindowsIdentity callerWindowsIdentity =
ServiceSecurityContext.Current.WindowsIdentity;
if (callerWindowsIdentity == null)
{
throw new InvalidOperationException
("The caller cannot be mapped to a WindowsIdentity");
}
using (callerWindowsIdentity.Impersonate())
{
// Access a file as the caller.
}
return "Hello";
}
}
Also, if you need another leg in the process (i.e. the back-end service is on another server), you will need to use Delegation to propagate the credentials. You may also do this declaratively. See this article for full details: http://msdn.microsoft.com/en-us/library/ms730088.aspx
Since it worked when the SQL Server was on the same box, it could be connected to transactions.
It may be that it is trying to use the the MSDTC, and the impersonated users are lacking some rights.
Another thing that you could try is to log on to the web server with a user that you are trying to impersonate, and see if you can then connect to the sql server.
If Delegation is your problem, see this article for enabling constrained delegation
http://msdn.microsoft.com/en-us/library/ms730088.aspx
go to the very bottom to see how to set up an account for constrained delegation. I know its a WCF article, but the process for setting up an account to use delegation should be the same.
for even more details, go here
http://technet.microsoft.com/en-us/library/cc739587(WS.10).aspx
Alternatively, have your SQL server enable TCP access and access it that way, as Remus explained.

Resources