Annotation of loncom/lonnet/perl/lonnet.pm, revision 1.24
1.1 albertel 1: # The LearningOnline Network
2: # TCP networking package
1.12 www 3: #
4: # Functions for use by content handlers:
5: #
6: # plaintext(short) : plain text explanation of short term
1.21 www 7: # allowed(short,url) : returns codes for allowed actions F,R,S,C
8: # definerole(rolename,sys,dom,cou) : define a custom role rolename
9: # set priviledges in format of lonTabs/roles.tab for
10: # system, domain and course level,
11: # assignrole(udom,uname,url,role,end,start) : give a role to a user for the
12: # level given by url. Optional start and end dates
13: # (leave empty string or zero for "no date")
14: # assigncustomrole (udom,uname,url,rdom,rnam,rolename,end,start) : give a
15: # custom role to a user for the level given by url.
16: # Specify name and domain of role author, and role name
17: # revokerole (udom,uname,url,role) : Revoke a role for url
18: # revokecustomrole (udom,uname,url,rdom,rnam,rolename) : Revoke a custom role
1.24 ! www 19: # appenv(hash) : adds hash to session environment
1.12 www 20: # store(hash) : stores hash permanently for this url
21: # restore : returns hash for this url
22: # eget(namesp,array) : returns hash with keys from array filled in from namesp
23: # get(namesp,array) : returns hash with keys from array filled in from namesp
24: # put(namesp,hash) : stores hash in namesp
1.15 www 25: # dump(namesp) : dumps the complete namespace into a hash
1.23 www 26: # ssi(url,hash) : does a complete request cycle on url to localhost, posts
27: # hash
1.17 www 28: # repcopy(filename) : replicate file
29: # dirlist(url) : gets a directory listing
1.12 www 30: #
1.1 albertel 31: # 6/1/99,6/2,6/10,6/11,6/12,6/14,6/26,6/28,6/29,6/30,
1.5 www 32: # 7/1,7/2,7/9,7/10,7/12,7/14,7/15,7/19,
1.8 www 33: # 11/8,11/16,11/18,11/22,11/23,12/22,
1.12 www 34: # 01/06,01/13,02/24,02/28,02/29,
35: # 03/01,03/02,03/06,03/07,03/13,
1.15 www 36: # 04/05,05/29,05/31,06/01,
37: # 06/05,06/26 Gerd Kortemeyer
38: # 06/26 Ben Tyszka
1.22 www 39: # 06/30,07/15,07/17,07/18,07/20,07/21,07/22,07/25 Gerd Kortemeyer
1.23 www 40: # 08/14 Ben Tyszka
1.24 ! www 41: # 08/22 Gerd Kortemeyer
1.1 albertel 42:
43: package Apache::lonnet;
44:
45: use strict;
46: use Apache::File;
1.8 www 47: use LWP::UserAgent();
1.15 www 48: use HTTP::Headers;
1.11 www 49: use vars
50: qw(%perlvar %hostname %homecache %spareid %hostdom %libserv %pr %prp $readit);
1.1 albertel 51: use IO::Socket;
1.8 www 52: use Apache::Constants qw(:common :http);
1.1 albertel 53:
54: # --------------------------------------------------------------------- Logging
55:
56: sub logthis {
57: my $message=shift;
58: my $execdir=$perlvar{'lonDaemons'};
59: my $now=time;
60: my $local=localtime($now);
61: my $fh=Apache::File->new(">>$execdir/logs/lonnet.log");
62: print $fh "$local ($$): $message\n";
63: return 1;
64: }
65:
66: sub logperm {
67: my $message=shift;
68: my $execdir=$perlvar{'lonDaemons'};
69: my $now=time;
70: my $local=localtime($now);
71: my $fh=Apache::File->new(">>$execdir/logs/lonnet.perm.log");
72: print $fh "$now:$message:$local\n";
73: return 1;
74: }
75:
76: # -------------------------------------------------- Non-critical communication
77: sub subreply {
78: my ($cmd,$server)=@_;
79: my $peerfile="$perlvar{'lonSockDir'}/$server";
80: my $client=IO::Socket::UNIX->new(Peer =>"$peerfile",
81: Type => SOCK_STREAM,
82: Timeout => 10)
83: or return "con_lost";
84: print $client "$cmd\n";
85: my $answer=<$client>;
1.9 www 86: if (!$answer) { $answer="con_lost"; }
1.1 albertel 87: chomp($answer);
88: return $answer;
89: }
90:
91: sub reply {
92: my ($cmd,$server)=@_;
93: my $answer=subreply($cmd,$server);
94: if ($answer eq 'con_lost') { $answer=subreply($cmd,$server); }
1.12 www 95: if (($answer=~/^error:/) || ($answer=~/^refused/) ||
96: ($answer=~/^rejected/)) {
97: &logthis("<font color=blue>WARNING:".
98: " $cmd to $server returned $answer</font>");
99: }
1.1 albertel 100: return $answer;
101: }
102:
103: # ----------------------------------------------------------- Send USR1 to lonc
104:
105: sub reconlonc {
106: my $peerfile=shift;
107: &logthis("Trying to reconnect for $peerfile");
108: my $loncfile="$perlvar{'lonDaemons'}/logs/lonc.pid";
109: if (my $fh=Apache::File->new("$loncfile")) {
110: my $loncpid=<$fh>;
111: chomp($loncpid);
112: if (kill 0 => $loncpid) {
113: &logthis("lonc at pid $loncpid responding, sending USR1");
114: kill USR1 => $loncpid;
115: sleep 1;
116: if (-e "$peerfile") { return; }
117: &logthis("$peerfile still not there, give it another try");
118: sleep 5;
119: if (-e "$peerfile") { return; }
1.12 www 120: &logthis(
121: "<font color=blue>WARNING: $peerfile still not there, giving up</font>");
1.1 albertel 122: } else {
1.12 www 123: &logthis(
124: "<font color=blue>WARNING:".
125: " lonc at pid $loncpid not responding, giving up</font>");
1.1 albertel 126: }
127: } else {
1.12 www 128: &logthis('<font color=blue>WARNING: lonc not running, giving up</font>');
1.1 albertel 129: }
130: }
131:
132: # ------------------------------------------------------ Critical communication
1.12 www 133:
1.1 albertel 134: sub critical {
135: my ($cmd,$server)=@_;
136: my $answer=reply($cmd,$server);
137: if ($answer eq 'con_lost') {
138: my $pingreply=reply('ping',$server);
139: &reconlonc("$perlvar{'lonSockDir'}/$server");
140: my $pongreply=reply('pong',$server);
141: &logthis("Ping/Pong for $server: $pingreply/$pongreply");
142: $answer=reply($cmd,$server);
143: if ($answer eq 'con_lost') {
144: my $now=time;
145: my $middlename=$cmd;
1.5 www 146: $middlename=substr($middlename,0,16);
1.1 albertel 147: $middlename=~s/\W//g;
148: my $dfilename=
149: "$perlvar{'lonSockDir'}/delayed/$now.$middlename.$server";
150: {
151: my $dfh;
152: if ($dfh=Apache::File->new(">$dfilename")) {
1.7 www 153: print $dfh "$cmd\n";
1.1 albertel 154: }
155: }
156: sleep 2;
157: my $wcmd='';
158: {
159: my $dfh;
160: if ($dfh=Apache::File->new("$dfilename")) {
161: $wcmd=<$dfh>;
162: }
163: }
164: chomp($wcmd);
1.7 www 165: if ($wcmd eq $cmd) {
1.12 www 166: &logthis("<font color=blue>WARNING: ".
167: "Connection buffer $dfilename: $cmd</font>");
1.1 albertel 168: &logperm("D:$server:$cmd");
169: return 'con_delayed';
170: } else {
1.12 www 171: &logthis("<font color=red>CRITICAL:"
172: ." Critical connection failed: $server $cmd</font>");
1.1 albertel 173: &logperm("F:$server:$cmd");
174: return 'con_failed';
175: }
176: }
177: }
178: return $answer;
179: }
180:
1.5 www 181: # ---------------------------------------------------------- Append Environment
182:
183: sub appenv {
1.6 www 184: my %newenv=@_;
185: my @oldenv;
186: {
187: my $fh;
188: unless ($fh=Apache::File->new("$ENV{'user.environment'}")) {
1.5 www 189: return 'error';
1.6 www 190: }
191: @oldenv=<$fh>;
192: }
193: for (my $i=0; $i<=$#oldenv; $i++) {
194: chomp($oldenv[$i]);
1.9 www 195: if ($oldenv[$i] ne '') {
196: my ($name,$value)=split(/=/,$oldenv[$i]);
1.24 ! www 197: unless (defined($newenv{$name})) {
! 198: $newenv{$name}=$value;
! 199: }
1.9 www 200: }
1.6 www 201: }
202: {
203: my $fh;
204: unless ($fh=Apache::File->new(">$ENV{'user.environment'}")) {
205: return 'error';
206: }
207: my $newname;
208: foreach $newname (keys %newenv) {
209: print $fh "$newname=$newenv{$newname}\n";
210: }
1.5 www 211: }
212: return 'ok';
213: }
1.1 albertel 214:
215: # ------------------------------ Find server with least workload from spare.tab
1.11 www 216:
1.1 albertel 217: sub spareserver {
218: my $tryserver;
219: my $spareserver='';
220: my $lowestserver=100;
221: foreach $tryserver (keys %spareid) {
222: my $answer=reply('load',$tryserver);
223: if (($answer =~ /\d/) && ($answer<$lowestserver)) {
224: $spareserver="http://$hostname{$tryserver}";
225: $lowestserver=$answer;
226: }
227: }
228: return $spareserver;
229: }
230:
231: # --------- Try to authenticate user from domain's lib servers (first this one)
1.11 www 232:
1.1 albertel 233: sub authenticate {
234: my ($uname,$upass,$udom)=@_;
1.12 www 235: $upass=escape($upass);
1.1 albertel 236: if (($perlvar{'lonRole'} eq 'library') &&
237: ($udom eq $perlvar{'lonDefDomain'})) {
1.3 www 238: my $answer=reply("encrypt:auth:$udom:$uname:$upass",$perlvar{'lonHostID'});
1.2 www 239: if ($answer =~ /authorized/) {
1.9 www 240: if ($answer eq 'authorized') {
241: &logthis("User $uname at $udom authorized by local server");
242: return $perlvar{'lonHostID'};
243: }
244: if ($answer eq 'non_authorized') {
245: &logthis("User $uname at $udom rejected by local server");
246: return 'no_host';
247: }
1.2 www 248: }
1.1 albertel 249: }
250:
251: my $tryserver;
252: foreach $tryserver (keys %libserv) {
253: if ($hostdom{$tryserver} eq $udom) {
1.10 www 254: my $answer=reply("encrypt:auth:$udom:$uname:$upass",$tryserver);
1.1 albertel 255: if ($answer =~ /authorized/) {
1.9 www 256: if ($answer eq 'authorized') {
257: &logthis("User $uname at $udom authorized by $tryserver");
258: return $tryserver;
259: }
260: if ($answer eq 'non_authorized') {
261: &logthis("User $uname at $udom rejected by $tryserver");
262: return 'no_host';
263: }
1.1 albertel 264: }
265: }
1.9 www 266: }
267: &logthis("User $uname at $udom could not be authenticated");
1.1 albertel 268: return 'no_host';
269: }
270:
271: # ---------------------- Find the homebase for a user from domain's lib servers
1.11 www 272:
1.1 albertel 273: sub homeserver {
274: my ($uname,$udom)=@_;
275:
276: my $index="$uname:$udom";
277: if ($homecache{$index}) { return "$homecache{$index}"; }
278:
279: my $tryserver;
280: foreach $tryserver (keys %libserv) {
281: if ($hostdom{$tryserver} eq $udom) {
282: my $answer=reply("home:$udom:$uname",$tryserver);
283: if ($answer eq 'found') {
284: $homecache{$index}=$tryserver;
285: return $tryserver;
286: }
287: }
288: }
289: return 'no_host';
290: }
291:
292: # ----------------------------- Subscribe to a resource, return URL if possible
1.11 www 293:
1.1 albertel 294: sub subscribe {
295: my $fname=shift;
296: my $author=$fname;
297: $author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/;
298: my ($udom,$uname)=split(/\//,$author);
299: my $home=homeserver($uname,$udom);
300: if (($home eq 'no_host') || ($home eq $perlvar{'lonHostID'})) {
301: return 'not_found';
302: }
303: my $answer=reply("sub:$fname",$home);
304: return $answer;
305: }
306:
1.8 www 307: # -------------------------------------------------------------- Replicate file
308:
309: sub repcopy {
310: my $filename=shift;
1.23 www 311: $filename=~s/\/+/\//g;
1.8 www 312: my $transname="$filename.in.transfer";
1.17 www 313: if ((-e $filename) || (-e $transname)) { return OK; }
1.8 www 314: my $remoteurl=subscribe($filename);
315: if ($remoteurl eq 'con_lost') {
316: &logthis("Subscribe returned con_lost: $filename");
317: return HTTP_SERVICE_UNAVAILABLE;
318: } elsif ($remoteurl eq 'not_found') {
319: &logthis("Subscribe returned not_found: $filename");
320: return HTTP_NOT_FOUND;
1.20 www 321: } elsif ($remoteurl eq 'rejected') {
322: &logthis("Subscribe returned rejected: $filename");
1.8 www 323: return FORBIDDEN;
1.20 www 324: } elsif ($remoteurl eq 'directory') {
325: return OK;
1.8 www 326: } else {
327: my @parts=split(/\//,$filename);
328: my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]";
329: if ($path ne "$perlvar{'lonDocRoot'}/res") {
330: &logthis("Malconfiguration for replication: $filename");
331: return HTTP_BAD_REQUEST;
332: }
333: my $count;
334: for ($count=5;$count<$#parts;$count++) {
335: $path.="/$parts[$count]";
336: if ((-e $path)!=1) {
337: mkdir($path,0777);
338: }
339: }
340: my $ua=new LWP::UserAgent;
341: my $request=new HTTP::Request('GET',"$remoteurl");
342: my $response=$ua->request($request,$transname);
343: if ($response->is_error()) {
344: unlink($transname);
345: my $message=$response->status_line;
1.12 www 346: &logthis("<font color=blue>WARNING:"
347: ." LWP get: $message: $filename</font>");
1.8 www 348: return HTTP_SERVICE_UNAVAILABLE;
349: } else {
1.16 www 350: if ($remoteurl!~/\.meta$/) {
351: my $mrequest=new HTTP::Request('GET',$remoteurl.'.meta');
352: my $mresponse=$ua->request($mrequest,$filename.'.meta');
353: if ($mresponse->is_error()) {
354: unlink($filename.'.meta');
355: &logthis(
356: "<font color=yellow>INFO: No metadata: $filename</font>");
357: }
358: }
1.8 www 359: rename($transname,$filename);
360: return OK;
361: }
362: }
363: }
364:
1.15 www 365: # --------------------------------------------------------- Server Side Include
366:
367: sub ssi {
368:
1.23 www 369: my ($fn,%form)=@_;
1.15 www 370:
371: my $ua=new LWP::UserAgent;
1.23 www 372:
373: my $request;
374:
375: if (%form) {
376: $request=new HTTP::Request('POST',"http://".$ENV{'HTTP_HOST'}.$fn);
377: $request->content(join '&', map { "$_=$form{$_}" } keys %form);
378: } else {
379: $request=new HTTP::Request('GET',"http://".$ENV{'HTTP_HOST'}.$fn);
380: }
381:
1.15 www 382: $request->header(Cookie => $ENV{'HTTP_COOKIE'});
383: my $response=$ua->request($request);
384:
385: return $response->content;
386: }
387:
1.14 www 388: # ------------------------------------------------------------------------- Log
389:
390: sub log {
391: my ($dom,$nam,$hom,$what)=@_;
392: return reply("log:$dom:$nam:$what",$hom);
393: }
394:
1.9 www 395: # ----------------------------------------------------------------------- Store
396:
397: sub store {
398: my %storehash=shift;
1.12 www 399: my $namevalue='';
400: map {
401: $namevalue.=escape($_).'='.escape($storehash{$_}).'&';
402: } keys %storehash;
403: $namevalue=~s/\&$//;
404: return reply("store:$ENV{'user.domain'}:$ENV{'user.name'}:"
405: ."$ENV{'user.class'}:$ENV{'request.filename'}:$namevalue",
406: "$ENV{'user.home'}");
1.9 www 407: }
408:
409: # --------------------------------------------------------------------- Restore
410:
411: sub restore {
1.12 www 412: my $answer=reply("restore:$ENV{'user.domain'}:$ENV{'user.name'}:"
413: ."$ENV{'user.class'}:$ENV{'request.filename'}",
414: "$ENV{'user.home'}");
415: my %returnhash=();
416: map {
417: my ($name,$value)=split(/\=/,$_);
418: $returnhash{&unescape($name)}=&unescape($value);
419: } split(/\&/,$answer);
1.13 www 420: return %returnhash;
1.9 www 421: }
1.1 albertel 422:
1.11 www 423: # -------------------------------------------------------- Get user priviledges
424:
425: sub rolesinit {
426: my ($domain,$username,$authhost)=@_;
427: my $rolesdump=reply("dump:$domain:$username:roles",$authhost);
1.12 www 428: if (($rolesdump eq 'con_lost') || ($rolesdump eq '')) { return ''; }
1.11 www 429: my %allroles=();
430: my %thesepriv=();
431: my $now=time;
1.21 www 432: my $userroles="user.login.time=$now\n";
1.11 www 433: my $thesestr;
434:
435: if ($rolesdump ne '') {
436: map {
1.21 www 437: if ($_!~/^rolesdef\&/) {
1.11 www 438: my ($area,$role)=split(/=/,$_);
1.21 www 439: $area=~s/\_\w\w$//;
1.11 www 440: my ($trole,$tend,$tstart)=split(/_/,$role);
1.21 www 441: $userroles.='user.role.'.$trole.'.'.$area.'='.
442: $tstart.'.'.$tend."\n";
1.11 www 443: if ($tend!=0) {
444: if ($tend<$now) {
445: $trole='';
446: }
447: }
448: if ($tstart!=0) {
449: if ($tstart>$now) {
450: $trole='';
451: }
452: }
453: if (($area ne '') && ($trole ne '')) {
1.12 www 454: my ($tdummy,$tdomain,$trest)=split(/\//,$area);
455: if ($trole =~ /^cr\//) {
456: my ($rdummy,$rdomain,$rauthor,$rrole)=split(/\//,$trole);
457: my $homsvr=homeserver($rauthor,$rdomain);
458: if ($hostname{$homsvr} ne '') {
459: my $roledef=
1.21 www 460: reply("get:$rdomain:$rauthor:roles:rolesdef_$rrole",
1.12 www 461: $homsvr);
462: if (($roledef ne 'con_lost') && ($roledef ne '')) {
463: my ($syspriv,$dompriv,$coursepriv)=
1.21 www 464: split(/\_/,unescape($roledef));
1.12 www 465: $allroles{'/'}.=':'.$syspriv;
466: if ($tdomain ne '') {
467: $allroles{'/'.$tdomain.'/'}.=':'.$dompriv;
468: if ($trest ne '') {
469: $allroles{$area}.=':'.$coursepriv;
470: }
471: }
472: }
1.11 www 473: }
1.12 www 474: } else {
475: $allroles{'/'}.=':'.$pr{$trole.':s'};
476: if ($tdomain ne '') {
477: $allroles{'/'.$tdomain.'/'}.=':'.$pr{$trole.':d'};
478: if ($trest ne '') {
479: $allroles{$area}.=':'.$pr{$trole.':c'};
480: }
481: }
1.11 www 482: }
1.12 www 483: }
484: }
1.11 www 485: } split(/&/,$rolesdump);
486: map {
487: %thesepriv=();
488: map {
489: if ($_ ne '') {
490: my ($priviledge,$restrictions)=split(/&/,$_);
491: if ($restrictions eq '') {
492: $thesepriv{$priviledge}='F';
493: } else {
494: if ($thesepriv{$priviledge} ne 'F') {
495: $thesepriv{$priviledge}.=$restrictions;
496: }
497: }
498: }
499: } split(/:/,$allroles{$_});
500: $thesestr='';
501: map { $thesestr.=':'.$_.'&'.$thesepriv{$_}; } keys %thesepriv;
502: $userroles.='user.priv.'.$_.'='.$thesestr."\n";
503: } keys %allroles;
504: }
505: return $userroles;
506: }
507:
1.12 www 508: # --------------------------------------------------------------- get interface
509:
510: sub get {
511: my ($namespace,@storearr)=@_;
512: my $items='';
513: map {
514: $items.=escape($_).'&';
515: } @storearr;
516: $items=~s/\&$//;
517: my $rep=reply("get:$ENV{'user.domain'}:$ENV{'user.name'}:$namespace:$items",
518: $ENV{'user.home'});
1.15 www 519: my @pairs=split(/\&/,$rep);
520: my %returnhash=();
521: map {
522: my ($key,$value)=split(/=/,$_);
523: $returnhash{unespace($key)}=unescape($value);
524: } @pairs;
525: return %returnhash;
526: }
527:
528: # -------------------------------------------------------------- dump interface
529:
530: sub dump {
531: my $namespace=shift;
532: my $rep=reply("dump:$ENV{'user.domain'}:$ENV{'user.name'}:$namespace",
533: $ENV{'user.home'});
1.12 www 534: my @pairs=split(/\&/,$rep);
535: my %returnhash=();
536: map {
537: my ($key,$value)=split(/=/,$_);
538: $returnhash{unespace($key)}=unescape($value);
539: } @pairs;
540: return %returnhash;
541: }
542:
543: # --------------------------------------------------------------- put interface
544:
545: sub put {
546: my ($namespace,%storehash)=@_;
547: my $items='';
548: map {
549: $items.=escape($_).'='.escape($storehash{$_}).'&';
550: } keys %storehash;
551: $items=~s/\&$//;
552: return reply("put:$ENV{'user.domain'}:$ENV{'user.name'}:$namespace:$items",
553: $ENV{'user.home'});
554: }
555:
556: # -------------------------------------------------------------- eget interface
557:
558: sub eget {
559: my ($namespace,@storearr)=@_;
560: my $items='';
561: map {
562: $items.=escape($_).'&';
563: } @storearr;
564: $items=~s/\&$//;
565: my $rep=reply("eget:$ENV{'user.domain'}:$ENV{'user.name'}:$namespace:$items",
566: $ENV{'user.home'});
567: my @pairs=split(/\&/,$rep);
568: my %returnhash=();
569: map {
570: my ($key,$value)=split(/=/,$_);
571: $returnhash{unespace($key)}=unescape($value);
572: } @pairs;
573: return %returnhash;
574: }
575:
576: # ------------------------------------------------- Check for a user priviledge
577:
578: sub allowed {
579: my ($priv,$uri)=@_;
580: $uri=~s/^\/res//;
581: $uri=~s/^\///;
1.14 www 582: if ($uri=~/^adm\//) {
583: return 'F';
584: }
1.12 www 585: my $thisallowed='';
586: if ($ENV{'user.priv./'}=~/$priv\&([^\:]*)/) {
587: $thisallowed.=$1;
588: }
589: if ($ENV{'user.priv./'.(split(/\//,$uri))[0].'/'}=~/$priv\&([^\:]*)/) {
590: $thisallowed.=$1;
591: }
592: if ($ENV{'user.priv./'.$uri}=~/$priv\&([^\:]*)/) {
593: $thisallowed.=$1;
594: }
595: return $thisallowed;
596: }
597:
598: # ----------------------------------------------------------------- Define Role
599:
600: sub definerole {
601: if (allowed('mcr','/')) {
602: my ($rolename,$sysrole,$domrole,$courole)=@_;
1.21 www 603: map {
604: my ($crole,$cqual)=split(/\&/,$_);
605: if ($pr{'cr:s'}!~/$crole/) { return "refused:s:$crole"; }
606: if ($pr{'cr:s'}=~/$crole\&/) {
607: if ($pr{'cr:s'}!~/$crole\&\w*$cqual/) {
608: return "refused:s:$crole&$cqual";
609: }
610: }
611: } split('/',$sysrole);
612: map {
613: my ($crole,$cqual)=split(/\&/,$_);
614: if ($pr{'cr:d'}!~/$crole/) { return "refused:d:$crole"; }
615: if ($pr{'cr:d'}=~/$crole\&/) {
616: if ($pr{'cr:d'}!~/$crole\&\w*$cqual/) {
617: return "refused:d:$crole&$cqual";
618: }
619: }
620: } split('/',$domrole);
621: map {
622: my ($crole,$cqual)=split(/\&/,$_);
623: if ($pr{'cr:c'}!~/$crole/) { return "refused:c:$crole"; }
624: if ($pr{'cr:c'}=~/$crole\&/) {
625: if ($pr{'cr:c'}!~/$crole\&\w*$cqual/) {
626: return "refused:c:$crole&$cqual";
627: }
628: }
629: } split('/',$courole);
1.12 www 630: my $command="encrypt:rolesput:$ENV{'user.domain'}:$ENV{'user.name'}:".
631: "$ENV{'user.domain'}:$ENV{'user.name'}:".
1.21 www 632: "rolesdef_$rolename=".
633: escape($sysrole.'_'.$domrole.'_'.$courole);
1.12 www 634: return reply($command,$ENV{'user.home'});
635: } else {
636: return 'refused';
637: }
638: }
639:
640: # ------------------------------------------------------------------ Plain Text
641:
642: sub plaintext {
1.22 www 643: my $short=shift;
644: return $prp{$short};
1.12 www 645: }
646:
647: # ----------------------------------------------------------------- Assign Role
648:
649: sub assignrole {
1.21 www 650: my ($udom,$uname,$url,$role,$end,$start)=@_;
651: my $mrole;
652: if ($role =~ /^cr\//) {
653: unless ($url=~/\.course$/) { return 'invalid'; }
654: unless (allowed('ccr',$url)) { return 'refused'; }
655: $mrole='cr';
656: } else {
657: unless (($url=~/\.course$/) || ($url=~/\/$/)) { return 'invalid'; }
658: unless (allowed('c'+$role)) { return 'refused'; }
659: $mrole=$role;
660: }
661: my $command="encrypt:rolesput:$ENV{'user.domain'}:$ENV{'user.name'}:".
662: "$udom:$uname:$url".'_'."$mrole=$role";
663: if ($end) { $command.='_$end'; }
664: if ($start) {
665: if ($end) {
666: $command.='_$start';
667: } else {
668: $command.='_0_$start';
669: }
670: }
671: return &reply($command,&homeserver($uname,$udom));
672: }
673:
674: # ---------------------------------------------------------- Assign Custom Role
675:
676: sub assigncustomrole {
677: my ($udom,$uname,$url,$rdom,$rnam,$rolename,$end,$start)=@_;
678: return &assignrole($udom,$uname,$url,'cr/'.$rdom.'/'.$rnam.'/'.$rolename,
679: $end,$start);
680: }
681:
682: # ----------------------------------------------------------------- Revoke Role
683:
684: sub revokerole {
685: my ($udom,$uname,$url,$role)=@_;
686: my $now=time;
687: return &assignrole($udom,$uname,$url,$role,$now);
688: }
689:
690: # ---------------------------------------------------------- Revoke Custom Role
691:
692: sub revokecustomrole {
693: my ($udom,$uname,$url,$rdom,$rnam,$rolename)=@_;
694: my $now=time;
695: return &assigncustomrole($udom,$uname,$url,$rdom,$rnam,$rolename,$now);
1.17 www 696: }
697:
698: # ------------------------------------------------------------ Directory lister
699:
700: sub dirlist {
701: my $uri=shift;
1.18 www 702: $uri=~s/^\///;
703: $uri=~s/\/$//;
1.19 www 704: my ($res,$udom,$uname,@rest)=split(/\//,$uri);
705: if ($udom) {
706: if ($uname) {
707: my $listing=reply('ls:'.$perlvar{'lonDocRoot'}.'/'.$uri,
708: homeserver($uname,$udom));
709: return split(/:/,$listing);
710: } else {
711: my $tryserver;
712: my %allusers=();
713: foreach $tryserver (keys %libserv) {
714: if ($hostdom{$tryserver} eq $udom) {
715: my $listing=reply('ls:'.$perlvar{'lonDocRoot'}.'/res/'.$udom,
716: $tryserver);
717: if (($listing ne 'no_such_dir') && ($listing ne 'empty')
718: && ($listing ne 'con_lost')) {
719: map {
720: my ($entry,@stat)=split(/&/,$_);
721: $allusers{$entry}=1;
722: } split(/:/,$listing);
723: }
724: }
725: }
726: my $alluserstr='';
727: map {
728: $alluserstr.=$_.'&user:';
729: } sort keys %allusers;
730: $alluserstr=~s/:$//;
731: return split(/:/,$alluserstr);
732: }
733: } else {
734: my $tryserver;
735: my %alldom=();
736: foreach $tryserver (keys %libserv) {
737: $alldom{$hostdom{$tryserver}}=1;
738: }
739: my $alldomstr='';
740: map {
741: $alldomstr.=$perlvar{'lonDocRoot'}.'/res/'.$_.'&domain:';
742: } sort keys %alldom;
743: $alldomstr=~s/:$//;
744: return split(/:/,$alldomstr);
745: }
1.12 www 746: }
747:
748: # -------------------------------------------------------- Escape Special Chars
749:
750: sub escape {
751: my $str=shift;
752: $str =~ s/(\W)/"%".unpack('H2',$1)/eg;
753: return $str;
754: }
755:
756: # ----------------------------------------------------- Un-Escape Special Chars
757:
758: sub unescape {
759: my $str=shift;
760: $str =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
761: return $str;
762: }
1.11 www 763:
1.1 albertel 764: # ================================================================ Main Program
765:
766: sub BEGIN {
767: if ($readit ne 'done') {
768: # ------------------------------------------------------------ Read access.conf
769: {
770: my $config=Apache::File->new("/etc/httpd/conf/access.conf");
771:
772: while (my $configline=<$config>) {
773: if ($configline =~ /PerlSetVar/) {
774: my ($dummy,$varname,$varvalue)=split(/\s+/,$configline);
1.8 www 775: chomp($varvalue);
1.1 albertel 776: $perlvar{$varname}=$varvalue;
777: }
778: }
779: }
780:
781: # ------------------------------------------------------------- Read hosts file
782: {
783: my $config=Apache::File->new("$perlvar{'lonTabDir'}/hosts.tab");
784:
785: while (my $configline=<$config>) {
786: my ($id,$domain,$role,$name,$ip)=split(/:/,$configline);
787: $hostname{$id}=$name;
788: $hostdom{$id}=$domain;
789: if ($role eq 'library') { $libserv{$id}=$name; }
790: }
791: }
792:
793: # ------------------------------------------------------ Read spare server file
794: {
795: my $config=Apache::File->new("$perlvar{'lonTabDir'}/spare.tab");
796:
797: while (my $configline=<$config>) {
798: chomp($configline);
799: if (($configline) && ($configline ne $perlvar{'lonHostID'})) {
800: $spareid{$configline}=1;
801: }
802: }
803: }
1.11 www 804: # ------------------------------------------------------------ Read permissions
805: {
806: my $config=Apache::File->new("$perlvar{'lonTabDir'}/roles.tab");
807:
808: while (my $configline=<$config>) {
809: chomp($configline);
810: my ($role,$perm)=split(/ /,$configline);
811: if ($perm ne '') { $pr{$role}=$perm; }
812: }
813: }
814:
815: # -------------------------------------------- Read plain texts for permissions
816: {
817: my $config=Apache::File->new("$perlvar{'lonTabDir'}/rolesplain.tab");
818:
819: while (my $configline=<$config>) {
820: chomp($configline);
821: my ($short,$plain)=split(/:/,$configline);
822: if ($plain ne '') { $prp{$short}=$plain; }
823: }
824: }
825:
1.22 www 826:
1.1 albertel 827: $readit='done';
1.12 www 828: &logthis('<font color=yellow>INFO: Read configuration</font>');
1.1 albertel 829: }
830: }
831: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>