Sunday, September 27, 2009

ssh-agent and passwordless ssh

In addition to password authentication, ssh also provides public key authentication. Setup of public key authentication is described here . The summary of authentication is as follows:

* Generate a private key /public key pair:

ssh-keygen -t rsa

This will create a private key named id_rsa and public key named id_rsa.pub under ~/.ssh directory of the user. Here we are using RSA version 2 as the encryption protocol. Alternatively you can specify DSA ( -t dsa ) or RSA version 1 ( -t rsa1 ). If you want to create the key pair with an alternate name/location, specify it with -f option. The above command will prompt you for a passphrase for the private key. You can either give a passphrase or just press enter to have a blank passphrase (alternatively use -P '' option). The problem with having a blank passphrase is that anybody who has access to your private key file will be able to view and use it to impersonate your login. A passphrase for the private key prevents this from happening.

* Copy your public key to destination server and append it to ~/.ssh authorized_keys.

Once this is setup you can login to the destination server without using your account password. If you have provided a blank passphrase while generating public/private key you will be directly logged in. But if you have give a passphrase for you private key, you wil be prompted for that. While this gives a more secure way of logging in, for the end user it is just like replacing one password with another one. To get around this without compromising on security, we can use ssh-agent which will cache your password for repeated use.

ssh-agent is a key management program that can manage all our keys. We just need to unlock/decrypt our private keys - with the passphrase - once and add them into the agent, and for the rest of that session ssh-agent will automatically supply your key credentials whenever a new ssh connection is initiated.

Let us see the usage now.

* Start the agent.

[safeer@fcds ~]$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-EQayeR4473/agent.4473; export SSH_AUTH_SOCK;
SSH_AGENT_PID=4474; export SSH_AGENT_PID;
echo Agent pid 4474;

Now that the agent is running you need to add your keys to the agent.

[safeer@fcds ~]$ ssh-add
Enter passphrase for /home/safeer/.ssh/id_rsa:
Identity added: /home/safeer/.ssh/id_rsa (/home/safeer/.ssh/id_rsa)
Identity added: /home/safeer/.ssh/id_dsa (/home/safeer/.ssh/id_dsa)

here you will prompted to enter the pasphrace for your keys. if all your private keys have the same passphrase, you will be prompted only once.

To see the keys added to ssh:

[safeer@fcds ~]$ ssh-add -l
2048 20:83:de:3d:7c:5f:a4:32:c2:75:c9:12:f6:7f:f2:be /home/safeer/.ssh/id_rsa (RSA)
1024 7a:29:5a:73:6b:56:d0:0d:73:4e:70:67:39:99:80:c8 /home/safeer/.ssh/id_dsa (DSA)

Since the keys are added to ssh-agent you can use private keys without being prompted for passphrase throughout this session.

To remove a specific key from the agent

[safeer@fcds ~]$ ssh-add -d /home/safeer/.ssh/id_rsa
Identity removed: /home/safeer/.ssh/id_rsa (/home/safeer/.ssh/id_rsa.pub)

If you want to remove all the keys, just use "ssh-add -d"

Friday, September 18, 2009

Recovering your kjots books

For those who don't know about kjots, it is a note taking utility that comes with the KDE desktop environment. It allows you to organize your notes into Books. Each book will have pages where you can actually save your notes. It has formating options like font selection,color,alignment etc. It allows you to export your books and/or pages to text/html formats. There are many other handy function like bookmarking searching etc.. It is a very handy and lightweight application.

I was using this for quite some time and had two books full of notes. One fine morning my KDE crashed leaving my system in hung state. When it came up after the reboot, I found that all the notes in Kjots were gone leaving two blank books in it. So I was sitting there scratching my head, suddenly it came to my mind that Kjots has an automatic backup facility and decided to try my luck.

All kde applications store their per user configuration and user data inside the local kde directory under the respective user's home directory. In most of the cases it will be .kde directory under the users home directory. But in KDE4 this wil change to .kde4. So to determine the kde directory for your user account you need to run the following command.

safeer@cms-netbook:~$ kde-config --localprefix
/home/safeer/.kde/

The kjots data is located in the path share/apps/kjots under ~/.kde. Lets examine the contents of this directory:

safeer@cms-netbook:~/.kde/share/apps/kjots$ ls
Oj6443.book Oj6443.book.2 Oj6443.book.4 Oj6443.book.6~ xA4048.book xA4048.book.10~ xA4048.book.3~ xA4048.book.6~ xA4048.book.8~
Oj6443.book.1 Oj6443.book.2~ Oj6443.book.4~ Oj6443.book.7~ xA4048.book.1 xA4048.book.2 xA4048.book.4~ xA4048.book.7 xA4048.book.9
Oj6443.book.1~ Oj6443.book.3 Oj6443.book.5 Oj6443.book.8~ xA4048.book.1~ xA4048.book.2~ xA4048.book.5~ xA4048.book.7~ xA4048.book.9~
Oj6443.book.10~ Oj6443.book.3~ Oj6443.book.5~ Oj6443.book.9~ xA4048.book.10 xA4048.book.3 xA4048.book.6 xA4048.book.8

Kjots by default assigns a random filename to each of your kjots books. This will not be the same as the name you have assigned to the book. Kjots stores its books in xml format. If you want to know which file corresponds to which book, use this command. Here the name I gave to this kjots book is "TrainingNotes".

safeer@cms-netbook:~/.kde/share/apps/kjots$ grep -A 1 -m 1 KJotsBook Oj6443.book.6~|grep Title|cut -d '>' -f2|cut -d '<' -f1
TrainingNotes

Kjots takes backup of your books every time you close it. In addition to the original book, kjots will keep 10 most recent backups of each book. The backup and book naming scheme is as follows.

Book name convention: .book
Eg: Oj6443.book

Backup book name: .book.~ with .book.1~ being the most recent book.
Eg: Oj6443.book.3~
Most recent backup for the above book will have name Oj6443.book.1~

Now that you know about the kjots backup scheme, let us see how I recovered my kjots. First find out the good backup of each books.

safeer@cms-netbook:~/.kde/share/apps/kjots$ ls -l
total 576
-rw------- 1 safeer safeer 0 2009-09-10 16:14 Oj6443.book
-rw------- 1 safeer safeer 0 2009-09-24 18:39 Oj6443.book.1~
-rw------- 1 safeer safeer 19774 2009-09-10 16:52 Oj6443.book.10~
-rw------- 1 safeer safeer 0 2009-09-19 16:37 Oj6443.book.2~
-rw------- 1 safeer safeer 0 2009-09-18 18:16 Oj6443.book.3~
-rw------- 1 safeer safeer 48278 2009-09-17 21:45 Oj6443.book.4~
-rw------- 1 safeer safeer 48278 2009-09-17 21:21 Oj6443.book.5~
-rw------- 1 safeer safeer 48278 2009-09-17 21:21 Oj6443.book.6~
-rw------- 1 safeer safeer 48278 2009-09-16 17:15 Oj6443.book.7~
-rw------- 1 safeer safeer 48278 2009-09-16 17:02 Oj6443.book.8~
-rw------- 1 safeer safeer 19774 2009-09-16 16:59 Oj6443.book.9~
-rw------- 1 safeer safeer 0 2009-09-24 18:39 xA4048.book
-rw------- 1 safeer safeer 0 2009-09-24 18:39 xA4048.book.1~
-rw------- 1 safeer safeer 39850 2009-09-10 16:52 xA4048.book.10~
-rw------- 1 safeer safeer 0 2009-09-19 16:37 xA4048.book.2~
-rw------- 1 safeer safeer 0 2009-09-18 18:16 xA4048.book.3~
-rw------- 1 safeer safeer 42450 2009-09-17 21:45 xA4048.book.4~
-rw------- 1 safeer safeer 42450 2009-09-17 21:21 xA4048.book.5~
-rw------- 1 safeer safeer 42450 2009-09-17 21:21 xA4048.book.6~
-rw------- 1 safeer safeer 42450 2009-09-16 17:15 xA4048.book.7~
-rw------- 1 safeer safeer 39850 2009-09-16 17:02 xA4048.book.8~
-rw------- 1 safeer safeer 39850 2009-09-16 16:59 xA4048.book.9~

As you can see, the most recent good copy for both the books were backed up on 2009-09-17 21:45 (this should be the time when I closed the Kjots on the previous day). All files after this has zero size. So copying this backup files to the corresponding books will get my books back. Make sure to close Kjots before doing this.

safeer@cms-netbook:~/.kde/share/apps/kjots$ cp Oj6443.book.4~ Oj6443.book
safeer@cms-netbook:~/.kde/share/apps/kjots$ cp xA4048.book.4~ xA4048.book

Relaunched Kjots and my books were back with all the contents!

Monday, September 14, 2009

VB script to move files based on creation date

My friend had this issue where he was supposed to move thousands of files sitting in one directory to separate directories based on their creation time.  Right now this script will only check the month and year of creation.  But this can be easily extended to consider up to seconds in creation time.  Explanation for each step is given as comments itself.


SplitAndMove.vbs

'Declare all varibles in advance
Dim curPath,srcDir,dstDir,myDir,objFSO,objFolder,objFiles,objFile

'Create a file sytem object as a base for manipulating files and directories
Set objFSO = CreateObject("Scripting.FileSystemObject")

'Process command line arguments
Select Case WScript.Arguments.Count
'If only one argument is given, take it as source directory
'then create a destination directory in the current working directory
       Case 1
       srcDir = WScript.Arguments.Item(0)
       curPath = objFSO.GetAbsolutePathName(".")
     dstDir = curPath & "\Split_Move_" & Day(Now()) & Month(Now()) & Year(Now()) & Hour(Now()) & Minute(Now()) & Second(Now())
       Case 2
'Two arguments given, first one is source directory
'Second one is destination directory
       srcDir = WScript.Arguments.Item(0)
     dstDir = WScript.Arguments.Item(1)
'In all other cases display Usage and exit script
       Case Else
       Wscript.Echo "Usage: " & Wscript.ScriptName & "<Source Directory> [<Destination Directory>]"
       WScript.Quit 1
End Select

'If source directory does not exist, display error message and exit script
If ( Not objFSO.FolderExists(srcDir) ) Then
   Wscript.Echo "Invalid Source Directory"
   WScript.Quit 1
End If

'If destination directory does not exist, create it.
If Not objFSO.FolderExists(dstDir) Then
   objFSO.CreateFolder(dstDir)
End If

'Get list of files in source directory
Set objFolder = objFSO.getFolder( srcDir )
Set objFiles = objFolder.files

'For each file in source directory, destination should be:
'a directory under destination directory,
'that directory's name should constitute month and year of the file's creation time.
For Each objFile in objFiles
'Construct destination directory name with month and year of file's creation time
myDir = dstDir & "\" & Month(objFile.DateCreated) & "_" & Year(objFile.DateCreated)
'If directory exists, move the file there.
If objFSO.FolderExists(myDir) Then
    objFSO.MoveFile objFile.Path , myDir & "\" & objFile.Name
'Otherwise create the directory and then move the file there.
Else
   objFSO.CreateFolder(myDir)
   objFSO.MoveFile objFile.Path , myDir & "\" & objFile.Name
End If
Next