2009-12-30

AVR, Gentoo and Paludis

Seeing that there is a new AVR simulator for linux in town, simavr, I decided to get the latest avr gcc packages for Gentoo. (More about simavr when I have gotten a bit accustomed to it)

As the crossdev scripts don't really wants to play nice with Paludis the packages have to be "created" manually. This is really a simple procedure as the packages themself already works for different targets, they just need to be told. I got the information on how to do it from the Gentoo wiki.

First one needs a repo for the cross avr chain. We will call it cross-avr. It is created by putting this configuration file in /etc/paludis/repositories:

master_repository = gentoo
format = ebuild
location = /var/paludis/repositories/cross-avr
names_cache = /var/cache/paludis/names
write_cache = /var/cache/paludis/metadata

And to get the files in the repo, make the directory and create symbolink links for the required packages:

mkdir /var/paludis/repositories/cross-avr/{cross-avr,profiles} -p
cd /var/paludis/repositories/cross-avr/cross-avr
ln -s /usr/portage/dev-embedded/avr-libc
ln -s /usr/portage/sys-devel/binutils
ln -s /usr/portage/sys-devel/gcc
ln -s /usr/portage/sys-devel/gdb

The repo also needs to be named and as the category is not in the master tree (portage) it needs to be added to the categories file:

cd ../profiles
echo cross-avr > repo_name
echo cross-avr > categories

Finally we need to tell paludis to use the avr-gcc for the other cross-avr packages, by placing this in /etc/paludis/bashrc

#cross-build avr
if [[ "${CATEGORY}" == "cross-avr" ]]
then
    if [[ "${PN}" != "gcc" && "${PN}" != "binutils" ]]
    then
        CBUILD=${CHOST}
        CHOST=avr
        CFLAGS="-Os"
    fi
fi

Now we have the ("auto-syncing" :D) repo set up!

To make sure that paludis knows about the new packages we run:
paludis --regenerate-installable-cache cross-avr


Next up is the installation. Do a pretend to see what paludis will pull in:
paludis cross-avr/binutils cross-avr/gcc cross-avr/avr-libc cross-avr/gdb -ip

Here it is important to note all the use flags for gcc. My experience is that most of them will break avr-gcc and my recommendation is to turn them all off.

At last we are ready. Start the build and grab a mug of cocoa.

While you wait it may be interesting to know that avr-libc will place the libs in /usr/avr. And if you want to start playing with simavr you need to change AVR_ROOT, in its Makefile.common, to this path. But more on that another time ;)

When the packages are installed you may want to create a symlink in /usr/avr/lib to /usr/x86_64-pc-linux-gnu/avr/lib/ldscripts (substitute architechture as appropriate) because ld will have problems finding the linker scripts otherwise. (/usr/libexec/gcc/avr/ld: cannot open linker script file ldscripts/avr4.x: No such file or directory, Gentoo bug)

Now you can compile your avr projects with avr-gcc! Happy hacking!

2009-05-29

Custom PATH in KDE run dialog

It has bothered me for a while that the KDE run dialog (Alt+F2) won't find my custom scripts in ~/bin. After a failed attempt, with ~/.kde/env/bin_path, I found a way that should (in theory) work with any desktop manager.

The solution is to put the export command in a file called ~/.xprofile

export PATH="/home/thomas/bin:${PATH}:/home/thomas/installs/bin"

(I keep all my user installed apps in ~/installs/bin ;))

2009-05-22

freeSSHd administrator stupidity, and fix

Searching for a ssh server for a Windows machine I stumbled upon freeSSHd. I thought it looked nice and threw up a remote desktop the Windows machine and installed version 1.2.4.

Everything went fine until I tried to start the administration interface. It told me I need to be an administrator. Well, fine, I am in the administrator group but not the administrator. Tried running the application as the administrator user, no luck.

Going through their forums I found out the user have to be named "Administrator", case and all. Tough luck for us running non-English Windows versions...

As their did not appear to exist a good solution I finally ended up using OllyDbg (great tool, version 2 is under way) to disable the test. I won't post a patched version as I'm pretty sure it is not legal to do so, but I will show what you need to change, either using OllyDbg (yea, it can edit and save the asm directly) or the hex editor of your choice. You probably should make a backup of the original file and stop the freeSSHd service before you start.

Okay, so what you need to do is to replace the JE (jump equal/zero) instruction, that takes us down the wrong road, with two NOPs (no operation). It is at address 00013726 (yea, it's hex, try Ctrl+G in your tool and specify (file) offset), reading 74 49.

Just simply replace those two bytes with 90 90 and save the file.

Voila, it is possible to administrate freeSSHd!



(I would have posted this on the freeSSHd forum if I was able to register :P)

edit.

Seems it starts a new instance when it's run by the "wrong" user. To get around this just stop the service, make the changes, and restart the service (ie from services.msc).

2009-01-23

Yubikey and sv_dvorak

I recently received a yubikey which I immediately started to play with.



To get it to work with a pam authentication module I needed its id. As instructed I tried logging in at the administration site but it kept saying my key was invalid. After some head-scratching I realized why: the yubikey acts as a keyboard and "hits" the keys in the password string. The problem is, I don't use qwerty, so the key was not outputting the characters it thought it did.

So I ended up writing a patch for YubiPAM. It is a bit hackish and I should really have used some sort of dictionary, but at least it works ;)

yubipam-1.0.4-sv_dvorak.patch

--- src/utils/yk_chkpwd.c.old 2008-09-24 09:55:24.000000000 +0200
+++ src/utils/yk_chkpwd.c 2009-01-23 19:15:53.000000000 +0100
@@ -65,6 +65,9 @@

#define MAXPASS 200 /* the maximum length of a password */

+// "abcdefghijklmnopqrstuvwxyz"
+#define DVORAK_MAP "anihdyujgcvpmlsrxo_kf.,bt-"
+
#include <security/_pam_types.h>

int _yubi_verify_password(char *, char *);
@@ -215,6 +218,42 @@
{
pass[npass] = '\0'; /* NUL terminate */
retval = _yubi_verify_password(user, pass);
+
+ if(retval == PAM_CRED_INSUFFICIENT)
+ {
+ // try se_sv_dvorak
+ // password will always get the same size or smaller, because of multibyte chars
+ int y, dy;
+ char c;
+ for(y = 0, dy = 0; (c = pass[y]) != 0; y++, dy++)
+ {
+ // special cases first, we really want to use some sort of dictionary here!
+ if(c == 0xFFFFFFC3) //multibyte
+ {
+ c = pass[++y];
+ switch(c)
+ {
+ case 0xFFFFFFA5: //å
+ pass[dy] = 'q';
+ break;
+ case 0xFFFFFFA4: //ä
+ pass[dy] = 'z';
+ break;
+ }
+ }
+ else if(c == '.')
+ pass[dy] = 'e';
+ else if(c == ',')
+ pass[dy] = 'w';
+ else if(c >= 'a' && c <= 'z')
+ pass[dy] = DVORAK_MAP[c - 'a'];
+ else
+ break; //bail
+ }
+ pass[npass = ++dy] = 0;
+
+ retval = _yubi_verify_password(user, pass);
+ }
}

memset(pass, '\0', MAXPASS); /* clear memory of the password */


As it turns out I started with a patch for yubico-c-client which uses the yubico servers for validation. I switched to YubiPAM when I realized that yubico-pam only supports ssh.

libyubikey-client-1.4-sv_dvorak.patch

Quick 'n' dirty sv_dvorak libyubi with fallback to default layout.

--- libykclient.c.old 2008-09-15 15:27:13.000000000 +0200
+++ libykclient.c 2009-01-21 22:22:40.000000000 +0100
@@ -48,6 +48,9 @@
# define D(x) /* nothing */
#endif

+// "abcdefghijklmnopqrstuvwxyz"
+char* dvorak_map = "anihdyujgcvpmlsrxo_kf.,bt-";
+
struct yubikey_client_st
{
CURL *curl;
@@ -114,11 +117,45 @@
yubikey_client_t p;
int ret;

+ char dvorak_yubikey[100];
+ char c;
+ int y;
+ int dy;
+ for(y = 0, dy = 0; (c = yubikey[y]) != 0; y++, dy++)
+ {
+ // special cases first, we really want to use some sort of dictionary here!
+ if(c == 0xFFFFFFC3) //multibyte
+ {
+ c = yubikey[++y];
+ switch(c)
+ {
+ case 0xFFFFFFA5: //å
+ dvorak_yubikey[dy] = 'q';
+ break;
+ case 0xFFFFFFA4: //ä
+ dvorak_yubikey[dy] = 'z';
+ break;
+ }
+ }
+ if(c == '.')
+ dvorak_yubikey[dy] = 'e';
+ else if(c == ',')
+ dvorak_yubikey[dy] = 'w';
+ else if(c >= 'a' && c <= 'z')
+ dvorak_yubikey[dy] = dvorak_map[c - 'a'];
+ else
+ break; //bail
+ }
+ dvorak_yubikey[++dy] = 0;
+
p = yubikey_client_init ();

yubikey_client_set_info (p, client_id, keylen, key);

- ret = yubikey_client_request (p, yubikey);
+ ret = yubikey_client_request (p, dvorak_yubikey); //sv_dvorak
+ if(ret == YUBIKEY_CLIENT_BAD_OTP)
+ ret = yubikey_client_request(p, yubikey); //qwerty
+

yubikey_client_done (&p);