Impersonation succeeds but database connection fails - c#

I have C# (.NET 4.5) code like this (simplified for demonstration) used to connect to a SQL Server 2012 database:
public static void Test(WindowsIdentity ident)
{
using (WindowsImpersonationContext ctx = ident.Impersonate())
{
using (SqlConnection con = new SqlConnection("Data Source=MyServer;Initial Catalog=MyDatabase;Persist Security Info=False;Integrated Security=SSPI;Network Library=dbmssocn"))
{
con.Open();
}
ctx.Undo();
}
}
The Open() method throws the following exception every time:
System.Data.SqlClient.SqlException (0x80131904): 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: TCP Provider, error: 0 - No
connection could be made because the target machine actively refused
it.)
The impersonation is succeeding because if I add tracing like this:
public static void Test(WindowsIdentity ident)
{
using (TextWriterTraceListener listener = new TextWriterTraceListener(#"C:\temp\trace.log"))
{
using (WindowsImpersonationContext ctx = ident.Impersonate())
{
listener.WriteLine("Impersonated");
using (SqlConnection con = new SqlConnection("Data Source=MyServer,MyPort;Initial Catalog=MyDatabase;Persist Security Info=False;Integrated Security=SSPI;Network Library=dbmssocn"))
{
listener.WriteLine("About to open connection; WindowsIdentity.GetCurrent().Name = " + WindowsIdentity.GetCurrent().Name);
con.Open();
}
ctx.Undo();
listener.WriteLine("Impersonation undone");
}
}
}
I get this:
Impersonated
About to open connection; WindowsIdentity.GetCurrent().Name = MyDomain\MyUser
If I put the exact same connection string in a .udl file, run it under the same "MyDomain\MyUser" account on the same machine, and click Test Connection, it succeeds. Since that's the case, I just don't see how the problem could be a firewall or anything of that nature. Does anyone know what could be going wrong? I do not have access to log onto the database server itself, so I cannot check its event log (etc.) at this point.

Your problem come from the connection string. The "Network Library = dbmssocn" in connection string will make client attempting to connect to SQL server on the UDP port 1434 rather than the TCP port 1433. You remove the "Network Library = dbmssocn" from the your application's connection string the application will connect to SQL server successfully.

The anonymous login failed error means that kerberos authentication failed for some reason.
Kerberos delegation (delegation is when your impersonated credentials are passed to a different machine) is relatively simple in theory. In practice it is fraught with gotcha's and can be one of the most frustrating things to troubleshoot.
In your case, it is entirely possible that from the standpoint of your program, the impersonation is succeeding, but the token it is passing to sql server isn't usable.
If you are lucky and have access to a really good network/system admin, then they can help you troubleshoot it.
Otherwise googling "sql server kerberos delegation" will point you in the right direction.
This is the kind of problem that requires substantial back and forth to resolve and is more suited to a forum than a Q&A site.

Related

ADO.NET FirebirdSql.Data.FirebirdClient.FbException: "Unable to complete network request to host "

I have a pretty strange problem when trying to connect my C# program to an existing Firebird server.
First of all, this is reproducable with the default connection example from the Firebird documentation at https://github.com/FirebirdSQL/NETProvider/blob/master/Provider/docs/ado-net.md
using (var connection = new FBConnection("database=192.168.0.150:c:\\Data\\demo.fdb;user=sysdba;password=m#sterkey"))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
using (var command = new FbCommand("select * from demo", connection, transaction))
{
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var values = new object[reader.FieldCount];
reader.GetValues(values);
Console.WriteLine(string.Join("|", values));
}
}
}
}
}
It all works fine when I am on my machine, I also can connect to a Firebird server on my coworkers PC.
But I cannot connect to the Firebird server on my other development server. I found an answer in another question and want to tell you that the server does not have internet access.
https://stackoverflow.com/a/57569057/2785084
This is the exception I get:
FirebirdSql.Data.FirebirdClient.FbException: "Unable to complete
network request to host " No message for error code 335544721 found."
IscException: Unable to complete network request to host " No message
for error code 335544721 found. IOException: Unable to read data from
the transport connection: An existing connection was forcibly closed
by the remote host
I already updated to the latest stable Version of Firebird. I can guarantee that the server is running and no firewall is blocking my connection, because when I try to connect with our old Delphi program, everything works. I also can connect using the lightweight Firebird management tool Flamerobin from Flamerobin.org, which is written in C++, I think.
When I try to connect with DBeaver I get the following message:
[SQLState:28000, ISC error code:335544472] Your user name and
password are not defined. Ask your database administrator to set up a
Firebird login.
I'm pretty sure that the user and password are correct. I do not use the default password, but a password with an # sign in it, maybe it has something to do with that.
I now have 2 programs that can Connect (Delphi and C++), and two that cannot connect (C# and Java). Does anyone have any clue or tweak how to change the connection that I can connect to the server?
Thanks to Mark Rotteveel for the comment which got me to the solution.
I can connect with the default password "masterkey", so it is obvious that the srp user was created with the default credentials and therefore a connection with the other credentials is not possible.
I have to correct the users in my old server.
Thanks for the hint that ADO.NET only supports srp.

Can't connect with Azure SQL using SQLConnection on Linux

I'm currently developing an ASP.NET Core WebApi that uses an Azure SQL Db for data persistence.
I use Linux Mint 19 as a development environment.
Unfortunately when dbConnection.Open() is called I keep getting SQLException:
Exception has occurred: CLR/System.Data.SqlClient.SqlException
An exception of type 'System.Data.SqlClient.SqlException' occurred in
System.Data.SqlClient.dll but was not handled in user code: '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: TCP
Provider, error: 40 - Could not open a connection to SQL Server)'
Here's my code:
private const string connectionString = "Server=tcp:{myserver}.database.windows.net,1433;Initial Catalog={mydb};Persist Security Info=False;User ID={user};Password={pass};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;";
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "my_server.database.windows.net";
builder.UserID = "my_user";
builder.Password = "my_pass";
builder.InitialCatalog = "my_db";
using(IDbConnection dbConnection = new SqlConnection(builder.ConnectionString)){
dbConnection.Open();
var result = dbConnection.Query<Task>("SELECT * FROM Tasks");
if (dbConnection.State == ConnectionState.Open)
{
dbConnection.Close();
}
}
I've tried both using SQLConnectionStringBuilder and passing connectionString with my credentials. None of it worked.
I've opened port 1433 using the command:
sudo ufw allow 1433
but it didn't help, still getting the same exception.
Any help would be much appreciated.
Thanks.
UPDATE
I managed to connect with Azure SQL. It looks like my ISP blocks connection. I was able to connect using my smartphone WiFi hotspot.
First, make sure you have created appropriate firewall rule to allow traffic from your network to reach Azure SQL Database. Learn here how to do it.
Please try to ping your SQL Azure server. The ping should fail but it should return the current IP Address of the Azure SQL Database logical server. If you cannot see that IP returned then the issue is a DNS issue.
With the IP address returned on the previous step, try to telnet that IP address on port 1433.
telnet 181.37.11.112 1433
If you cannot connect using telnet, use traceroute command to diagnose when locate where data loss occurs.

Intermittent SQL Server Connection Failure

So we keep getting these errors, intermittently.
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)
Notice the part there about Named Pipes Provider?
Here is my connection string:
var conStr = "Data Source=tcp:MyServer;Initial Catalog=MyDatabase;User ID=myusername;Password=myuserpassword;Max Pool Size=100;MultipleActiveResultSets=True;Connect Timeout=120;";
In my connection string you'll notice I specify TCP. So this error message is crazy to me. I cant replicate this with any sort of reliability, but, it happens every, single, day. Nothing in the event logs, sql server log, surrounding application logs, nothing. Also when it happens there are at least 2k other connections from various other applications/servers throughout the enterprise that dont have this issue, until they do.
I should add that these are all VMs living inside of a VSphere cluster with 40Gbps connectivity between all the various hosts.
I've read every single hit 3 pages deep on google search results (yep, I went 3 whole pages deep). I'm lost.
What does the exception really mean?
Why does it say its using Named Pipers Provider?
Per request:
static void Main(string[] args)
{
var conStr = "Data Source=tcp:MyServer;Initial Catalog=MyDatabase;User ID=myusername;Password=myuserpassword;Max Pool Size=100;MultipleActiveResultSets=True;Connect Timeout=120;";
using (var con = new SqlConnection(conStr))
{
con.Open();
}
}

C# Console Application Unable to Connect to Remote SQL Server 2008 Using TCP/IP Protocol

I am currently unable to connect to a remote SQL Server using the TCP/IP protocol in C#.
Using named pipes does work, but the TCP/IP connection doesn't. The frustrating thing is that I can connect to the database using the TCP/IP protocol in the server explorer window within Visual Studio 2015, but my code cannot, even though I am copying and pasting the exact connection strings.
As soon I a remove "Network Library = dbmssocn" from the connection strings, the code works, but this makes it use named pipes, which I cannot rely on being an an option outside of the development environment.
Just in case, I have verified that the TCP/IP protocol is enabled on the SQL Server. This makes sense, since I can specify the TCP/IP protocol in visual studio's server explorer window and those connections work.
The server is also configured for both SQL authentication and Windows authentication. The windows firewall is probably also not the issue as it is currently turned off.
Here is the code that I'm using:
DbConnection testConnectionIntegrated = new SqlConnection("Data Source = MyServer; Initial Catalog = MyDatabase; Integrated Security = True; Encrypt = True; TrustServerCertificate = True; Network Library = dbmssocn");
try
{
Console.Write("Attempting to connect using Windows Authentication...");
testConnectionIntegrated.Open();
Console.WriteLine(testConnectionIntegrated.State);
}
catch (Exception caughtException)
{
Console.WriteLine("Integrated Security Connection Failed");
Console.WriteLine(caughtException.Message);
}
finally
{
Console.Write("Closing connection...");
testConnectionIntegrated.Close();
Console.WriteLine(testConnectionIntegrated.State);
}
DbConnection testConnectionSQLAuth = new SqlConnection("Data Source = MyServer; Initial Catalog = MyDatabase; Persist Security Info = True; User ID = my_user_name; Password = my_password; Encrypt = True; TrustServerCertificate = True; Network Library = dbmssocn");
try
{
Console.Write("Attempting to connect using SQL Authentication...");
testConnectionSQLAuth.Open();
Console.WriteLine(testConnectionSQLAuth.State);
}
catch (Exception caughtException)
{
Console.WriteLine("SQL Authentication Connection Failed");
Console.WriteLine(caughtException.Message);
}
finally
{
Console.Write("Closing connection...");
testConnectionSQLAuth.Close();
Console.WriteLine(testConnectionIntegrated.State);
}
And this is the error message I'm seeing for both connection attempts:
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: TCP Provider, error: 0 - A non-recoverable error occurred during a database lookup.)
Is there anything that I'm missing?
Edit:
I have verified the following on the server:
Remote connections are allowed.
The TCP/IP protocol is enabled and configured.
The named pipes protocol is enabled and configured.
Firewall is not the problem.
The SQL Server and SQL Server Browser services are running.
I have restarted the services to make sure.
Also, I have restarted my development machine, and the problem still exists.

TCP/IP Connection

I have been trying and searched thousands of times in other sites but never found a sample or simple code to use.
I've created an application C# which uses an ODBC connection, i have also MS SQL installed and configured to enable remoting database information sharing. I want to make my database available to everyone uses this application i have made by using a connection.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace CaseMatter
{
public partial class mainLog : Form
{
string userID, userName, userAddress, userFName, userLastName, userCity, userPassword, userTele;
public mainLog()
{
InitializeComponent();
this.Size = new Size(442, 162);
}
private void Submitbtn_Click(object sender, EventArgs e)
{
string ConnectionString =
"Data Source=xx.xx.xx.xx,1433;Initial Catalog=master;Integrated Security=SSPI;";
var conn = new SqlConnection(ConnectionString);
conn.Open();
var strSQLCommand = "SELECT Name FROM example WHERE id='1'";
var command = new SqlCommand(strSQLCommand, conn);
var reader = command.ExecuteReader();
while (reader.Read())
{
passwordBox.Text = reader.GetString(0);
}
reader.Close();
conn.Close();
}
}
}
I have just edited the code and tried it, i have added a try catch to handle sql exceptions but it still freezes when i click on submit button.
Hopefully someone figures this out.
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: TCP Provider, error: 0 - No connection could be made because the target machine actively refused it.)"
I suspect there are one of four things going on here.
The SQL Server is misconfigured and isn't responding to tcp connections. The easiest way to trouble shoot this is to use SQL Management Studio to connect. If you can't connect this way then you'll have to look at the sql server service setup. Also, make sure that the SQL Browser service is running on the server.
The SQL Server is configured to use a different TCP port than the one you are trying. Remove the ",1433" from your connection string and try again. SQL Browser should respond back with the actual port that sql server is listening on.
The SQL Server has a firewall in place that is blocking remote connections. Temporarily turn off the firewall and see if you can connect. If you can, then configure the firewall correctly and turn it back on.
Your local box has some type of firewall that is blocking outgoing connections on that port. Try turning yours off to see if this helps. If so, configure it correctly and turn it back on.
If this is a brand new sql server that no one has remotely connected to then it's very likely to be entirely within the configuration of SQL server or the Windows configuration.
In your example you are not passing the USER ID and Password. Is that just because you didnt want to include your credentials? I assume not as you properly XXX out your IP address. I would start by supplying credentials of a SQL server account that can access your database.
I noticed that you're using SqlConnection which is not an ODBC connection object. With SqlConnection you're actually connecting via ADO.NET. The connection string syntax for SqlConnection (both ODBC and ADO.NET) can be found on the following site:
http://connectionstrings.com
By the way, if you're connecting to SQL 2005, the connection string would look like this:
using System.Data.SqlClient;
// trusted connection (SQL configured to use your windows ID)
string ConnectionString =
"Data Source=xxxxxxx;Initial Catalog=xxxxxx;Integrated Security=SSPI;"
// sql authentication (SQL manages its own users/pwds)
//string ConnectionString =
//"Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword;"
var conn = new SqlConnection(ConnectionString);
conn.Open();
var strSQLCommand = "SELECT Name from [example_autoincrement] where id='1'";
var command = new SqlCommand(strSQLCommand, conn);
var reader = command.ExecuteReader();
while (reader.Read())
{
passwordBox.Text = reader.GetString(0);
}
reader.Close();
conn.Close();
Ok, this is a strange one to check but just make sure the time and date is accurate on client and server. SSPI requires a maximum gap of 5 minutes between each

Categories