SQL create assembly without access to disc drive - sql-server

Is it possible to create assembly without access to C: drive on server? Suppose have got access to database only.
Is it possible to create assembly from a variable string where we could store DLL file?
CREATE ASSEMBLY MyAssembly FROM #variable_containing_dll
WITH PERMISSION_SET = SAFE;

OK, found it. On the server where the assembly is installed right-click on the assembly, create it and here you are. You get there CREATE ASSEMBLY with the bits ready to move anywhere without DLL file.

The FROM clause can specify a binary literal or a varbinary(MAX) variable containing the assembly bits. SSDT uses a binary literal for assembly deployment rather than a DLL.

Related

Error with adding dll in SQL Server 2014. Problem's with CLR

I have problem with adding assembly dll in SQL Server 2014. I try to create assemble stored procedure like this
CREATE ASSEMBLY pdf_create FROM 'dll path\test.dll' WITH PERMISSION_SET = SAFE
SQL Server returns this error:
Assembly 'test' references assembly 'system.drawing, version=2.0.0.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a.', which is not present in the current database. SQL Server attempted to locate and automatically load the referenced assembly from the same location where referring assembly came from, but that operation has failed (reason: 2(Не удается найти указанный файл.)). Please load the referenced assembly into the current database and retry your request.
Help please if you have any ideas
So the question is why you would need a dependency on system.drawing.dll in an SQLCLR assembly? I would look at the code for the test.dll, and try to get rid of that particular dependency.
What you can do, if you absolutely need to include system.drawing.dll, is to copy it and put it in the same directory as the dll you try to create the assembly from, as SQL Server automatically creates assemblies from dependent assemblies if they are in the same path.
However, if you do that, then you probably need to change the permission set for the assembly you create as (if I remember correctly) system.drawing.dll needs a lesser permission set than SAFE.
So all in all, try to get rid of the dependency, you save yourself a lot of trouble that way.

Decompile a C file to Pro*C

I'm currently working in Auditing a software we are supposed to start working on February. As part of the source code, we've recevied what seems to be a C file generated from a Pro*C file.
Pro*C files are compiled using the application "proc" into a C file, then you would use gcc to compile it into an actual executable file.
We are having some troubles with the previous owner of the application, and they refuse to provide us so far with the Pro*C file (pc extension).
I'm not sure if it's possible to revert it back from the C file to the Pro*C, using "proc" or any other tools.
Has anyone been able to do so, and if so, how?
Thanks in advance.
There is no decompiler for C to *Proc file. A C file containing SQL statement in it is call an embedded *Proc file, an utility provided by Oracle. Once you translate this embedded file to C by using a proc translator provided by Oracle it turn that *Proc file into a C file which modify these SQL statement with oracle provided library APIs.
Now my advice to you is, find out all the methods/functions in that C file (generated from a *Proc file) and check and understand what they are doing in Oracle database, especially all the database transactions. Once you understood that, just try to create your own C or C++ file by using ODBC driver api provided by Oracle.

F# with sqlclr in a reasonably safe way and scripted assembly

There exist some blog posts about how to use F# with SQLCLR in SQL Server that are helpful: http://richardminerich.com/2015/12/a-safer-way-to-use-f-with-sql-clr/, http://thelastexpression.blogspot.com/2012/04/f-agents-and-sqlclr.html, https://rojepp.wordpress.com/2011/08/03/f_on_sqlclr/, Can the F# core libs be SQLCLR-approved?
and for the C# approach: http://www.sqlservercentral.com/Authors/Articles/Solomon_Rutzky/294002/
I am wondering/hoping that with the passage of time there is a blog post out there, which I haven't been able to find yet or an answer here, which addresses how to use F# with SQLCLR such that the assembly can be scripted into hex using Visual Studio (or some other tool), like is done with C# deployment (I don't have access to install code on the server except through SQL Server Management Studio), and is at least more safe than using 'trustworthy on' or 'unsafe'. I've written F# and lots of T-SQL before and the prototype I wrote (which now must live in SQL Server) in Common Lisp would map better to F# (and make me happier than using C#).
I'm skeptical of the approach shown in your first link ( http://richardminerich.com/2015/12/a-safer-way-to-use-f-with-sql-clr/ ) as it does not directly show the loading of the FSharp.Core library, hence it is not clear that the author did not have to set TRUSTWORTHY ON in order to at least get that part working. What seems highly suspicious is that in Step 5, the Asymmetric Key-based Login is granted the wrong permission:
GRANT EXTERNAL ACCESS ASSEMBLY TO FSHARP_CLR_Login
Granting EXTERNAL ACCESS ASSEMBLY does not allow for setting an Assembly to UNSAFE. That requires the UNSAFE ASSEMBLY permission. It could be a copy / paste error when writing the post, but no proof is shown (i.e. from sys.databases) that TRUSTWORTHY is currently OFF, or that the author's code wasn't working prior to creating that Login and granting that permission to it.
So, I just tried this by installing the most recent build of FSharp.Core – 4.1.2 – and here is what I found:
Confirm that TRUSTWORTHY is OFF (i.e. 0) via:
SELECT [name], is_trustworthy_on FROM sys.databases WHERE [database_id] = DB_ID();
Attempt to load FSharp.Core as SAFE, just to see if it works:
USE [TestDB];
CREATE ASSEMBLY [FSharp.Core]
FROM N'C:\path\to\project\packages\FSharp.Core.4.1.2\lib\net45\FSharp.Core.dll'
WITH PERMISSION_SET = SAFE;
That receives the following error:
Msg 6211, Level 16, State 1, Line 32
CREATE ASSEMBLY failed because type 'Microsoft.FSharp.Collections.FSharpMap`2' in safe assembly 'FSharp.Core' has a static field 'empty'. Attributes of static fields in safe assemblies must be marked readonly in Visual C#, ReadOnly in Visual Basic, or initonly in Visual C++ and intermediate language.
Attempt to load FSharp.Core again, but as UNSAFE:
USE [TestDB];
CREATE ASSEMBLY [FSharp.Core]
FROM N'C:\path\to\project\packages\FSharp.Core.4.1.2\lib\net45\FSharp.Core.dll'
WITH PERMISSION_SET = UNSAFE;
That works. But, I didn't set the Database to TRUSTWORTHY ON, nor did I create a Login and grant it the EXTERNAL ACCESS ASSEMBLY permission. Meaning: the violation is probably found via a run-time verification instead of a load-time verification. And I have no way to test beyond this part, but I would expect that an error will occur.
If an error does occur regarding the UNSAFE Permission Set for this Assembly, then you can handle that without resorting to setting TRUSTWORTHY ON, but you will need to create a Certificate in master and a Certficate-based Login:
USE [master];
CREATE CERTIFICATE [FSharpCert45]
FROM EXECUTABLE FILE =
N'C:\path\to\project\packages\FSharp.Core.4.1.2\lib\net45\FSharp.Core.dll';
CREATE LOGIN [FSharpLogin45] FROM CERTIFICATE [FSharpCert45];
GRANT UNSAFE ASSEMBLY TO [FSharpLogin45];
IF your Assembly is also required to be marked as UNSAFE, then you can create an Asymmetric Key from the DLL in master and then a Key-based Login from that Asymmetric Key, and then grant that Key-based Login the UNSAFE ASSEMBLY permission. (this assumes that your Assembly is signed -- and protected with a password)
Of course, all of the above assumes that you can get the DLL onto the server or at least onto a share that the SQL Server service account has access to, and you did mention wanting to deploy this via hex bytes. That should be possible by doing:
In Visual Studio, under "References" in the "Solution Explorer", go to the "Properties" for FSharp.Core and set Model Aware to True and Permission Set to Unsafe. This will cause the publish process to include the DLL in the build script.
If the DLL is already in your target DB, then it probably won't generate the CREATE ASSEMBLY statement for this Assembly since publish scripts are incremental changes. If this is the case, then go to the project properties, and under Project Settings, check the box for Create script (.sql file) (if not already checked). This will cause the build process to always produce a _Create.sql script, and in there will definitely be the CREATE ASSEMBLY statement for FSharp.Core.
That CREATE ASSEMBLY [FSharp.Core] FROM 0x... statement will obviously be used to load the Assembly into the target DB (i.e. where your Assembly is also getting loaded into).
That CREATE ASSEMBLY [FSharp.Core] FROM 0x... statement will also be your ticket to creating the objects in master as follows:
USE [master];
CREATE ASSEMBLY [FSharp.Core]
FROM 0x4D....
WITH PERMISSION_SET = UNSAFE;
CREATE CERTIFICATE [FSharpCert45]
FROM ASSEMBLY [FSharp.Core];
DROP ASSEMBLY [FSharp.Core];
CREATE LOGIN [FSharpLogin45] FROM CERTIFICATE [FSharpCert45];
GRANT UNSAFE ASSEMBLY TO [FSharpLogin45];
This worked for me on SQL Server 2012, the only difference being I used the file path instead of the hex bytes.

How to find the assembly registered in SQL Server?

i have an assembly registered in SQL Server:
CREATE ASSEMBLY [CLRFunctions]
AUTHORIZATION [dbo]
FROM 0x4D5A90000300000...
WITH PERMISSION_SET = SAFE
How can i find the path to the this assembly?
It is not an assembly reference in SQL Server, the assembly is actually loaded in the database. Therefore there isn't a typical "path".
If you're looking for a SQLPS (PowerShell) path then it'd be:
SQLSERVER:\SQL\YourServerName\YourInstanceName\Databases\YourDatabaseName\Assemblies\
The deprecated (as of the release of SQL Server 2005 which introduced SQLCLR) extended stored procedure API / feature (i.e. XPs) did point to external DLLs. This meant that they could get deleted and were not included in backups of the database. With SQLCLR, the assemblies are imported into the database and can be accessed via sys.assembly_files. Having the assemblies contained within the database guarantees that they are included in all DB backups (among the other benefits of not magically disappearing or being replaced without your knowledge, etc).
Execute the following to see what assemblies you have loaded, their original paths (only if they were loaded from an external DLL and not from a VARBINARY literal / hex bytes), and their full contents/bytes:
SELECT asm.[name] AS [Assembly], afl.[name] AS [PathOrAltName], afl.[content]
FROM sys.assembly_files afl
INNER JOIN sys.assemblies asm
ON asm.[assembly_id] = afl.[assembly_id]
ORDER BY asm.[name];
If the assembly was loaded from a VARBINARY literal / hex bytes (i.e. 0x4D5A9000...), then the [name] column in sys.assembly_files should be the same as the [name] column in sys.assemblies (which is the name used in the CREATE ASSEMBLY statement).
For more information on working with SQLCLR in general, please visit: SQLCLR Info

CLR Assembly says it can't find a referenced assembly that already exists in the database

I have a CLR project that references an external assembly. I created the referenced assembly first as follows:
CREATE ASSEMBLY [GraphClient]
FROM 'C:\Users\rknight\Desktop\GraphServerClientProject\GraphServerClient\GraphClient\GraphClient\bin\Debug\GraphClient.dll'
WITH PERMISSION_SET = UNSAFE
Then in my CLR project I was able to reference it just fine under the "SQL Server" tab. Built the CLR project and it compiles with no errors. But when I create the new assembly I get an error:
CREATE ASSEMBLY [GraphCLR]
FROM 'C:\Users\rknight\Desktop\GraphServerClientProject\GraphServerClient\GraphClient\GraphCLR\bin\Debug\GraphCLR.dll'
WITH PERMISSION_SET = UNSAFE
Msg 10301, Level 16, State 1, Line 1
Assembly 'GraphCLR' references assembly 'graphclient, version=0.0.0.0, culture=neutral, publickeytoken=null.', which is not present in the current database. SQL Server attempted to locate and automatically load the referenced assembly from the same location where referring assembly came from, but that operation has failed (reason: 2(The system cannot find the file specified.)). Please load the referenced assembly into the current database and retry your request.
I had this problem and I eventually worked it out. I was referencing an x86 assembly on a 64 bit server. I rebuilt the referenced assembly as Any CPU, installed in on the server, re-added the reference to the project, rebuilt my project as Any CPU, and then SQL Server could resolve the reference and install the assembly.
A message along the lines of "You're referencing an assembly that's built for the wrong platform" would have been rather useful :)
This should work. Are you positive GraphClient is successfully loaded before the GraphCLR deployment is attempted? Instead of relying on the database project to deploy correctly I would first manually load the dlls in the right order, then if that works go back and mess with the project to ensure the dependencies are correct and deployment is ordered correctly.
If that doesnt help, have you tried setting trustworthy on to eliminate any obscure permissions issues?

Resources