Configuring ssh server for pubkey + password authentication

In a struggle to secure my home computer I did battle with the ssh server once again to configure it “just the way I want it” ™. I prefer pubkey + password since this ensures that if I lose the laptop/phone/whatever then the lucky finder will not find his/her way into my home computer.

So, without further fanfare here are various bits that need to be done.

Configuring the ssh server
edit /etc/ssh/sshd_config and use the following entries:
Protocol 2 # protocol 1 is outdated
PubkeyAuthentication yes # I want public key to be used for authentication (and possibly to be combined with a pass phrase)

And of course there a bunch of authentication protocols that are not needed:
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
PasswordAuthentication no
UsePAM no

Creating the keys
Still on the server in the home folder of the user you want to login remotely with, create the private/public pair using ssh-keygen -t dsa in ~/.ssh (the default location for ssh-keygen). You get two files: id_dsa (private key) and id_dsa.pub (public key).

I used dsa keys in this post and you can use rsa keys if you pass -t rsa to ssh-keygen.

In the same folder on the server create a file called authorized_keys which has the public key (it can just be a copy of id_dsa.pub but has the potential to contain many keys – possibly one per user that can connect to said account or one per roaming device).

When creating the key pair you will be prompted for a pass phrase. This is where you choose whether or not you will need a pass phrase (which acts as a password) in order to access this account. If you leave the pass phrase empty you’re allowing key only access with no password which is dangerous since if anyone gets a hold of your roaming device he/she can access your account with no extra data.

Distributing the keys
Copy the private key ~/.ssh/id_dsa to the roaming devices you want to access the server from (laptop, phone, whatever). If the roaming device is a Linux box then put the private key in the same location (~/.ssh/id_dsa) in the home folder of the user that wishes to access the server. If you are using some other ssl tool besides command line ssh on a Linux box to access the server then it should have a place where you plug the private key into. If it doesn’t have such a place then dump it. Putty (a widely used ssh client on windows) has an option to use a private key for connection.

Note:
While trying this out a lot of people seem to fail because they do all the experimentation on a desktop. In a desktop there is a system called ssh-agent which does the authentication for you in order to save you typing the same password multiple times. This agent is a problem when doing experimentation since it needs to be notified that you switched keys. So, every time you switch keys (regenerate the ~/.ssh/{id_dsa,id_dsa.pub} files) you need to run ssh-add to let the agent know this. Another option is not do all of the experimentation from a desktop but rather from a login shell (Ctrl+Alt+1 or whatever) so that the agent does not come into the game (which is complicated enough without it). Only after everything is setup re login to the graphical desktop and try everything out.

Command line id3 2.4 tagging in Linux

In the past couple of weeks I have been dabbling with command line to tag and inspect tags of mp3 files. Linux has an abundance of tools to fill this niche and it’s confusing to know what to use. What follows are my conclusions.

id3: only handles 1.1 tags.
id3v2: does not handle 2.4 tags.
id3tool: does not handle 2.4 tags. Not maintained.
eyeD3: handles everything (especially 2.4 tags), has lots of options and seems to be supported.

So it’s fairly obvious what to choose. Please let me know if you have any more candidates to add to this list or you disagree with any of my conclusions.

Finding broken symbolic links

I sometimes need to find all broken symbolic links in a folder, recursively or not. find(1) is the all UNIX right tool for the job as far as finding files is concerned but it does not have an explicit -and -type brokenlink option…

Some solutions involve sending the output of find(1) to some other tool. These solutions are sub-optimal in that once you leave the comfort of find(1) you give up the ability to use many of it’s fine features and run into other problems (file names with white space characters just to name one such problem).

Other solutions involve doing find -L . -type l which forces find(1) to follow all symbolic links and ultimately only print those which it cannot follow. This solution has other drawbacks. One is that you do not necessarily want find(1) to follow every symbolic link since this may cause it to wander to huge areas of your hard drive that you do not wish to scan. Another deficiency is the fact that there is a difference between a symbolic link that cannot be followed and one which cannot be read.

My solution is this:

find . -type l -and -not -exec test -e {} \; -print

Producing MySQL dates on the command line

I often find myself in need of inserting data manually into a MySQL database using some kind of database editor. In a database editor you find yourself manually inserting values into cells of a table and in most of them you are not allowed to enter an SQL expression (the MySQL Query Browser is a prime example). In this case I need some way to generate the current date and time as per the MySQL format quickly on the command line. I will usually use:

alias date_mysql="date +'%F %T'"

Grep is broken – use perl instead

In the course of running various grep(1) combination to find various defects in source files I ran into inherent grep(1) difficulties. It seems that the regular expression syntax in grep(1) is very limited and so it’s better to use perl to solve these issues as it’s regular expression support is fantastic. A small script can solve all your grepping needs. So here it is. Please comment with fixes and I’ll incorporate them if you want to add features.

#!/usr/bin/perl -w
 
# This is a general script to grep using perl to overcome some of the deficiencies
# of grep(1) grepping...
 
use strict;
use diagnostics;
 
my($pattern)=$ARGV[0];
my($debug)=0;
my($print_filename)=1;
 
for(my($i)=1;$i<@ARGV;$i++) {
        my($filename)=$ARGV[$i];
        if($debug) {
                print "filename is [$filename]\n";
        }
        open(FILE,$filename) || die "Can't open file [$filename]: $!";
        my($line);
        while($line=<FILE>) {
                if($line=~$pattern) {
                        if($print_filename) {
                                print $filename.": ";
                        }
                        print $line;
                }
        }
        close(FILE) || die("unable to close file [$filename]: $!");
}