X-Git-Url: https://git.treefish.org/fex.git/blobdiff_plain/97b87610331f53e756d032ad21db786037f921a1..20160328:/bin/sexsend diff --git a/bin/sexsend b/bin/sexsend index 8a2a799..9a7d48b 100755 --- a/bin/sexsend +++ b/bin/sexsend @@ -12,14 +12,15 @@ use Getopt::Std; use Socket; use IO::Handle; use IO::Socket::INET; -use Digest::MD5 qw(md5_hex); # encypted ID / SID +use Digest::MD5 qw(md5_hex); # encypted ID / SID use constant k => 2**10; use constant M => 2**20; eval 'use Net::INET6Glue::INET_is_INET6'; -our $version = 20150729; +our $version = 20160328; +our $DEBUG = $ENV{DEBUG}; my %SSL = (SSL_version => 'TLSv1'); my $sigpipe; @@ -32,7 +33,7 @@ $0 =~ s:.*/::; $| = 1; # sexsend is default -$usage = +$usage = "usage: ... | $0 [options] [SEX-URL/]recipient [stream]\n". "options: -v verbose mode\n". " -g show transfer rate\n". @@ -43,7 +44,7 @@ $usage = "example: tail -f /var/log/syslog | $0 fex.flupp.org/admin log\n"; if ($0 eq 'sexget' or $0 eq 'fuckme') { - $usage = + $usage = "usage: $0 [options] [[SEX-URL/]user:ID] [stream]\n". "options: -v verbose mode\n". " -g show transfer rate\n". @@ -56,7 +57,7 @@ if ($0 eq 'sexget' or $0 eq 'fuckme') { } if ($0 eq 'sexxx') { - $usage = + $usage = "usage: $0 [-v] [-g] [-c] [-u [SEX-URL/]user] [-s stream] [files...]\n". "usage: $0 [-v] [-g] [-u [SEX-URL/]user] [-s stream] | ...\n". "options: -v verbose mode\n". @@ -102,7 +103,7 @@ $opt_u = $opt_s = $opt_c = $opt_t = ''; $_ = "$fexhome/config.pl"; require if -f; if ($0 eq 'sexxx') { - + # xx server URL, user and auth-ID if ($FEXXX = $ENV{FEXXX}) { $FEXXX = decode_b64($FEXXX) if $FEXXX !~ /\s/; @@ -118,7 +119,7 @@ if ($0 eq 'sexxx') { } close $idf; } - + getopts('hgvcu:s:') or die $usage; die $usage if $opt_h; die $usage unless -t; @@ -140,8 +141,10 @@ if ($0 eq 'sexxx') { unless ($user) { die "$0: no xx user found, use \"$0 -u user\"\n"; } - + } elsif ($0 eq 'sexget' or $0 eq 'fuckme') { + + $opt_g = 0; getopts('hgvVdu:') or die $usage; die $usage if $opt_h; @@ -150,11 +153,11 @@ if ($0 eq 'sexxx') { print "Version: $version\n"; exit unless @ARGV; } - + if (not $opt_u and @ARGV and $ARGV[0] =~ m{^anonymous|/|:}) { $opt_u = shift @ARGV; } - + if ($opt_u) { $fexcgi = $1 if $opt_u =~ s:(.+)/::; ($user,$id) = split(':',$opt_u); @@ -168,14 +171,14 @@ if ($0 eq 'sexxx') { unless ($fexcgi) { die "$0: no SEX URL found, use \"$0 -u SEX-URL/recipient\" or \"fexsend -I\"\n"; } - + unless ($user) { die "$0: no recipient found, use \"$0 -u SEX-URL/recipient\" or \"fexsend -I\"\n"; } - + } else { # sexsend - - $opt_g = 1; + + $opt_g = 0; getopts('hguvqVTt:') or die $usage; die $usage if $opt_h; @@ -183,7 +186,7 @@ if ($0 eq 'sexxx') { print "Version: $version\n"; exit unless @ARGV; } - + if ($opt_t and $opt_t =~ /^\d+$/) { $timeout = "&timeout=$opt_t"; } @@ -191,7 +194,7 @@ if ($0 eq 'sexxx') { my $save_user = $user; $user = shift or die $usage; $fexcgi = $1 if $user =~ s:(.+)/::; - + if ($user =~ /^anonymous/) { die "$0: need SEX-URL with anonymous SEX\n" unless $fexcgi; $mode = 'anonymous'; @@ -211,7 +214,7 @@ if ($0 eq 'sexxx') { die "$0: no SEX URL found, use \"$0 SEX-URL/recipient\" or \"fexsend -I\"\n"; } } - + } &get_ssl_env; @@ -220,14 +223,14 @@ $fexcgi =~ s(^http://)()i; $fexcgi =~ s(/fup.*)(); $server = $fexcgi; -if ($server =~ s(^https://)()i) { $port = 443 } -elsif ($server =~ /:(\d+)/) { $port = $1 } -else { $port = 80 } +if ($server =~ s(^https://)()i) { $port = 443 } +elsif ($server =~ /:(\d+)/) { $port = $1 } +else { $port = 80 } $server =~ s([:/].*)(); ## set up tcp/ip connection -# $iaddr = gethostbyname($server) +# $iaddr = gethostbyname($server) # or die "$0: cannot find ip-address for $server $!\n"; # socket(SH,PF_INET,SOCK_STREAM,getprotobyname('tcp')) or die "$0: socket $!\n"; # connect(SH,sockaddr_in($port,$iaddr)) or die "$0: connect $!\n"; @@ -240,21 +243,21 @@ if ($port == 443) { } eval "use IO::Socket::SSL"; die "$0: cannot load IO::Socket::SSL\n" if $@; - $SH = IO::Socket::SSL->new( - PeerAddr => $server, - PeerPort => $port, + $SH = IO::Socket::SSL->new( + PeerAddr => $server, + PeerPort => $port, Proto => 'tcp', %SSL - ); -} else { + ); +} else { $SH = IO::Socket::INET->new( PeerAddr => $server, PeerPort => $port, - Proto => 'tcp', - ); + Proto => 'tcp', + ); } -die "cannot connect $server:$port - $!\n" unless $SH; +die "cannot connect $server:$port - $!\n" unless $SH; warn "TCPCONNECT to $server:$port\n" if $opt_v; # autoflush $SH 1; @@ -328,10 +331,10 @@ if ($mode eq 'anonymous') { } request("POST /sex?BS=$bs&user=$user$mode$type$timeout$stream HTTP/1.0"); -print STDERR "==> (streaming ...)\n" if $opt_v; +print STDERR "--> (streaming ...)\n" if $opt_v; transfer(STDIN,$SH); - + exit; @@ -340,7 +343,7 @@ sub transfer { my $destination = shift; my ($t0,$t1,$tt); my ($B,$b,$bt); - + $t0 = $t2 = time; $tt = $t0-1; $t1 = 0; @@ -370,9 +373,9 @@ sub transfer { } die "$0: no stream data\n" unless $B; - + $tt = (time-$t0)||1; - + if ($opt_v or $opt_g) { if ($B>2097152) { printf STDERR "transfered: %d MB in %d s with %d kB/s\n", @@ -385,27 +388,29 @@ sub transfer { $B,$tt,int($B/1024/$tt); } } - + } sub request { my $req = shift; - - print STDERR "==> $req\n" if $opt_v; - syswrite $SH,"$req\r\n\r\n"; + + print STDERR "--> $req\n" if $opt_v; + syswrite $SH,"$req\r\n"; + syswrite $SH,"User-Agent: sexsend\r\n"; + syswrite $SH,"\r\n"; for (;;) { unless (defined($_ = &getline)) { die "$0: server has closed the connection\n"; } if (/^HTTP\/[\d\.]+ 200/) { - print STDERR "<== $_" if $opt_v; + print STDERR "<-- $_" if $opt_v; last; } elsif (/^HTTP\/[\d\.]+ 199/) { - print STDERR "<== $_" if $opt_v; + print STDERR "<-- $_" if $opt_v; } else { if ($opt_v) { - print STDERR "<== $_"; + print STDERR "<-- $_"; exit 3; } else { s:^HTTP/[ \d\.]+::; @@ -417,7 +422,7 @@ sub request { while (defined($_ = &getline)) { last if /^\s*$/; $H{uc($1)} = $2 if /(.+):\s*(.+)/; - print STDERR "<== $_" if $opt_v; + print STDERR "<-- $_" if $opt_v; } } @@ -456,23 +461,23 @@ sub query_sid { my ($server,$port,$id) = @_; my $req; local $_; - + $req = "GET SID HTTP/1.1"; - print STDERR "==> $req\n" if $opt_v; + print STDERR "--> $req\n" if $opt_v; syswrite $SH,"$req\r\n\r\n"; $_ = &getline; - unless (defined $_ and /\w/) { + unless (defined $_ and /\w/) { print STDERR "\n" if $opt_v; die "$0: no response from server\n"; } s/\r//; if (/^HTTP.* 201 (.+)/) { - print STDERR "<== $_" if $opt_v; + print STDERR "<-- $_" if $opt_v; $id = 'MD5H:'.md5_hex($id.$1); - while (defined($_ = &getline)) { + while (defined($_ = &getline)) { s/\r//; last if /^\n/; - print STDERR "<== $_" if $opt_v; + print STDERR "<-- $_" if $opt_v; } } else { die "$0: $server does not support session ID\n"; @@ -480,7 +485,7 @@ sub query_sid { return $id; } -sub sigpipehandler { +sub sigpipehandler { local $_ = ''; $SIG{ALRM} = sub { }; alarm(1); @@ -503,15 +508,15 @@ sub getline { local $SIG{ALRM} = sub { die "$0: timeout while waiting for server reply\n" }; alarm($opt_t||300); - + # must use sysread to avoid perl line buffering while (sysread $SH,$c,1) { $line .= $c; last if $c eq "\n"; } - + alarm(0); - + return $line; } @@ -520,7 +525,7 @@ sub decode_b64 { local $_ = shift; my $uu = ''; my ($i,$l); - + tr|A-Za-z0-9+=/||cd; s/=+$//; tr|A-Za-z0-9+/| -_|; @@ -559,9 +564,9 @@ sub get_ssl_env { $SSL{SSL_verify_mode} = $ENV{SSLVERIFY} if defined($ENV{SSLVERIFY}); foreach my $opt (qw( SSL_version - SSL_cipher_list - SSL_verify_mode - SSL_ca_path + SSL_cipher_list + SSL_verify_mode + SSL_ca_path SSL_ca_file) ) { my $env = uc($opt); @@ -604,16 +609,10 @@ sub serverconnect { my ($server,$port) = @_; my $connect = "CONNECT $server:$port HTTP/1.1"; local $_; - - if ($opt_v and $port == 443 and %SSL) { - foreach my $v (keys %SSL) { - printf "%s => %s\n",$v,$SSL{$v}; - } - } - + if ($proxy) { tcpconnect(split(':',$proxy)); - if ($port == 443) { + if ($https) { printf "--> %s\n",$connect if $opt_v; nvtsend($connect,""); $_ = <$SH>; @@ -622,14 +621,13 @@ sub serverconnect { unless (/^HTTP.1.. 200/) { die "$0: proxy error : $_"; } - eval "use IO::Socket::SSL"; - die "$0: cannot load IO::Socket::SSL\n" if $@; + &enable_ssl; $SH = IO::Socket::SSL->start_SSL($SH,%SSL); } } else { tcpconnect($server,$port); } -# if ($port == 443 and $opt_v) { +# if ($https and $opt_v) { # printf "%s\n",$SH->get_cipher(); # } } @@ -638,16 +636,15 @@ sub serverconnect { # set up tcp/ip connection sub tcpconnect { my ($server,$port) = @_; - + if ($SH) { close $SH; undef $SH; } - - if ($port == 443) { + + if ($https) { # eval "use IO::Socket::SSL qw(debug3)"; - eval "use IO::Socket::SSL"; - die "$0: cannot load IO::Socket::SSL\n" if $@; + &enable_ssl; $SH = IO::Socket::SSL->new( PeerAddr => $server, PeerPort => $port, @@ -661,24 +658,37 @@ sub tcpconnect { Proto => 'tcp', ); } - + if ($SH) { autoflush $SH 1; + binmode $SH; } else { die "$0: cannot connect $server:$port - $@\n"; } - + print "TCPCONNECT to $server:$port\n" if $opt_v; } +sub enable_ssl { + eval "use IO::Socket::SSL"; + die "$0: cannot load IO::Socket::SSL\n" if $@; + eval '$SSL{SSL_verify_mode} = 0 if Net::SSLeay::SSLeay() <= 9470143'; + if ($opt_v) { + foreach my $v (keys %SSL) { + printf "%s => %s\n",$v,$SSL{$v}; + } + } +} + + sub sendheader { my $sp = shift; my @head = @_; my $head; - + push @head,"Host: $sp"; - + foreach $head (@head) { print "--> $head\n" if $opt_v; print {$SH} $head,"\r\n"; @@ -690,12 +700,12 @@ sub sendheader { sub nvtsend { local $SIG{PIPE} = sub { $sigpipe = "@_" }; - + $sigpipe = ''; - + die "$0: internal error: no active network handle\n" unless $SH; die "$0: remote host has closed the link\n" unless $SH->connected; - + foreach my $line (@_) { print {$SH} $line,"\r\n"; if ($sigpipe) { @@ -703,17 +713,29 @@ sub nvtsend { return 0; } } - + return 1; } +sub quote { + local $_ = shift; + s/([^\w\@\/%^,.=+_:+-])/\\$1/g; + return $_; +} + + +sub debug { + print "## DEBUG: @_\n" if $DEBUG; +} + + # from MIME::Base64::Perl sub encode_b64 { my $res = ""; my $eol = "\n"; my $padding; - + pos($_[0]) = 0; $res = join '',map(pack('u',$_)=~ /^.(\S*)/, ($_[0]=~/(.{1,45})/gs)); $res =~ tr|` -_|AA-Za-z0-9+/|;