#!/usr/bin/perl ########################################################################## # # # ACHTUNG: # # # # modifizierte Version von smswebde.pl speziell für den Einsatz als CGI! # # # # 10.10.2001, Leo Fellermayr # # # ########################################################################## # # FEATURES: - Check auf mehrere laufende Instanzen (= nicht erlaubt) # - IP-Subnetz-basierte SMS-Quotas (pro Tag) # - Check auf berechtigten HTTP-Referer (Formular) # # ----- some global settings for security my @valid_referers = qw (http://forster.dyndns.org/); # allowed referers my @subnets = qw (10.0.); # subnet list my @limits = qw (20); # limitations for @subnets my $limits_other = 5; # all other subnets my $tmp_path = "/tmp"; # ______ _______ ______ _____ _ _ # / _____|_______)/ _____)/ __ \ | | | | # ( (____ _ _ _( (____ | | / ) _ _ _____| |__ __| |_____ # \____ \| ||_|| |\____ \| | \__/ | | | ___ | _ \ / _ | ___ | # _____) ) | | |_____) ) |____| | | | ____| |_) | (_| | ____| # (______/|_| |_(______/ \_____)\___/|_____)____(_)____|_____) # # ---------------------------------------------------------- # - SMS @ Web.de - # - SMS sending tool for freemail.web.de - # ---------------------------------------------------------- # Released under the GNU Public License # (C) 2000 by Patrick Hagemeister # # ---------------------------------------------------------- # ** Modules ** package RequestAgent; no strict; use LWP::UserAgent; # libwww-perl ($proxy_username,$proxy_password,$last_redirect) = (undef,undef,undef); @ISA = qw(LWP::UserAgent); sub new { $self = LWP::UserAgent::new(@_); $self->agent("smsweb"); $self; } sub get_basic_credentials { my $self = shift; return ($proxy_username,$proxy_password); } sub redirect_ok { my($self, $request) = @_; $last_redirect=$request->uri; return TRUE; } package smswebde; use strict; # Avoid bugs :) use Getopt::Long; ###################################### begin modifications (10.10.2001, lf) # ** print HTML header ** print "pragma: no-cache\n"; print "Content-type: text/html\n\n"; print<<"..."; SMS-Sendebericht

SMS-Sendebericht


... # ** Check server load ** sub check_load { my $sane = `/bin/ps -auxwww | grep perl | grep smswebde\.pl | grep -v grep | /usr/bin/wc -l`; chomp $sane; # Es kann nur einen geben ! if ($sane > 1) { print "Es wird gerade eine SMS verschickt. Bitte warten, bis dieser Vorgang abgeschlossen ist.

\n"; print "Es ist vollkommen nutzlos, mehrmals auf den "Senden"-Button zu klicken
\n"; print "da jede Wiederholung des Sendevorgangs vom Server ignoriert wird! *G*
\n"; print "Eine Überlastung des Servers wird auf diese Weise ausgeschlossen!
\n"; finish_html (); exit (); } } my %data = (); # ** Get CGI form data ** sub read_form { my ($buffer, $pair, $name, $value) = ""; my @pairs = (); if ($ENV{'REQUEST_METHOD'} eq "GET") { $buffer = $ENV{'QUERY_STRING'}; } elsif ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $name =~ tr/+/ /; $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; if (defined $data{$name}) { $data{$name} = $data{$name}.",".$value; } else { $data{$name} = $value; } } } &read_form (); print "
\n";


###################################### end modifications (10.10.2001, lf)



# ** Definitions **
my $url_loginpage	= "http://freemail.web.de/online/";	# URL of Freemail-Login-Script
my $url_smspage		= "http://%s/online/logic/action.htm?si=%s&rv_do_newsms=yes";
my $url_sendpage	= "http://%s/online/logic/action.htm";

my $send_formvals 	= "si=%s&rv_mid=%s&rv_smsnumber=%s&rv_subject=%s&rv_recover_user=%s&rv_umskey=%s&rv_do_savemsg=yes&rv_goto=/online/ordner&msg_type=2&recover_dbserver=dbmail04&rv_do_send=Senden";

my $configfile		= "/wwwroot/cgi-bin/.smsrc";
my %config;		# Define Configuration-Hash
my @config_required 	= qw(username password wget_path gocr_path code_temp); # Required Configuration-Variables

my $debuglevel		= 5;	# Debuglevel (1..5)
my $quiet		= undef;

my $smsnumber;
my $message;

my $sessionid;
my $messageid;

my $host;

# ** LWP Definitions **
my $agent 	= RequestAgent->new;  # Create an UserAgent object
my $request 	= HTTP::Request->new; 
my $response;


# ----------------------------------------------------------------------------
# ** Misc Functions **
sub fatalerror {
	my ($id,$text,$res) = @_;
	print "Error: [$id] $text\n";
	print "\n".$res->error_as_HTML if (($res) && ($debuglevel>1));
	finish_html ();
	exit;
}

# ----------------------------------------------------------------------------
# ** Config-File Management **

# Read the config-file (filename $configfile) into %config.
sub read_configfile {
	print "Configfile lesen...\n" if ($debuglevel>1);
	open (CONFIG, "<$configfile") || &fatalerror("read_configfile","Could not open config-file \"$configfile\" for reading ! Please make sure you set up ~/.smsrc (see Documentation)");
	while () {
		if ((!(/^#/)) && (/=/)) {
			chomp;
			my ($key,$value) = split(/=/);
			$key =~ s/\s//g;	  # Remove spaces from key
			$value =~ s/(^\s*|\t)//g; # Remove spaces from the beginning and any tabs from the value
			$config{$key} = $value;
		}
	}
	close CONFIG;
}

# ----------------------------------------------------------------------------
# ** Sanity Checks **

sub usage {
	my ($reason) = @_;
	if ($reason) { print "Syntaxfehler: $reason\n"; }
	print "Syntax: \n\t$0   [--debug=1..5]\n";
	finish_html ();
	exit;
}

# Check Configuration and Parameters
sub checksanity {
	# Check for required fiedls @config_required in %config	
	foreach (@config_required) {
		if (!defined($config{$_})) {
			&fatalerror("checksanity","Missing required field \"$_\" in Configfile");	
		}
	}
	
	# Strip spaces from proxy username/password
	if ($config{"proxy_username"}) {
		$config{"proxy_username"} =~ s/(\s|\t)//g;  
	}
	if ($config{"proxy_username"}) {
		$config{"proxy_password"} =~ s/(\s|\t)//g;
	}
}

sub parse {
	# Check Command-Line Parmaters
        GetOptions("debug=i",\$debuglevel,"quiet",\$quiet);
        $debuglevel=5 if ($debuglevel >5);
        $debuglevel=1 if ($debuglevel <1);

	# Check ARGV count

###################################### begin modifications (10.10.2001, lf)
#        &usage unless ($#ARGV > 0);
#        $smsnumber = $ARGV[0];
	$smsnumber = $data{'handynr'};
	$message   = $data{'text'};
###################################### end modifications (10.10.2001, lf)

	# Valid SMS-Number (100% digits) or valid alias given ?
	if (($smsnumber =~ /\D/)  && (! $config{$smsnumber})) {
		&usage("Ungültige SMS-Nummer/Alias \"$smsnumber\" !");
		
	}
	# "translate" alias to number
	if ($config{$smsnumber}) {
		$smsnumber = $config{$smsnumber};
	}

###################################### begin modifications (10.10.2001, lf)
#        shift(@ARGV);
#        $message = join(" ",@ARGV);
###################################### end modifications (10.10.2001, lf)

}

# ** Login **

sub login {
	print "Logging in... \n" if ($debuglevel>1);
	
	# Prepare Request (POST)
	$request->method("POST");
	$request->uri($url_loginpage);

	# Insert Form-Data
	$request->content_type('application/x-www-form-urlencoded');
        $request->content("rv_passwd=".$config{"password"}."&rv_uname=".$config{"username"}."&rv_dologon=Anmelden");

	# Do the Request
	$response = $agent->request($request);	
	
	# Request succsesfull ?
	if ($response->is_success) {
		print "- Loaded sucessfully: $url_loginpage \n" if ($debuglevel>3);
	} else {
		fatalerror("login","Konnte nich laden: $url_loginpage",$response);
	}	

	# Did we get redirected ?
	if ($response->previous->is_redirect) {
		print "- Redirect zu: $RequestAgent::last_redirect \n" if ($debuglevel>4);
	} else {
		fatalerror("login","Kein redirect !");
	}
	
	# Login incorrect ?
	if ($RequestAgent::last_redirect =~ /failed/i) {
		fatalerror("login","Login falsch ! Benutzername/PW falsch ?");
	}

	# Session ID given ? 
	if ($response->previous->headers->header("Location") =~ /si=/) {
		# Filter out Sessionid
		$sessionid = $response->previous->headers->header("Location");
		$sessionid = (split(/si=/,$sessionid))[1];
		$sessionid =~ s/&.*//g;
	} else {
		fatalerror("login","Keine Session-ID erhalten. Login falsch ?");	
	}

	# Filter out remote host we got redirected to !
	$host = (split(/\//,$RequestAgent::last_redirect))[2];

	# Debug output
	print "Remote Host: $host\n" if ($debuglevel>2);
	print "Session-ID erhalten: $sessionid\n" if ($debuglevel >2);

	print "Login erfolgreich !\n" if ($debuglevel>1);
}

sub sendsms {
	my ($smsnumber,$message) = @_;

	print "Senden der SMS...\n" if ($debuglevel>1);
	
	# Build URL to sms-page
	my $url = sprintf($url_smspage,$host,$sessionid);

	# Set up the request
	$request->method("GET");
        $request->uri($url);
        
	# Do the Request
        $response = $agent->request($request);

        # Request succsesfull ?
        if ($response->is_success) {
                print "- Erfolgreich geladen: $url \n" if ($debuglevel>3);
        } else {
                fatalerror("send","Konnte nicht laden: $url",$response);
        }

        # Did we get redirected ?
        if ($response->previous->is_redirect) {
                print "- Redirect zu: $RequestAgent::last_redirect \n" if ($debuglevel>4);
        } else {
                fatalerror("send","Kein Redirect !");
        }

        # Message-ID given ? 
        if ($RequestAgent::last_redirect =~ /rv_mid=/) {
                # Filter out Message-ID
                $messageid = $RequestAgent::last_redirect;
                $messageid = (split(/rv_mid=/,$messageid))[1];
                $messageid =~ s/&.*//g;
        } else {
                fatalerror("login","Keine Session-ID erhalten, Login falsch ?");
        }

	print "Message-ID erhalten: $messageid\n" if ($debuglevel >2); 
 
	# ---------

        # Build the sms-send-url
	$url = sprintf($url_sendpage,$host);

	# Prepare Request (POST)
        $request->method("POST");
        $request->uri($url);
		
	my $secure_sessionid = $sessionid;
	$secure_sessionid =~ s/[^A-Za-z0-9.]//g;
	my $surl = "http://$host/online/smsfaxgengif.cnf?si=$secure_sessionid";
	print "Holen des Code-Images von $surl\n" if ($debuglevel >2);

	my $command = $config{"wget_path"}." -O ".$config{"code_temp"}." ".$surl;
	if ($debuglevel < 4) { `$command >/dev/null 2>&1`; } else {  `$command`; }

	
	# Get Security-Code from image using wget & gocr
	$command = $config{"gocr_path"}." ".$config{"code_temp"};
	print "OCR'ing Code-Image : $command\n" if ($debuglevel >3);
	my $scode = `$command`;
	chomp($scode);

	# replace "_" with "5" in code (gocr does not detect the "5", it seems)
	$scode =~ s/_/5/g;
###################################### begin modifications (10.10.2001, lf)
	# gocr has problems with 0 (zero) and O, but there are digits only...
	$scode =~ s/O/0/g;
	$scode =~ s/ //g;
###################################### end modifications (10.10.2001, lf)

	print "web.de-Image-Cookie OCR-decodiert: $scode\n" if ($debuglevel >3);

	`rm $config{"code_temp"}`; # delete tempfile
	
	# Build Form-Data
	my $formdata = sprintf($send_formvals,$sessionid,$messageid,$smsnumber,$message,$config{"username"},$scode);	
	#print $formdata."\n";

        # Insert Form-Data
        $request->content_type('application/x-www-form-urlencoded');
        $request->content($formdata);

	# Do the Request
        $response = $agent->request($request);

        # Request succsesfull ?
        if ($response->is_success) {
                print "- Erfolgreich geladen: $url \n" if ($debuglevel>3);
        } else {
                fatalerror("send","Konnte nicht laden: $url",$response);
        }
	
###################################### begin modifications (10.10.2001, lf)
	print "SMS an $smsnumber erfolgreich verschickt.\n" unless ($quiet)
###################################### end modifications (10.10.2001, lf)
}



# ** MAIN **


###################################### begin modifications (10.10.2001, lf)

##### auf laufende Instanzen überprüfen

&check_load;

##### SMS-Quotas überprüfen

# ----- perform HTTP referer check

my $ref_ok = 0;

print "Dein HTTP-Referer: " . $ENV{'HTTP_REFERER'} . "
\n"; foreach (@valid_referers) { if ($ENV{'HTTP_REFERER'} =~ /$_.*/) { print "Referer ist in Ordnung (" . $_ . ").
\n"; $ref_ok = 1; last; } } if (!$ref_ok) { print "Referer UNZULAESSIG! Sie dürfen dieses Script nicht benutzen!
\n"; finish_html (); exit (); } # ----- check IP subnet and print limits my $found = 0; my $z = -1; my ($sms_limit, $ip_group); print "Deine IP: " . $ENV{'REMOTE_ADDR'} . "
\n"; foreach (@subnets) { $z++; if ($ENV{'REMOTE_ADDR'} =~ /$_.*/) { $found = 1; $sms_limit = $limits[$z]; $ip_group = $_; last; } } if (!$found) { $sms_limit = $limits_other; $ip_group = "other"; } # ----- get today's date use Time::localtime; my $tm = localtime (time ()); my $today = sprintf ("%02d.%02d.%04d", $tm->mday, $tm->mon + 1, $tm->year + 1900); # ----- writes new file with resetted limits sub writenew ($) { my $sent = shift; print "Aktualisieren der Status-Datei...
\n"; open (LIMIT, ">$tmp_path/smswebde-$ip_group"); print LIMIT "date=" . $today . "\n"; print LIMIT "sent=" . $sent . "\n"; close (LIMIT); } # ---- reads parameters from file my %file = (); sub readfile () { open (LIMIT, "<$tmp_path/smswebde-$ip_group"); while () { my ($field, $value) = split /=/, $_; chomp $value; $file{$field} = $value; } close (LIMIT); } # create new file if needed if (!-e "$tmp_path/smswebde-$ip_group") { print "Status-Datei für " . $ip_group . " existiert noch nicht, wird neu angelegt.
\n"; writenew (0); } # read tmp file for this group readfile (); if ($file{date} != $today) { print "Status-Datei noch auf altem Datum, Aktualisierung notwendig.
\n"; writenew (0); # neu einlesen readfile (); } if ($file{sent} < $sms_limit) { print "Es sind heute (" . $file{date} . ") bereits " . $file{sent} . " SMS aus Ihrem IP-Subnetz verschickt worden.
\n"; print "Das Limit liegt in Ihrem Subnetz " . $ip_group . "* bei " . $sms_limit . " SMS pro Tag.
\n"; print "=> Es dürfen noch SMS versendet werden.
\n"; } else { print "=> Es sind heute bereits " . $file{sent} . " SMS verschickt worden! Sorry...
\n"; finish_html (); exit (); } # write new status file writenew ($file{sent} + 1); ###################################### end modifications (10.10.2001, lf) &read_configfile; &parse; &checksanity; if ($config{"proxy"}) { $agent->proxy("http",$config{proxy}); $RequestAgent::proxy_username=$config{"proxy_username"}; $RequestAgent::proxy_password=$config{"proxy_password"}; } &login; &sendsms($smsnumber,$message); ###################################### begin modifications (10.10.2001, lf) finish_html (); # ----- finish HTML code if terminated abnormally sub finish_html { print<<"...";


Zurück ]

... } ###################################### end modifications (10.10.2001, lf)