Tuesday, November 2, 2010

How to use certificate from disk with MS CryptoAPI

This article describes, how to digitaly sign data using a certificate which is stored outside the Windows Certificate Store. So it may be distributed as external file or is hardcoded into your application.

Provided code samples are for demonstration purposes only and are not intended to be used in a production system - you should at least add proper error handling and release allocated memory.

Preparing key-pair with self-signed certificate

A key-pair can be generated using the OpenSSL. List of commands used for generation follows, many special articles with details how to generate certificate can be found on internet, so I don't mention any details about it here. On the projects website you can find also links to binaries for appropriate platform.
  • Generate private key of desired length (1024 bits)
    openssl genrsa -des3 -out server.key 1024
  • Create request for self-signed certificate
    openssl req -new -key server.key -out server.csr
  • Remove password from the private key
    openssl rsa -in server.key -out server2.key
  • Self-sign the certificate request (-days is expiration in days)
    openssl x509 -req -days 365 -in server.csr -signkey server2.key -out server.crt
  • Convert output to PKCS#12 format which we can use in code (-keysig parameter allows us to use key-pair for signing)
    openssl pkcs12 -export -in server.crt -inkey server2.key –keysig -out c:\mykey.p12

Signing data

Final solution is quite easy as you can see in the code below. The only important thing is, that your key-pair must be saved in PKCS#12 form (.p12 extension).
CRYPT_DATA_BLOB data;

// load key-pair from disk to memory. This can be quite
// easily changed to have key-pair hardcoded
FILE *fIn = fopen("C:\\mykey.p12", "rb");
fseek(fIn, 0, SEEK_END);
data.cbData = ftell(fIn);
fseek(fIn, 0, SEEK_SET);
data.pbData = (BYTE *)malloc(pData.cbData);
fread(data.pbData, 1, pData.cbData, fIn);
fclose(fIn);

// Convert key-pair data to the in-memory certificate store
// If the P12 file is protected with a password, pass it to
// the function    
HCERTSTORE hCertStore = PFXImportCertStore(&data, L"P12ExportPassword", 0);

// If in-memory certificate store wasn't initialized, try
// empty password (NULL has different meaning than empty string)
if (!hCertStore)
  hCertStore = PFXImportCertStore(&data, L"", 0);
if (!hCertStore)
  hCertStore = PFXImportCertStore(&data, NULL, 0);

// Find the certificate in P12 file (we expect there is only one)    
PCCERT_CONTEXT hContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);

BOOL bFreeHandle;
HCRYPTPROV hProv;
DWORD dwKeySpec;
// acquire private key to this certificate, returned hProv handle must be closed
// if bFreeHandle is TRUE    
BOOL bResult = CryptAcquireCertificatePrivateKey(hContext, 0, NULL, &hProv, &dwKeySpec, &bFreeHandle);

const char szBuffToSign[] = "Hello world!";    
DWORD dwSize = 0;
And now, based on our needs sign data as a message, which allow us to include selected certificates:
CRYPT_SIGN_MESSAGE_PARA p;
memset(&p, 0, sizeof(CRYPT_SIGN_MESSAGE_PARA));
p.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
p.dwMsgEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
p.pSigningCert = hContext;
p.HashAlgorithm.pszObjId = szOID_OIWSEC_sha1;
p.cMsgCert = 1;
p.rgpMsgCert = &hContext;
    
DWORD dwSizes[] = {
                    strlen(szBuffToSign)
                  };

const BYTE *byMessageArray[] = { 
                    (const BYTE *) szBuffToSign
};

bResult = CryptSignMessage(&p, FALSE, 1, byMessageArray,  dwSizes, NULL, &dwSize);
    
BYTE *pBuff = (BYTE *) malloc(dwSize);
memset(pBuff, 0, dwSize);
bResult = CryptSignMessage(&p, FALSE, 1, byMessageArray, dwSizes, pBuff, &dwSize);
Or generate a has from data and sign this hash:
HCRYPTHASH hHash;
CryptCreateHash(hProv, CALG_SHA1, NULL, 0, &hHash);
CryptHashData(hHash, (const BYTE *)szBuffToSign, strlen(szBuffToSign), 0);    
CryptSignHash(hHash, AT_SIGNATURE, "", 0, NULL, &dwSize);

BYTE *pBuff = (BYTE *) malloc(dwSize);
memset(pBuff, 0, dwSize);
CryptSignHash(hHash, AT_SIGNATURE, "", 0, pBuff, &dwSize);

Links

Friday, August 27, 2010

How to remove items from Collection using lambda expression

Usefull extension method which allows removal of all items in ObservableCollection based on lambda expression.

It can be modified for any type of collection which allows access to items using indexer (including arrays).

public static class ObservableCollectionExtensions
    {
        public static void RemoveAll(this ObservableCollection items, Func match)
        {
            for (int i = items.Count - 1; i >= 0; i--)
            {
                if (match(items[i]))
                {
                    items.RemoveAt(i);
                }
            }
        }
    }

Now you can easily remove any items from collection by calling:
collection.RemoveAll(ii => ii.State == ObjectState.Deleted);

Thursday, July 22, 2010

Zkušenosti s Thule Euroclassic G5 909

Zkušenosti

Zadní nosič kol na tažné zařízení Thule Euroclassic G5 909 používáme s Citroenem Berlingo First koupeným v ČR včetně tažného zařízení.
Původně jsem ještě zvažoval obdobné zařízení Atera Strada, ale prodavač z obchodu níže mě nakonec přesvědčil, že  lepší je Thule.
Dosavadní zkušenosti jsou vskutku výborné a celkově můžu jen a jen doporučit (v e-shopu jsem měl navíc možnost nosič zadělat na auto ještě před koupí).
Před koupí je však potřeba zvážit, kde se bude nosič skladovat.
Výhody
  • Rozšiřitelnost o 4 kolo.
  • Opravdu snadná montáž (žádné šmrdlání ráčnou apod.). Nosič se položí na kouli a přitáhne se pákou.
  • Díky sklopné funkci, je možné i u našeho Citroen Berlinga pootevřít zadní dveře (dvojdílné otevírané do stran).
  • Nezvyšuje výšku vozidla, není tedy nutné hlídat výšku tunelů, podjezdů, vjezdů do podzemních garáží atd.
  • Snadná a rychlá montáž kol.
  • Konstrukční rychlost 130km/h, v podstatě neovlivňuje jízdní vlastnosti vozidla-
Nevýhody
  • Neskladnost a váha celého nosiče (a vzhledem k jeho ceně ho nechci nechávat ve sklepě či garáži našeho domu).
  • Problém se třetí SPZ. Používám "náhradu", neboť třetí SPZ u nás není možné získat. Problém s policií jsem zatím neměl.
  • Pro české tažné zařízení je třeba použít redukci zásuvky. Tato bohužel prodlužuje značně zástrčku a zvyšuje náchylnost na "nefunčknost" světel na nosiči.

Náhradní díly

Bohužel po pár měsících používání jsem si "blbě" nacouval do auta stojícího za námi. Při prvním pohledu jsem nosič zcela odepsal.

Nakonec jsem ale zjistil, že díky promyšlené konstrukci to není tak zlé. V podstatě došlo pouze k prohnutí jednoho z příčných nosníků na kola a rozlomení plastového rámečku levého světla.
Kontaktoval jsem tedy prodejce (fima Omnipuls). Překvapila mě jak ochota a vstřícnost ohledně objednání nového dílu tak i jeho cena (rámeček stál pouze 440,- Kč).
Po domluvených 14 dnech skutečně dorazil, zástupce prodejce mě kontaktoval a rámeček jsem bez problémů druhý den vyzvedl.
Nutno podotknout, že náhradní rámeček obsahoval také kompletní příslušenství potřebné pro jeho montáž (šrouby a nýt).

Reference

Nosič jsme zakoupili u firmy Omnipuls, s.r.o., Hradec Králové (http://www.stresni-nosice.cz).

Wednesday, July 21, 2010

DbKeeperNet 1.4.1.1 Released

Abstract

Another version of this very useful component which will help you in managing relational database schema changes and database schema distribution was just now released.

What is new

There are following changes in the project:
  • Oracle support (tested on version 10g)
  • New precondition DbTriggerNotFound (supported only on Oracle and MsSQL)
  • New Oracle specific precondition OraDbSequenceNotFound
  • IDatabaseService interface extended by TriggerExists() method contract
Files are available for download on Google Code: http://code.google.com/p/dbkeepernet/downloads/list

How to use it

To enable DbKeeperNet within your project:
  1. Download the engine
  2. Update your App.Config (or Web.Config)
  3. Prepare your database update script (check the sample projects within the source package)
  4. Add following 8 lines of code to enable the DbKeeperNet within your project (the code below should be part of an installation procedure):

    using (UpdateContext context = new UpdateContext())
    {
       context.LoadExtensions();
       context.InitializeDatabaseService(connString);
    
       Updater updater = new Updater(context);
       updater.ExecuteXmlFromConfig();
    }
    

References

Thursday, July 1, 2010

Running ASP.NET websites on Apache 2.2

Motivation

I was running a VPS hosting for a few years. The problem with it is lack of latest technologies I would to play with. And of course - as we have the hosting mainly for fun I would not pay a lot.
Originally the VPS was preinstalled with .NET 2.0 framework. During years I have upgraded it to .NET 3.5 but at the end I was almost out of free space and I was still missing upgraded SQL Server.
So I was thinking how to solve it. At home I had an old notebook with installed Windows XP Professional.
Unfortunatelly on Windows XP can't be hosted multiple domains under built-in IIS server.
When I was testing the module, I have found that there is a problem with support of multiple cookies set from ASP.NET application. Fortunatelly there is also a patch available for it - but you must recompile the mod_aspdotnet module.

Prerequisities

System setup

  • Windows XP SP2
  • MS SQL Express 2005
  • Apache 2.2
  • Mail Enable SMTP server
  • 2 domains, 5 subdomains (ASP.NET 2.0 applications and MVC 1.0 applications)

Apache installation

I installed Apache using it's default settings with the only one exception - I enabled development components for installation. It was because I was recompiling mod_aspdotnet module.

Module compilation

I recompiled the mod_aspdotnet because of a bug in support of multiple cookies. Here is available patch for this bug, but at the meantime it wasn't integrated into the sources.

Installation is quite simple. In the root of the source tree is available a batch file () which will show you how to manually install the compiled binaries.

Apache configuration

Apache configuration is very simple and straightforward - an example which allows multiple virtual servers and Microsoft MVC for ASP.NET follows (more information can be found on the modules home page):
LoadModule aspdotnet_module modules/mod_aspdotnet.so 
LoadModule rewrite_module modules/mod_rewrite.so

AddHandler asp.net asax ascx ashx asmx aspx axd \ 
           config cs csproj licx rem resources resx \ 
           soap vb vbproj vsdisco webinfo 

AliasMatch /aspnet_client/system_web/(\d+)_(\d+)_(\d+)_(\d+)/(.*) "C:/Windows/Microsoft.NET/Framework/v$1.$2.$3/ASP.NETClientFiles/$4" 
<Directory "C:/Windows/Microsoft.NET/Framework/v*/ASP.NETClientFiles"> 
  Options FollowSymlinks 
  Order allow,deny Allow from all 
</Directory>

NameVirtualHost *

<VirtualHost *> 
  ServerAdmin admin@domain.net
  DocumentRoot c:/webroot/domain.net/test
  ServerName test.domain.net
  ErrorLog "logs/test.domain.net-error.log
  AspNetMount / "C:/webroot/domain.net/test"
# folders which shouldn't be handled thru Asp.net
# (see SetHandler in Directory definition)
  <Location ~ "/(Content|Scripts)">
    SetHandler None
  </Location>
  <Directory "C:/webroot/domain.net/test">
    RewriteEngine On 
    RewriteBase /
# redirect to the default location
    RewriteRule ^$ /Default.aspx [R=301]
# handle all files in directory thru the Asp.Net
    SetHandler asp.net
    Options FollowSymlinks Indexes
    AspNet All
    Order allow,deny
    Allow from all
    DirectoryIndex Default.aspx
  </Directory>
</VirtualHost>

References

Tuesday, June 29, 2010

PBNI and error PBX_E_GET_PBVM_FAILED

The error PBX_E_GET_PBVM_FAILED (code -12) occurs in my program when I was developing PBNI extension for PowerBuilder 9 on my Windows Vista 64bit and MS Visual Studio 2005 executed with administrator privileges and I was logged in as "normal" user.

All paths to my PBD's/PBL's in library list for CreateSession() method of the IPB_VM interface obtained from pbvm90.dll were defined to a substituted disk and they were not found under administrator context. When I updated paths to be correct under admin context, everything works fine.

Same error occurs in the case, when use use Unicode parameters for CreateSession() method of the IPB_VM interface for ANSI version of the method.

Sunday, June 27, 2010

Using SVN as source control for Sybase PowerBuilder

This article in short describes an idea how to use SVN for Powerbuilder to improve development process. This solution is based on previously used CVS (described in another article).
CVS we were are using for about 6 years and it was working perfectly.
But currently we have to change hardware and operating system it was running on, so we decided to move forward and use a bit better but still free solution - SVN running on Windows.

PBL problems

The main difficulty of the Sybase Power Builder is in PBL libraries. PBL libraries are binary libraries containing both - sources and precompiled sources.
This solution causes many problems:
  • PBLs are also very inclinable to faults (in Power Builder 7 it was not very surprissing that after fullrebuild failure were PBLs completely broken).
  • Object sources saved in PBLs are not easily comparable.
  • Also built-in support for inefficience (sources are checked-out to temporary PBL library, offline access is not very comfortable etc).
  • In the case of multiple developers working on the same project this causes many problems with sources synchronization (you can use many utilities, but it was always hell after one week track all changes and put them together - it tooks for about half a day per week and it was quiet often, that some changes were lost).

Solution

  • Use SVN as source control (you can use both *nix or Windows platform).
  • Use TortoiseSVN (or any other free SVN GUI clients) for access to sources.
  • Use Winmerge or any other free utility for sources differencies comparison.
  • Export all sources into SVN project source tree (the best way is to export every PBL library into the separate directory in the SVN source tree).
  • On building machine use PowerGen for project compilation and PBLs restore. In each build you can take your PBLs from the scratch (PowerGen can resolve all dependecies between objects and import them back into PBLs in the correct order).
  • Every developer takes fresh PBLs after every build.
  • Use existing Windows Domain authentication for access to SVN server.
  • Integrate with current project management system.

SVN server setup on Windows

  • Download Apache 2.2 installation MSI and install it (any examples will reffer to the default location)
  • Install module mod_auth_sspi
  • Download and install SVN. You have to choose correct version for Apache 2.2. I suggest to use MSI installation package, because it will setup all required paths etc.
  • Setup new SVN repository (svnadmin create c:/svnroot)
  • Restart computer, if necessary.
Apache 2.2 example configuration
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so
LoadModule sspi_auth_module modules/mod_auth_sspi.so

<location svn="">
   DAV svn
   SVNPath c:/svnroot

   AuthName "SVN Access"
   AuthType SSPI
   SSPIAuth on
   SSPIAuthoritative on
   SSPIOfferBasic on
   SSPIDomain ourdom.ourcompany
   require group "ourdom\development"
</location>

SVN repository organization

The SVN repository is organized a bit differently than in CVS. You can definitely find more details on Google. Below are only some details.

  • Each project consist of three subfolders, no sources should be commited directly under project name folder.
  • branching code means that you made a repository copy to a branch folder.
  • trunk folder - contains sources of the main branch.
  • branches folder - contains branch folders for branch copies.
  • tags folder - contains branch folders for tag copies.
Sample SVN repository structure>
MyProject
  +-- trunk
  +-- branches
     +-- fixes-1.3
     +-- fixes-1.5
  +-- tags
     +-- build-1.3.1
     +-- build-1.3.2
     +-- build-1.5.1
     +-- build-1.6.1

Editing sources

  • Every developer can take fresh PBLs generated by PowerGen after build.
  • Before change perform Update command on existing object.
  • Import this object from SVN sandbox into your work PBL (replacing existing one).
  • Perform any required changes.
  • Export modified object from working PBL to the SVN sandbox.
  • Execute Commit command on the exported object in SVN sandbox, provide proper comment and send it to the SVN source control.
  • You can also (and I strongly suggest this) perform commit on the entire SVN sandbox - this will send all modified files at once as single transaction. In history you can later see all files checked in as single commit.

Benefits

  • All sources are stored in plain text (including datawindows).
  • All changes are simply trackable (from Power Builder 9 (?8?) this works much better, because in previous versions Power Builder changes order of methods on every save) - at least you know who and why made the change.
  • You can simply resolve any conflicts (no more hell with sharing and synchronizing PBLs between developers).
  • PBLs can't contain any old errors from rebuilding etc.
  • You can also connect additional actions to every souce file commit/checkout/tag and automatically connect those into other company systems.
  • You can also use tags and branches for tracking your builds.
  • SVN checkins are tracked as transactions, in history you can directly see all files related to the commit.

Project Management System Integration

I found project CaptainHook on SourceForge which allows exactly what I wanted - creation of SVN server hooks using .NET code. So I made two simple plugins to it:

  • One which disallows commiting changes to the tag folder.
  • Second which tooks commit messages formatted same way as in CVS which exports information to the proprietaty project management system.

CVS to SVN migration

There are plenty of tools available for the repository migration from CVS to SVN. We have migrated a repository which had almost 1GB in CVS without any problems to our new SVN source control including tags and branches including the whole history of changes. Migration was running for about 12 hours.

Links

Friday, June 25, 2010

Using CVS as source control with Sybase PowerBuilder

This article in short describes, how to use CVS for Powerbuilder. This solution we are using for about 6 years and it works very good.

PBL problems

The main difficulty of the Sybase Power Builder is in PBL libraries. PBL libraries are binary libraries containing both - sources and precompiled sources.
This solution causes many problems:
  • PBLs are also very inclinable to faults (in Power Builder 7 it was not very surprissing that after fullrebuild failure were PBLs completely broken).
  • Object sources saved in PBLs are not easily comparable.
  • Also built-in support for inefficience (sources are checked-out to temporary PBL library, offline access is not very comfortable etc).
  • In the case of multiple developers working on the same project this causes many problems with sources synchronization (you can use many utilities, but it was always hell after one week track all changes and put them together - it tooks for about half a day per week and it was quiet often, that some changes were lost).

Solution

  • Use CVS as source control (use can use both *nix or Windows solution).
  • Use TortoiseCVS (or any other free CVS GUI clients) for access to sources.
  • Use Winmerge or any other free utility for sources differencies comparison.
  • Export all sources into CVS project source tree (the best way is to export every PBL library into the separate directory in the CVS source tree).
  • On building machine use PowerGen for project compilation and PBLs restore. In each build you can take your PBLs from the scratch (PowerGen can resolve all dependecies between objects and import them back into PBLs in the correct order).
  • Every developer takes fresh PBLs after every build.

Editing sources

  • Every developer can take fresh PBLs generated by PowerGen after build.
  • Before change perform Update command on existing object.
  • Import this object from CVS sandbox into your work PBL (replacing existing one).
  • Perform any required changes.
  • Export modified object from working PBL to the CVS sandbox.
  • Execute Commit command on the exported object in CVS sandbox, provide proper comment and send it to the CVS source control.

Benefits

  • All sources are stored in plain text (including datawindows).
  • All changes are simply trackable (from Power Builder 9 (?8?) this works much better, because in previous versions Power Builder changes order of methods on every save) - at least you know who and why made the change.
  • You can simply resolve any conflicts (no more hell with sharing and synchronizing PBLs between developers).
  • PBLs cann't contain any old errors from rebuilding etc.
  • You can also connect additional actions to every souce file commit/checkout/tag and automatically connect those into other company systems.
You can also use tags and branches for tracking your builds.

Links

Sunday, March 7, 2010

Intersection table

Common name for middle table allowing relation of type Many-to-Many.