#!/usr/bin/perl -sw- # ---------------------------------------------------------- # listen for stub notifications # # Meng Weng Wong # $Id$ # runs as a daemon; writes stub notifications to a text file that contains stub notifications. # # in the future, write stub notifications to a database, and avoid attacks by uniq'ing the stub url. # # usage: # # arguments: # # flags: # # input: # # output: # # license: GPL # # must run as root to bind to port 252. # meng selected port 252 as the stub listener, but that's really determined by the _stub._udp SRV record. # ---------------------------------------------------------- # ---------------------------------------------------------- # initialization # ---------------------------------------------------------- # ---------------------------------------------------------- # no user-serviceable parts below this line # ---------------------------------------------------------- use strict; use vars qw($port $ip $outputdir); use Socket; use File::Path; my $MAXLEN = 4096; my $NOTIFROOT = "/home/mengwong/stubmail/stubs"; use IO::Socket::INET; use Convert::Bencode qw(bencode bdecode); my $MySocket = new IO::Socket::INET->new(Proto=>'udp', LocalPort=>252) or die "unable to bind.\n";; $> = $< = getpwnam("mengwong"); my $text; $|++; while ($MySocket->recv($text, $MAXLEN)) { my($port, $ipaddr) = sockaddr_in($MySocket->peername); $ipaddr = inet_ntoa($ipaddr); print join "\t", (time, scalar localtime, "raw: $text\n"); my $decoded = bdecode($text); use Data::Dumper; my $logline = join ("\t", time, scalar(localtime), join ("; ", "client_ip=$ipaddr", "port=$port", map { "$_=$decoded->{$_}" } sort keys %$decoded) ) . "\n"; print $logline; # 1144627144 Sun Apr 9 19:59:04 2006 raw: d1:r30:mengwong@rssemail.mailzone.com1:s18:mengwong@pobox.com1:u130:http://blizzard.pobox.com/~mengwong/stubmail/simple_format_1.cgi/24475cfe2f71a969aefc33c33a96db77/c51a61183fee369e7e12d2542906c635e # 1144627144 Sun Apr 9 19:59:04 2006 client_ip=209.2.32.37; port=52653; r=mengwong@rssemail.mailzone.com; s=mengwong@pobox.com; u=http://blizzard.pobox.com/~mengwong/stubmail/simple_format_1.cgi/24475cfe2f71a969aefc33c33a96db77/c51a61183fee369e7e12d2542906c635 my $receiver_notification_filename = $decoded->{r}; $receiver_notification_filename =~ s/\///g; my $sender_as_filename = $decoded->{s}; $sender_as_filename =~ s/\///g; # all kinds of taint problems ... maybe we don't want to use the actual filenames provided. ($receiver_notification_filename) = ($receiver_notification_filename =~ /([-\@\w.]+)/); ($sender_as_filename) = ($sender_as_filename =~ /([-\@\w.]+)/); my $yyyy = sprintf "%04d", (localtime)[5] + 1900; my $mm = sprintf "%02d", (localtime)[4] + 1; my $dd = sprintf "%02d", (localtime)[3]; eval { mkpath(["$NOTIFROOT/$receiver_notification_filename/$yyyy/$mm/$dd"], 0, 0777); }; if (not $@) { if (open NOTIFICATION, ">> $NOTIFROOT/$receiver_notification_filename/$yyyy/$mm/$dd/$sender_as_filename") { print NOTIFICATION "url = $decoded->{u}\n"; print NOTIFICATION "sender = $decoded->{s}\n"; print NOTIFICATION "receiver = $decoded->{r}\n"; print NOTIFICATION "time = " . time . "\n"; print NOTIFICATION "localtime = " . localtime() . "\n"; print NOTIFICATION "client_ip = " . $ipaddr . "\n"; print NOTIFICATION "port = " . $port . "\n"; print NOTIFICATION "log = $logline"; print NOTIFICATION "\n"; close NOTIFICATION; } } else { die "$@"; } } # ---------------------------------------------------------- # chunks of text # ---------------------------------------------------------- # ---------------------------------------------------------- # main # ---------------------------------------------------------- # ---------------------------------------------------------- # functions # ---------------------------------------------------------- # ---------------------------------------------------------- # format statements # ----------------------------------------------------------