tiberius icon indicating copy to clipboard operation
tiberius copied to clipboard

Connection Failure with MSSQL: Special Character Password

Open keithmss opened this issue 1 year ago • 4 comments

Summary

I'm encountering a connection issue when attempting to tiberius to connect to a Microsoft SQL Server. This issue does not arise when connecting via php or sqlcmd with the same credentials.

Detailed Description

I have successfully connected to the MSSQL server using both php and sqlcmd commands, indicating that the server is accessible and the credentials are correct. The connection details include a password that contains the special character $ followed by numbers, which I suspect might be related to the issue. Here are examples of the successful connection attempts for reference:

  • Using sqlcmd:
sqlcmd -S "sql.foo.com,999" -d "Database" -u "User" -P "Password`$1337"
  • Using php:
// PHP 7.2, ODBC 17
$conn=odbc_connect(Server=sql.foo.com,999;Database=Database","User","Password$1337");

However, attempting the same connection using this library:

use anyhow::Result;
use tiberius::Client;
use tiberius::Config;
use tokio::net::TcpStream;
use tokio_util::compat::TokioAsyncWriteCompatExt;

const CONNECTION_STRING: &str = r"Server=sql.foo.com,999;Database=Database;UID='User';PWD='Password$1337'";

#[tokio::main]
async fn main() -> Result<()> {
    let mut config = Config::from_ado_string(CONNECTION_STRING)?;
    config.trust_cert();
    let tcp = TcpStream::connect(config.get_addr()).await?;
    tcp.set_nodelay(true)?;
    let _ = Client::connect(config, tcp.compat_write()).await?;
    Ok(())
}

Fails with the following error message:

Error: Token error: 'Login failed for user 'User'.' on server SERVER executing  on line 1 (code: 18456, state: 1, class: 14)

Environment

Server: Microsoft SQL Server 2019 (RTM-CU19) (KB5023049 - 15.0.4298.1 (X64))

Issue Analysis

The error suggests a login failure, which is peculiar given that the same credentials work with other methods. The inclusion of a special character in the password and its handling within the Rust environment might be contributing factors but I'm not sure.

keithmss avatar Mar 01 '24 17:03 keithmss

Does it work if you urlencode the special character?

janpio avatar Mar 01 '24 17:03 janpio

By hand:

use anyhow::Result;
use tiberius::Client;
use tiberius::Config;
use tokio::net::TcpStream;
use tokio_util::compat::TokioAsyncWriteCompatExt;

const CONNECTION_STRING: &str = r"Server=sql.foo.com,999;Database=Database;UID='User';PWD='Password%241337'";

#[tokio::main]
async fn main() -> Result<()> {
    let mut config = Config::from_ado_string(CONNECTION_STRING)?;
    config.trust_cert();
    let tcp = TcpStream::connect(config.get_addr()).await?;
    tcp.set_nodelay(true)?;
    let _ = Client::connect(config, tcp.compat_write()).await?;
    Ok(())
}

It does not.

keithmss avatar Mar 01 '24 17:03 keithmss

Update: By using wireshark and setting encryption to NotSupported I can confirm that the login packet contains the correct password. I can't compare packets because SqlCmd does encrypt the login.

What is interesting is that SqlCmd uses an older version of the pre login message.

SqlCmd uses version: 0.0.1537 Tiberius uses version: 0.2.3072

Should this be a cause for concern?

keithmss avatar Mar 01 '24 21:03 keithmss