How to read SQL Always-encrypted column from classic ASP - sql-server

I maintain a classic ASP app (yeah, I know, we're working on it) and need to access Always Encrypted columns in SQL 2017.
I've imported the cert and tested in SSMS and PowerShell and that much works. The best I've been able to do in ASP is to get the encrypted value as a byte array. I've tried more connection string combinations than I can remember.
My ASP dev box is Windows 10; the data server is SQL 2017.
cnn = "Provider=MSOLEDBSQL; DataTypeCompatibility=80; " _
& "DRIVER={ODBC Driver 17 for SQL Server}; " _
& "SERVER=xxxx; UID=xxxxx; PWD=xxxxx; DATABASE=xxxx; " _
& "ColumnEncryption=Enabled; Column Encryption Setting=Enabled;"
Set oDB = CreateObject( "ADODB.Connection" )
oDB.Open cnn
set oCmd = Server.CreateObject("ADODB.Command")
oCmd.ActiveConnection = cnn
oCmd.CommandText = "SELECT top 10 ID, Enc FROM tbl1"
set rst = oCmd.Execute()
The code works without error but the encrypted column (Enc, varchar(50)) is returned as a byte array. I seem to be getting the encrypted value when I should get the plain text value. I've also tried calling a Stored Procedure with the same results. No filter in the query, so nothing to parameterize.
Any ideas what to try next?
Answer:
1) Import the cert as the same user as the AppPool Identity for that web app.
2) Set Anon authorization for the web app to Application Pool Identity.
3) Use this connection string:
cnn = "Provider=MSDASQL;" _
& "Extended Properties=""Driver={ODBC Driver 17 for SQL Server};" _
& "SERVER=***; UID=***; PWD=***;" _
& "DATABASE=***;ColumnEncryption=Enabled;"" "

The new Microsoft OleDb Provider for SQL Server (MSOLEDBSQL) doesn't support AlwaysEncrypted (currently). You'll have to use ODBC, which means the OleDb provider should be the Microsoft OleDb Provider for ODBC (MSDASQL). So you can either configure a system DSN using Microsoft® ODBC Driver 17 for SQL Server with a connection string like:
cnn = "Provider=MSDASQL;DSN=testdb;"
or embed all the ODBC driver parameters in the "Extended Properties" of the MSDASQL connection string. Like
cnn = "Provider=MSDASQL;Extended Properties=""Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=testdb;Trusted_Connection=yes;ColumnEncryption=Enabled;"" "
Here's walkthrough, using first VBScript for testing before testing with ASP.
Starting with:
create database testdb
go
use testdb
create table tbl1(id int, Enc varchar(200))
insert into tbl1(id,enc) values (1,'Hello')
Then running through the column encryption wizard in SSMS, which stores the certificate on for the current user, on the machine running SSMS:
Then the listing of query.vbs:
cnn = "Provider=MSDASQL;Extended Properties=""Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=testdb;Trusted_Connection=yes;ColumnEncryption=Enabled;"" "
Set oDB = CreateObject( "ADODB.Connection" )
oDB.Open cnn
set oCmd = CreateObject("ADODB.Command")
oCmd.ActiveConnection = cnn
oCmd.CommandText = "SELECT top 10 ID, Enc FROM tbl1"
set rst = oCmd.Execute()
rst.MoveFirst()
msgbox( cstr(rst("Enc")) )
Which can be run from the commandline with:
cscript .\query.vbs
To do this from ASP you'll additionally have to place the certificate in the user certificate store of the IIS App Pool account, per the docs here. Note that the relative path to the certificate has to be the same for all users. You can't store it in the machine store on the IIS box if you initially configured it to be stored in the user's certificate store. SQL Server stores the key_path of the key and instructs the clients where to find the certificate, eg CurrentUser/my/388FF64065A96DCF0858D84A88E1ADB5A927DECE.
So discover the key path of the Column Master Key
select name, key_path from sys.column_master_keys
Then export the certificate from the machine that has it:
PS C:\Windows> $path = "cert:\CurrentUser\My\388FF64065A96DCF0858D84A88E1ADB5A927DECE"
PS C:\Windows> $mypwd = ConvertTo-SecureString -String "xxxxxxx" -Force -AsPlainText
PS C:\Windows> Export-PfxCertificate -Cert $path -FilePath c:\temp\myexport.pfx -ChainOption EndEntityCertOnly -Password $mypwd
Running as the app pool identity user on the IIS server, import it
PS C:\WINDOWS> $mypwd = ConvertTo-SecureString -String "xxxxxxx" -Force -AsPlainText
PS C:\WINDOWS> Import-PfxCertificate -FilePath C:\temp\myexport.pfx -CertStoreLocation Cert:\LocalMachine\My -Password $mypwd
And if you're using Anonymous/Forms auth sure you've configured IIS Anonymous Auth to run under the App Pool identity, not the default IUSR.
Here's an ASP page to test with:
<!DOCTYPE html>
<html>
<body>
<p>Output :</p>
<%
Set objNetwork = CreateObject("Wscript.Network")
Response.write("The current user is " & objNetwork.UserName)
cnn = "Provider=MSDASQL;Extended Properties=""Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=testdb;Trusted_Connection=yes;ColumnEncryption=Enabled;"" "
Set oDB = CreateObject( "ADODB.Connection" )
oDB.Open cnn
set oCmd = CreateObject("ADODB.Command")
oCmd.ActiveConnection = cnn
oCmd.CommandText = "SELECT top 10 ID, Enc FROM tbl1"
set rst = oCmd.Execute()
rst.MoveFirst()
Response.write(cstr(rst("Enc")) )
%>
</body>
</html>

Related

how to connect VBScript (Excel) to SQL Server web database (via IP)

I'm at my job trying to do some unknow stuff for me, you see, we're trying to connect an excel document with a VBScript Macro to a databse stored in web server but for some reason doesn't recognizes the user and throws an error repeatedly, i discarded a connection issue since it returns an SQL error instead of something like a timeout or server doesn't exists or something like that, we're trying to connect to the server using the ip address, we also checked that the logging method is on mixed (win and sql) and remotes connections to the server are enabled as well, also if i use the credentials provided in the connection string (username and password) i can actually log in to SQL Server without any issue, we also tried a direct connection (external vpn) because we thought it could be our firewall, but got the same error anyway, so we have no clue what it could be and we're kinda running out of ideas on how to do this, i'll post down below the code i'm using to trying the connection (obviously test data but similar to reality)
picture of the error i'm getting (don't post the original since it's in spanish but is very similar to this):
code i'm currently trying:
Sub excel_sqlsrv()
Set rs = CreateObject("ADODB.Recordset")
Set conn = CreateObject("ADODB.Connection")
strConn = "Driver={ODBC Driver 17 for SQL Server};Server=10.20.30.5;Database=mydb;UID=sa;PWD=abcd12345;"
conn.Open strConn
strSqL = "SELECT * FROM USERS"
rs.Open strSqL
End Sub
Any advice, tip or trick could be of tremendous help for me, i'll be looking forward to any kind of comment, thanks in advance
Use the ODBC Data Source Administrator to create a connection named mydb and test it works. Then use
Sub excel_sqlsrv()
Const strConn = "mydb" ' ODBC source
Const strsql = "SELECT * FROM USERS"
Dim conn As Object, rs As Object
Set rs = CreateObject("ADODB.Recordset")
Set conn = CreateObject("ADODB.Connection")
On Error Resume Next
conn.Open strConn
If conn.Errors.Count > 0 Then
Dim i, s
For i = 0 To conn.Errors.Count - 1
s = s & conn.Errors(i) & vbLf
Next
MsgBox s
Else
On Error GoTo 0
Set rs = conn.Execute(strsql)
Sheet1.Range("A1").CopyFromRecordset rs
End If
End Sub
You can try using OLEDB provider instead of ADODB.

Unable to open Linked Access 2003 table to MS SQL Server in VBA code

I have a table in Access 2003 that is linked to a MS SQL server table.
I am able to go into the Access table, manually update it and see the changes
reflected in the MS Sql server table.
However, I'm unable to even just open the table and put the result in the record set in my VBA code.
Set rs = CurrentDb.OpenRecordset("dbo_tbl_EventLogs", dbOpenTable)
(rs is always at nothing)
The same line of code works on a 'local' Access table.
Consider using dbOpenDynaset option which is used by default for linked tables or stored queries whereas dbOpenTable is used for local tables as mentioned for OpenRecordset() method:
If you open a Recordset in a Microsoft Access workspace and you don't
specify a type, OpenRecordset creates a table-type Recordset, if
possible. If you specify a linked table or query, OpenRecordset
creates a dynaset-type Recordset.
Set rs = CurrentDb.OpenRecordset("dbo_tbl_EventLogs", dbOpenDynaset)
You need to connect to your DB using ADO. Is simple and easy. Just change to your info and enjoy it.
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
ServerName = "yourServer,yourPort(example: 1442)" 'Enter your server name and a port here
DatabaseName = "yourDBinTheServer" 'Enter your database name here
UserID = "yourUserID" 'Enter your user ID here
Password = "yourPassword" 'Enter your password here
Set rs = New ADODB.Recordset
Set cn = New ADODB.Connection
cn.Open "Driver={SQL Server};Server=" & ServerName & ";Database=" & DatabaseName & ";Uid=" & UserID & ";Pwd=" & Password & ";"
rs.open yourQueryAsString, cn
Make sure you store the user credentials used to connect to the database...
(attribute dbAttachSavePWD)

Multi database query ACCESS and SQL SERVER

I'm not able to figure out how to make a multi database query usign two diffent ditabase.
The first database is an ACCESS mdb database and the second one is a SQL Server 2012 database.
I'm using Visual Basic 6.
The code I'm using is that:
ConnectionString1 = "Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False;Data Source=C:\MyDatabase.mdb"
ConnectionString2 = "DSN=ODBC_NAME;UID=user;PWD=password"
SQL = "SELECT tabScheda.sWorkNum FROM tabScheda WHERE codScheda NOT IN" + _
" (SELECT ORDERID FROM [" + ConnectionString2 + "].V_PRESETTING_SP_HEADER WHERE MODE = 'TC')"
cn.Open ConnectionString1
Set rc = cn.Execute(SQL)
rc.Close
Set rc = Nothing
cn.Close
Set cn = Nothing
Please help me :D

VBscript - SQL Connection fails SQL Server does not exist or access denied

this is pretty strange.
I've got this string that connect to a SQLServer in the same domain as the computers are running and compares username with employeeID. Then takes that row and dumps it into the lokal computers registry. This is working in Windows XP, but not Windows 7 it seems.
I get this exact error message:
Line:39
Char:1
Error: [DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or access denied.
Code: 80004005
Source: Microsoft OLE DB Provider for SQL Server.
This is the script itself. I've removed the actual servernames. Reckon nobody needs those.
Set oConn = CreateObject("ADODB.Connection")
oConn.Open "Provider=sqloledb;Data Source=mysqlserver04\mysqlserver04;Initial Catalog=orginfo;Integrated Security=SSPI"
sSQL = "select top 1 * from dbo.Mal_personinfo where empid = '" & EID & "'"
'wscript.echo sSQL
set rs = oConn.Execute(sSQL)
set oSystem = CreateObject("WScript.Shell")
for iTeller = 0 to rs.fields.count - 1
Text = Text & rs.fields(iTeller).Name & "=" & rs.fields(iTeller).Value & " - "
oSystem.RegWrite "HKCU\Software\MalData\" & rs.fields(iTeller).Name,rs.fields(iTeller).Value,"REG_SZ"
next
'wscript.echo Text
Why does this work on Windows XP but not Windows 7?
Since you're using integrated security, let me ask you about the account that is running the application. Did you add that account as a user to the database? If not, and it's an admin account, you're probably relying on the old "admins can do everything" and under Windows 7 that's not true any more.
To test this, try running the application elevated (right click the exe and Run As Administrator.) This will cause it to keep your "admin-ness" and might let it into the database. If that works, don't continue to run it elevated, but instead go to SQL and add yourself as a user. Then the app should work fine non-elevated.

Unable to connect to SQL2005 using VBScript

I have the following VBScript, which is supposed to connect to a SQL Server 2005 database. But, my connection is failing. Why?
Set dbConnection = CreateObject("ADODB.Connection")
dbConnString = "Provider=SQLOLEDB.1;Data Source=srv\test1;" & _
"Initial Catalog=tset_DB;user id ='abc';password='abc'"
'Open the connection
dbConnection.Open dbConnString
You don't need quotations around your username and password. Try this:
Set dbConnection = CreateObject("ADODB.Connection")
dbConnString = "Provider=SQLOLEDB.1;Data Source=srv\test1;" & _
"Initial Catalog=test_DB;user id =abc;password=abc"
'Open the connection
dbConnection.Open dbConnString
Also, your Initial Catalog was set to tset_DB, when I'm guessing it should be test_DB.
ConnectionStrings.com is a huge help for ensuring that your connection strings are valid.

Resources