#!/usr/bin/perl -U # # v0.02 (c)mahatma, no warranty, 12/2004 # # RSA code (c) John Hanna 2004, GPL, http://shop-js.sf.net, 10/13/2004 use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); # optional: #use MD5; my $use_MD5=1; # uncomment to use faster MD5 lib use Math::BigInt; my $use_BigInt=1; # comment to no RSA (for $auth==1) my $cgi = new CGI; my $session="$ENV{REMOTE_ADDR} $ENV{HTTP_X_FORWARDED_FOR}"; my %b64; my $b64s='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"'; {my $n=0; for (split(//,$b64s)) {$b64{$_}=$n++}} umask 0177; ### config start ## $auth - password: 0-none/.htpasswd; 1:crypt; 2:unencrypted; 3:md5 ## 1 - RSA encrypted login; 2,3 - md5 hashed; my $auth=0; ## RSA login only ($auth==1 && $use_BigInt==1): ## NOW you MUST generate own keys: http://shop-js.sf.net/crypto2.htm ## other ways may be in new version my @pub_rsa_key=(136867779,84822705,160); my $priv_rsa_key=[[14636137,3346344,66],[230684127,11],[139074205,13]]; my $pub_rsa_e=17; ## don't touch this (better): my ($user,$password,@sig) = $auth==0?($ENV{REMOTE_USER},''):login_get(); my $passwd=""; # passwords filename ($auth!=0) my %hpasswd; # predefined or buffer ## you may use own password database (undef $passwd first): #dbmopen(%hpasswd,'/etc/dbpasswd/dbpasswd',600); ## or you may enter own login: #$hpasswd{'user'}='password'; my $base="./"; my $webbase="/"; my $iam=$ENV{SCRIPT_NAME}; my $secure=0; # 0:none; 1:uid/gid; 2:1+deny chown/chmod my @suid; ## for upload: #$cgi::POST_MAX = 1048576; # max to upload #my $temp='/tmp/'; # undef = direct #my $mv='/bin/mv'; # if $temp defined only ### config end ### alt config - standard multi-user unix hosting example, exec as root #my $auth=1; #my @pub_rsa_key=(136867779,84822705,160); #my $priv_rsa_key=[[14636137,3346344,66],[230684127,11],[139074205,13]]; #my $pub_rsa_e=17; #my ($user,$password,@sig) = $auth==0?($ENV{REMOTE_USER},''):login_get(); #my $passwd="/etc/shadow"; #my %hpasswd; #my $base="/home/$user/public_html/"; #my $webbase="/~$user/"; #my $iam=$ENV{SCRIPT_NAME}; #my $secure=1; #my @suid=($user,$user); ##$cgi::POST_MAX = 1048576; ##my $temp='/tmp/'; ##my $mv='/bin/mv'; ### alt config end my @md5_i=(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9); my @md5_s=(7,12,17,22,5,9,14,20,4,11,16,23,6,10,15,21); my @md5_t=(0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391); #push (@INC, "/home/~$user"); #$ENV{PATH}="/home/~$user"; my $header="Content-type: text/html\n\n"; my $head=''; my $error; my $path=param('path')||''; my $action=param('action')||'start'; my @item; my $lastpath=''; my $it; for(my $i=0;$i<65535 && defined($it=param("item$i")) && $it ne '';$i++){ push @item,param("item$i"); }; ### install ### install() if($ARGV[0] eq install); if($action eq 'menu'){a_menu();ex(0)} elsif($action eq 'start'){a_start();ex(0)} ### /install ### if(!login()){ $error.='Invalid login
' if($user ne ''); $error.='Not logged in!'; $user=$password=''; @item=(); a_ls(); ex(-2); } seq() if($secure>0); if($action eq 'ls' || $action eq 'reload'){a_lsd()} elsif($action eq 'get'){a_get()} elsif($action eq 'upload'){a_upload()} elsif($action eq 'delete'){a_rm()} elsif($action eq 'mkdir'){a_mkdir()} elsif($action eq 'chmod'){a_chmod()} elsif($action eq 'chown'){a_chown()} elsif($action eq 'link'){a_link()} elsif($action eq 'symlink'){a_symlink()} elsif($action eq 'logoff'){a_logoff()} else{zerr("Invalid command \"$action\"")} ex(0); ### login ### sub login_get{ my $i=param('sig'); $i=rsaDecode($priv_rsa_key,$i) if($auth==1&&$use_BigInt&&$i ne ''); my @s=split(/:/,$i); for($i=0;$i<=$#s;$i++){@s[$i]=unesc(@s[$i])} return @s; } sub login_js{ my $t='p'; $t="md5h($t)" if($auth==3); $t="md5h($t+t+s)" if($auth>1); $t="escape(fm1.document.f.item0.value)+':'+escape($t)+':'+escape(t)"; $t.="+':'+escape(s)" if($auth==1); $t="rsaEncode([$pub_rsa_e],".a2js("%u",@pub_rsa_key).",$t)" if ($auth==1&&$use_BigInt); $t=qq( var sig=''; function setpass(p,t,s){sig=$t} function sign(f){f.sig.value=sig} function logoff(){sig=''} ); $t=md5h_js().$t if(index($t,'md5h',0)>=0); $t=RSA_js().$t if(index($t,'rsa',0)>=0); return $t; } sub login{ return 1 if($auth==0); my $u,$p,$l; if(defined($passwd)){ open PF,"<$passwd" or return 0; while(defined($l=)){ ($u,$p)=(split(/:/, $l))[0,1]; if($u eq $user){ $hpasswd{$u}=$p; last; } } close(PF); } return 0 if(!defined($p=$hpasswd{$user})); if($auth==1){ return 0 if(@sig[1] ne $session); $password=crypt($password,$p) }else{ $p=md5h("$p@sig[0]$session"); } return ($password eq $p); } sub logoff{ @sig=[]; $user=$password=''; } ### /login ### sub md5h{ my ($s,$a,$b,$c,$d,$xx)=(shift,0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xffffffff); return MD5->hexhash($s) if($use_MD5); my $e,$m,$i,$j,@x; my $l=length($s); my $n=((($l+8)>>6)+1)<<4; $xx++; for($i=0;$i<$n;$i++) {@x[$i]=0} $s.="\x80"; for($i=0;$i<=$l;$i++) {@x[$i>>2]|=(ord(substr($s,$i,1))&0xFF)<<(($i&3)<<3)} @x[$n-2]=$l<<3; for($i=0;$i<$n;$i+=16){ my ($a1,$b1,$c1,$d1)=($a,$b,$c,$d); for($j=0;$j<64;$j++){ $e=(((($m=($a+@x[$i+@md5_i[$j]]+@md5_t[$j]+(($e=$j>>4)==0?($b&$c)|($d&~$b):$e==1?($b&$d)|($c&~$d):$e==2?$b^$c^$d:$c^($b|~$d)))%$xx)<<($l=@md5_s[$e<<2|($j&3)]))|($m>>(32-$l))&((1<<$l)-1))+$b)%$xx; $a=$d;$d=$c;$c=$b;$b=$e; } $a=($a+$a1)%$xx;$b=($b+$b1)%$xx;$c=($c+$c1)%$xx;$d=($d+$d1)%$xx; } my @r=($a,$b,$c,$d),$h=''; for($i=0;$i<16;$i++) {$h.=sprintf("%x%x",@r[$j=$i>>2]>>4&15,@r[$j]&15);@r[$j]>>=8;} return $h; } ################################################################## ### rsa ### sub rc4 { my ($key, $string)=@_; #"""Return string rc4 (de/en)crypted with RC4.""" my($i,$j,$klen,@s)=(0,0,length($key),0 .. 255); for(0 .. 1) { for $i (0 .. 255) { $j=(ord(substr($key,$i%$klen,1))+$s[$i]+$j)%256; ($s[$i],$s[$j])=($s[$j],$s[$i]) } } my $r=''; for $i (0 .. length($string)-1) { my $i2=$i % 256; $j=($s[$i2]+$j)%256; ($s[$i2],$s[$j])=($s[$j],$s[$i2]); $r.=chr(ord(substr($string,$i,1))^$s[($s[$i2]+$s[$j])%256]); } return $r; } sub crt_RSA { my ($m, $d, $p, $q)=@_; #""" Compute m**d mod p*q for RSA private key operations.""" return $m->bmodpow($d,$p*$q); } sub base64ToText { my $text=shift; my ($r,$m,$a,$c)=('',0,0,0); for $i (0 .. length($text)-1) { $c=$b64{substr($text,$i,1)}; #print substr($text,$i,1),"=$i=$c|\n"; if(defined $c) { $r .= chr(($c << (8-$m))& 255 | $a) if $m; $a = $c >> $m; $m=($m+2) % 8; } } return $r; } sub t2b { my $s=shift; my $r=Math::BigInt->bzero(); my $m=Math::BigInt->bone(); for $i (0 .. length($s)-1) { $r+=$m*ord(substr($s,$i,1)); $m*=256; } return $r } sub b2t { my $b=shift; my $r=''; while($b) { $r.=chr($b % 256); $b/=256; } return $r; } sub fix { my $a=shift; my $r=Math::BigInt->bzero(); my $s=0; for $i (@$a) { $r+=Math::BigInt->new($i) << $s; $s+=28; } return $r; } sub rsaDecode { my ($key,$text)=@_; #""" decode the text based on the given rsa key. """ # separate the session key from the text $text=base64ToText($text); my $sessionKeyLength=ord(substr($text,0,1)); my $sessionKeyEncryptedText=substr($text,1,$sessionKeyLength); $text=substr($text,$sessionKeyLength+1); my $sessionKeyEncrypted=t2b($sessionKeyEncryptedText); # un-rsa the session key my $sessionkey=crt_RSA($sessionKeyEncrypted,fix($key->[0]),fix($key->[1]),fix($key->[2])); $sessionkey=b2t($sessionkey); $text=rc4($sessionkey,$text); return $text } ### /rsa ### sub err_{ my $e=shift; return "$!; $action \"$e\"
"; } sub ex{ exit shift; } sub seq{ my $u=defined(@suid[0])?(getpwnam(@suid[0]) or &zerr("uid:\"@suid[0]\"")):-1; my $g=defined(@suid[1])?(getgrnam(@suid[1]) or &zerr("gid:\"@suid[1]\"")):-1; $)="$g $g"; $(=$g; $<=$>=$u; if($) ne "$g $g" or $(!=$g or $!=$u){ print "$header Security error (set uid/gid)"; &ex(-3); } } sub seq2{ &zerr('Denyed') if($secure==2); } sub chk{ my $n=unesc(shift); my @d=split(/\//,$n); for (my $i=0;$i<=$#d;$i++){ if(@d[$i] eq '.' or @d[$i] eq ''){ splice(@d,$i,1); $i-- if($i>-1); }elsif(@d[$i] eq '..'){ if($i>0){splice(@d,--$i,2)} else{splice(@d,$i,1)}; $i-- if($i>-1); } } $n=''; my $f=pop(@d); for my $i(@d) {$n.=$i.'/'}; $n.=$f; return $n; } sub a_logoff{ $error.='Logged out!'; logoff(); @item=(); a_ls(); } sub a_get{ for my $it(@item){ my @s=stat(my $n=$base.(my $i=&chk("$path$it"))); # err($n) if(!$s); # if(-d $n){ if(@s[2]&0x4000){ $lastpath=$path; $path=$i; $path.='/' if($path ne ''); a_lsd(); }else{ open FH,"<$n" or err($it); print "Content-type: application/unknown\nContent-Length: @s[7]\nLast-Modified: ".localtime(@s[9])."\nContent-Transfer-Coding: binary\nContent-Disposition: download; filename=\"$it\"\n\n", or err($it); close(FH); } } } sub a_upload{ for my $it(@item){ my @n=split(/[\\\/:]/,$it); my $d=&chk($path.pop(@n)); my $f=defined($temp)?"$temp$user.".time.".tmp":"$base$d"; open FH, ">$f" or err($it); # chown @own[0],@own[1],$f or err($it.rm()) if(defined(@own)); # binmode FH; print FH <$it> or err($it.rm()); close (FH); `$mv -f $f $base$d` if(defined($temp)); } a_lsd(); sub rm{ close FH; unlink FH; return ''; } } sub a_link{ for my $its(@item){for my $it(split(/,/,$its)){ my ($l,$ll)=split(/:/,$it,2); link $base.&chk($ll),$base.&chk($l) or &err("$l -> $ll"); }} a_lsd(); } sub a_symlink{ for my $its(@item){for my $it(split(/,/,$its)){ my ($l,$ll)=split(/:/,$it,2); my @l0=split(/\//,&chk($l)); my @l1=split(/\//,&chk($ll)); my $n=0; my $i; for($i=0;($i<=$#l0)&&(@l0[$i] eq @l1[$i]);$i++){ $n++}; splice(@l0,0,$n); splice(@l1,0,$n); $ll=''; my $f=pop(@l1); for($i=0;$i<$#l0;$i++) {$ll.='../'}; for $i(@l1) {$ll.=$i.'/'}; $ll.=$f; symlink $ll,"$base$l" or &err("$l -> $ll"); }} a_lsd(); } sub a_mkdir{ for my $it(@item){mkdir($base.&chk("$path$it")) or err(&chk("$path$it"))} a_lsd(); } sub a_rm{ for my $its(@item){for my $it(split(/,/,$its)){ my $n=$base.&chk("$path$it"); if(-l $n) {unlink($n) or err($it)} elsif(-d $n) {rmdir($n) or err($it)} else{unlink($n) or err($it);} }}; a_lsd(); }; sub a_chmod{ seq2(); for my $its(@item){for my $it(split(/,/,$its)){ my @it1=split(/:/,$it,2); #### try 1 or 2!!! @it1[1]=$base.&chk($path.@it1[1]); chmod @it1 or err($it); }}; a_lsd(); }; sub zerr{ my $e=shift; $error.="$e
"; a_lsd(); &ex(-1); } sub a_chown{ seq2(); for my $its(@item){ my @its1=split(/,/,$its); my @u=split(/:/,pop(@its1)); my @uid; if(@u[0] && @u[0] ne '') {($uid=getpwnam(@u[0])) or &zerr(@u[0]);} my $gid; if(@u[1] && @u[1] ne '') {($gid=getgrnam(@u[1])) or &zerr(@u[1]);} for my $it(@its1){ chown $uid||-1,$gid||-1,$base.&chk("$path$it") or err($it); } } a_lsd(); } ################################################################## sub err{ $error.=&err_(shift||''); a_lsd(); &ex(-1); } sub a_lsd{ @item=(''); a_ls(); } sub esc{ my $x=shift; #$x=~s/([\x00-\x29\x2c\x3a-\x3f\x5b-\x5e\x60\x7b-\x7f])/sprintf('%%%02X',ord($1))/eg; $x=~s/([\x00-\x1f,:\"\'\\])/sprintf('%%%02X',ord($1))/eg; return $x; } sub unesc{ my $x=shift; $x=~s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; return $x; } sub a_ls{ my $e=''; my $err; my $t=qq($header$head
$session
Login:


$x); $t.=" onload='document.f.item0.focus()'"; } $e.=qq(); }else{$t.=" onload=\'$ret\'";}; $t.=">$e"; print $t; }; ### install ### sub a2js{ my ($f,$s,$c)=(shift,'[',''); for my $x(@_){ $s.=$c.sprintf($f,$x); $c=','; } return "$s]"; } sub md5h_js{ return "var md5_i=".&a2js("%u",@md5_i).",\nmd5_s=".&a2js("%u",@md5_s).",\nmd5_t=".&a2js("0x%x",@md5_t).qq(,nums='0123456789abcdef'.split(''); function s32(x,y){ var l=(x&0xFFFF)+(y&0xFFFF); return (((x>>16)+(y>>16)+(l>>16))<<16)|(l&0xFFFF); } function md5h(s){ var a=0x67452301,b=0xefcdab89,c=0x98badcfe,d=0x10325476,e,m,l=s.length,n=(((l+8)>>6)+1)<<4,i,j,x=[]; for(i=0;i>2]|=(s.charCodeAt(i)&0xFF)<<((i&3)<<3); x[i>>2]|=0x80<<((i&3)<<3); x[n-2]=l<<3; for(i=0;i>4)==0?(b&c)|(d&~b):e==1?(b&d)|(c&~d):e==2?b^c^d:c^(b|~d))),s32(x[i+md5_i[j]],md5_t[j])))<<(l=md5_s[e<<2|(j&3)]))|(m>>>(32-l))),b); a=d;d=c;c=b;b=e; } a=s32(a1,a);b=s32(b1,b);c=s32(c1,c);d=s32(d1,d); } var r=[a,b,c,d],h=''; for(i=0;i<16;i++) {h+=nums[r[j=i>>2]>>4&15]+nums[r[j]&15];r[j]>>=8;} return h; } ); } # - suggested (not sure): # "e=s32..."-> e=(((m=a+((e=j>>4)==0?(b&c)|(d&~b):e==1?(b&d)|(c&~d):e==2?b^c^d:c^(b|~d))+x[i+md5_i[j]]+md5_t[j])<<(l=md5_s[e<<2|(j&3)]))|(m>>>(32-l)))+b; # "a=s32..."-> a+=a1;b+=b1;c+=c1;d+=d1; # and remove "s32" func sub RSA_js{ < bs=16, 64bit -> bs=32 // bm is the mask, bs is the shift //bm=0xf; bs=4; // low base useful for testing if digits handled ok bs=28; bx2=1<>1; bd=bs>>1; bdm=(1 << bd) -1 log2=Math.log(2) function badd(a,b) { // binary add var al=a.length, bl=b.length if(al < bl) return badd(b,a) var c=0, r=[], n=0 for(; n>>=bs } for(; n>>=bs } if(c) r[n]=c return r } function beq(a,b) { // returns 1 if a == b if(a.length != b.length) return 0 for(var n=a.length-1; n>=0; n--) if(a[n] != b[n]) return 0 return 1 } function bsub(a,b) { // binary subtract var al=a.length, bl=b.length, c=0, r=[] if(bl > al) {return []} if(bl == al) { if(b[bl-1] > a[bl-1]) return [] if(bl==1) return [a[0]-b[0]] } for(var n=0; n>=bs } for(;n>=bs } if(c) {return []} if(r[n-1]) return r while(n>1 && r[n-1]==0) n--; return r.slice(0,n) } function bmul(a,b) { // binary multiply b=b.concat([0]) var al=a.length, bl=b.length, r=[], n,nn,aa, c, m var g,gg,h,hh, ghhb for(n=al+bl; n>=0; n--) r[n]=0 for(n=0; n>bd; h=aa & bdm m=n for(nn=0; nn>bd; g=g & bdm //(gg*2^15 + g) * (hh*2^15 + h) = (gghh*2^30 + (ghh+hgg)*2^15 +hg) ghh = g * hh + h * gg ghhb= ghh >> bd; ghh &= bdm c += r[m] + h * g + (ghh << bd) r[m] = c & bm c = (c >> bs) + gg * hh + ghhb } } } n=r.length if(r[n-1]) return r while(n>1 && r[n-1]==0) n--; return r.slice(0,n) } function blshift(a,b) { var n, c=0, r=[] for(n=0; n>=bs } if(c) r[n]=c return r } function brshift(a) { var c=0,n,cc, r=[] for(n=a.length-1; n>=0; n--) { cc=a[n]; c<<=bs r[n]=(cc | c)>>1 c=cc & 1 } while(r.length > 1 && r[r.length-1]==0) { r=r.slice(0,-1) } this.a=r; this.c=c return this } function zeros(n) {var r=[]; while(n-->0) r[n]=0; return r} function toppart(x,start,len) { var n=0 while(start >= 0 && len-->0) n=n*bx2+x[start--] return n } //14.20 Algorithm Multiple-precision division from HAC function bdiv(x,y) { var n=x.length-1, t=y.length-1, nmt=n-t // trivial cases; x < y if(n < t || n==t && (x[n]0 && x[n]==y[n] && x[n-1]0; i--) y[i]=((y[i]<> shift2); y[0]=(y[0]<0; i--) x[i]=((x[i]<> shift2); x[0]=(x[0]<t; i--) { m=i-t-1 if(i >= x.length) q[m]=1 else if(x[i] == yt) q[m]=bm else q[m]=Math.floor(toppart(x,i,2)/yt) topx=toppart(x,i,3) while(q[m] * top > topx) q[m]-- //x-=q[m]*y*b^m y2=y2.slice(1) x2=bsub(x,bmul([q[m]],y2)) if(x2.length==0) { q[m]-- x2=bsub(x,bmul([q[m]],y2)) } x=x2 } // de-normalize if(shift) { for(i=0; i>shift) | ((x[i+1] << shift2) & bm); x[x.length-1]>>=shift } while(q.length > 1 && q[q.length-1]==0) q=q.slice(0,q.length-1) while(x.length > 1 && x[x.length-1]==0) x=x.slice(0,x.length-1) this.mod=x this.q=q return this } function bmod(p,m) { // binary modulo if(m.length==1) { if(p.length==1) return [p[0] % m[0]] if(m[0] < bdm) return [simplemod(p,m[0])] } var r=bdiv(p,m) return r.mod } function simplemod(i,m) { // returns the mod where m < 2^bd if(m>bdm) return mod(i,[m]) var c=0, v for(var n=i.length-1; n>=0; n--) { v=i[n] c=((v >> bd) + (c<=0; n--) mu[n]=0; mu=bdiv(mu,m).q for(n=0; n 0) { return bmod2(x.slice(0,xl).concat(bmod2(x.slice(xl),m,mu)),m,mu) } var ml1=m.length+1, ml2=m.length-1,rr //var q1=x.slice(ml2) //var q2=bmul(q1,mu) var q3=bmul(x.slice(ml2),mu).slice(ml1) var r1=x.slice(0,ml1) var r2=bmul(q3,m).slice(0,ml1) var r=bsub(r1,r2) //var s=('x='+x+'\\nm='+m+'\\nmu='+mu+'\\nq1='+q1+'\\nq2='+q2+'\\nq3='+q3+'\\nr1='+r1+'\\nr2='+r2+'\\nr='+r); if(r.length==0) { r1[ml1]=1 r=bsub(r1,r2) } for(var n=0;;n++) { rr=bsub(r,m) if(rr.length==0) break r=rr if(n>=3) return bmod2(r,m,mu) } return r } function sub2(a,b) { var r=bsub(a,b) if(r.length==0) { this.a=bsub(b,a) this.sign=1 } else { this.a=r this.sign=0 } return this } function signedsub(a,b) { if(a.sign) { if(b.sign) { return sub2(b,a) } else { this.a=badd(a,b) this.sign=1 } } else { if(b.sign) { this.a=badd(a,b) this.sign=0 } else { return sub2(a,b) } } return this } function modinverse(x,n) { // returns x^-1 mod n // from Bryan Olson var y=n.concat(), t, r, bq, a=[1], b=[0], ts a.sign=0; b.sign=0 while( y.length > 1 || y[0]) { t=y.concat() r=bdiv(x,y) y=r.mod q=r.q x=t t=b.concat(); ts=b.sign bq=bmul(b,q) bq.sign=b.sign r=signedsub(a,bq) b=r.a; b.sign=r.sign a=t; a.sign=ts } if(beq(x,[1])==0) return [0] // No inverse; GCD is x if(a.sign) { a=bsub(n,a) } return a } function crt_RSA(m, d, p, q) { // Compute m**d mod p*q for RSA private key operations. -- Bryan Olson via deja.com var xp = bmodexp(bmod(m,p), bmod(d,bsub(p,[1])), p) var xq = bmodexp(bmod(m,q), bmod(d,bsub(q,[1])), q) var t=bsub(xq,xp); if(t.length==0) { t=bsub(xp,xq) t = bmod(bmul(t, modinverse(p, q)), q); t=bsub(q,t) } else { t = bmod(bmul(t, modinverse(p, q)), q); } return badd(bmul(t,p), xp) } // conversion functions: // text to binary and binary to text, text to base64 and base64 to text // OK, so this isn't exactly base64 -- fix it if you care function t2b(s) { var bits=s.length*8, bn=1, r=[0], rn=0, sn=0, sb=1; var c=s.charCodeAt(0) for(var n=0; n bm) {bn=1; r[++rn]=0; } if(c & sb) r[rn]|=bn; bn<<=1 if((sb<<=1) > 255) {sb=1; c=s.charCodeAt(++sn); } } return r; } function b2t(b) { var bits=b.length*bs, bn=1, bc=0, r=[0], rb=1, rn=0 for(var n=0; n 255) {rb=1; r[++rn]=0; } if((bn<<=1) > bm) {bn=1; bc++; } } while(r[rn]==0) {rn--;} var rr='' for(var n=0; n<=rn; n++) rr+=String.fromCharCode(r[n]); return rr; } b64s='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"' function textToBase64(t) { var r=''; var m=0; var a=0; var tl=t.length-1; var c for(n=0; n<=tl; n++) { c=t.charCodeAt(n) r+=b64s.charAt((c << m | a) & 63) a = c >> (6-m) m+=2 if(m==6 || n==tl) { r+=b64s.charAt(a) if((n%45)==44) {r+="\\n"} m=0 a=0 } } return r } function base64ToText(t) { var r=''; var m=0; var a=0; var c for(n=0; n= 0) { if(m) { r+=String.fromCharCode((c << (8-m))&255 | a) } a = c >> m m+=2 if(m==8) { m=0 } } } return r } // RC4 stream encryption // adapted from www.cpan.org crypt::rc4 -- thanks! function rc4(key, text) { var i, x, y, t, x2, kl=key.length; s=[]; for (i=0; i<256; i++) s[i]=i y=0 for(j=0; j<2; j++) { for(x=0; x<256; x++) { y=(key.charCodeAt(x%kl) + s[x] + y) % 256 t=s[x]; s[x]=s[y]; s[y]=t } } var z="" for (x=0; x>n) | ((a<<(8-n))&255)):a;} function hash(s,l) { var sl=s.length,r=[],rr='',v=1,lr=4; for(var n=0; n); } sub a_menu{ print $header,menu(); }; ##################################################### sub start{ return qq($head FM/3 Frames & JavaScript required ) } sub a_start{ print $header,start(); } sub wrfile{ my $f=shift; my $s=shift; my $m=shift; my %ss=('fm3.cgi\?action=menu'=>'fm3menu.htm'); for my $i (keys %ss) {$s=~s/$i/$ss{$i}/g} open FF,">$f" or die $!; print FF $s; close(FF); chmod $m,$f; } sub install{ my $ss='',$c; my $n=1; my @st=stat($0); open FF,"<$0" or die $!; while (defined($c=$s=)){ chomp($c); $ss.=$s if($n=$n?$c ne '### install ###':$c eq '### /install ###'); } close(FF); $iam='fm3.cgi'; &wrfile($iam,$ss,@st[2]); &wrfile("fm3menu.htm",menu(),0444); &wrfile("fm3.htm",start(),0444); exit(0); } 1; =head1 NAME fm.pl - FM/3, File Manager for WWW (uploader, etc). =head1 DESCRIPTION Manage your files (upload, delete, access rights and more) witheout telnet & ftp client. JavaScript (client-side) required. For personal and root/multiuser usage. Light security login in some modes. =head1 README FM/3 v.0.01m, (c) Denis Kaganovich AKA mahatma, 2004 There are free software with NO WARRANTIES. Also see Perl and RSA lycenses before using this. RSA code (exclude MD5) Copyright John Hanna (c) 2004 under the terms of the GPL. All "security" terms are not strong by default and only make abuse less easy then witheout it. FM/3 works in default and "installed" modes. Just configure single-script and (if you want) run "./fm.pl install". You will get fm3.cgi, fm3.htm & fm3menu.htm. There are just some faster. Possible password ways ($auth): 0 - none (default); 1 - stored in crypt(), transport - RSA (now slow, will be cached in future); 2 - stored unencrypted, transport - MD5; 3 - MD5, MD5. Config are inside. Default - personal mode witheout login and security. Use it for apache/.htaccess. Also you may find commented out example of root/multiuser config with RSA. WARNING: for $auth==1 & $use_BigInt (ONLY!) you must generate OWN RSA keys: http://shop-js.sf.net/crypto2.htm !!! I will try to add auto key generation, but not sure... Not it just work and work some secure and it is good. Used "own" both-side MD5, based on RFC 1321 and various examples. I am suggest to change 2 lines in JS/MD5 to commented if you sure to browser compatibility. Also I am not sure in current Perl/MD5 code compatibility. If you have bad results in your Perl, just try to remove all "%$xx" and "$xx++;" - I think, it may be only in single case (pure 32 bit integer). Other RSA code: Copyright John Hanna (c) 2004 under the terms of the GPL; see http://shop-js.sf.net for details and latest version. PS To edit mode bits just click to mode bit letters... ;) =head1 PREREQUISITES Perl 5 =head1 COREQUISITES Perl 5. MD5 for security (not required). =pod OSNAMES Linux, unix =pod SCRIPT CATEGORIES Web, Networking, UNIX : System_administration =cut