0x80090020 when attempting to load a .PFX Private Key Certificate into a CAPICOM_MEMORY_STORE using Store.Load() or Certificate.Load() using CAPICOM 2.1.0.2

System Requirements:

  • Windows Server 2008, R2
  • Windows Vista
  • Windows 7
  • Windows 8, 8.1
  • 7.0, 7.5, 8.0
  • ASP 3.0 (Classic)
  • CAPICOM 2.1.0.2

The Problem:

Ah encryption, that most noble of things. One thing that is sure to drive every developer close to the brink on the odd occasion. The one time where clear, concise API documentation should be considered mandatory – and the one place where good API documentation it seems is an obligation itself not to provide. Be it Microsoft, Java, BouncyCastle, PHP it would seem they are all blighted with the same issue.

Attempting to use legacy API on an unsupported platform should seem like an exercise in masochism, however, you know how much I like to avoid using .net whenever I can.

If you attempt to do this

Dim cert
set cert = Server.CreateObject("CAPICOM.Certificate")
call cert.load("c:\myPrivateKey.pfx", "test", CAPICOM_KEY_STORAGE_EXPORTABLE)

or this

const CAPICOM_MEMORY_STORE = 0
const CAPICOM_LOCAL_MACHINE_STORE = 1
const CAPICOM_STORE_OPEN_READ_WRITE = 1
const CAPICOM_KEY_STORAGE_EXPORTABLE = 1Dim store
set store = Server.CreateObject("CAPICOM.Store")
call store.Open(CAPICOM_MEMORY_STORE, "MemoryStore1", CAPICOM_STORE_OPEN_READ_WRITE)
call store.load("c:\myPrivateKey.pfx", "test", CAPICOM_KEY_STORAGE_EXPORTABLE)

you will get back

error '80090020'
/file.asp, line ###

If you send in a .cer file instead of a .pfx, it works without error but doesn’t allow you to access the Private Key.

More Info

Taking the two code samples in order

Dim cert
set cert = Server.CreateObject("CAPICOM.Certificate")
call cert.load("c:\myPrivateKey.pfx", "test", CAPICOM_KEY_STORAGE_EXPORTABLE)

Should you be getting a 0x80070056 error, your password is wrong. If the file doesn’t have a password, only send parameter 1 (which is about to cause you a problem). To resolve the 0x80090020 error while using a CAPICOM_MEMORY_STORE, you need to stop CAPICOM from attempting to insert the certificate as a resource for a user. If the IIS worker process that you are using doesn’t connect to a user account and has no permissions, the default parameter CAPICOM_CURRENT_USER_KEY or 0 will throw 0x80090020.

To change the scope, ensure that you use the fourth parameter and set the value to CAPICOM_LOCAL_MACHINE_KEY.

const CAPICOM_CURRENT_USER_KEY = 0
const CAPICOM_LOCAL_MACHINE_KEY = 1Dim cert
set cert = Server.CreateObject("CAPICOM.Certificate")
call cert.load("c:\myPrivateKey.pfx", "test", CAPICOM_KEY_STORAGE_EXPORTABLE, CAPICOM_LOCAL_MACHINE_KEY)

To resolve the second issue, modify the original code to make use of the now fixed certificate.load() call and import it vie the long route.

const CAPICOM_MEMORY_STORE = 0
const CAPICOM_LOCAL_MACHINE_STORE = 1
const CAPICOM_STORE_OPEN_READ_WRITE = 1
const CAPICOM_KEY_STORAGE_EXPORTABLE = 1Dim cert
Dim store
set store = Server.CreateObject("CAPICOM.Store")
call store.Open(CAPICOM_MEMORY_STORE, "MemoryStore1", CAPICOM_STORE_OPEN_READ_WRITE)set cert = Server.CreateObject("CAPICOM.Certificate")
call cert.load("c:\myPrivateKey.pfx", "test", CAPICOM_KEY_STORAGE_EXPORTABLE, CAPICOM_LOCAL_MACHINE_KEY)

call store.add(cert)

If you receive 0x80070005, you are either getting an Access Denied error to the MEMORY_STORE or you are attempting to import a certificate into the instantiated store which already exists. Similarly, if you receive 0x80070056, your password is wrong.

“Cannot connect to Primary Server” from Mac OS X clients running Sophos Anti-Virus 8.x after the Enterprise Console has been updated to distribute Anti-Virus 8/9 for OS X via a HTTP connection served through IIS 6, 7, 7.5, 8

System Requirements:

  • Sophos Enterprise Console 5.2.1
  • Mac OS X 10.4+

The Problem:

If you have been deploying Sophos Enterprise Console 5 to update Mac OS X using a HTTP connection, end devices may start refusing to connect to the Primary server. The Sophos Anti-Virus 8 log will state that it was unable to connect to the server.

Windows clients can update successfully from the same server over HTTP.

More Info

In this particular case, the HTTP distribution point was backed from a public facing web server running IIS 7.5 under Windows Server 2008 R2. The server has an encrypted tunnel connection and read-only pass through authentication to a SMB share on an internal security server running Windows Server 2008 SP2 and Sophos Enterprise Console 5.2.1.

The SMB share is the same as the one exposed to the internal LAN for direct SMB updating and Windows clients using either HTTP or SMB will update successfully.

Mac OS X 10.7, 10.8 or 10.9 clients were however locked at Anti-Virus 8.0.5 and were only receiving definition updates from the secondary server at Sophos. The client will connect to the Primary HTTP share and begin to download, but terminate after a few kilobytes have been transferred.

The Fix

Somewhere between 8.0.5 and the current 9.0.5, there would appear to have been a change in the internal structure of the Sophos Anti-virus .mpkg.

Enable directory browsing and test that you can open the following file:

/SophosUpdate/CIDs/S000/ESCOSX/Sophos Anti-Virus.mpkg/Contents/_CodeSignature/CodeDirectory

Note that CodeDirectory is a file and not a folder. This is the root of the problem.

Under the default metabase configuration in IIS, IIS will only serve files with known extensions and registered MIME types. So what happens with file with no file extension? By default a 404 error.

Under IIS 6

  1. Right click your servicing web site in IIS manager and choose Properties
  2. Go to the HTTP Headers tab and choose MIME Types
  3. Click New…
  4. In Extension type:
    .*
  5. In MIME type type:
    application/octet-stream
  6. Commit all changes

Under IIS 7

  1. Select the servicing web site in IIS manager
  2. Choose MIME Types under the IIS heading
  3. Click Add… in the top right
  4. In File name extension type:
    .*
  5. In MIME type type:
    application/octet-stream

Under IIS 7.5 / 8

  1. Select the servicing web site in IIS manager
  2. Choose MIME Types under the IIS heading
  3. Click Add… in the top right
  4. In File name extension type:
    .
  5. In MIME type type:
    application/octet-stream

Under IIS 7, 7.5, 8 you may also need to add the following to your root Web.config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<security>
<requestFiltering>
<fileExtensions allowUnlisted="true" />
</requestFiltering>
</security>
</system.webServer>
</configuration>

“StartServiceCtrlDispatcher failed (error 6)” is returned from attempting to start SQL Server Agent and “System.NullReferenceException: Object reference not set to an instance of an object.” is returned when attempting to start SQL Server Agent in SQL Server Management Studio

System Requirements:

  • Microsoft SQL Server 2008

The Problem:

It’s another instance of a new SQL Server installation on a newly installed Windows Server system that refuses to do what it is supposed to do. It seems to me that this is the rule rather than the exception, but I digress.

If you pull up a command prompt and attempt to manually start the SQL Server Agent process e.g.

"F:\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Binn\SQLAGENT.EXE" -i MSSQLSERVER

You will receive

StartServiceCtrlDispatcher failed (error 6)

Similarly, if you attempt to start the SQL Server Agent inside SQL Server Management Studio you will receive the ubiquitous

See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.

************** Exception Text **************
System.NullReferenceException: Object reference not set to an instance of an object.

Server stack trace:
at Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.ObjectExplorer.FindObjectExplorerFrame()
at Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.ObjectExplorer.GetObjectExplorer(Boolean activateWindow)
at Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.ObjectExplorer.ShowError(Exception e)
at Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.Service.Start()
at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(RuntimeMethodHandle md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)

In addition if you check the SQL Server Logs, the current log for SQL Server Agent will be blank or will have nothing logged recently (this is important)

More Info

If you are seeing up to date events in the SQL Server Agent log, then this fix likely does not apply to your situation. If you have a blank or a stationary log file then chances are it does.

Basically, the SQL Server Agent is refusing to start because it cannot write TO the log file. Obviously it is extremely hard to have the process termination log or output that fact otherwise Microsoft would have done it already… sigh.

The Fix

It is probably either or both of:

  1. Check the error log file path for accuracy
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL10.MSSQLSERVER\SQLServerAgent
    Reg_SZ: ErrorLogFile
  2. Check the file / folder permissions for the path stated above, the SQLAGENT.OUT file and the SQLAGENT.# files. You can either reset them so that the SQL Server Agent’s process account has Full Control access or (depending on your logging policy) delete the files and SQL Server Agent will re-create the logs at startup

PEAR for PHP Error “No releases available for package “xxx” install failed” after running ‘pear install xxx’ on Windows Server 2008

System Requirements:

  • Windows Vista
  • Windows 7
  • Windows Server 2008, 2008 R2

The Problem:

You know that something a bit odd is going on when one of a batch of servers starts throwing errors that the others sailed past. In this case trying to configure PEAR for a new PHP install with Mail, Mail_Mime and Net_SMTP (pear.php.net/mail, pear.php.net/mail_mime and pear.php.net/net_smtp) should be fairly standard. The other servers took the install and even this server too Mail and Mail_Mime but would not accept Net_SMTP returning:

C:\Program Files (x86)\PHP>pear install net_smtp
No releases available for package “pear.php.net/net_smtp”
install failed

Leaving it overnight before rolling up my sleeves (in case it was just downtime at the package repository) the fix was fairly simple.

The Fix

If you are experiencing the same problem this server was having, running the following

pear remote-list

Will result in

SECURITY ERROR: Will not write to C:\Users\<user[8.3]>\AppData\Local\Temp\pear\cache\e9b88593398eb79a9aa91024351d646arest.cacheid as it is symlinked to C:\Users\<user>\AppData\Local\Temp\pear\cache\e9b88593398eb79a9aa91024351d646arest.cacheid – Possible symlink attack

If you get something akin to the above simply browse to:

C:\Users\<user>\AppData\Local\Temp\

and delete the pear folder