Posts

Showing posts with the label coding

Why Go is not my favourite language

Go has exceptions and return values for error Yes it does. Yes, it really really does. We can discuss this for hours but in the end it boils down to four points: In Go some errors cause stack unrolling, with the possibility to for each step in the call stack register code that runs before the stack is unrolled further, or for the unrolling to stop. In programming languages, that's called "exceptions". Idiomatic use in a language of the feature doesn't affect what the feature is . Saying that Go doesn't have exceptions is like saying Go doesn't have NULL pointers (it has nil pointers). There is no non-tautology definition of exceptions that includes the ones in Python, C++ and Java, but does not include panic/rescue in Go. Go on, try to language lawyer your way into a definition. In spoken/written lang...

Compiling C++ statically

To properly compile a static C++ binary on Linux you have to supply -static , -static-libgcc and -static-libstdc++ when linking. That's fucked up. Never EVER think that linking (at link time or runtime) is easy or obvious. I link my current pet project with: g++ -Wl,-z,now -Wl,-z,relro -pie -static-libstdc++ The binary then seems to work across the systems I currently want to run it on. Specifically it makes me able to run the binary compiled on Debian Testing on a Debian Stable installation. Skipping that whole dynamic libraries thing is something Go got right. Update: some clarification on why you'd want to compile statically Let's start with the reason for wanting to compile static in the first place. While shared libraries are better in some aspects, "save RAM" is no longer a good reason for always compiling dynamically. There are reasons why you'd want dynamic linking still, ...

Interesting Arping bug report

A few months ago I was strolling in the Debian bug tracking system and found a curious bug filed against Arping , a program I maintain. It said that unlike Arping 2.09, in Arping 2.11 the ARP cache was not updated after successful reply. I thought that was odd, since there's no code to touch the ARP cache, neither read nor write. Surely this behaviour hasn't changed? I tried to reproduce the behaviour and sure enough, with Arping 2.09 the arp cache is updated, while with 2.11 it's not. $ arp -na | grep 192.168.0.123 $ # --- First try Arping 2.11 --- $ sudo ./arping-2.11 -c 1 192.168.0.123 ARPING 192.168.0.123 60 bytes from 00:22:33:44:55:66 (192.168.0.123): index=0 time=1.188 msec --- 192.168.0.123 statistics --- 1 packets transmitted, 1 packets received, 0% unanswered (0 extra) $ arp -na | grep 192.168.0.123 $ # --- Ok, that didn't change the ARP cache. Now try 2.09 --- $ sudo ./arping-2.09 -c 1 192.168.0.123 ARPI...

Shared libraries diamond problem

Image
If you split up code into different libraries you can get a diamond dependency problem. That is you have two parts of your code that depend on different incompatible versions of the same library. Normally you shouldn't get in this situation. Only someone who hates their users makes a non backwards compatible change to a library ABI. You don't hate your users, do you? (just kidding about hating your users.) Disclaimer I thought I'd dive into this problem as a weekend project. Don't rely on this article as a source of truth, but please correct me where I'm wrong. I'm not an expert in creating shared libraries, and it's much harder that it would first appear. The existence of libtool proves that. Example project described can be found here . Multiple versions of the same library The lovely land of modern Unix will allow you to have multiple versions of the same library installed at th...

Be careful with hashmaps

As you remember from long ago hashes are O(1) best case, but can be O(n) if you get hash collisions. And if you're adding n new entries that means O(n^2) . I thought I'd take a look at the hash_set/hash_map GNU C++ extension. In /usr/include/c++/4.4.3/backward/hash_fun.h : 1 2 3 4 5 6 7 8 inline size_t __stl_hash_string ( const char * __s ) { unsigned long __h = 0 ; for ( ; * __s ; ++ __s ) __h = 5 * __h + * __s ; return size_t ( __h ); } Test program that loads some strings: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include<time.h> #include<iostream> #include<hash_set> double getclock () { struct timespec ts ; clock_gettime ( CLOCK_MONOTONIC , & ts ); return ts . tv_sec + ts . tv_nsec / 1e9 ; } _GLIBCXX_BEGIN_NAMESPACE ( __gnu_cxx ) template <> struct hash < :: std :: string ...

TPM-backed SSL

This is a short howto on setting up TPM-backed SSL. This means that the secret key belonging to an SSL cert is protected by the TPM and cannot be copied off of the machine or otherwise inspected. Meaning even if you get hacked the attackers cannot impersonate you, if you manage to kick them off or just shut down the server. The secret key is safe. It has never been outside the TPM and never will be. This can be used for both client and server certs. Prerequisites A TPM chip. Duh. May need to be turned on in the BIOS. Could be called "security chip" or something. If you don't have a TPM chip but still want to follow along (maybe add TPM support to some program) then you can install a TPM emulator. See links at the end on how to install a TPM emulator. A working CA that will sign your CSR. I will assume you're running your own CA, but you can send the CSR to someone else to sign if you want...

Yubico is awesome

Yubico and their products are awesome. That pretty much sums up this blog post but I'm going to go on anyway. If you're thinking of introducing two-factor authentication to your company, or you're using something that's fundamentally broken (like RSA SecureID) you simply must at least take Yubikeys into consideration. When I say that SecureID (and others) are fundamentally broken what I mean is that when (not if, as recent history has shown) RSA (the company) is broken into YOUR security is now compromised. When I first used SecureID and found out that you as a customer aren't in control of your own keys my first thought was "well that's just stupid". Why are you giving the keys to the kingdom to someone else? Enter Yubikeys. They just beat SecureID in every way (almost). Benefits: Open specification. You can set your own keys (secrets) and don't have to show them to a third party who...

gettimeofday() should never be used to measure time

gettimeofday() and time() should only be used to get the current time if the current wall-clock time is actually what you want. They should never be used to measure time or schedule an event X time into the future. What's the problem? gettimeofday() returns the current wall clock time and timezone. time() returns a subset of this info (only whole seconds, and not timezone). Using these functions in order to measure the passage of time (how long an operation took) therefore seems like a no-brainer. After all, in real life you measure by checking your watch before and after the operation. The differences are: 1. Nobody sneaks in and changes your wristwatch when you're not looking You usually aren't running NTP on your wristwatch, so it probably won't jump a second or two (or 15 minutes) in a random direction because it happened to sync up against a proper clock at that point. Good NTP implementations try to not make...

tlssh - a replacement for SSH

I've started writing a replacement for SSH. Why? Because SSH has some drawbacks that sometimes annoy me. I also wanted an authentication scheme that's more similar to SSL/TLS than what SSH does. With tlssh you don't specify username or password, you simply connect to the server using a client-side certificate to log in as the user specified in the certificate. No interaction until you reach the shell prompt on the server. Of course you can log in using a public key with SSH, but it's only a public/private key pair, there's none of the PKI that SSL has. Specifically, what I was missing in SSH was: Expiring keys, both login-keys and server certificates CRL s (Certificate Revocation Lists) - wouldn't it be nice to just revoke the all certificates that were on a compromised machine and they'll suddenly be unusable everywhere? (I will add OCSP too. Same thing but more "online") Pureness. Not all th...

Redirecting to the closest site using Javascript

I'm sure this problem has been solved this way many times before, but I haven't seen it while idly browsing around sites about scalability and load balancing. So here it is, a Javascript solution to the closest-site problem . For static content optimizing for latency is easy and cheap. Just put your files in a CDN such as Amazon CloudFront and you're done. Low (lower) latency all over the world. Done. For dynamic content it's a bit harder. You can set up several data centers (sites) and try to redirect the user to their closest site. But how do you find out what site is the closest one, and how do you redirect the user to the right one? There are several solutions to this, such as using anycast BGP or source-aware DNS. But they have big drawbacks. DNS based solutions depend on the users resolver to be close to the user and that the ip2location database is correct. BGP-based solutions depend on you having access to BGP (and the staf...

10 years of maintaining an open source program

Arping 0.1 was released 10 years ago last month or so. It's since been included as a package in Debian GNU/Linux, Ubuntu, OpenBSD, FreeBSD and NetBSD, Gentoo and some other smaller and bigger OSs and distributions. It's interesting that not one of these asked or even let me know, which is kind of fun. I only noticed because I ego-googled. A couple of German magazines did ask before putting it on their CDs. I told them that it's GPL so they can do what they want, but thanked them for letting me know. Linux Journal could have told me though. Arping was rewritten for libnet 1.1 as Arping 2.x. I fixed the IRIX port of libnet 1.1 just so that I could get Arping to work on it. I get bug reports or feature requests every now and then. Most build errors are due to someone not having libnet and/or libpcap installed. The new version (2.09) checks for these dependencies and present a friendly error message in case they're missi...

Clipboard sniffer

Yes clipboard, not keyboard. I've made a clipboard sniffer for X called ClipSniff. It periodically saves whatever is in the clipboard (both the "PRIMARY" and the "CLIPBOARD") into a sqlite database. git clone http://github.com/ThomasHabets/clipsniff.git It wasn't that hard when you knew where to look. You just: Connect to the X server. XOpenDisplay() Create a window (you don't need to display it). XCreateSimpleWindow() Ask the X server who owns the PRIMARY and CLIPBOARD atoms, and ask that window to send you the data. XInternAtom() , XConvertSelection() Wait for the reply event. Loop of NextEvent() Helpful links when coding Xlib Minimal XGetWindowProperty Example Xlib Programming Manual (O'Reilly & Associates, Inc.) X Selections, Cut Buffers, and Kill Rings (jwz) X Windows Copy-Paste mini HOWTO (Stelios Xathakis)

Lightwave. Like Google Wave only much less

I felt sorry for all those who don't yet have a Google Wave account, and I was impressed with their demo. And I also wanted an Erlang project. So I killed three birds with one stone. I made Lightwave. It's like Google Wave only: Dumber Buggier Uglier More incomplete Written in Erlang Future plans include API for hooking in bots Only save data for last X time or entries Automatic on-disk persistence Links Lightwave on Github Lightwave "technology preview" :-)

Autotools is nice

I was recently asked why autotools was so good. I thought I might as well post what I answered. Small differences There are always some small differences between OSs. For example if uint64_t exists or if it's called u_int64_t . Instead of doing an #ifdef __linux__ with lots of garbage and another block of #ifdef __OpenBSD__ you can solve the problem right. Otherwise you'll end up with duplicated sections of defines and other things like: 1 2 3 4 5 6 7 8 9 10 11 12 #if __FreeBSD__ # define foo bar # define OStype joonix #elif defined __OpenBSD__ # define foo bar # define OStype joonix #elif defined __linux__ # define foo BAZ # define OStype joonix #else # error "Unknown OS, please add your OS here and define the things that the other OSs do above" #endif Supported interfaces Even if an OS doesn't support some API (such as sendfile() or openpty() ) today, it may do so in a year. It would be a shame if your p...

Moving a process to another terminal

Image
I've always wanted to be able to move a process from one terminal to another. For example if I've started a long-running foreground process (such as irssi or scp) outside of a screen and I have to log out my local terminal. I looked around and there doesn't seem to be any way to do this. There is a program called retty that I found later on that sort of does this, but it only closes and re-opens stdin/out et al. It doesn't seem to do full terminal handling. Nor does it seem to detach the original terminal. It only allows you to peek into the process, control it for a bit, and then hand it back. If you shut down the original terminal you're still screwed. Attempt 1: pass the fd for the real pty I thought I could ptrace() attach to the process, inject code to dup2() onto stdin/out/err, and do some ioctl()s and that would be that. No such luck as we shall see. The easiest (and most portable way) to do it would be to dlopen() a shared libr...