How code push notifications on the iPhone 3.0

July 15th, 2009 by Richard No comments »

I recently spent an entire evening trying to get this to work within an App and then post the message from my PHP application to Apple’s service.

First up you must create a CSR using your private key, you must have done this before to even be using the SDK so I’ll skip over it.

Login to the Apple Dev Center then to the iPhone Developer Program Portal.

Click on App IDs and add a New App ID.

  1. You need to create an App ID without wildcard in the Program Portal (that means one cert for one app.  They explain how to do this in the portal)
  2. Generate a certificate signing request from your Mac’s keychain and save to disk
  3. Upload the CertificateSigningRequest.certSigningRequest to the Program Portal
  4. Wait for the generation of cert (about 1 min). Download the certificate (aps_developer_identity.cer) from the Program Portal (and also the distribution certificate if you wish too, we’ll deal with just the developer identity for this)
  5. Keep the 2 files (steps 2 and 4) in a safe place. You might need the CertificateSigningRequest.certSigningRequest file to request a production cert in the future or renew it again.
  6. Import the aps_developer_identity.cer to the keychain. Then you have to export these new cert and the private key of this cert (not the public key) and saved as .p12 files.
  7. Then you use these commands to generate the cert and key in Mac’s Terminal for PEM format (Privacy Enhanced Mail Security Certificate)
    openssl pkcs12 -clcerts -nokeys -out certificate.pem -in cert.p12
    openssl pkcs12 -nocerts -out key.pem -in key.p12
  8. The certificate and private key files are used by your software to communicate with APNS
  9. You might want to remove the passphrase from the private key (you don’t have to do this but it makes it slightly more complicated in your code). To do this
    openssl rsa -in key.pem -out key.unencrypted.pem

    Then you’ll need to generate a single .pem file combining your certificate and key files

    cat certificate.pem key.unencrypted.pem > apnsdev.pem

So copy the generate apnsdev.pem file to your server and then you can setup your PHP application to push notifications to your iPhone.

$deviceToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; // masked for security reason
// Passphrase for your private key
// $pass = '';

$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'apnsdev.pem');
// assume the private key passphase was removed.
// stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);

$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
if (!$fp) {
  print "Failed to connect $err $errstr\n";
}
else {
  print "Connection OK\n";
  $payload = '{"aps":{"badge":' . $number . '}}';
  $msg = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;
  print "sending message :" . $payload . "\n";
  fwrite($fp, $msg);
  fclose($fp);
}

Note: if as a developer you install your app with your developer provision profile you’ll have to use the sandbox to communicate with your phone, you won’t be able to use the production push servers without the distribution profile

So that’s stage one, how to configure your web server with PHP to push to an iPhone, but how does the App actually register itself for push and secondly how do you get the device token to your server?

In XCode, in AppDelegate.m

- (void)applicationDidFinishLaunching:(UIApplication *)application {

 // This tells APNS that you wish to receive both Badge notifications and sound
 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
}

Then we can make two delegate functions in AppDelegate.m too

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  NSLog(@"deviceToken: %@", deviceToken);
  [self sendToMyServer:deviceToken];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
  NSLog(@"Error in registration. Error: %@", error);
}

You’ll need to create a function for ’sendToMyServer’ and deal with the deviceToken, such as convert it to a string, etc. But essentially that is how you deal with push notifications on your iPhone!

Update: Oh and if you get the error

Warning: stream_socket_client() [function.stream-socket-client]: Unable to set local cert chain file `apnsdev.pem'; Check that your cafile/capath settings include details of your certificate and its issuer in /Library/WebServer/Documents/notifyTest/anps.php on line 33

or similar, the chances are you’ve exported the wrong certificate and/or key from your OS X Keychain

adLDAP 3.2

June 26th, 2009 by Richard No comments »

Over the past few weeks I’ve been hacking to bits adLDAP to suit my own needs.  Of course I’ve contributed those findings back to the community in the adLDAP library at http://adldap.sourceforge.net

Version 3.2 of adLDAP has a lot more under the skin than would first imply by the version number.  Firstly in version 3.0 I made adLDAP truly PHP 5.x only with protected configuration variables.  However in adLDAP 3.2 I’ve allowed overloading with getters and setters that I’ve previously blogged on.

I’ve also added new computer information functions, I’ve also created a connect and disconnect function.  The intention is to allow changing connection details mid script.  The constructor and destructor normally handle the connections and disconnections but there might be a need to change certain connection properties mid-script and that is the point of these new functions.

I’ve also added a new folder_list() function.  This function will deliver a list of objects, whether they be OU’s, users, groups, etc in a specific OU.  With this function I believe you could effectively deliver a web based Active Directory User’s and Computers application.

See http://adldap.sourceforge.net/wiki/doku.php?id=api for more information.

It’s The Only Language They Understand

June 10th, 2009 by Richard No comments »

I’m going to repost Iain Dale’s blog post on the Tube strike in it’s entirety as it sums up everything you need to know about the strike.

Did you have trouble getting to work this morning? If so, spare a thought for those poor, downtrodden train drivers. You know, the ones who earn more than nurses. Who earn more than paramedics. Who earn more than most teachers, or NHS dentists.

They are demanding a pay rise of 5% and a guarantee of no redundancies. Transport for London and Boris Johnson must not give in to the bully boy tactics of Bob Crow and his henchmen. They give trade unionism a bad name. Every year, Crow brings his lackies out on strike. If it isn’t about pay it’s for some spurious reason about health and safety at work.

Did you know newly qualified drivers get 8 weeks paid holiday? And one of the reasons for this strike is that TFL sacked a driver for opening his doors on the wrong side and then lying about it, while a second driver was sacked for theft. Why on earth would people go on strike in support of people like that?

If this were any other industry, most of these drivers would have been sacked by now. It’s time Peter Hendy grew a backbone.

NB The average salary of a train driver is: £37,231. This is MORE than a paramedic (£21,720), a nurse (23,044), a secondary school teacher (£31,340), and even a dentist (£31,747). Hattip TrueBlueBlood.

Getters and Setters in PHP?

May 30th, 2009 by Richard 1 comment »

This is the question I’ve been pondering this week.

In older versions of PHP other than to keep code neat there was no real need for this functionality, but with PHP 5 you can declare access properties for variables and functions in classes.  In other OO languages, such as C# we’ve been used to it for a long time.  In traditional OOP, if we wanted to get or set an object’s private member, we would need to write a public method to do the job.
The reason behind making a member data private and then accessing it through a public method is to avoid the implementing-user to access it directly.  There can be many reasons for prohibiting direct access to member data to the implementing-code.

PHP traditionally has a weak type system, a further check of the data type may be necessary. PHP 5 and C# .NET have a getter and setter method feature, making it look like we’re accessing the data member directly.

For instance in PHP

class Circle
 {
        private $radius; # integer
        # Constructor
        public function __construct($radius = 15)
         {
                self::__set('radius', $radius);
         }

        # Setter
        public function __set($name, $value)
         {
                switch ($name)
                 {
                        case 'radius':
                          if (!is_numeric($value)) # is_int() for strict type checking
                           throw new Exception('Radius must be of a numeric type');
                          if ($value < 10 || $value > 500)
                           throw new Exception('Radius must be within the range of 10 - 500');
                          $this->radius = $value;
                        break;
                        default:
                          throw new Exception("Attempt to set a non-existing property: $name");
                        break;
                 }
         }

        # Getter
        public function __get($name)
         {
                if (in_array($name, array('radius')))
                 return $this->$name;

                switch ($name)
                 {
                        default:
                          throw new Exception("Attempt to get a non-existing property: $name");
                        break;
                 }
         }

 }

$c = new Circle();
$c->radius = 25;
echo $c->radius;

The problems with this method are two fold. Firstly, because PHP is a weakly typed language you can’t really guarantee that the set and get are in the right format so you have to handle that in the __set and __get functions, and secondly you would be able to set or get any private variable in that class.

Based on the second point, is it therefore worth actually defining a manual setter and getter for each private variable you want to allow access to? For example:

class test {
	private $count;
	public function setCount( $value )
	{
		$this->count = $value;
	}
	public function getCount()
	{
		return $this->count;
	}
}

Because if we use this method we could actually check in the setter if the variable is_int($value) and throw an exception if it isn’t.

My question is, based on the fact that traditionally PHP is a weakly typed language, is it worth

  • using the traditional OO format of getters and setters __get and __set
  • is it worth declaring your own get and set public functions for only specific variables you want to allow
  • or is it worth just making the variable public and setting it directly from outside the class e.g.
class testClass {
    public $count;
}
$myclass = new testClass();
$myclass->count = 1;

The reason I ask is that is that I’m considering how to handle getters and setters in adLDAP. adLDAP is a PHP library that I’m one of two developers maintaining. This is an open source library that provides Microsoft Active Directory integration over LDAP for PHP scripts, such as creating user accounts, Exchange mailboxes, managing groups and authentication, etc.

The library currently has private member variables for things such as the domain controller, a domain admin username and password, ssl settings, etc. The __construct function also allows these to be set through an array passed to it. However I have the need to actually disconnect from my domain controller, change a property and re-connect again. So my reason for this post is, what’s the best way to handle these getters and setters based on my three choices above?

.NET installers

May 26th, 2009 by Richard No comments »

Setup ScreenIt’s always been one of the most important, yet often overlooked part of a Windows application, the installation process.

I started off in Visual Studio using the default setup process project and for the most part it worked absolutely fine. In VS2005 I’d build my project, I’d create a setup.exe wrapper around my MSI, then bundle it in a self extracting zip file to launch setup.exe. That worked for me and I liked the setup.

Then came Visual Studio 2008 and that all changed. Microsoft didn’t seem to change too much in the setup process yet I was finding my setup projects were crashing constantly and consistently. I discovered that with the 2008 setup system the .exe wrapper was calling the msi and immediately exiting allowing the .msi to carry on. Yet the WinZip self extracting .exe tool was waiting for the .exe to finish before cleaning up the files. Effectively as soon as setup.exe finished, WinZip deleted the .msi even if it was still being used.

After hours of research I couldn’t find a way to change this so I decided to look for decent applications out there that not only would replicate what the Visual Studio setup project would do, but actually enhance it.

My requirements were pretty straight forward.

  1. It must detect pre-requisites such as .NET Framework, screen resolutions, etc
  2. Allow me to put custom settings in the registry or shortcut folders
  3. Allow me to create custom components and features that the user can toggle those features on or off
  4. I wanted to be able to associate file extensions with my applications
  5. I wanted to be able to perform actions after an installation or in uninstall (such as add a component to the Visual Studio toolbox)

Nice to haves would be to allow me to have licensing integrated at the installer level rather than the application level, customising the interface, etc

My research led me to a number of applications, but the only one that grabbed me was an application called Advanced Installer by Caphyon.

Advanced Installer

This software comes in a number of different versions, most notably a free version too.  I elected for the professional version though but the comparisons are available from their website.

What amazed me about this software was it was so simple to use and build my installer yet the interface to do so was very straight forward, including a number of built in wizards for creating shortcuts, file extension associations, etc.

So much so that I migrated all of my Windows apps to Advanced Installer as soon as I could.

The current version, just released, is version 7.0, which includes an installer for the Windows Mobile Platform.  For me this release is going to solve a problem I hadn’t even researched.  Basically I am currently developing a lightweight app for Windows that I have thought in passing would be perfect for Windows Mobile too, yet I hadn’t actually thought how to deploy for Windows Mobile as I’ve never written a Windows Mobile app before.

So into my Inbox this morning, pops an email from Caphyon telling me about version 7.0 and it’s new features.  I haven’t tested this feature yet, but if it works as well as the rest of the application does, this is going to solve hours or even days in working out how to deploy my applications on the Windows Mobile Platform.

I’m looking forward to their new GUI interface enhancements to the end-user installation screens as well as the MSIE 8 detection. The one other feature that I’m looking forward to is, in version 7.0 they have added a feature to allow detection of free ports on the PC on installation.  This will solve many issues with connectivity that user’s face in their own apps all the time!

Basically guys, if you want a decent installer for Windows applications, and you don’t want to spend a fortune, there is only one way to go… Advanced Installer.

How to truely make a PictureBox background transparent

May 26th, 2009 by Richard No comments »

Recently I wanted to overlay a PictureBox over the top of a WebBrowser control in C# for Windows Forms. I added a transparent PNG to a PictureBox and set the Background to transparent.

However the problem with this approach is the Background of the PictureBox isn’t truely transparent, it simply inherits the background colour or background image of the control in the layer beneath it.

So in Visual Studio I have the following (note the scroll bar at the bottom right hand corner which can’t be seen or accessed due to the image overlaying it)

untitled-1

However I found a small function that will take the colour of the PictureBox at pixel position x=0, y=0 (which in my image happens to be transparent and apply that to all other transparent elements.

public static System.Drawing.Drawing2D.GraphicsPath Transparent(Image im)
        {
            int x;
            int y;
            Bitmap bmp = new Bitmap(im);
            System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
            Color mask = bmp.GetPixel(0, 0);

            for (x = 0; x <= bmp.Width - 1; x++)
            {
                for (y = 0; y <= bmp.Height - 1; y++)
                {
                    if (!bmp.GetPixel(x, y).Equals(mask))
                    {
                        gp.AddRectangle(new Rectangle(x, y, 1, 1));
                    }
                }
            }
            bmp.Dispose();
            return gp;

        }

Then in your form load event handler

System.Drawing.Drawing2D.GraphicsPath gp = Resources.Images.Transparent(pictureBox1.Image);
pictureBox1.Region = new System.Drawing.Region(gp);

And voila, when you compile your application you'll get

untitled-2

Installing a SSL certificate on your Domain Controller

May 12th, 2009 by Richard No comments »

We’ve recently had the need to install an SSL certificate on our Domain Controllers.  Without SSL you cannot change Active Directory passwords or create user accounts (with a password) over LDAP.

There are two Microsoft Documents that help this process along

  1. A KB article entitled “How to enable LDAP over SSL with a third party certification authority
  2. A TechNet article “Advanced Certificate Enrollment and Management

Certificate Authority

In the first instance, we are installing a standalone CA (certificate authority) and a seperate Windows Server 2008 system.

Generate the Request

On the Domain controller we create a file called request.inf

;----------------- request.inf -----------------
[Version]
Signature="$Windows NT$
[NewRequest]
Subject = "CN=<DC fqdn>" ; replace with the FQDN of the DC
KeySpec = 1
KeyLength = 1024
; Can be 1024, 2048, 4096, 8192, or 16384.
; Larger key sizes are more secure, but have
; a greater impact on performance.
Exportable = TRUE
MachineKeySet = TRUE
SMIME = False
PrivateKeyArchive = FALSE
UserProtected = FALSE
UseExistingKeySet = FALSE
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = PKCS10
KeyUsage = 0xa0
[EnhancedKeyUsageExtension]
OID=1.3.6.1.5.5.7.3.1 ; this is for Server Authentication
;-----------------------------------------------

From the command line we then run

certreq -new request.inf request.req

A file called request.req is created

Change the Request Settings

We then copy the request.req file over to the CA.  This is where things get more complicated.

Again from the command line we need to run

certreq -attrib "CertificateTemplate:DomainController" request.req

This will give us a request ID, this is important, make a note of it.

The next stage mentions we need to copy the .asn file from the domain controller to the CA.  Hang on a moment, what .asn file and where is it?

Microsoft gloss over this and it took us around 2 hours to find the answer to this, it’s mentioned in Appendix 2, basically create and run this vbs script and it will create your .inf and your .asn files for you.

Set oArgs = WScript.Arguments
Set oShell = WScript.CreateObject("WScript.Shell")
'
' Parse command line
'
if oArgs.Count < 1 then
    sTemplateName = "DomainController"
    sType = "E"
else
    if ((oArgs(0) = "-?") or (oARgs.Count < 2)) then
        Wscript.Echo "Usage: reqdccert.vbs [Templatename] [Type]"
        Wscript.Echo "[Templatename] is the name of a V2 template"
        Wscript.Echo "[Type]         can be E for Email and A for Authentication certificate"
        Wscript.Echo "If no option is specified, the DomainController certificate template is used."
        Wscript.Quit 1
    else
        sTemplateName = oArgs(0)
                sType = oArgs(1)
    end if
end if
Set oFilesystem = CreateObject("Scripting.FileSystemObject")
Set objSysInfo = CreateObject("ADSystemInfo")
Set objDC = GetObject("LDAP://" & objSysInfo.ComputerName)
sGUID = objDC.GUID
sDNShostname = objDC.DNShostname
sHostname = objDC.cn
'##############################################################################
'
' Create the ASN.1 file
'
'##############################################################################
Dim aASNsubstring(2, 5)
Const HEX_DATA_LENGTH = 1
Const ASCIIDATA = 2
Const HEXDATA = 3
Const HEX_BLOB_LENGTH = 4
Const HEX_TYPE = 5
aASNsubstring(0, ASCIIDATA) = sDNShostname
aASNsubstring(0, HEX_TYPE) = "82"
'
' Convert DNS name into Hexadecimal
'
For i = 1 to Len(aASNsubstring(0, ASCIIDATA))
    aASNsubstring(0, HEXDATA) = aASNsubstring(0, HEXDATA) & _
                                    Hex(Asc(Mid(aASNsubstring(0, ASCIIDATA), i, 1)))
Next
aASNsubstring(0, HEX_DATA_LENGTH) = ComputeASN1 (Len(aASNsubstring(0, HEXDATA)) / 2)
'
' Build the ASN.1 blob for DNS name
'
sASN = aASNsubstring(0, HEX_TYPE) & _
       aASNsubstring(0, HEX_DATA_LENGTH) & _
       aASNsubstring(0, HEXDATA)
'
' Append the GUID as other name
'
if (sType = "E") then
    aASNsubstring(1, HEXDATA) = sGUID
    aASNsubstring(1, HEX_TYPE) = "A0"
    aASNsubstring(1, HEX_DATA_LENGTH) = ComputeASN1 (Len(aASNsubstring(1, HEXDATA)) / 2)
    sASN = sASN & _
           "A01F06092B0601040182371901" & _
           aASNsubstring(1, HEX_TYPE) & _
           "120410" & _
           aASNsubstring(1, HEXDATA)
end if
'
' Write the ASN.1 blob into a file
'
Set oFile = oFilesystem.CreateTextFile(sHostname & ".asn")
'
' Put sequence, total length and ASN1 blob into the file
'
oFile.WriteLine "30" & ComputeASN1 (Len(sASN) / 2) & sASN
oFile.Close
'
' Use certutil to convert the hexadecimal string into bin
'
oShell.Run "certutil -f -decodehex " & sHostname & ".asn " & _
                                       sHostname & ".bin", 0, True
'
' Use certutil to convert the bin into base64
'
oShell.Run "certutil -f -encode " & sHostname & ".bin " & _
                                    sHostname & ".b64", 0, True
'##############################################################################
'
' Create the INF file
'
'##############################################################################
Set iFile = oFilesystem.OpenTextFile(sHostname & ".b64")
Set oFile = oFilesystem.CreateTextFile(sHostname & ".inf")
oFile.WriteLine "[Version]"
oFile.WriteLine "Signature= " & Chr(34) & "$Windows NT$" & Chr(34)
oFile.WriteLine ""
oFile.WriteLine "[NewRequest]"
oFile.WriteLine "KeySpec = 1"
oFile.WriteLine "KeyLength = 1024"
oFile.WriteLine "Exportable = TRUE"
oFile.WriteLine "MachineKeySet = TRUE"
oFile.WriteLine "SMIME = FALSE"
oFile.WriteLine "PrivateKeyArchive = FALSE"
oFile.WriteLine "UserProtected = FALSE"
oFile.WriteLine "UseExistingKeySet = FALSE"
oFile.WriteLine "ProviderName = " & Chr(34) & _
                "Microsoft RSA SChannel Cryptographic Provider" & Chr(34)
oFile.WriteLine "ProviderType = 12"
oFile.WriteLine "RequestType = PKCS10"
oFile.WriteLine "KeyUsage = 0xa0"
oFile.WriteLine ""
oFile.WriteLine "[EnhancedKeyUsageExtension]"
oFile.WriteLine "OID=1.3.6.1.5.5.7.3.1"
oFile.WriteLine "OID=1.3.6.1.5.5.7.3.2"
oFile.WriteLine ";"
oFile.WriteLine "; The subject alternative name (SAN) can be included in the INF-file"
oFile.WriteLine "; for a Windows 2003 CA."
oFile.WriteLine "; You don't have to specify the SAN when submitting the request."
oFile.WriteLine ";"
oFile.WriteLine "[Extensions]"
iLine = 0
Do While iFile.AtEndOfStream <> True
    sLine = iFile.Readline
    If sLine = "-----END CERTIFICATE-----" then
        Exit Do
    end if
    if sLine <> "-----BEGIN CERTIFICATE-----" then
        if iLine = 0 then
            oFile.WriteLine "2.5.29.17=" & sLine
        else
            oFile.WriteLine "_continue_=" & sLine
        end if
        iLine = iLine + 1
    end if
Loop
oFile.WriteLine "Critical=2.5.29.17"
oFile.WriteLine ";"
oFile.WriteLine "; The template name can be included in the INF-file for any CA."
oFile.WriteLine "; You don't have to specify the template when submitting the request."
oFile.WriteLine ";"
oFile.WriteLine ";[RequestAttributes]"
oFile.WriteLine ";CertificateTemplate=" & sTemplateName
oFile.Close
iFile.Close
'##############################################################################
'
' Create the certreq.exe command-line to submit the certificate request
'
'##############################################################################
Set oFile = oFilesystem.CreateTextFile(sHostname & "-req.bat")
oFile.WriteLine "CERTREQ -attrib " _
                 & Chr(34) & "CertificateTemplate:" & sTemplateName _
                 & Chr(34) & " " & sHostname & ".req"
'
' The GUID structure needs to be reconstructed. The GUID is read
' as a string like f4aaa8576e6828418712b6ca89fbf5bc however the
' format that is required for the certreq command looks like
' 57a8aaf4-686e-4128-8712-b6ca89fbf5bc. The bytes are reordered
' in the following way:
'
'                            11111111112222222222333
'             Position 12345678901234567890123456789012
'                      |------|--|--|--|--------------|
' Original GUID:       f4aaa8576e6828418712b6ca89fbf5bc
'
'                            11 1 1111 1112 222222222333
'             Position 78563412 1290 5634 7890 123456789012
'                      |------- |--- |--- |--- |----------|
' Reformatted GUID:    57a8aaf4-686e-4128-8712-b6ca89fbf5bc
'
oFile.WriteLine "REM "
oFile.WriteLine "REM !!! Only valid for Windows 2003 or later versions !!!"
oFile.WriteLine "REM If you do not specify certificate extensions in the *.INF file"
oFile.WriteLine "REM they can be specified here like the following example"
oFile.WriteLine "REM "
oFile.WriteLine "REM CERTREQ -submit -attrib " _
                 & Chr(34) & "CertificateTemplate:" & sTemplateName _
                 & "\n" _
                 & "SAN:guid=" _
                 & Mid(sGUID, 7, 2) _
                 & Mid(sGUID, 5, 2) _
                 & Mid(sGUID, 3, 2) _
                 & Mid(sGUID, 1, 2) & "-" _
                 & Mid(sGUID, 11, 2) _
                 & Mid(sGUID, 9, 2) & "-" _
                 & Mid(sGUID, 15, 2) _
                 & Mid(sGUID, 13, 2) & "-" _
                 & Mid(sGUID, 17, 4) & "-" _
                 & Mid(sGUID, 21, 12) _
                 & "&DNS=" & sDNShostname & Chr(34) & " " & sHostname & ".req"
oFile.Close
'##############################################################################
'
' Create the certificate verification script
'
'##############################################################################
Set oFile = oFilesystem.CreateTextFile(sHostname & "-vfy.bat")
oFile.WriteLine "certutil -viewstore " & Chr(34) & objDC.distinguishedname & _
                "?usercertificate" & chr(34)
oFile.Close
'##############################################################################
'
' Compute the ASN1 string
'
'##############################################################################
Function ComputeASN1 (iStrLen)
    If Len(Hex(iStrLen)) Mod 2 = 0 then
        sLength = Hex(iStrLen)
    else
        sLength = "0" & Hex(iStrLen)
    end if
    if iStrLen > 127 then
        ComputeASN1 = Hex (128 + (Len(sLength) / 2)) & sLength
    else
        ComputeASN1 = sLength
    End If
End Function

So now we have generated a .req and a .asn file we can copy the .asn to the CA.  We actually used the .inf file created from this VBS script, but the contents look similar enough.

certutil -setextension <RequestID> 2.5.29.17 1 @<dcname>.asn

What Microsoft also doesn’t tell you here, is that if you are using Windows Server 2008, this command will not work unless you have loaded the command prompt with elevated priviledges (UAC). The subject alternative name, which is identified by the object identifier 2.5.29.17, is set with the attributes that are defined in the <dcname>.asn file. The fourth parameter that is set to “1” marks the extension as critical.

The TechNet ‘Processing Domain Controller Certificates‘ article mentions how to validate the certificate request is good, however we are assuming these tests come back as positive so next we need to issue and retrieve the certificate.

Retrieve the Certificate

From the CA now run

certutil –resubmit <RequestID>

and then finally

CERTREQ -retrieve <RequestID> <dcname>.cer <dcname>.p7b

You will now have a .cer and a .p7b file which you can copy back to the domain controller.

Install the Certificate

To install the certificate, from the command line on the domain controller

CERTREQ -ACCEPT <dcname>.p7b

Microsoft tells you to restart the Domain Controller.  In our experience this was not necessary and SSL over LDAP was available immediately

Test LDAP over SSL

After a certificate is installed, follow these steps to verify that LDAPS is enabled:

  1. Start the Active Directory Administration Tool (Ldp.exe).
  2. On the Connection menu, click Connect.
  3. Type the name of the domain controller to which you want to connect.
  4. Type 636 as the port number.
  5. Click OK

Update:  I’ve just updated the adLDAP Wiki documentation to reflect this.

Pirate Bay founders genius idea

May 11th, 2009 by Richard No comments »

Found via Dizzy

The Pirate Bay founders have come up with an genius idea to get their 30million SEK fine paid, which they’ve said they won’t pay.

The plan involves all internet users to pay a small, tiny amount to the law firm that prosecuted them and represnted the music industry..  Basically everyone sends an electronic transfer to their bank account, suggested 1 SEK (which is about $0.13 USD).  Apparently the law firm’s bank account is only allowed 1000 electronic transactions before it starts to cost them, the account holder money.

The best part is that after that 1000 transactions, the fee for each transaction is… 2 SEK! Therefore after those 1000  SEK, if people send just 1 SEK it will cost the law firm more than the money they receive to process, yet in the process no-one will have broken the law!

MPs fleecing us for all we have

May 9th, 2009 by Richard No comments »

So not only are they content with taxing us to the hilt, now they’ve decided that we should pay for everything they need to buy, including all their food!

Read this in the Telegraph, and we can see

In response to this newspaper’s disclosures about the routine abuse by MPs of their second home allowance, the House of Commons authorities last night asked the police to investigate – not the wrong-doing of Members of Parliament, but how the information exposing it was leaked. If evidence were needed that parliament simply fails to understand the deep anger felt in the country about the tawdry goings on at the Palace of Westminster, then this, surely, is it.

Now on to some of the claims themselves

Barbara Follett, the Minister for Tourism, claimed more than £25,000 in expenses for security patrols at her central London home, because she said she did not feel safe there. Not only is Mrs Follett married to a multi-millionaire author and, therefore, not short of money, but nobody forced her to live in a townhouse in Soho.

Next

Phil Hope, the minister in charge of community care. He claimed more than £37,000 in just four years to re-equip a flat that was arguably too small to contain all the items purchased. He also charged the taxpayer £120 for a barbecue – even though Commons rules say that MPs can only claim for the cost of maintaining a garden.

Next

Keith Vaz, the chairman of the Commons home affairs select committee, who lives in a £1.15 million house 12 miles from Parliament, but also claims for a second home in Westminster. Mr Vaz moved his designated second home to a property in his Leicester constituency for one year only, claiming £20,000 during that time, before once again making his Westminster flat his second home. Will he resign? 

Next

Phil Woolas, the Immigration Minister, trying to stop Gurkhas settling in the UK. He has claimed for nappies and women’s clothes, even though the rules state clearly that personal items such as toiletries will not be reimbursed, nor items bought for anyone else

I’m sure that members of all parties will be exposed as milking the system, but just because technically the rules have not been broken does not make the system morally acceptable.

Quite simply, anyone who has de-frauded the public, must resign with immediate effect, it’s the only way the reputation of politicians in the UK can be saved.

If you tried to do what our MPs have done in any other career, you’d be sacked, quite rightly and probably arrested for fraud. Do you think that’ll happen here?  I seriously doubt it, after all our MPs make the laws!