Tuesday 16 December 2014

Allow non admin users to connect with OpenVPN client

On Windows OpenVPN creates VPN tunnels and then changes the routes to send all relevant traffic down the tunnel. This is a problem for normal user accounts which do not have permissions to change the routes. Even when a user is given this permission, processes they invoke are not granted this permission by default. The easiest way around this is to make the user an administrator on their machine and set the OpenVPN-Gui shortcut to run as an administrator - however this then gives the user account full admin access to the machine. Not something that is a good idea in many situations.

Most of the guides I found on the internet seemed to be geared towards people who had admin rights and just wanted to avoid the UAC prompt.

A workaround to this that allows "normal" users to use the OpenVPN clinet on Windows without disabling UAC or similar is described below:

First log in with an account that has admin rights and open a command prompt as an administrator. Give the user account permission to edit network settings by adding them to the "Network Configuration Operators" group:
net localgroup "Network Configuration Operators" <username> /add
Next we need to allow this user account to be used for batch services so that scheduled tasks in their name will run. Go to Start -> Run and type "gpedit.msc" then hit enter. Browse to the following entry and add the username of the VPN user.
Local Computer Policy -> Computer Configuration -> Windows Settings -> Security Settings -> Local Policies -> User Rights Assignment -> Log on as a batch job 
Finally create a task to start the VPN GUI shortly after the user logs on to the computer by opening "Task Scheduler" (Start -> Run -> taskschd.msc) and selecting "Create a task". This is the step that pulls the solution together as in scheduled tasks you can control the permissions that a task is run with, plus you can automate the startup.

  1. General Tab
    1. Name - Set to OpenVPN
    2. When running the task, use the following user account - set to the user who will be using the VPN
    3. Run only when user is logged in - select this
    4. Run with highest Privileges - select this
  2. Triggers Tab
    1. New Trigger
    2. Begin Task - At log on
    3. Specific User - Set to user who will be using VPN
    4. Delay task for - set to 30 seconds
  3. Actions Tab
    1. New Action, Start a program
    2. Browse to c:\program files\openvpn\bin\openvpn-gui
  4. Conditions Tab
    1. Start the task only if the computer is on AC power - DESELECT THIS or the VPN will only be available when laptop is plugged in
  5. Settings Tab
    1. No changes from defaults

Now test the connection by logging in as the user. The VPN client should automatically start in the system tray shortly after the user logs in and they should be able to bring up the VPN tunnel and access resources over it.

This guide was written based on a Windows 8.1 Pro laptop - it should also apply to Windows 7 but some of the screens might be slightly different. It was based partly on the more advanced solution at http://community.openvpn.net/openvpn/wiki/Nonprivileged - that will automatically do all the above for any user that logs on so is great for a machine many users could use, or an auto deployment system. As a one off for a single user it is more complicated than required though and the 3 steps above have the same end result.

Saturday 15 March 2014

Importing your existing GPG key into a Yubikey Neo using Linux

NOTE: Since July 2014 Yubico have been shipping the Neo with the required applets already installed. You should be able to skip the first half of this guide. I've left it up for anyone who wants to start using an older Yubikey.

The Yubikey Neo is a very interesting piece of kit. It can generate secure passwords on the press of a button via a USB connection or by swiping over a NFC sensor. This allows it to be used as a second factor authentication for a variety of websites and services like Lastpass. I've previously blogged about getting a Yubikey working to authenticate a VPN tunnel with Netscreen SSG Firewalls linked to Active Directory and use it to secure my Lastpass account. However it can also be used as a CCID virtual smartcard for encrypting files with GPG and authenticating SSH connections in a very secure manner. Because your private key is stored on the Yubikey Neo and can not be removed this means that you can use it in less secure environments without the risk of your private key itself being compromised.

There are already lots of good guides on the net regarding how to do this if you are happy to generate your private keys on the Neo itself however this has one big drawback (which is also one of the big security features). A private key cannot be removed from the Neo. This means that if you generate the key on the Neo itself and then lose the Neo you have lost your only copy of that private key. In many cases this is good - you do not want anyone to "borrow" your Neo and copy your private keys. Generating new Keys can be done relatively easily. However if you already have a private key that you use in secure environments but also want the ability to access it elsewhere (maybe you have a private key you use personally which you want to also use at work but all the system administrators at your work can access your work file system for example) then I have not seen many guides for importing existing keys to the Neo. Partly this is because the firmware that comes with the Neo only supports generating keys on the device not importing. Once you hit software that needs compiling a lot of assumed knowledge can get in the way. So for a full walk-through of adding an existing key to a Neo read on:

Initial Linux Setup

The first thing you will need to do is get a Yubikey Neo (Sorry, it has to be the Neo for now - other Yubikeys do not include the ccid/GPG abilities).

For this guide I started with a fresh install of Debian 7.3.0 64 bit from the netinstall image and then upgraded to testing (from Wheezy to Jessie). I did not install the Desktop or Print Server components during install but if you do this with a desktop installation then it should not make much difference. Any recent Linux distro should work but writing this guide from a fresh install means you can reproduce my steps exactly if required. I had multiple issues with Gnupg 2.0.19 which is the version in Debian Stable which is why I upgraded to Testing which has version 2.0.22 (improved support for card readers).

The first step is therefore to install Debian Stable and check internet access is working. To upgrade to Debian Testing edit /etc/apt/sources.list and change every instance of the word wheezy to jessie. Then start the upgrade - this step will take a while.
# apt-get update
# apt-get dist-upgrade
 - Accept warning about needing to uninstall a few packages that are blocking the upgrade, then later press q to close the screen of upgrade notices about various packages.
After upgrading I always prefer to reboot to ensure there are no unexpected issues that will appear next time I turn the machine on. There are then a few packages that you need to install from the repositories so you might as well get them all now:

To compile the new applet for installing on your Yubikey you will need:
# aptitude install openjdk-6-jdk ant
# aptitude install junit4
To compile the Yubikey Personalisation Tool you also need:
# aptitude install libyubikey-dev pkg-config libusb-1.0-0-dev libjson0-dev make
And to compile gpshell (for installing the new applet on the Neo) you need:
# apt-get install libpcsclite-dev zlib1g-dev libssl-dev
GPG version 2 is required for this:
# apt-get install gnupg2 scdaemon
Finally to actually access the card you need pcsc:
# apt-get install pcscd
Download the Java Card Classic Development Kit from http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javame-419430.html#java_card_kit-2.2.2-oth-JPR, then extract some of the files:
# mkdir jckit
# cd jckit
# unzip /path/to/java_card_kit-2_2_2-linux.zip
# cd java_card_kit-2_2_2/
# unzip java_card_kit-2_2_2-rr-bin-linux-do.zip

Compile the new Applet

Then you will need to download and compile an upgraded applet from https://github.com/Yubico/ykneo-openpgp/tree/features/jckit3. Download the applet source directly from https://github.com/Yubico/ykneo-openpgp/archive/master.zip, unzip and compile it.
# wget https://github.com/Yubico/ykneo-openpgp/archive/master.zip
# unzip master.zip
# cd ykneo-openpgp-master
# ant -DJAVACARD_HOME=/path/to/jckit/java_card_kit-2_2_2/
You should now have a cap file in the sub folder applet/bin/openpgpcard/javacard/openpgpcard.cap

Enable CCID mode on Neo

By default the Yubikey Neo does not have CCID smartcard functionality enabled, so that needs to be turned on. http://opensource.yubico.com/yubikey-personalization/

Note: If you want a slightly quicker way to do this then download the Windows version - it comes with a pre-compiled executable so you can jump straight to running the command.

# wget http://opensource.yubico.com/yubikey-personalization/releases/ykpers-1.15.0.tar.gz
# tar xvf ykpers-1.15.0.tar.gz
# cd ykpers-1.15.0
# ./configure
# make check install
# ldconfig
Plug in your Neo now - you are ready to enable the CCID functionality.
# ykpersonalize -m82
Confirm that you want to set mode 0x82 Take the NEO out and plug it back in to restart it in the new mode.

Install updated openPGP Applet on Neo

Download the gpshell, global platform and the gppcscconnectionplugin  from  http://sourceforge.net/projects/globalplatform/
# tar zxvf globalplatform-6.0.0.tar.gz
# cd globalplatform-6.0.0
# ./configure
# make
# make install
# cd .. 
# tar zxvf gpshell-1.4.4.tar.gz
# cd gpshell-1.4.4
# ./configure
# make
# make install
# cd .. 
# tar zxvf gppcscconnectionplugin-1.1.0.tar.gz
# cd gppcscconnectionplugin-1.1.0.tar.gz
# ./configure
# make
# make install

Unplug the Neo and plug it in again so it is detected correctly. Now you need to go back to the ykneo-openpgp-master folder (from when you compiled the applet) and install the applet on the Yubikey:
# LD_LIBRARY_PATH=/usr/local/lib gpshell gpinstall.txt
You should be rewarded with several screens of text rushing by.

Prepare GPG key and back it up

The Yubikey NEO can support GPG keys up to 2048 bit RSA - bigger keys will not fit. A lot of people store their main key offline and generate encryption and signing subkeys which they import onto a card for day to day use. This has the advantage that if the card is lost they can just generate new encryption and signing subkeys and their main GPG identity will not lose all the signatures which validate their real identity. Another advantage is that the main key can then be 4096 bits in strength (if you are that paranoid) and the subkeys only 2048 bit so they fit on the The certification part of the key is not present however so they will not be able to certify any other persons key is genuine without getting access to their main/full key.

By default GPG will create 2 keys - the first is used for signing (files) and certifying (other GPG keys). The second is used for Encryption. I'm going to create a new subkey for signing so only this goes onto the Yubikey. Gpg outputs a lot of text and this post feels big enough already so I'm going to skip most of the output - you will get far more on your screen than is shown here.

First to add a new signing key of 2048 bit size. My main key ID in this example is 3edda8ae - change this for your ID:
# gpg2 --edit-key 3edda8ae
pub  2048R/3EDDA8AE  created: 2014-03-14  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
sub  2048R/581671D8  created: 2014-03-14  expires: never       usage: E
[ultimate] (1). test key (test 2048R key) <[email protected]>
gpg> addkey
Please enter the passphrase to unlock the secret key: *****

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
Your selection? 4
What keysize do you want? (2048) 2048
Key is valid for? (0) 1y
Is this correct? (y/N) y
Really create? (y/N) y
pub  2048R/3EDDA8AE  created: 2014-03-14  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
sub  2048R/581671D8  created: 2014-03-14  expires: never       usage: E
sub  2048R/5B48E4AF  created: 2014-03-14  expires: 2015-03-14  usage: S
[ultimate] (1). test key (test 2048R key) <[email protected]>
You should now be able to see the extra line ending in "usage: S" to denote the signing only key. If you are using an existing key and the Encryption key is not shown as "sub 2048R" then you will need to create a new encryption subkey as above but choosing "RSA (encrypt only) as the type.

Final step before you move the keys to the Neo is to back them all up. If you do not want to trap your only copy of the private key on a Neo then back it up first! Once more because this step is important: BACK UP YOUR KEYS!
gpg> save
# gpg2 --export -a 3edda8ae >public_key_backup.key
# gpg2 --export-secret-key -a 3edda8ae > private_key_backup.key
# ls
private_key_backup.key      public_key_backup.key

Move these backup files somewhere safe - you do not want to accidentally overwrite or delete them. Next lets put the encryption subkey onto the Yubikey (you need to pulg the Yubikey in now if it is not already):

Move the keys to the Neo

# gpg2 --edit-key 3edda8ae
gpg> toggle
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb 2048R/581671D8 created: 2014-03-14 expires: never
ssb 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
(1) test key (test 2048R key) <[email protected]>
gpg> key 1
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb* 2048R/581671D8 created: 2014-03-14 expires: never
ssb 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
(1) test key (test 2048R key) <[email protected]>
gpg> keytocard
Please select where to store the key:
(2) Encryption key
Your selection?
2
Please enter the passphrase to unlock the secret key: *****
scdaemon[22389]: 3 Admin PIN attempts remaining before card is permanently locked
Please enter the Admin PIN: *****
writing new key
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb* 2048R/581671D8 created: 2014-03-14 expires: never
                                     card-no: 0000 00000001
ssb 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
(1) test key (test 2048R key) <[email protected]>
"key 1" selects the first subkey (it is shown with an asterisk). "keytocard" MOVES the selected subkey to the card after you have confirmed both the gpg pass-phrase as well as the card administrator pin. There is only one slot to store this kind of key so you need to choose option 2. Finally the keys are shown but with the encryption key having a card number underneath it to show it is no longer present on the computer.

Next we need to move the signing key to the NEO:
gpg> key 1
gpg> key 2
sec  2048R/3EDDA8AE  created: 2014-03-14  expires: never  
ssb  2048R/581671D8  created: 2014-03-14  expires: never  
                     card-no: 0000 00000001
ssb* 2048R/5B48E4AF  created: 2014-03-14  expires: 2015-03-14
(1)  test key (test 2048R key) <[email protected]>
gpg> keytocard
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1
Please enter the passphrase to unlock the secret key: *****
writing new key
sec  2048R/3EDDA8AE  created: 2014-03-14  expires: never  
ssb  2048R/581671D8  created: 2014-03-14  expires: never  
                     card-no: 0000 00000001
ssb* 2048R/5B48E4AF  created: 2014-03-14  expires: 2015-03-14
                     card-no: 0000 00000001
(1)  test key (test 2048R key) <[email protected]>
gpg> quit
Save changes? (y/N) y
"key 1" deselects the first (encryption) subkey, then "key 2" selects the second (signing) subkey. "keytocard" is used to MOVE the signing subkey to the NEO. Finally quit saving changes.

As a quick test remove the Neo. Encrypt a random file to this new key and then try to decrypt it - you will get an error:
# echo "my secret message" > test.txt
# gpg2 -r test -e test.txt 
# ls
test.txt      test.txt.gpg
# gpg -d test.txt.gpg 
gpg: pcsc_list_readers failed: unknown PC/SC error code (0x8010002e)
gpg: card reader not available
gpg: encrypted with 2048-bit RSA key, ID 581671D8, created 2014-03-14
      "test key (test 2048R key) <[email protected]>"
gpg: public key decryption failed: general error
gpg: decryption failed: secret key not available
 Now plug the NEO in again and run exactly the same command:
# gpg -d test.txt.gpg 
gpg: detected reader `Yubico Yubikey NEO OTP+CCID 00 00'
Please enter the PIN
Enter PIN:
*****
gpg: encrypted with 2048-bit RSA key, ID 581671D8, created 2014-03-14
      "test key (test 2048R key) <[email protected]>"
my secret message
The output at the end will be the secret message you added to test.txt. This would only be possible to decrypt with the NEO plugged in, as only a stub of the private encryption key is stored on the local hard drive.

You can now backup the private key from your computer (which only contains a stub of the full private key). This stub and the public key you saved earlier can be manually imported on any other computer without risking loss of control of your keys as you also need the Yubikey connected to use it.

From your working computer:
# gpg2 --export-secret-key -a 3edda8ae > private_key_backup_STUB.key
Copy those 2 files to another computer and import them with:
# gpg2 --import public_key_backup.key
# gpg2 --allow-secret-key-import --import private_key_backup_STUB.key
You can make life a bit easier in 2 ways. Firstly if you upload your key to a keyserver then you can automatically pull down the required files with this command (after plugging in the NEO):

# gpg2 --card-edit
gpg/card> fetch

If however you do not want to upload this key to the public keyservers you can upload it to a specific url and program the NEO to look there. The --armor switch below instructs gpg to only use a character set that is safe to use in emails (mail programs have a habit of treating some obscure characters inconsistently which is not good if those characters are in the middle of your key!

# gpg2 --armor --export 3edda8ae > public_key_armor.key

Upload this file to anywhere you control and make a note of the direct link to the file. I uploaded to my Dropbox account so for me the file was accessible at https://dl.dropboxusercontent.com/u/120364/public_key_armor.key. We need to add this link to the URL field of the NEO:
# gpg2 --card-edit
Application ID ...: D2760001240102000000000000010000
Version ..........: 2.0
Manufacturer .....: test card
Serial number ....: 00000001
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: 2048R 2048R 2048R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
Signature key ....: 26EF 14F4 A5B6 B24A 0EFE  E39C F5E2 68CB 5B48 E4AF
      created ....: 2014-03-14 16:56:48
Encryption key....: CFA0 0AE0 1C27 0463 36DE  2960 0FBF CAD4 5816 71D8
      created ....: 2014-03-14 16:22:28
Authentication key: [none]
General key info..:
pub  2048R/5B48E4AF 2014-03-14 test key (test 2048R key) <[email protected]>
sec   2048R/3EDDA8AE  created: 2014-03-14  expires: never  
ssb>  2048R/581671D8  created: 2014-03-14  expires: never  
                      card-no: 0000 00000001
ssb>  2048R/5B48E4AF  created: 2014-03-14  expires: 2015-03-14
                      card-no: 0000 00000001
gpg/card> admin
Admin commands are allowed
gpg/card> url
URL to retrieve public key: https://dl.dropboxusercontent.com/u/120364/public_key_armor.key
scdaemon[2887]: 3 Admin PIN attempts remaining before card is permanently locked
Please enter the Admin PIN :
gpg/card> quit
You can check this worked as expected by running gpg2 --card-status and checking the output now contains your URL. To make this a decent test I am going to delete the entire local public and private keyring files, then import the keys using the NEO and online public file before repeating the encryption test I performed earlier to prove decryption only works with the NEO installed. First to delete the local files:
# cd .gnupg/
:~/.gnupg# ls
gpg.conf  private-keys-v1.d  pubring.gpg  pubring.gpg~ random_seed  reader_0.status  secring.gpg  trustdb.gpg
:~/.gnupg# rm pub ring.gpg
:~/.gnupg# rm pubring.gpg~ :~/.gnupg# rm secring.gpg :~/.gnupg# rm trustdb.gpg 

Trying to list keys will now just show GPG creating new keyring files:
:~/.gnupg# gpg2 --list-keys
gpg: keyring `/root/.gnupg/pubring.gpg' created
gpg: /root/.gnupg/trustdb.gpg: trustdb created

Time to fetch the public key. Plug in the NEO and run the following commands:
:~/.gnupg# gpg2 --card-edit
gpg: keyring `/root/.gnupg/secring.gpg' created
scdaemon[3125]: reading public key failed: Card error
Application ID ...: D2760001240102000000000000010000
Version ..........: 2.0
<SNIP extra info>
Sex ..............: unspecified
URL of public key : https://dl.dropboxusercontent.com/u/120364/public_key_armor.key
Login data .......: [not set]
<SNIP extra info>
gpg/card> fetch
gpg: requesting key 5B48E4AF from https server dl.dropboxusercontent.com
gpg: key 3EDDA8AE: public key "test key (test 2048R key) <[email protected]>" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
gpg/card> quit

You can now try encrypting a message to your private key and it will only decrypt if the NEO is plugged in:
# echo "my secret message encrypted to NEO key" > test_file_Neo.txt
# gpg2 -r test -e test_file_Neo.txt
# gpg2 -d test_file_Neo.txt.gpg 
scdaemon[3285]: DBG: asking for PIN '||Please enter the PIN'
      "test key (test 2048R key) <[email protected]>"
my secret message encrypted to NEO key
Congratulations! Firstly for reading through everything above (assuming you didn't cheat and skip all the way down here!) You should now have a GPG key which you can use relatively easily on any computer with GPG but you do not need to place the private key on that computer. For me this means I can freely use my personal GPG key on work computers without any chance of losing control of a copy, but it could just as easily be that you want to protect your work GPG key when visiting client sites.

I have not tested this thoroughly on different distributions but as far as I know any distro with gnupg 2.0.22 available should also meet the other requirements. If you know of any distros that this will or will not work on then please let me know and I'll update this guide. Any questions please ask - I'll help if I can.

Changing the user and admin pin on the NEO

Use of the gpg key stored on the NEO requires you to enter a pin code (default is normally 123456). Getting the pin code wrong 3 times locks the user pin. The default admin pin is normally 12345678. Getting the admin pin code wrong 3 times will lock the card and cannot be reset. Make sure you remember these pin codes!

use the "gpg --change-pin" command and change both the user and admin pin to something you will remember:
# gpg2 --change-pin
gpg: detected reader `Yubico Yubikey NEO OTP+CCID 00 00'
gpg: OpenPGP card no. D2760001240102000000000000010000 detected
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Other things to do

There are several other things you should do to if you have not already:

Problems...

There are a few problems that are worth bearing in mind when following this guide depending on how secure you want your end result to be.

Randomness matters. A computer builds up a pool of entropy from various sources during use. This entropy is then used by /dev/random when anything needs random numbers - however on a clean install with no extra software running that has probably only just booted up there is not much entropy to go around. This could lead to weak keys being generated. A program like haveged may well eliminate this problem if you can not use a genuine hardware random number generator like the Entropykey (I know nothing about this project beyond the fact is looks cool and is reasonably cheap).

By using Debian Testing I am also using a system with less immediate security patching. Stable Debian receives security patches very quickly and Unstable Debian also receives them quickly (but then it receives everything quickly, including patches, new software and new bugs/security problems - that is why it is called "Unstable" Testing Debian tends to receive updates after they have been tested a for a while and have no known serious bugs so sometimes a security problem might be unpatched on Testing after both Stable has been patched and Unstable has received a newer version that also fixes the problem. Alternatives if you are concerned - gnupg 2.0.22 is not in Debian Backports so you could either manually install packages from the Debian Jessie repository or use a different distro with a later version of gnupg. Or compile gnupg from source if you were feeling adventurous.

I did all this as the root user. Normally bad but in my defense: A lot of this had to be done as root anyway, you need to trust the system you are generating the keys on completely (eg don't use if for browsing facebook!) and you have to trust the software you are installing completely. Since I'm using a fresh minimal install and not connecting to random internet sites the risks are minimized.

Troubleshooting

Yubikey Neo not recognised as a CCID device.

If you are using an older distro that does not fully recognise the Yubikey Neo as a ccid device then you need to take a few more steps:

A Debian Wheezy install I have been using does not know that the Yubikey can be a smart card. Not too hard to fix though: edit /etc/libccid_Info.plist. You need to add two lines at the top of 3 sections.
Find array ifdVendorID and add the following two lines at the top:
<string>0x1050</string>
<string>0x1050</string>
Find array ifdProductID and add the following two lines at the top:
<string>0x0111</string>
<string>0x0112</string>
Find array ifdFriendlyName and add the following two lines at the top:
<string>YubiKey Neo Composite</string>
<string>YubiKey Neo CCID</string>
Restart the service:
/etc/init.d/pcscd restart
Unplug and replug the neo and the output of dmesg should now include "Yubikey NEO OTP+CCID"


Guides used to create this guide:

Far too many web pages to list fully, but the main sources of information I used were:
https://github.com/Yubico/ykneo-openpgp
Yubico Forums eg: Adding the Yubikey Neo to known hardware (not required in the end as I switched to Debian Testing) http://forum.yubico.com/viewtopic.php?f=26&t=982&start=10#p3767
Creating subkeys and seperating out from the main key for security reasons: http://www.void.gr/kargig/blog/2013/12/02/creating-a-new-gpg-key-with-subkeys/
How to add GPG keys to cards: http://www.gnupg.org/howtos/card-howto/en/ch05.html

If you have any comments or suggestions then please let me know.

Wednesday 15 May 2013

Join Debian Wheezy to Windows Active Directory Domain

While looking for something to keep me busy on a quiet day I decided to work out how to get Debian 7 authenticating against our Active Directory domain. I have been doing this for a few years with our Redhat/CentOS systems but we have a few Debian boxes for variety and as they are small/unimportant/just keep ticking over without issues getting them on the domain has never been a high priority. For Redhat there is a very good and thorough guide HERE which does an excellent job of explaining the options and how to setup various configurations. By contrast this guide is far more focused on a single scenario and nowhere near as detailed - but it should contain everything required to get a fresh Debian Wheezy (7)  install authenticating users using Active Directory accounts as well as local accounts.

Other than authenticating against the Windows domain I also want to ensure that all domain users get the same UID/GID so that sharing files between systems is easier.

The first steps are to ensure that the time is correct on the servers and that DNS is working correctly.
# apt-get install ntp
edit /etc/netp.conf and set the server lines to point to the systems you want to use for time updates then restart ntp and check the current time is correct
# /etc/init.d/ntp restart
# date
Tue May 14 11:03:42 BST 2013

Check that the "hostname -f" command returns the correct fully qualified server host name. If not edit both /etc/hostname and /etc/hosts and then reboot. Also check that another host on your network can ping the machine by hostname and if not then fix your DNS server so it can.

Install samba and winbind:
#  apt-get install samba smbclient samba-common winbind
Start smb service and set it to start up on boot from now on:
# /etc/init.d/samba start
# update-rc.d samba enable

Install Kerberos, backup the original config file and then replace with minimal setup
# apt-get install krb5-user
# cp -p /etc/krb5.conf /etc/krb5.conf.orig
# vi /etc/krb5.conf
replace with the contents below, changing DOMAIN.COM for your domain and DC.DOMAIN.COM for your primary domin controller - if you have more than one domain controller you can have multiple kdc= lines.

[libdefaults]
 default_realm = DOMAIN.COM
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
[realms]
 DOMAIN.COM = {
  kdc = dc.domain.com
  admin_server = dc.domain.com
 }
[domain_realm]
 .domain.com = DOMAIN.COM
 domain.com = DOMAIN.COM
Clear anything cached and then try to get a kerberos ticket - the first klist should report no credentials, the second klist should show expiry dates for the user's kerberos ticket.
# kdestroy
# klist
# kinit [email protected]
# klist
Your machine can now get tickets from the AD domain successfully. Next we need to join the domain then enable this for login and then sort out the UID's so they match across servers.
# apt-get install libpam-krb5
# cp -p /etc/samba/smb.conf /etc/samba/smb.conf.orig
Now edit /etc/samba/smb.conf and make the following changes. If a variable is not in the config file then add it. ("domain logons = no" controls if this machine can authenticate users for other machines, not if domain users can logon here...):
[global]
workgroup = DOMAIN
security = ads
realm = domain.com
password server = dc.domain.com
domain logons = no
template homedir = /home/%D/%U
template shell = /bin/bash
winbind enum groups = yes
winbind enum users = yes
winbind use default domain = yes
domain master = no
local master = no
prefered master = no
os level = 0
idmap config *:backend = tdb
idmap config *:range = 11000-20000
idmap config DOMAIN:backend = rid
idmap config DOMAIN:range=10000000-19000000
And then comment out the entire [homes], [printers] and [print$] sections at the bottom (unless you plan to use them...)

Stop and restart the services:

# /etc/init.d/winbind stop
# /etc/init.d/samba restart
# /etc/init.d/winbind start
Then try to join the domain and test it is all working(replace dc with the hostname of your domain controller):
# net join -S dc -U administrator
# net ads testjoin
# net ads info
# wbinfo -u
# wbinfo -g
Check that the wbinfo commands show users and groups from active directory. For some reason my Winbind shuts down when i join a domain so I get an error "Error looking up domain users" - starting winbind again seems to fix this and it has not died for me since. Hopefully you have now joined the domain and if you look on your domain controller you should see the computer on the domain. Next we need to setup authentication so you can log in using domain credentials.


Edit /etc/nsswitch.conf to add winbind for looking up passwords and groups
# vi /etc/nsswitch.conf
passwd:    compat winbind
group:       compat winbind
shadow:    compat
And check that domain users and groups are returned by the following commands:

# getent passwd
# getent group 
Note that if you have a problem with these two getent commands not returning any domain level records check your smb.conf file for the idmap syntax - for some reason the version of the config file I received with samba had a different structure for the idmap line that stopped getent working. Entering it as shown above makes these two command work.

Finally set the system up to automatically create home folders for users when they first log on by adding the following two lines (if not already in the file).
# vi /etc/pam.d/common-session
session required pam_unix.so
session required pam_mkhomedir.so umask=0022 skel=/etc/skel

You should now be able to log in to the system using a domain username/password combination and a home folder will be automatically created for you on first logon. If the backend=rid part is working then the user ID on each system should be the same for all users making it easier to share files between machines. you can check the UID with the "id" command which will show the user id (UID), group id (GID) and all the groups that the current user is a member of.

My next steps are to add a domain administrators group to the visudo permissions file to allow jumping to root when required and then to block root access by ssh.

You can also now list windows fileshares with:

$ smbclient -L WindowsServer -k
and mount them with:
$ sudo mount ­t cifs //WindowsServer/Share /mnt/WindowsServerShare ­-o username=AD_UserName
Although this will only give you read only access unless you jump to root. Adding it to your fstab file will give you a more useable share.








Friday 22 March 2013

Create your own S/MIME email certificates with Openssl

Following on from creating my own Certificate Authority for signing internal https connections as covered in a previous post, the same Openssl CA can be used to create certificates for signing emails. This has many of the same benefits and limitations as self signed with SSL certificates for websites. On the plus side it is free and because you control it you can instantly create as many certificates as you desire. It is just as secure cryptographically as a certificate from a big player like Verisign. The negatives are that you will need to convince everybody you deal with to trust your certificates since they will not be automatically trusted and there is no insurance associated with them if something goes wrong. For internal use and testing they are therefore perfectly fine, for external customer facing use you are probably better off paying to get a certificate from one of the commercial players in the market.

Update the Certificate Authority for S/MIME

So assuming you have followed my previous guide and have a working Certificate Authority there is one change to make. Copy the openssl.cfn file to openssl-users.cnf, open the new file in a text editor and in the [ usr_cert ] section comment change the nsCertType as follows:
# nsCertType = server  # <---- comment out this line
nsCertType = client, email # <---- un-comment this line
Certs created will now be defaulting to client and email use so they can be used as part of  vpn or similar and also encrypt and sign emails.

Create Private Key and CSR

We can now create a private key and csr for the user in question:
$ openssl req -config openssl-users.cnf -new -newkey rsa:2048 -keyout private/Users_Name.key -out csr/Users_Name.csr -days 365
Note that the only difference here from my server key generation is that I have not added the -nodes command. This means that the private key will have a password on it that needs to be entered when used. My logic is that server keys are both on more secure machines and might need to reboot for updates on a schedule so requiring a password there might not be practical. For a users email key it will be on a normal workstation so more exposed to security risks and also you will always be there to enter the password since you will have just typed out an email!

Answer the wizard with the values you wish to have on your certificate. The "common name" should be your actual name and make sure the email address is exactly correct.

Create Certificate and Convert to PCKS12 Format

Next you need to sign the csr with the CA key:
$ openssl ca -config openssl-users.cnf -out certs/Users_Name.crt -infiles csr/Users_Name.csr
Check that the cert type is correct to make sure the config changes were done correctly. Next you need to convert this certificate into PCKS12 format so it can be used by email clients. This new file will contain the public certificate and private keys so it needs to be kept secure.
$ openssl pkcs12 -export -in certs/Users_Name.crt inkey private/Users_Name.key -out private/Users_Name.p12

Import Into Email Client

I'll leave this largely as an exercise for the reader because there are too many different email clients to choose from. The two main email clients I use are Outlook and GMail.

  • For Outlook just double click on the *.p12 file - Windows will automatically walk you through adding it to the correct certificate store and configure the security options for you.
  • For gmail it is currently not possible to use S/MIME encryption :( I am guessing that since their Postini service offers encryption they do not want to allow this competition. If you connect another mail client to GMail (Outlook/thunderbird etc) then you can set up the encryption there and it will work fine, it will just show garbage in the gmail web interface.
Remember after importing a certificate you will be able to sign email but not encrypt it! To encrypt email you need to get the public certificate of the person you want to send emails to. The easiest way to sent your public key to someone is to send them a signed email.

Wednesday 20 March 2013

Synology Self Signed SSL Certificates Invalid Cipher Type

UPDATE: The new version of Synology's DSM (version 4.2) does not have the problem discussed in this post - so the simple fix is to update your Synology to version 4.2 or above. An anonymous comment also suggests a quicker fix than mine that sounds good but since I've already upgraded to 4.2 I can not test it.

Recently I started signing my own SSL certificates for internal use at my company. One of the systems which refused to play nice with my certificates was a Synology DS412+ running version 4.1 of their DSM software. The Synology guides for creating a self signed certificate assume you will be happy creating the CA on the Synology itself, not using a self signed certificate created on another separate CA system. Since I already have my own private internal CA which is trusted on my domain this was not ideal for me. When trying to import the certificate I created on my private CA I received a very unhelpful error...
Illegal certificate
...with no clarification on what was wrong with it. My first breakthrough came when I noticed that my certificate has a block of human readable text at the top and certificates generated using the guide on the Synology Wiki did not. Removing all text in the .crt file above "-----BEGIN CERTIFICATE-----" solved this problem - it is a text file so can be edited easily with vi, notepad or any other basic text editor.

Unfortunately importing the certificate now gives a new error:
Invalid cipher type. Please use another certificate and private key.
Again, this left me stumped for a bit. I managed to get it working by using the following series of commands to generate the certificate signing request and sign it:
$ openssl genrsa -out private/synology.key 1024
$ openssl req -config -new -key private/synology.key -out csr/synology.csr
$ openssl ca -config openssl.cnf -out certs/synology.crt -infiles csr/synology.csr
However I am still no wiser as to why this works when replacing the first two lines with my normal way of generating csr's...
$ openssl req -config openssl.cnf -new -nodes -newkey rsa:1024 -keyout private/synology.key -out csr/synology.csr -days 365
fails... If anyone can shed any light on this I'd love to learn what is happening. As far as I can tell both options would create rsa 1024 bit csr's which is the obvious interpretation of "Invalid cipher" and both commands use the same config file for defaults and v3 extensions etc. At least its working now and hopefully this will let anyone with the same problem generate their own ssl certificates for Synology devices.

Monday 18 March 2013

Become Your Own SSL Certificate Authority

I have recently started signing my own SSL certificates for internal use at my company. I had several reasons to do this:

  • I was fed up of getting SSL warnings for every new system I deployed because of its self generated SSL certificates
  • I wanted to improve security and stop training myself and others to click "proceed to site" which for some was becoming an automatic reflex
  • I wanted to investigate the options for adding SSL certificates to things like VPN connections and direct access via IPv6
  • I was also interested in learning more about securing emails with SSL for identity verification etc although I'm currently more than happy with GPG it is not for everyone.
  • It sounded like a fun challenge
Please also note that I'm using the term "SSL" throughout this guide. SSL (Secure Sockets Layer) has now been depreciated and replaced with TLS (Transport Layer Security) however everyone still refers to TLS as SSL so that is what I'm doing in this guide. Certificates generated using OpenSSL as in this guide are TLS certificates and fully trustworthy which you can check by viewing the connection properties when you have applied a certificate to a server. See Wikipedia for more details on this.

In order for this to work I would need to create my own certificate authority and import that into all computers as trusted. Importing into computers can be done manually however since I have a windows domain it is easier to distribute the authority to all computers via GPO. Then I could start creating CSR's (Certificate Signing Requests) and signing SSL certs for the various systems around the company. First things first though I needed to create a Certificate Authority.

Choosing a Live Linux Distro

Conventional wisdom with Certificate Authorities is that it needs to be a dedicated machine that is not connected to any network. You can generate the keys as required on this machine and then copy them to a blank USB key which never returns to the dedicated box. In theory therefore the CA's key is only stored on a single machine that is not possible to hack into over the network and if it is compromised is not able to communicate anything confidential. In practice I have a few problems with this idea. Firstly it means you need to have a dedicated machine sitting somewhere taking up space. This machine needs to highly reliable since it will be important and probably left unused for long periods of time. You also need so make sure this machine is secure which adds overhead in the setup - decent password policy, physically securing it to make sure nobody gets near it, ensure that nobody decides to use it as a test machine for something because "it has not been touched in ages so can't be needed any more" etc. Finally you need to backup the ultra secret CA private key somewhere else anyway which leads to my solution.

I boot from a live Linux CD on a machine not connected to the network (in my case an old laptop with no hard drive). I have a pair of USB memory sticks that are only ever connected to this system (one live and one backup) for storing the private CA key and other required files and then use another blank memory stick to copy the signed SSL certificates to the relevant host. Effectively therefore my whole CA infrastructure is a simple USB memory stick which is easy to physically secure. Any time I need to use it I can get any suitable live Linux distro and boot on any isolated system. No need to worry about securing the machine I use since secret stuff is only stored in memory while the machine is on.

That said the first challenge was finding a live distro to use which already had an up to date OpenSSL installed and in a suitable working condition for running a CA since I did not really want to connect to the internet do download additional packages since that would probably weaken the overall security. Finding a list of packages included on live CD's proved easier than expected using the search at Distrowatch.  Distrowatch has a search page that lets you find distro's with a specific version of a package and also lists the package versions for each distro at the bottom of its page. Not ideal as for some it has an updated package in the current distro but the live image is much older.
  • Debian live 6.0.7 LXDE (openssl version 0.9.8o from June 2010 - typical of Debian's legendary release cycles)
  • Ubuntu 12.10 desktop (openssl version 1.0.1c)
  • Mageia 2 (openssl version 1.0.0j)
  • Fedora (openssl version 1.0.1c)
Since most live distro's seem to include Openssl the choice largely comes down to personal preference. I went with Ubuntu since it was one of the more up to date and I am most at home in Debian based systems but any of the above should work. Obviously you might hit some problems if you follow this guide exactly but use a different system as config files etc might be subtly different. Once you have decided on which distro to use you then need to get started on generating the root CA key and certificate. Watch out for keyboard layouts though - most live distro's default to US english layout which can cause chaos down the line with your password...


Creating a Certificate Authority

First you need to setup your working directories and Openssl config file:
$ mkdir CA
$ cd CA
$ mkdir certs crl newcerts private csr
$ touch index.txt
$ echo 1000 > serial
$ cp /usr/lib/ssl/openssl.cnf .
Now edit the openssl.cnf file and make the following change in the CA_default section: change "dir = ./demoCA" to "dir = . ". You can also change the defaults for country, company name etc if they will always be the same (search for countryName_default to jump to the right area of the config file).

By default certificates are created with permission to do everything EXCEPT code signing. Since all you probably want to do is connect via https securely it is also worth un-commenting this line in the [ usr_cert ] section:
nsCertType = server
Next generate the private RSA key for the CA with 4096 bits (should be enough for now, increase to match your levels of paranoia) Enter a strong password when prompted as this private key will be encrypted with tripple Des (-des3 switch)
$ openssl genrsa -des3 -out private/cakey.pem 4096
And then use this key to create the CA x509 certificate with a 10 year lifetime (or whatever you wish - since this cert should never leave the key generation system it is reasonably safe to give it a long lifetime). Enter the password you used for the key generation and then enter details for the certificate as prompted. This stuff will be visible in the final certs so don't put dummy data in there.
$ openssl req -new -x509 -extensions v3_ca -key private/cakey.pem -out cacert.pem -days 3650

Generate SSL certificates for servers

The CA is now setup and ready to go. Time to create a key and csr for a test server, this time only valid for 365 days as it will be more exposed to loss being on a server that is hosting a website. Again fill in the details with real data for the server you want the ssl cert for. Do not enter a challenge password here unless you want the server to prompt for an ssl certificate password on every reboot. This step can be completed on the server that needs the certificate rather than the CA system if preferred - you just need to copy the csr file (NOT the .key file) to the CA system in order to create the certificate. Note that if you do not do this on the CA server you probably want to omit the "-config openssl.cnf" bit from this command.
$ openssl req -config openssl.cnf -new -nodes -newkey rsa:2048 -keyout private/testserver1.key -out csr/testserver1.csr -days 365
Now you just need to sign the csr with the CA's private key (this step will need to be done on the CA system)
$ openssl ca -config openssl.cnf -out certs/testserver1.crt -infiles csr/testserver1.csr
You will now have the signed ssl certificate for the server in certs/testserver1.crt, the serial file will have been incremented by 1 and the index.txt file will have an entry for the certificate you just created.

Import the root CA certificate into your computers manually

This is nice and easy on windows - copy the cacert.pem file to your computer, rename it to cacert.crt and then double click on it. A wizard will step you through adding to the default certificate store and it will then be accessible by your web browsers (at least in Chrome and Internet Explorer - Firefox uses its own certificate store so you will need to import manually for that to work).

Import certificate into domain

I did this on my Server 2003 domain so it might be slightly different on newer server OS's. You can either re use an existing group policy or create a new one and apply it as required. In "Group Policy  Object Editor" browse to Computer Configuration --> Windows Settings --> Security Settings --> Public Key Policies --> Trusted Root Certification Authorities. Right click and choose "import" and you will get a very similar wizard to importing directly on a computer. Once done you can either wait for the group policy to propagate or on a computer run "gpupdate /force" to pull in the updated GPO with certificate immediately  Your computers will now show any relevant SSL certificates as trusted.

Tidy Up

After creating any new certificates you will need to ensure your CA folder is backed up to at least two separate highly secure memory sticks since if you lose these files you have just lost the ability to create new certificates with this Authority. Keep the certificates you generate safe as if somebody gets hold of one they will be able to impersonate that server - ideally they should only be stored on the server that hosts the SSL site and maybe on the secure memory sticks.

Troubleshooting


  • TXT_DB Error number 2 when generating certificates - By default Openssl will only generate a single certificate for each server and if you try to generate another one then it gives this cryptic error. Either you need to revoke the previous certificate or edit the openssl.cnf file and uncomment the "#unique_subject = no" line. To revoke the previous certificate find the serial number of the certificate from the index.txt file. Then issue the command "openssl ca -config openssl.cnf -revoke newcerts/<NUMBER OF CERT>.pem"

Friday 9 March 2012

Netscreen SSG140 dual factor VPN with Yubikey

For a while I have been meaning to type up a guide to setting up dual factor VPN's on Netscreen SSG firewalls.  It took me a while to figure it all out, referring to lots of online sources so hopefully this will be useful to someone.  I have a Juniper Netscreen SSG 140 firewall which various users are logging into, getting access to different systems based on their permissions.  I used the excellent and cheap Yubikey from Yubico to get the second factor working. Feel free to post any queries or suggestions, I'll try to answer any I can but I'm far from an expert.