Annotation of doc/install/linux/install.pl, revision 1.45.2.23
1.1 raeburn 1: #!/usr/bin/perl
2: # The LearningOnline Network
3: # Pre-installation script for LON-CAPA
4: #
5: # Copyright Michigan State University Board of Trustees
6: #
7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
8: #
9: # LON-CAPA is free software; you can redistribute it and/or modify
10: # it under the terms of the GNU General Public License as published by
11: # the Free Software Foundation; either version 2 of the License, or
12: # (at your option) any later version.
13: #
14: # LON-CAPA is distributed in the hope that it will be useful,
15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: # GNU General Public License for more details.
18: #
19: # You should have received a copy of the GNU General Public License
20: # along with LON-CAPA; if not, write to the Free Software
21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22: #
23: # http://www.lon-capa.org/
24: #
25:
26: use strict;
27: use File::Copy;
28: use Term::ReadKey;
29: use DBI;
1.45.2.11 raeburn 30: use File::Spec;
1.43 raeburn 31: use Cwd();
32: use File::Basename();
33: use lib File::Basename::dirname(Cwd::abs_path($0));
1.1 raeburn 34: use LCLocalization::localize;
35:
36: # ========================================================= The language handle
37:
38: my %languages = (
39: ar => 'Arabic',
40: de => 'German',
41: en => 'English',
42: es => 'Spanish (Castellan)',
43: fa => 'Persian',
44: fr => 'French',
45: he => 'Hebrew',
46: ja => 'Japanese',
47: pt => 'Portuguese',
48: ru => 'Russian',
49: tr => 'Turkish',
50: zh => 'Chinese Simplified'
51: );
52:
53: use vars qw($lh $lang);
54: $lang = 'en';
55: if (@ARGV > 0) {
56: foreach my $poss (keys(%languages)) {
57: if ($ARGV[0] eq $poss) {
58: $lang = $ARGV[0];
59: }
60: }
61: }
62:
63: &get_language_handle($lang);
64:
65: # Check user has root privs
66: if (0 != $<) {
67: print &mt('This script must be run as root.')."\n".
68: &mt('Stopping execution.')."\n";
69: exit;
70: }
71:
72:
73: # Globals: filehandle LOG is global.
74: if (!open(LOG,">>loncapa_install.log")) {
75: print &mt('Unable to open log file.')."\n".
76: &mt('Stopping execution.')."\n";
77: exit;
78: } else {
1.45.2.23! raeburn 79: print LOG '$Id: install.pl,v 1.45.2.22 2024/08/01 12:57:23 raeburn Exp $'."\n";
1.1 raeburn 80: }
81:
82: #
1.2 raeburn 83: # Helper routines and routines to establish recommended actions
1.1 raeburn 84: #
85:
86: sub get_language_handle {
87: my @languages = @_;
88: $lh=LCLocalization::localize->get_handle(@languages);
89: }
90:
91: sub mt (@) {
92: if ($lh) {
93: if ($_[0] eq '') {
94: if (wantarray) {
95: return @_;
96: } else {
97: return $_[0];
98: }
99: } else {
100: return $lh->maketext(@_);
101: }
102: } else {
103: if (wantarray) {
104: return @_;
105: } else {
106: return $_[0];
107: }
108: }
109: }
110:
111: sub texthash {
112: my (%hash) = @_;
113: foreach (keys(%hash)) {
114: $hash{$_}=&mt($hash{$_});
115: }
116: return %hash;
117: }
118:
119:
120: sub skip_if_nonempty {
121: my ($string,$error)=@_;
122: return if (! defined($error));
123: chomp($string);chomp($error);
124: if ($string ne '') {
125: print_and_log("$error\n".&mt('Stopping execution.')."\n");
126: return 1;
127: }
128: return;
129: }
130:
131: sub writelog {
132: while ($_ = shift) {
133: chomp();
134: print LOG "$_\n";
135: }
136: }
137:
138: sub print_and_log {
139: while ($_=shift) {
140: chomp();
141: print "$_\n";
142: print LOG "$_\n";
143: }
144: }
145:
146: sub get_user_selection {
147: my ($defaultrun) = @_;
148: my $do_action = 0;
149: my $choice = <STDIN>;
150: chomp($choice);
151: $choice =~ s/(^\s+|\s+$)//g;
152: my $yes = &mt('y');
153: if ($defaultrun) {
154: if (($choice eq '') || ($choice =~ /^\Q$yes\E/i)) {
155: $do_action = 1;
156: }
157: } else {
158: if ($choice =~ /^\Q$yes\E/i) {
159: $do_action = 1;
160: }
161: }
162: return $do_action;
163: }
164:
165: sub get_distro {
1.45.2.1 raeburn 166: my ($distro,$gotprereqs,$updatecmd,$packagecmd,$installnow,$unknown);
1.1 raeburn 167: $packagecmd = '/bin/rpm -q LONCAPA-prerequisites ';
1.45.2.3 raeburn 168: if (-e '/etc/oracle-release') {
169: open(IN,'</etc/oracle-release');
170: my $versionstring=<IN>;
171: chomp($versionstring);
172: close(IN);
173: if ($versionstring =~ /^Oracle Linux Server release (\d+)/) {
174: my $version = $1;
175: $distro = 'oracle'.$1;
176: $updatecmd = 'yum install LONCAPA-prerequisites';
177: $installnow = 'yum -y install LONCAPA-prerequisites';
178: }
179: } elsif (-e '/etc/redhat-release') {
1.1 raeburn 180: open(IN,'</etc/redhat-release');
181: my $versionstring=<IN>;
182: chomp($versionstring);
183: close(IN);
184: if ($versionstring =~ /^Red Hat Linux release ([\d\.]+) /) {
185: my $version = $1;
186: if ($version=~/^7\./) {
187: $distro='redhat7';
188: } elsif ($version=~/^8\./) {
189: $distro='redhat8';
190: } elsif ($version=~/^9/) {
191: $distro='redhat9';
192: }
193: } elsif ($versionstring =~ /Fedora( Core)? release ([\d\.]+) /) {
194: my $version=$2;
195: if ($version - int($version) > .9) {
196: $distro = 'fedora'.(int($version)+1);
197: } else {
198: $distro = 'fedora'.int($version);
199: }
200: $updatecmd = 'yum install LONCAPA-prerequisites';
201: $installnow = 'yum -y install LONCAPA-prerequisites';
202: } elsif ($versionstring =~ /Red Hat Enterprise Linux [AE]S release ([\d\.]+) /) {
203: $distro = 'rhes'.$1;
204: $updatecmd = 'up2date -i LONCAPA-prerequisites';
205: } elsif ($versionstring =~ /Red Hat Enterprise Linux Server release (\d+)/) {
206: $distro = 'rhes'.$1;
207: $updatecmd = 'yum install LONCAPA-prerequisites';
208: $installnow = 'yum -y install LONCAPA-prerequisites';
1.45.2.3 raeburn 209: } elsif ($versionstring =~ /Red Hat Enterprise Linux release (\d+)/) {
210: $distro = 'rhes'.$1;
211: $updatecmd = 'dnf install LONCAPA-prerequisites';
212: $installnow = 'dnf -y install LONCAPA-prerequisites';
1.45.2.18 raeburn 213: } elsif ($versionstring =~ /CentOS(| Linux| Stream) release (\d+)/) {
214: $distro = 'centos'.$2;
215: if ($1 eq ' Stream') {
216: $distro .= '-stream';
217: }
1.1 raeburn 218: $updatecmd = 'yum install LONCAPA-prerequisites';
219: $installnow = 'yum -y install LONCAPA-prerequisites';
1.22 raeburn 220: } elsif ($versionstring =~ /Scientific Linux (?:SL )?release ([\d.]+) /) {
1.1 raeburn 221: my $ver = $1;
222: $ver =~ s/\.\d+$//;
223: $distro = 'scientific'.$ver;
224: $updatecmd = 'yum install LONCAPA-prerequisites';
225: $installnow = 'yum -y install LONCAPA-prerequisites';
1.45.2.18 raeburn 226: } elsif ($versionstring =~ /Rocky Linux release ([\d.]+)/) {
227: my $ver = $1;
228: $ver =~ s/\.\d+$//;
229: $distro = 'rocky'.$ver;
230: $updatecmd = 'dnf install LONCAPA-prerequisites';
231: $installnow = 'dnf -y install LONCAPA-prerequisites';
232: } elsif ($versionstring =~ /AlmaLinux release ([\d.]+) /) {
233: my $ver = $1;
234: $ver =~ s/\.\d+$//;
235: $distro = 'alma'.$ver;
236: $updatecmd = 'dnf install LONCAPA-prerequisites';
237: $installnow = 'dnf -y install LONCAPA-prerequisites';
1.1 raeburn 238: } else {
239: print &mt('Unable to interpret [_1] to determine system type.',
240: '/etc/redhat-release')."\n";
1.45.2.1 raeburn 241: $unknown = 1;
1.1 raeburn 242: }
243: } elsif (-e '/etc/SuSE-release') {
244: open(IN,'</etc/SuSE-release');
245: my $versionstring=<IN>;
246: chomp($versionstring);
247: close(IN);
248: if ($versionstring =~ /^SUSE LINUX Enterprise Server ([\d\.]+) /i) {
249: $distro='sles'.$1;
250: if ($1 >= 10) {
251: $updatecmd = 'zypper install LONCAPA-prerequisites';
252: } else {
253: $updatecmd = 'yast -i LONCAPA-prerequisites';
254: }
255: } elsif ($versionstring =~ /^SuSE Linux ([\d\.]+) /i) {
256: $distro = 'suse'.$1;
1.12 raeburn 257: $updatecmd = 'yast -i LONCAPA-prerequisites';
1.1 raeburn 258: } elsif ($versionstring =~ /^openSUSE ([\d\.]+) /i) {
259: $distro = 'suse'.$1;
260: if ($1 >= 10.3 ) {
261: $updatecmd = 'zypper install LONCAPA-prerequisites';
262: } else {
263: $updatecmd = 'yast -i LONCAPA-prerequisites';
264: }
265: } else {
266: print &mt('Unable to interpret [_1] to determine system type.',
267: '/etc/SuSE-release')."\n";
1.45.2.1 raeburn 268: $unknown = 1;
1.1 raeburn 269: }
270: } elsif (-e '/etc/issue') {
271: open(IN,'</etc/issue');
272: my $versionstring=<IN>;
273: chomp($versionstring);
274: close(IN);
275: if ($versionstring =~ /^Ubuntu (\d+)\.\d+/i) {
276: $distro = 'ubuntu'.$1;
277: $updatecmd = 'sudo apt-get install loncapa-prerequisites';
278: } elsif ($versionstring =~ /^Debian\s+GNU\/Linux\s+(\d+)\.\d+/i) {
279: $distro = 'debian'.$1;
1.45.2.1 raeburn 280: $updatecmd = 'apt-get install loncapa-prerequisites';
1.1 raeburn 281: } elsif (-e '/etc/debian_version') {
282: open(IN,'</etc/debian_version');
283: my $version=<IN>;
284: chomp($version);
285: close(IN);
286: if ($version =~ /^(\d+)\.\d+\.?\d*/) {
287: $distro='debian'.$1;
1.45.2.1 raeburn 288: $updatecmd = 'apt-get install loncapa-prerequisites';
1.1 raeburn 289: } else {
290: print &mt('Unable to interpret [_1] to determine system type.',
291: '/etc/debian_version')."\n";
1.45.2.1 raeburn 292: $unknown = 1;
1.1 raeburn 293: }
1.45.2.1 raeburn 294: }
295: if ($distro ne '') {
296: $packagecmd = '/usr/bin/dpkg -l loncapa-prerequisites ';
1.1 raeburn 297: }
298: } elsif (-e '/etc/debian_version') {
299: open(IN,'</etc/debian_version');
300: my $version=<IN>;
301: chomp($version);
302: close(IN);
303: if ($version =~ /^(\d+)\.\d+\.?\d*/) {
304: $distro='debian'.$1;
305: $packagecmd = '/usr/bin/dpkg -l loncapa-prerequisites ';
306: $updatecmd = 'apt-get install loncapa-prerequisites';
307: } else {
308: print &mt('Unable to interpret [_1] to determine system type.',
309: '/etc/debian_version')."\n";
1.45.2.1 raeburn 310: $unknown = 1;
311: }
312: }
313: if (($distro eq '') && (!$unknown)) {
314: if (-e '/etc/os-release') {
315: if (open(IN,'<','/etc/os-release')) {
316: my ($id,$version);
317: while(<IN>) {
318: chomp();
319: if (/^ID="(\w+)"/) {
320: $id=$1;
321: } elsif (/^VERSION_ID="([\d\.]+)"/) {
322: $version=$1;
323: }
324: }
325: close(IN);
326: if ($id eq 'sles') {
327: my ($major,$minor) = split(/\./,$version);
328: if ($major =~ /^\d+$/) {
329: $distro = $id.$major;
330: $updatecmd = 'zypper install LONCAPA-prerequisites';
331: }
332: }
333: }
334: if ($distro eq '') {
335: print &mt('Unable to interpret [_1] to determine system type.',
336: '/etc/os-release')."\n";
337: $unknown = 1;
338: }
339: } else {
1.45.2.3 raeburn 340: print &mt('Unknown installation: expecting a debian, ubuntu, suse, sles, redhat, fedora, scientific linux, or oracle linux system.')."\n";
1.1 raeburn 341: }
342: }
343: return ($distro,$packagecmd,$updatecmd,$installnow);
344: }
345:
346: sub check_prerequisites {
347: my ($packagecmd,$distro) = @_;
348: my $gotprereqs;
349: if ($packagecmd ne '') {
350: if (open(PIPE,"$packagecmd|")) {
351: if ($distro =~ /^(debian|ubuntu)/) {
352: my @lines = <PIPE>;
353: chomp(@lines);
354: foreach my $line (@lines) {
355: if ($line =~ /^ii\s+loncapa-prerequisites\s+([\w\.]+)/) {
356: $gotprereqs = $1;
357: }
358: }
359: } else {
360: my $line = <PIPE>;
361: chomp($line);
1.8 raeburn 362: if ($line =~ /^LONCAPA\-prerequisites\-([\d\-]+)\.(?:[.\w]+)$/) {
1.1 raeburn 363: $gotprereqs = $1;
364: }
365: }
366: close(PIPE);
367: } else {
368: print &mt('Error: could not determine if LONCAPA-prerequisites package is installed')."\n";
369: }
370: }
371: return $gotprereqs;
372: }
373:
1.6 raeburn 374: sub check_locale {
375: my ($distro) = @_;
1.45.2.22 raeburn 376: my ($fh,$langvar,$command,$langcmd,$earlyout,$default);
1.8 raeburn 377: $langvar = 'LANG';
1.6 raeburn 378: if ($distro =~ /^(ubuntu|debian)/) {
379: if (!open($fh,"</etc/default/locale")) {
380: print &mt('Failed to open: [_1], default locale not checked.',
381: '/etc/default/locale');
1.45.2.7 raeburn 382: $earlyout = 1;
1.6 raeburn 383: }
1.45.2.1 raeburn 384: } elsif ($distro =~ /^(suse|sles)(\d+)/) {
385: if (($1 eq 'sles') && ($2 >= 15)) {
386: if (!open($fh,"</etc/locale.conf")) {
387: print &mt('Failed to open: [_1], default locale not checked.',
388: '/etc/locale.conf');
1.45.2.7 raeburn 389: $earlyout = 1;
1.45.2.1 raeburn 390: }
391: } else {
392: if (!open($fh,"</etc/sysconfig/language")) {
393: print &mt('Failed to open: [_1], default locale not checked.',
394: '/etc/sysconfig/language');
1.45.2.7 raeburn 395: $earlyout = 1;
1.45.2.1 raeburn 396: }
397: $langvar = 'RC_LANG';
1.8 raeburn 398: }
1.24 raeburn 399: } elsif ($distro =~ /^fedora(\d+)/) {
400: if ($1 >= 18) {
401: if (!open($fh,"</etc/locale.conf")) {
402: print &mt('Failed to open: [_1], default locale not checked.',
403: '/etc/locale.conf');
1.45.2.7 raeburn 404: $earlyout = 1;
1.24 raeburn 405: }
406: } elsif (!open($fh,"</etc/sysconfig/i18n")) {
407: print &mt('Failed to open: [_1], default locale not checked.',
408: '/etc/sysconfig/i18n');
1.45.2.7 raeburn 409: $earlyout = 1;
1.24 raeburn 410: }
1.45.2.18 raeburn 411: } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle|rocky|alma)(\d+)/) {
1.29 raeburn 412: if ($1 >= 7) {
413: if (!open($fh,"</etc/locale.conf")) {
414: print &mt('Failed to open: [_1], default locale not checked.',
415: '/etc/locale.conf');
1.45.2.7 raeburn 416: $earlyout = 1;
1.29 raeburn 417: }
418: } elsif (!open($fh,"</etc/sysconfig/i18n")) {
419: print &mt('Failed to open: [_1], default locale not checked.',
420: '/etc/sysconfig/i18n');
1.45.2.7 raeburn 421: $earlyout = 1;
1.29 raeburn 422: }
1.6 raeburn 423: } else {
424: if (!open($fh,"</etc/sysconfig/i18n")) {
425: print &mt('Failed to open: [_1], default locale not checked.',
426: '/etc/sysconfig/i18n');
1.45.2.7 raeburn 427: $earlyout = 1;
1.6 raeburn 428: }
429: }
1.45.2.22 raeburn 430: return () if ($earlyout);
1.6 raeburn 431: my @data = <$fh>;
432: chomp(@data);
1.45.2.22 raeburn 433: close($fh);
1.6 raeburn 434: foreach my $item (@data) {
1.25 raeburn 435: if ($item =~ /^\Q$langvar\E=\"?([^\"]*)\"?/) {
1.45.2.22 raeburn 436: $default = $1;
1.6 raeburn 437: if ($default ne 'en_US.UTF-8') {
438: if ($distro =~ /^debian/) {
1.25 raeburn 439: $command = 'locale-gen en_US.UTF-8'."\n".
440: 'update-locale LANG=en_US.UTF-8';
1.6 raeburn 441: } elsif ($distro =~ /^ubuntu/) {
1.25 raeburn 442: $command = 'sudo locale-gen en_US.UTF-8'."\n".
443: 'sudo update-locale LANG=en_US.UTF-8';
1.7 raeburn 444: } elsif ($distro =~ /^(suse|sles)/) {
1.45.2.3 raeburn 445: $command = 'yast language';
446: } elsif (-e '/usr/bin/system-config-language') {
1.6 raeburn 447: $command = 'system-config-language';
1.45.2.3 raeburn 448: } elsif (-e '/usr/bin/localectl') {
1.45.2.4 raeburn 449: $command = '/usr/bin/localectl set-locale LANG=en_US.UTF-8';
1.45.2.3 raeburn 450: } else {
451: $command = 'No standard command found';
1.6 raeburn 452: }
453: }
454: last;
455: }
456: }
1.45.2.22 raeburn 457: # Check for locales
458: if ($default ne 'en_US.UTF-8') {
459: my ($has_us_english,$has_other_code,$has_other_lang);
460: if (open(PIPE,"locale -a 2>/dev/null |")) {
461: while (<PIPE>) {
462: chomp();
463: next if (/^(C(|\.utf8)|POSIX)$/i);
464: if (/^en_US\.utf8/i) {
465: $has_us_english = 1;
466: } elsif (/^[A-Za-z]{2}_[A-Za-z]{2}/) {
467: $has_other_code = 1;
468: } elsif (/^[A-Za-z]{3,}/) {
469: $has_other_lang = 1;
470: }
471: }
472: close(PIPE);
473: if (!$has_us_english) {
474: if ($has_other_code || $has_other_lang) {
475: if ($distro =~ /^ubuntu/) {
476: $langcmd = "sudo apt-get install language-pack-en\n";
477: } elsif ($distro =~ /^debian/) {
478: $langcmd = "apt-get install language-pack-en\n";
479: } elsif ($distro =~ /^(suse|sles)/) {
480: $langcmd = &mt('Use yast: System > Language > Primary Language = English')."\n";
481: } elsif ($distro =~ /^fedora(\d+)$/) {
482: if ($1 > 23) {
483: $langcmd = "dnf install glibc-langpack-en\n";
484: } else {
485: $langcmd = "yum install glibc-common\n";
486: }
487: } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle|rocky|alma)(\d+)/) {
488: if ($1 > 7) {
489: $langcmd = "dnf install glibc-langpack-en\n";
490: } else {
491: $langcmd = "yum install glibc-common\n";
492: }
493: }
494: } else {
495: if ($distro =~ /^ubuntu/) {
496: $langcmd = "sudo apt-get install language-pack-en\n";
497: } elsif ($distro =~ /^debian/) {
498: $langcmd = "apt-get install language-pack-en\n";
499: } elsif ($distro =~ /^(suse|sles)/) {
500: $langcmd = &mt('Use yast: System > Language > Primary Language = English')."\n";
501: } elsif ($distro =~ /^fedora(\d+)$/) {
502: if ($1 > 23) {
503: $langcmd = &mt('Either install all languages[_1]or install English only[_2]',
504: ":\ndnf install glibc-all-langpacks\n\n",
505: ":\ndnf install glibc-langpack-en\n");
506: } else {
507: $langcmd = "yum install glibc-common\n";
508: }
509: } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle|rocky|alma)(\d+)/) {
510: if ($1 > 7) {
511: $langcmd = &mt('Either install all languages[_1]or install English only[_2]',
512: ":\ndnf install glibc-all-langpacks\n\n",
513: ":\ndnf install glibc-langpack-en\n");
514: } else {
515: $langcmd = "yum install glibc-common\n";
516: }
517: }
518: }
519: }
520: }
521: }
522: return ($command,$langcmd);
1.6 raeburn 523: }
524:
1.1 raeburn 525: sub check_required {
526: my ($instdir,$dsn) = @_;
527: my ($distro,$packagecmd,$updatecmd,$installnow) = &get_distro();
528: if ($distro eq '') {
529: return;
530: }
531: my $gotprereqs = &check_prerequisites($packagecmd,$distro);
532: if ($gotprereqs eq '') {
1.45.2.22 raeburn 533: return ($distro,$gotprereqs,'','',$packagecmd,$updatecmd);
1.6 raeburn 534: }
1.45.2.22 raeburn 535: my ($localecmd,$langcmd) = &check_locale($distro);
1.6 raeburn 536: unless ($localecmd eq '') {
1.45.2.22 raeburn 537: return ($distro,$gotprereqs,$localecmd,$langcmd);
1.1 raeburn 538: }
1.45.2.9 raeburn 539: my ($mysqlon,$mysqlsetup,$mysqlrestart,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,
540: %recommended,$downloadstatus,$filetouse,$production,$testing,$apachefw,
1.45.2.12 raeburn 541: $tostop,$uses_systemctl,$mysql_has_wwwuser);
1.1 raeburn 542: my $wwwuid = &uid_of_www();
543: my $wwwgid = getgrnam('www');
544: if (($wwwuid eq '') || ($wwwgid eq '')) {
545: $recommended{'wwwuser'} = 1;
546: }
547: unless( -e "/usr/local/sbin/pwauth") {
548: $recommended{'pwauth'} = 1;
549: }
550: $mysqlon = &check_mysql_running($distro);
551: if ($mysqlon) {
1.45.2.14 raeburn 552: ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser,$mysql_unix_socket) =
1.45.2.12 raeburn 553: &check_mysql_setup($instdir,$dsn,$distro);
1.34 raeburn 554: if ($mysqlsetup eq 'needsrestart') {
555: $mysqlrestart = '';
556: if ($distro eq 'ubuntu') {
1.45.2.19 raeburn 557: $mysqlrestart = 'sudo ';
1.34 raeburn 558: }
559: $mysqlrestart .= 'service mysql restart';
1.45.2.22 raeburn 560: return ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart);
1.1 raeburn 561: } else {
1.34 raeburn 562: if ($mysqlsetup eq 'noroot') {
1.1 raeburn 563: $recommended{'mysqlperms'} = 1;
1.34 raeburn 564: } else {
565: unless ($mysql_has_wwwuser) {
566: $recommended{'mysqlperms'} = 1;
567: }
568: }
569: if ($dbh) {
570: $has_lcdb = &check_loncapa_mysqldb($dbh);
571: }
572: unless ($has_lcdb) {
573: $recommended{'mysql'} = 1;
1.1 raeburn 574: }
575: }
576: }
1.5 raeburn 577: ($recommended{'firewall'},$apachefw) = &chkfirewall($distro);
1.35 raeburn 578: ($recommended{'runlevels'},$tostop,$uses_systemctl) = &chkconfig($distro,$instdir);
1.45.2.20 raeburn 579: if ((ref($uses_systemctl) eq 'HASH') && ($uses_systemctl->{'apache'})) {
580: $recommended{'systemd'} = &check_systemd_security($distro);
581: }
1.1 raeburn 582: $recommended{'apache'} = &chkapache($distro,$instdir);
583: $recommended{'stopsrvcs'} = &chksrvcs($distro,$tostop);
584: ($recommended{'download'},$downloadstatus,$filetouse,$production,$testing)
1.45.2.16 raeburn 585: = &need_download($distro,$instdir);
1.45.2.22 raeburn 586: return ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,
1.45.2.9 raeburn 587: $mysqlrestart,\%recommended,$dbh,$has_pass,$mysql_unix_socket,
588: $has_lcdb,$downloadstatus,$filetouse,$production,$testing,$apachefw,
589: $uses_systemctl);
1.1 raeburn 590: }
591:
592: sub check_mysql_running {
593: my ($distro) = @_;
1.23 raeburn 594: my $use_systemctl;
1.1 raeburn 595: my $mysqldaemon ='mysqld';
596: if ($distro =~ /^(suse|sles|debian|ubuntu)/) {
597: $mysqldaemon = 'mysql';
598: }
1.6 raeburn 599: my $process = 'mysqld_safe';
600: my $proc_owner = 'root';
601: if ($distro =~ /^ubuntu(\w+)/) {
602: if ($1 >= 10) {
603: $process = 'mysqld';
604: $proc_owner = 'mysql';
605: }
1.45.2.20 raeburn 606: if ($1 >= 16) {
607: $use_systemctl = 1;
608: }
1.45.2.19 raeburn 609: } elsif ($distro =~ /^debian(\w+)/) {
610: if ($1 >= 10) {
611: $process = 'mysql';
612: $proc_owner = 'mysql';
613: }
614: if ($1 >= 11) {
615: $mysqldaemon = 'mariadb';
616: }
1.45.2.20 raeburn 617: if ($1 >= 9) {
618: $use_systemctl = 1;
619: }
1.35 raeburn 620: } elsif ($distro =~ /^fedora(\d+)/) {
1.23 raeburn 621: if ($1 >= 16) {
622: $process = 'mysqld';
623: $proc_owner = 'mysql';
624: $use_systemctl = 1;
625: }
1.39 raeburn 626: if ($1 >= 19) {
1.37 raeburn 627: $mysqldaemon ='mariadb';
628: }
1.45.2.17 raeburn 629: if ($1 >= 34) {
630: $process = 'mariadb';
631: }
1.45.2.18 raeburn 632: } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.29 raeburn 633: if ($1 >= 7) {
634: $mysqldaemon ='mariadb';
635: $process = 'mysqld';
636: $proc_owner = 'mysql';
637: $use_systemctl = 1;
638: }
1.45.2.19 raeburn 639: if ($1 >= 9) {
640: $process = 'mariadb';
641: }
1.35 raeburn 642: } elsif ($distro =~ /^sles(\d+)/) {
643: if ($1 >= 12) {
644: $use_systemctl = 1;
1.42 raeburn 645: $proc_owner = 'mysql';
646: $process = 'mysqld';
1.35 raeburn 647: }
1.45.2.23! raeburn 648: if ($1 >= 12) {
1.45.2.1 raeburn 649: $mysqldaemon ='mariadb';
650: }
1.35 raeburn 651: } elsif ($distro =~ /^suse(\d+)/) {
652: if ($1 >= 13) {
653: $use_systemctl = 1;
654: }
1.29 raeburn 655: }
1.35 raeburn 656: if (open(PIPE,"ps -ef |grep $process |grep ^$proc_owner |grep -v grep 2>&1 |")) {
1.1 raeburn 657: my $status = <PIPE>;
658: close(PIPE);
659: chomp($status);
1.6 raeburn 660: if ($status =~ /^\Q$proc_owner\E\s+\d+\s+/) {
1.1 raeburn 661: print_and_log(&mt('MySQL is running.')."\n");
662: return 1;
663: } else {
1.23 raeburn 664: if ($use_systemctl) {
665: system("/bin/systemctl start $mysqldaemon.service >/dev/null 2>&1 ");
666: } else {
667: system("/etc/init.d/$mysqldaemon start >/dev/null 2>&1 ");
668: }
1.1 raeburn 669: print_and_log(&mt('Waiting for MySQL to start.')."\n");
670: sleep 5;
1.12 raeburn 671: if (open(PIPE,"ps -ef |grep $process |grep -v grep 2>&1 |")) {
672: $status = <PIPE>;
1.1 raeburn 673: close(PIPE);
674: chomp($status);
1.12 raeburn 675: if ($status =~ /^\Q$proc_owner\E\s+\d+\s+/) {
1.1 raeburn 676: print_and_log(&mt('MySQL is running.')."\n");
677: return 1;
678: } else {
1.12 raeburn 679: print_and_log(&mt('Still waiting for MySQL to start.')."\n");
680: sleep 5;
681: if (open(PIPE,"ps -ef |grep $process |grep -v grep 2>&1 |")) {
682: $status = <PIPE>;
683: close(PIPE);
684: chomp($status);
685: if ($status =~ /^\Q$proc_owner\E\s+\d+\s+/) {
686: print_and_log(&mt('MySQL is running.')."\n");
687: return 1;
688: } else {
689: print_and_log(&mt('Given up waiting for MySQL to start.')."\n");
690: }
691: }
1.1 raeburn 692: }
693: }
694: }
695: } else {
696: print &mt('Could not determine if MySQL is running.')."\n";
697: }
698: return;
699: }
700:
701: sub chkconfig {
1.8 raeburn 702: my ($distro,$instdir) = @_;
1.23 raeburn 703: my (%needfix,%tostop,%uses_systemctl);
1.1 raeburn 704: my $checker_bin = '/sbin/chkconfig';
1.23 raeburn 705: my $sysctl_bin = '/bin/systemctl';
1.6 raeburn 706: my %daemon = (
707: mysql => 'mysqld',
708: apache => 'httpd',
709: cups => 'cups',
710: ntp => 'ntpd',
711: memcached => 'memcached',
712: );
1.1 raeburn 713: my @runlevels = qw/3 4 5/;
714: my @norunlevels = qw/0 1 6/;
715: if ($distro =~ /^(suse|sles)/) {
716: @runlevels = qw/3 5/;
717: @norunlevels = qw/0 2 1 6/;
1.6 raeburn 718: $daemon{'mysql'} = 'mysql';
719: $daemon{'apache'} = 'apache2';
1.8 raeburn 720: $daemon{'ntp'} = 'ntp';
1.1 raeburn 721: if ($distro =~ /^(suse|sles)9/) {
1.6 raeburn 722: $daemon{'apache'} = 'apache';
1.1 raeburn 723: }
1.35 raeburn 724: if ($distro =~ /^(suse|sles)([\d\.]+)/) {
725: my $name = $1;
726: my $num = $2;
727: if ($num > 11) {
1.26 raeburn 728: $uses_systemctl{'apache'} = 1;
1.35 raeburn 729: if (($name eq 'sles') || ($name eq 'suse' && $num >= 13.2)) {
730: $uses_systemctl{'mysql'} = 1;
731: $uses_systemctl{'ntp'} = 1;
732: $uses_systemctl{'cups'} = 1;
733: $uses_systemctl{'memcached'} = 1;
1.45.2.23! raeburn 734: if ($name eq 'sles') {
! 735: if ($num >= 12) {
! 736: $daemon{'mysql'} = 'mariadb';
! 737: }
! 738: if ($num >= 15) {
! 739: $daemon{'ntp'} = 'chronyd';
! 740: } else {
! 741: $daemon{'ntp'} = 'ntpd';
! 742: }
1.45.2.1 raeburn 743: } else {
744: $daemon{'ntp'} = 'ntpd';
745: }
1.35 raeburn 746: }
1.26 raeburn 747: }
748: }
1.6 raeburn 749: } elsif ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
750: my $version = $1;
1.1 raeburn 751: @runlevels = qw/2 3 4 5/;
752: @norunlevels = qw/0 1 6/;
1.44 raeburn 753: if (($distro =~ /^ubuntu/) && ($version <= 16)) {
754: $checker_bin = '/usr/sbin/sysv-rc-conf';
755: } else {
756: $uses_systemctl{'ntp'} = 1;
757: $uses_systemctl{'mysql'} = 1;
758: $uses_systemctl{'apache'} = 1;
759: $uses_systemctl{'memcached'} = 1;
760: $uses_systemctl{'cups'} = 1;
761: }
1.6 raeburn 762: $daemon{'mysql'} = 'mysql';
763: $daemon{'apache'} = 'apache2';
764: $daemon{'ntp'} = 'ntp';
765: if (($distro =~ /^ubuntu/) && ($version <= 8)) {
766: $daemon{'cups'} = 'cupsys';
767: }
1.45.2.19 raeburn 768: if ((($distro =~ /^ubuntu/) && ($version >= 18)) ||
769: (($distro =~ /^debian/) && ($version >= 10))) {
1.45.2.6 raeburn 770: $daemon{'ntp'} = 'chrony';
771: }
1.45.2.23! raeburn 772: if (($distro =~ /^debian/) && ($version >= 10)) {
1.45.2.19 raeburn 773: $daemon{'mysql'} = 'mariadb';
774: }
1.26 raeburn 775: } elsif ($distro =~ /^fedora(\d+)/) {
1.23 raeburn 776: my $version = $1;
777: if ($version >= 15) {
778: $uses_systemctl{'ntp'} = 1;
779: }
780: if ($version >= 16) {
781: $uses_systemctl{'mysql'} = 1;
782: $uses_systemctl{'apache'} = 1;
1.35 raeburn 783: $uses_systemctl{'memcached'} = 1;
784: $uses_systemctl{'cups'} = 1;
1.23 raeburn 785: }
1.39 raeburn 786: if ($version >= 19) {
1.37 raeburn 787: $daemon{'mysql'} = 'mariadb';
788: }
1.45.2.5 raeburn 789: if ($version >= 26) {
790: $daemon{'ntp'} = 'chronyd';
791: }
1.45.2.18 raeburn 792: } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.29 raeburn 793: my $version = $1;
794: if ($version >= 7) {
795: $uses_systemctl{'ntp'} = 1;
796: $uses_systemctl{'mysql'} = 1;
797: $uses_systemctl{'apache'} = 1;
1.35 raeburn 798: $uses_systemctl{'memcached'} = 1;
799: $uses_systemctl{'cups'} = 1;
1.30 raeburn 800: $daemon{'mysql'} = 'mariadb';
1.29 raeburn 801: }
1.45.2.3 raeburn 802: if (($version >= 8) || ($distro eq 'oracle7')) {
803: $daemon{'ntp'} = 'chronyd';
804: }
1.1 raeburn 805: }
1.23 raeburn 806: my $nocheck;
1.1 raeburn 807: if (! -x $checker_bin) {
1.23 raeburn 808: if ($uses_systemctl{'mysql'} && $uses_systemctl{'apache'}) {
809: if (! -x $sysctl_bin) {
810: $nocheck = 1;
811: }
812: } else {
813: $nocheck = 1;
814: }
815: }
816: if ($nocheck) {
1.6 raeburn 817: print &mt('Could not check runlevel status for MySQL or Apache')."\n";
1.1 raeburn 818: return;
819: }
820: my $rlstr = join('',@runlevels);
821: my $nrlstr = join('',@norunlevels);
1.23 raeburn 822:
1.6 raeburn 823: foreach my $type ('apache','mysql','ntp','cups','memcached') {
824: my $service = $daemon{$type};
1.23 raeburn 825: if ($uses_systemctl{$type}) {
1.35 raeburn 826: if (($type eq 'memcached') || ($type eq 'cups')) {
827: if (-l "/etc/systemd/system/multi-user.target.wants/$service.service") {
828: $tostop{$type} = 1;
829: }
830: } else {
831: if (!-l "/etc/systemd/system/multi-user.target.wants/$service.service") {
832: $needfix{$type} = "systemctl enable $service.service";
833: }
1.23 raeburn 834: }
835: } else {
836: my $command = $checker_bin.' --list '.$service.' 2>/dev/null';
1.35 raeburn 837: if ($type eq 'cups') {
1.23 raeburn 838: if ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
839: my $version = $1;
840: if (($distro =~ /^ubuntu/) && ($version <= 8)) {
841: $command = $checker_bin.' --list cupsys 2>/dev/null';
1.19 raeburn 842: }
843: }
844: }
1.23 raeburn 845: my $results = `$command`;
846: my $tofix;
847: if ($results eq '') {
848: if (($type eq 'apache') || ($type eq 'mysql') || ($type eq 'ntp')) {
849: if ($distro =~ /^(debian|ubuntu)/) {
850: $tofix = "update-rc.d $type defaults";
851: } else {
852: $tofix = "$checker_bin --add $service\n";
853: }
1.6 raeburn 854: }
1.23 raeburn 855: } else {
856: my %curr_runlevels;
857: for (my $rl=0; $rl<=6; $rl++) {
858: if ($results =~ /$rl:on/) { $curr_runlevels{$rl}++; }
859: }
860: if (($type eq 'apache') || ($type eq 'mysql') || ($type eq 'ntp')) {
861: my $warning;
862: foreach my $rl (@runlevels) {
863: if (!exists($curr_runlevels{$rl})) {
864: $warning = 1;
865: }
866: }
867: if ($warning) {
868: $tofix = "$checker_bin --level $rlstr $service on\n";
869: }
870: } elsif (keys(%curr_runlevels) > 0) {
871: $tostop{$type} = 1;
1.1 raeburn 872: }
873: }
1.23 raeburn 874: if ($tofix) {
875: $needfix{$type} = $tofix;
1.1 raeburn 876: }
1.5 raeburn 877: }
1.1 raeburn 878: }
879: if ($distro =~ /^(suse|sles)([\d\.]+)$/) {
880: my $name = $1;
881: my $version = $2;
882: my ($major,$minor);
883: if ($name eq 'suse') {
884: ($major,$minor) = split(/\./,$version);
885: } else {
886: $major = $version;
887: }
1.45.2.1 raeburn 888: if (($major > 10) && ($major <= 13)) {
1.8 raeburn 889: if (&check_SuSEfirewall2_setup($instdir)) {
890: $needfix{'insserv'} = 1;
891: }
1.1 raeburn 892: }
893: }
1.35 raeburn 894: return (\%needfix,\%tostop,\%uses_systemctl);
1.1 raeburn 895: }
896:
1.45.2.20 raeburn 897: sub check_systemd_security {
898: my ($distro) = @_;
899: my $service = 'httpd.service';
900: if ($distro =~ /^(suse|sles|ubuntu|debian)/) {
901: $service = 'apache2.service';
902: }
903: system("systemctl daemon-reload");
904: if (open(PIPE,"systemctl show $service --property=ProtectHome 2>/dev/null |")) {
905: my $protection = <PIPE>;
906: close(PIPE);
907: chomp($protection);
908: if ($protection =~ /^ProtectHome=(read-only|yes)$/i) {
909: return 1;
910: }
911: } else {
912: print &mt('Could not check systemctl configuration for Apache')."\n";
913: }
914: return 0;
915: }
916:
1.45.2.1 raeburn 917: sub uses_firewalld {
918: my ($distro) = @_;
1.45.2.3 raeburn 919: my ($inuse,$checkfirewalld,$zone);
1.45.2.1 raeburn 920: if ($distro =~ /^(suse|sles)([\d\.]+)$/) {
921: if (($1 eq 'sles') && ($2 >= 15)) {
922: $checkfirewalld = 1;
923: }
924: } elsif ($distro =~ /^fedora(\d+)$/) {
925: if ($1 >= 18) {
926: $checkfirewalld = 1;
927: }
1.45.2.18 raeburn 928: } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.45.2.1 raeburn 929: if ($1 >= 7) {
930: $checkfirewalld = 1;
931: }
932: }
933: if ($checkfirewalld) {
934: my ($loaded,$active);
1.45.2.15 raeburn 935: if (open(PIPE,"systemctl status firewalld 2>/dev/null |")) {
1.45.2.1 raeburn 936: while (<PIPE>) {
937: chomp();
938: if (/^\s*Loaded:\s+(\w+)/) {
939: $loaded = $1;
940: }
1.45.2.15 raeburn 941: if (/^\s*Active:\s+(\w+)/) {
1.45.2.1 raeburn 942: $active = $1;
943: }
944: }
945: close(PIPE);
946: }
947: if (($loaded eq 'loaded') || ($active eq 'active')) {
948: $inuse = 1;
1.45.2.3 raeburn 949: my $cmd = 'firewall-cmd --get-default-zone';
950: if (open(PIPE,"$cmd |")) {
951: my $result = <PIPE>;
952: chomp($result);
953: close(PIPE);
954: if ($result =~ /^\w+$/) {
955: $zone = $result;
956: }
957: }
1.45.2.1 raeburn 958: }
959: }
1.45.2.3 raeburn 960: return ($inuse,$zone);
1.45.2.1 raeburn 961: }
962:
1.1 raeburn 963: sub chkfirewall {
1.5 raeburn 964: my ($distro) = @_;
1.1 raeburn 965: my $configfirewall = 1;
966: my %ports = (
967: http => 80,
968: https => 443,
969: );
1.5 raeburn 970: my %activefw;
1.45.2.3 raeburn 971: my ($firewalld,$zone) = &uses_firewalld($distro);
972: if ($firewalld) {
973: my %current;
974: if (open(PIPE,'firewall-cmd --permanent --zone='.$zone.' --list-services |')) {
975: my $svc = <PIPE>;
976: close(PIPE);
977: chomp($svc);
978: map { $current{$_} = 1; } (split(/\s+/,$svc));
979: }
980: if ($current{'http'} && $current{'https'}) {
981: $configfirewall = 0;
982: }
983: } else {
984: if (&firewall_is_active()) {
1.45.2.1 raeburn 985: my $iptables = &get_pathto_iptables();
986: if ($iptables eq '') {
987: print &mt('Firewall not checked as path to iptables not determined.')."\n";
988: } else {
989: my @fwchains = &get_fw_chains($iptables,$distro);
990: if (@fwchains) {
991: foreach my $service ('http','https') {
992: foreach my $fwchain (@fwchains) {
993: if (&firewall_is_port_open($iptables,$fwchain,$ports{$service})) {
994: $activefw{$service} = 1;
995: last;
996: }
1.1 raeburn 997: }
998: }
1.45.2.1 raeburn 999: if ($activefw{'http'}) {
1000: $configfirewall = 0;
1001: }
1002: } else {
1003: print &mt('Firewall not checked as iptables Chains not identified.')."\n";
1.1 raeburn 1004: }
1005: }
1.45.2.3 raeburn 1006: } else {
1007: print &mt('Firewall not enabled.')."\n";
1.1 raeburn 1008: }
1009: }
1.5 raeburn 1010: return ($configfirewall,\%activefw);
1.1 raeburn 1011: }
1012:
1013: sub chkapache {
1014: my ($distro,$instdir) = @_;
1015: my $fixapache = 1;
1.28 raeburn 1016: if ($distro =~ /^(debian|ubuntu)(\d+)$/) {
1017: my $distname = $1;
1018: my $version = $2;
1.33 raeburn 1019: my ($stdconf,$stdsite);
1.45.2.19 raeburn 1020: if ((($distname eq 'ubuntu') && ($version > 12)) ||
1021: (($distname eq 'debian') && ($version >= 10))) {
1.33 raeburn 1022: $stdconf = "$instdir/debian-ubuntu/ubuntu14/loncapa_conf";
1023: $stdsite = "$instdir/debian-ubuntu/ubuntu14/loncapa_sites";
1024: } else {
1025: $stdconf = "$instdir/debian-ubuntu/loncapa";
1026: }
1027: if (!-e $stdconf) {
1.1 raeburn 1028: $fixapache = 0;
1029: print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";
1.28 raeburn 1030: } else {
1.33 raeburn 1031: my ($configfile,$sitefile);
1.45.2.19 raeburn 1032: if ((($distname eq 'ubuntu') && ($version > 12)) ||
1033: (($distname eq 'debian') && ($version >= 10))) {
1.45.2.10 raeburn 1034: $sitefile = '/etc/apache2/sites-available/loncapa.conf';
1035: $configfile = '/etc/apache2/conf-available/loncapa.conf';
1.33 raeburn 1036: } else {
1.45.2.10 raeburn 1037: $configfile = '/etc/apache2/sites-available/loncapa';
1.28 raeburn 1038: }
1.33 raeburn 1039: if (($configfile ne '') && (-e $configfile) && (-e $stdconf)) {
1040: if (open(PIPE, "diff --brief $stdconf $configfile |")) {
1.28 raeburn 1041: my $diffres = <PIPE>;
1042: close(PIPE);
1043: chomp($diffres);
1044: unless ($diffres) {
1045: $fixapache = 0;
1046: }
1.1 raeburn 1047: }
1048: }
1.45.2.19 raeburn 1049: if ((!$fixapache) && ((($distname eq 'ubuntu') && ($version > 12)) ||
1050: (($distname eq 'debian') && ($version >= 10)))) {
1.33 raeburn 1051: if (($sitefile ne '') && (-e $sitefile) && (-e $stdsite)) {
1052: if (open(PIPE, "diff --brief $stdsite $sitefile |")) {
1053: my $diffres = <PIPE>;
1054: close(PIPE);
1055: chomp($diffres);
1.45.2.20 raeburn 1056: if ($diffres) {
1057: $fixapache = 1;
1058: } else {
1.33 raeburn 1059: $fixapache = 0;
1060: }
1061: }
1062: }
1063: }
1.1 raeburn 1064: }
1.6 raeburn 1065: if (!$fixapache) {
1066: foreach my $module ('headers.load','expires.load') {
1067: unless (-l "/etc/apache2/mods-enabled/$module") {
1068: $fixapache = 1;
1069: }
1070: }
1071: }
1.45.2.19 raeburn 1072: if ((!$fixapache) && (($distname eq 'ubuntu') || ($distname eq 'debian'))) {
1.45.2.7 raeburn 1073: my $sitestatus = "/etc/apache2/mods-available/status.conf";
1074: my $stdstatus = "$instdir/debian-ubuntu/status.conf";
1075: if ((-e $stdstatus) && (-e $sitestatus)) {
1076: if (open(PIPE, "diff --brief $stdstatus $sitestatus |")) {
1077: my $diffres = <PIPE>;
1078: close(PIPE);
1079: chomp($diffres);
1080: if ($diffres) {
1081: $fixapache = 1;
1082: }
1083: }
1084: }
1085: }
1.45.2.1 raeburn 1086: } elsif ($distro =~ /^(suse|sles)([\d\.]+)$/) {
1087: my ($name,$version) = ($1,$2);
1.1 raeburn 1088: my $apache = 'apache';
1.45.2.1 raeburn 1089: my $conf_file = "$instdir/sles-suse/default-server.conf";
1090: if ($version >= 10) {
1.8 raeburn 1091: $apache = 'apache2';
1.1 raeburn 1092: }
1.45.2.1 raeburn 1093: if (($name eq 'sles') && ($version >= 12)) {
1094: $conf_file = "$instdir/sles-suse/apache2.4/default-server.conf";
1095: }
1096: if (!-e $conf_file) {
1.1 raeburn 1097: $fixapache = 0;
1098: print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";
1.45.2.1 raeburn 1099: } elsif (-e "/etc/$apache/default-server.conf") {
1100: if (open(PIPE, "diff --brief $conf_file /etc/$apache/default-server.conf |")) {
1.9 raeburn 1101: my $diffres = <PIPE>;
1102: close(PIPE);
1103: chomp($diffres);
1104: unless ($diffres) {
1105: $fixapache = 0;
1106: }
1107: }
1108: }
1109: } elsif ($distro eq 'rhes4') {
1110: if (!-e "$instdir/rhes4/httpd.conf") {
1111: $fixapache = 0;
1112: print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";
1113: } elsif ((-e "/etc/httpd/conf/httpd.conf") && (-e "$instdir/rhes4/httpd.conf")) {
1114: if (open(PIPE, "diff --brief $instdir/rhes4/httpd.conf /etc/httpd/conf/httpd.conf |")) {
1.1 raeburn 1115: my $diffres = <PIPE>;
1116: close(PIPE);
1117: chomp($diffres);
1118: unless ($diffres) {
1119: $fixapache = 0;
1120: }
1121: }
1122: }
1123: } else {
1.14 raeburn 1124: my $configfile = 'httpd.conf';
1.45.2.5 raeburn 1125: my $mpmfile = 'mpm.conf';
1.45.2.18 raeburn 1126: if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.29 raeburn 1127: if ($1 >= 7) {
1128: $configfile = 'apache2.4/httpd.conf';
1129: } elsif ($1 > 5) {
1.14 raeburn 1130: $configfile = 'new/httpd.conf';
1131: }
1132: } elsif ($distro =~ /^fedora(\d+)$/) {
1.29 raeburn 1133: if ($1 > 17) {
1.45.2.5 raeburn 1134: $configfile = 'apache2.4/httpd.conf';
1.29 raeburn 1135: } elsif ($1 > 10) {
1.15 raeburn 1136: $configfile = 'new/httpd.conf';
1.14 raeburn 1137: }
1138: }
1139: if (!-e "$instdir/centos-rhes-fedora-sl/$configfile") {
1.1 raeburn 1140: $fixapache = 0;
1141: print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";
1.14 raeburn 1142: } elsif ((-e "/etc/httpd/conf/httpd.conf") && (-e "$instdir/centos-rhes-fedora-sl/$configfile")) {
1143: if (open(PIPE, "diff --brief $instdir/centos-rhes-fedora-sl/$configfile /etc/httpd/conf/httpd.conf |")) {
1.1 raeburn 1144: my $diffres = <PIPE>;
1145: close(PIPE);
1146: chomp($diffres);
1147: unless ($diffres) {
1148: $fixapache = 0;
1149: }
1150: }
1151: }
1.45.2.5 raeburn 1152: if (-e "/etc/httpd/conf.modules.d/00-mpm.conf") {
1153: if (!-e "$instdir/centos-rhes-fedora-sl/$mpmfile") {
1154: print &mt('Warning: No LON-CAPA Apache MPM configuration file found for installation check.')."\n";
1155: } elsif ((-e "/etc/httpd/conf.modules.d/00-mpm.conf") && (-e "$instdir/centos-rhes-fedora-sl/$mpmfile")) {
1156: if (open(PIPE, "diff --brief $instdir/centos-rhes-fedora-sl/$mpmfile /etc/httpd/conf.modules.d/00-mpm.conf |")) {
1157: my $diffres = <PIPE>;
1158: close(PIPE);
1159: chomp($diffres);
1160: if ($diffres) {
1161: $fixapache = 1;
1162: }
1163: }
1164: }
1165: }
1.1 raeburn 1166: }
1167: return $fixapache;
1168: }
1169:
1170: sub chksrvcs {
1171: my ($distro,$tostop) = @_;
1172: my %stopsrvcs;
1173: if (ref($tostop) eq 'HASH') {
1174: %stopsrvcs = %{$tostop};
1175: }
1.6 raeburn 1176: foreach my $service ('cups','memcached') {
1.1 raeburn 1177: next if (exists($stopsrvcs{$service}));
1178: my $daemon = $service;
1179: if ($service eq 'cups') {
1180: $daemon = 'cupsd';
1181: }
1182: my $cmd = "ps -ef |grep '$daemon' |grep -v grep";
1183: if (open(PIPE,'-|',$cmd)) {
1184: my $daemonrunning = <PIPE>;
1185: chomp($daemonrunning);
1186: close(PIPE);
1187: if ($daemonrunning) {
1.12 raeburn 1188: if ($service eq 'memcached') {
1.16 raeburn 1189: my $cmd = '/usr/bin/memcached';
1190: if ($distro =~ /^(suse|sles)/) {
1191: $cmd = '/usr/sbin/memcached';
1192: }
1.12 raeburn 1193: unless ($daemonrunning =~ m{^www[^/]+\Q$cmd -m 400 -v\E$}) {
1.10 raeburn 1194: $stopsrvcs{$service} = 1;
1195: }
1196: } else {
1197: $stopsrvcs{$service} = 1;
1198: }
1.1 raeburn 1199: }
1200: }
1.10 raeburn 1201: }
1.1 raeburn 1202: return \%stopsrvcs;
1203: }
1204:
1205: sub need_download {
1.45.2.16 raeburn 1206: my ($distro,$instdir) = @_;
1.1 raeburn 1207: my $needs_download = 1;
1208: my ($production,$testing,$stdsizes) = &download_versionslist();
1.45.2.16 raeburn 1209: my ($localcurrent,$localtesting,%tarball,%localsize,%bymodtime,
1.1 raeburn 1210: %bysize,$filetouse,$downloadstatus);
1.45.2.16 raeburn 1211: if (opendir(my $dir,$instdir)) {
1.1 raeburn 1212: my (@lcdownloads,$version);
1213: foreach my $file (readdir($dir)) {
1214: if ($file =~ /^loncapa\-([\w\-.]+)\.tar\.gz$/) {
1215: $version = $1;
1216: } else {
1217: next;
1218: }
1219: if (ref($stdsizes) eq 'HASH') {
1220: if ($version eq 'current') {
1.45.2.16 raeburn 1221: my @stats = stat("$instdir/$file");
1.1 raeburn 1222: $localcurrent = $stats[7];
1.4 raeburn 1223: if ($localcurrent == $stdsizes->{$production}) {
1.1 raeburn 1224: $needs_download = 0;
1225: $filetouse = $file;
1226: }
1227: } elsif ($version eq 'testing') {
1.45.2.16 raeburn 1228: my @stats = stat("$instdir/$file");
1.1 raeburn 1229: $localtesting = $stats[7];
1.4 raeburn 1230: if ($localtesting == $stdsizes->{$testing}) {
1.1 raeburn 1231: $needs_download = 0;
1232: $filetouse = $file;
1233: }
1234: }
1235: }
1236: $tarball{$version} = $file;
1237: push(@lcdownloads,$version);
1238: }
1239: if ($needs_download) {
1240: if (@lcdownloads > 0) {
1241: foreach my $version (@lcdownloads) {
1.45.2.16 raeburn 1242: my @stats = stat("$instdir/$tarball{$version}");
1.1 raeburn 1243: my $mtime = $stats[9];
1244: $localsize{$version} = $stats[7];
1245: if ($mtime) {
1246: push(@{$bymodtime{$mtime}},$version);
1247: }
1248: if ($localsize{$version}) {
1249: push(@{$bysize{$localsize{$version}}},$version);
1250: }
1251: }
1252: if ($testing) {
1253: if (exists($localsize{$testing})) {
1254: if ($stdsizes->{$testing} == $localsize{$testing}) {
1255: $needs_download = 0;
1256: $filetouse = 'loncapa-'.$testing.'.tar.gz';
1257: }
1258: }
1259: }
1260: if ($needs_download) {
1261: if ($production) {
1262: if (exists($localsize{$production})) {
1263: if ($stdsizes->{$production} == $localsize{$production}) {
1264: $needs_download = 0;
1265: $filetouse = 'loncapa-'.$production.'.tar.gz';
1266: }
1267: }
1268: }
1269: }
1270: if ($needs_download) {
1271: my @sorted = sort { $b <=> $a } keys(%bymodtime);
1272: my $newest = $sorted[0];
1273: if (ref($bymodtime{$newest}) eq 'ARRAY') {
1274: $downloadstatus =
1.45.2.16 raeburn 1275: "Latest LON-CAPA source download in $instdir is: ".
1.1 raeburn 1276: join(',',@{$bymodtime{$newest}})." (downloaded ".
1277: localtime($newest).")\n";
1278: }
1279: } else {
1280: $downloadstatus =
1.45.2.16 raeburn 1281: "The $instdir directory already contains the latest LON-CAPA version:".
1.1 raeburn 1282: "\n".$filetouse."\n"."which can be used for installation.\n";
1283: }
1284: } else {
1.45.2.16 raeburn 1285: $downloadstatus = "The $instdir directory does not appear to contain any downloaded LON-CAPA source code files which can be used for installation.\n";
1.1 raeburn 1286: }
1287: }
1288: } else {
1.45.2.16 raeburn 1289: $downloadstatus = "Could not open $instdir directory to look for existing downloads of LON-CAPA source code.\n";
1.1 raeburn 1290: }
1291: return ($needs_download,$downloadstatus,$filetouse,$production,$testing);
1292: }
1293:
1294: sub check_mysql_setup {
1.45.2.12 raeburn 1295: my ($instdir,$dsn,$distro) = @_;
1296: my ($mysqlsetup,$has_pass,$mysql_unix_socket,$mysql_has_wwwuser);
1.1 raeburn 1297: my $dbh = DBI->connect($dsn,'root','',{'PrintError'=>0});
1.45.2.19 raeburn 1298: my ($mysqlversion,$mysqlminorversion,$mysqlsubver,$mysqlname) = &get_mysql_version();
1299: if (($mysqlname =~ /^MariaDB/i) && (($mysqlversion == 10 && $mysqlminorversion >= 4) || ($mysqlversion >= 11))) {
1.45.2.9 raeburn 1300: if ($dbh) {
1301: my $sth = $dbh->prepare("SELECT Priv FROM mysql.global_priv WHERE (User = 'root' AND Host ='localhost')");
1302: $sth->execute();
1303: while (my $priv = $sth->fetchrow_array) {
1.45.2.14 raeburn 1304: if ($priv =~ /unix_socket/) {
1.45.2.9 raeburn 1305: $mysql_unix_socket = 1;
1306: last;
1307: }
1308: }
1309: $sth->finish();
1310: if ($mysql_unix_socket) {
1311: print_and_log(&mt('MariaDB using unix_socket for root access from localhost.')."\n");
1312: $mysqlsetup = 'rootok';
1.45.2.12 raeburn 1313: $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.45.2.9 raeburn 1314: return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser,$mysql_unix_socket);
1315: }
1316: }
1317: }
1.1 raeburn 1318: if ($dbh) {
1.45.2.12 raeburn 1319: $mysqlsetup = 'noroot';
1.45.2.19 raeburn 1320: if (($mysqlname !~ /^MariaDB/i) && (($mysqlversion == 5 && $mysqlminorversion >= 7) || ($mysqlversion >= 6))) {
1.45.2.12 raeburn 1321: my $sth = $dbh->prepare("SELECT plugin from mysql.user where User='root'");
1322: $sth->execute();
1323: while (my $priv = $sth->fetchrow_array) {
1324: if ($priv =~ /auth_socket/) {
1325: $mysql_unix_socket = 1;
1326: last;
1327: }
1328: }
1329: $sth->finish();
1330: if ($mysql_unix_socket) {
1331: print_and_log(&mt('MySQL using unix_socket for root access from localhost.')."\n");
1332: $mysqlsetup = 'rootok';
1333: $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1334: return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser,$mysql_unix_socket);
1335: }
1.45.2.14 raeburn 1336: }
1.1 raeburn 1337: } elsif ($DBI::err =~ /1045/) {
1338: $has_pass = 1;
1.34 raeburn 1339: } elsif ($distro =~ /^ubuntu(\d+)$/) {
1340: my $version = $1;
1341: if ($1 > 12) {
1342: print_and_log(&mt('Restarting mysql, please be patient')."\n");
1343: if (open (PIPE, "service mysql restart 2>&1 |")) {
1344: while (<PIPE>) {
1345: print $_;
1346: }
1347: close(PIPE);
1348: }
1349: $dbh = DBI->connect($dsn,'root','',{'PrintError'=>0});
1350: if ($dbh) {
1351: $mysqlsetup = 'noroot';
1.45.2.12 raeburn 1352: $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.34 raeburn 1353: } elsif ($DBI::err =~ /1045/) {
1354: $has_pass = 1;
1355: } else {
1356: $mysqlsetup = 'needsrestart';
1.45.2.16 raeburn 1357: $mysql_has_wwwuser = &check_mysql_wwwuser();
1.34 raeburn 1358: return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser);
1359: }
1360: }
1.1 raeburn 1361: }
1362: if ($has_pass) {
1363: print &mt('You have already set a root password for the MySQL database.')."\n";
1364: my $currpass = &get_mysql_password(&mt('Please enter the password now'));
1365: $dbh = DBI->connect($dsn,'root',$currpass,{'PrintError'=>0});
1366: if ($dbh) {
1367: $mysqlsetup = 'rootok';
1368: print_and_log(&mt('Password accepted.')."\n");
1.45.2.12 raeburn 1369: $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.1 raeburn 1370: } else {
1371: $mysqlsetup = 'rootfail';
1372: print_and_log(&mt('Problem accessing MySQL.')."\n");
1373: if ($DBI::err =~ /1045/) {
1374: print_and_log(&mt('Perhaps the password was incorrect?')."\n");
1375: print &mt('Try again?').' ';
1376: $currpass = &get_mysql_password(&mt('Re-enter password now'));
1377: $dbh = DBI->connect($dsn,'root',$currpass,{'PrintError'=>0});
1378: if ($dbh) {
1379: $mysqlsetup = 'rootok';
1380: print_and_log(&mt('Password accepted.')."\n");
1.45.2.12 raeburn 1381: $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.1 raeburn 1382: } else {
1383: if ($DBI::err =~ /1045/) {
1384: print_and_log(&mt('Incorrect password.')."\n");
1385: }
1.45.2.16 raeburn 1386: $mysql_has_wwwuser = &check_mysql_wwwuser();
1.1 raeburn 1387: }
1388: }
1389: }
1.34 raeburn 1390: } elsif ($mysqlsetup ne 'noroot') {
1.1 raeburn 1391: print_and_log(&mt('Problem accessing MySQL.')."\n");
1392: $mysqlsetup = 'rootfail';
1.45.2.16 raeburn 1393: $mysql_has_wwwuser = &check_mysql_wwwuser();
1.1 raeburn 1394: }
1.34 raeburn 1395: return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser);
1.1 raeburn 1396: }
1397:
1398: sub check_mysql_wwwuser {
1.45.2.12 raeburn 1399: my ($dbh) = @_;
1.1 raeburn 1400: my $mysql_wwwuser;
1.45.2.12 raeburn 1401: if ($dbh) {
1402: $mysql_wwwuser = $dbh->selectrow_array("SELECT COUNT(User) FROM mysql.user WHERE (User = 'www' AND Host ='localhost')");
1403: } else {
1404: my $dbhn = DBI->connect("DBI:mysql:database=information_schema",'www','localhostkey',
1405: {PrintError => +0}) || return;
1406: if ($dbhn) {
1407: $mysql_wwwuser = 1;
1408: $dbhn->disconnect;
1409: }
1.1 raeburn 1410: }
1411: return $mysql_wwwuser;
1412: }
1413:
1414: sub check_loncapa_mysqldb {
1415: my ($dbh) = @_;
1416: my $has_lcdb;
1417: if (ref($dbh)) {
1418: my $sth = $dbh->prepare("SHOW DATABASES");
1419: $sth->execute();
1420: while (my $dbname = $sth->fetchrow_array) {
1421: if ($dbname eq 'loncapa') {
1422: $has_lcdb = 1;
1423: last;
1424: }
1425: }
1426: $sth->finish();
1427: }
1428: return $has_lcdb;
1429: }
1430:
1431: sub get_pathto_iptables {
1432: my $iptables;
1433: if (-e '/sbin/iptables') {
1434: $iptables = '/sbin/iptables';
1435: } elsif (-e '/usr/sbin/iptables') {
1436: $iptables = '/usr/sbin/iptables';
1437: } else {
1438: print &mt('Unable to find iptables command.')."\n";
1439: }
1440: return $iptables;
1441: }
1442:
1443: sub firewall_is_active {
1444: if (-e '/proc/net/ip_tables_names') {
1.45.2.19 raeburn 1445: my $status;
1.45.2.1 raeburn 1446: if (open(PIPE,'cat /proc/net/ip_tables_names |grep filter |')) {
1.45.2.19 raeburn 1447: $status = <PIPE>;
1.45.2.1 raeburn 1448: close(PIPE);
1449: chomp($status);
1450: if ($status eq 'filter') {
1451: return 1;
1452: }
1453: }
1.45.2.19 raeburn 1454: unless ($status) {
1455: if (open(PIPE,'nft list tables |')) {
1456: while(<PIPE>) {
1457: chomp();
1458: if (/filter$/) {
1459: $status = 1;
1460: last;
1461: }
1462: }
1463: close(PIPE);
1464: if ($status) {
1465: return 1;
1466: }
1467: }
1468: }
1.1 raeburn 1469: }
1.45.2.1 raeburn 1470: return 0;
1.1 raeburn 1471: }
1472:
1473: sub get_fw_chains {
1.5 raeburn 1474: my ($iptables,$distro) = @_;
1.1 raeburn 1475: my @fw_chains;
1476: my $suse_config = "/etc/sysconfig/SuSEfirewall2";
1477: my $ubuntu_config = "/etc/ufw/ufw.conf";
1478: if (-e $suse_config) {
1479: push(@fw_chains,'input_ext');
1480: } else {
1481: my @posschains;
1482: if (-e $ubuntu_config) {
1483: @posschains = ('ufw-user-input','INPUT');
1.5 raeburn 1484: } elsif ($distro =~ /^debian5/) {
1485: @posschains = ('INPUT');
1.45.2.1 raeburn 1486: } elsif ($distro =~ /^(suse|sles)(\d+)/) {
1487: @posschains = ('IN_public');
1.1 raeburn 1488: } else {
1489: @posschains = ('RH-Firewall-1-INPUT','INPUT');
1490: if (!-e '/etc/sysconfig/iptables') {
1491: if (!-e '/var/lib/iptables') {
1492: print &mt('Unable to find iptables file containing static definitions.')."\n";
1493: }
1494: push(@fw_chains,'RH-Firewall-1-INPUT');
1495: }
1496: }
1497: if ($iptables eq '') {
1498: $iptables = &get_pathto_iptables();
1499: }
1500: my %counts;
1501: if (open(PIPE,"$iptables -L -n |")) {
1502: while(<PIPE>) {
1503: foreach my $chain (@posschains) {
1504: if (/(\Q$chain\E)/) {
1505: $counts{$1} ++;
1506: }
1507: }
1508: }
1509: close(PIPE);
1510: }
1511: foreach my $fw_chain (@posschains) {
1512: if ($counts{$fw_chain}) {
1513: unless(grep(/^\Q$fw_chain\E$/,@fw_chains)) {
1514: push(@fw_chains,$fw_chain);
1515: }
1516: }
1517: }
1518: }
1519: return @fw_chains;
1520: }
1521:
1522: sub firewall_is_port_open {
1523: my ($iptables,$fw_chain,$port) = @_;
1524: # returns 1 if the firewall port is open, 0 if not.
1525: #
1526: # check if firewall is active or installed
1527: return if (! &firewall_is_active());
1528: my $count = 0;
1529: if (open(PIPE,"$iptables -L $fw_chain -n |")) {
1530: while(<PIPE>) {
1531: if (/tcp dpt\:\Q$port\E/) {
1532: $count ++;
1533: last;
1534: }
1535: }
1536: close(PIPE);
1537: } else {
1538: print &mt('Firewall status not checked: unable to run [_1].','iptables -L')."\n";
1539: }
1540: return $count;
1541: }
1542:
1543: sub get_mysql_password {
1544: my ($prompt) = @_;
1545: local $| = 1;
1546: print $prompt.': ';
1547: my $newpasswd = '';
1548: ReadMode 'raw';
1549: my $key;
1550: while(ord($key = ReadKey(0)) != 10) {
1551: if(ord($key) == 127 || ord($key) == 8) {
1552: chop($newpasswd);
1553: print "\b \b";
1554: } elsif(!ord($key) < 32) {
1555: $newpasswd .= $key;
1556: print '*';
1557: }
1558: }
1559: ReadMode 'normal';
1560: print "\n";
1561: return $newpasswd;
1562: }
1563:
1564: sub check_SuSEfirewall2_setup {
1565: my ($instdir) = @_;
1566: my $need_override = 1;
1.9 raeburn 1567: if ((-e "/etc/insserv/overrides/SuSEfirewall2_setup") && (-e "$instdir/sles-suse/SuSEfirewall2_setup")) {
1568: if (open(PIPE, "diff --brief $instdir/sles-suse/SuSEfirewall2_setup /etc/insserv/overrides/SuSEfirewall2_setup |")) {
1.1 raeburn 1569: my $diffres = <PIPE>;
1570: close(PIPE);
1571: chomp($diffres);
1572: unless ($diffres) {
1573: $need_override = 0;
1574: }
1575: }
1576: }
1577: return $need_override;
1578: }
1579:
1580: sub download_versionslist {
1581: my ($production,$testing,%sizes);
1582: if (-e "latest.txt") {
1583: unlink("latest.txt");
1584: }
1585: my $rtncode = system("wget http://install.loncapa.org/versions/latest.txt ".
1586: "> /dev/null 2>&1");
1587: if (!$rtncode) {
1588: if (open(my $fh,"<latest.txt")) {
1589: my @info = <$fh>;
1590: close($fh);
1591: foreach my $line (@info) {
1592: chomp();
1593: if ($line =~ /^\QLATEST-IS: \E([\w\-.]+):(\d+)$/) {
1594: $production = $1;
1595: $sizes{$1} = $2;
1596: } elsif ($line =~ /^LATEST-TESTING-IS: \E([\w\-.]+):(\d+)$/) {
1597: $testing = $1;
1598: $sizes{$1} = $2;
1599: }
1600: }
1601: }
1602: }
1603: return ($production,$testing,\%sizes);
1604: }
1605:
1606: #
1607: # End helper routines.
1608: # Main script starts here
1609: #
1610:
1611: print "
1612: ********************************************************************
1613:
1614: ".&mt('Welcome to LON-CAPA')."
1615:
1616: ".&mt('This script will configure your system for installation of LON-CAPA.')."
1617:
1618: ********************************************************************
1619:
1620: ".&mt('The following actions are available:')."
1621:
1.4 raeburn 1622: ".&mt('1.')." ".&mt('Create the www user/group.')."
1.1 raeburn 1623: ".&mt('This is the user/group ownership under which Apache child processes run.')."
1624: ".&mt('It also owns most directories within the /home/httpd directory.')."
1625: ".&mt('This directory is where most LON-CAPA files and directories are stored.')."
1.4 raeburn 1626: ".&mt('2.')." ".&mt('Install the package LON-CAPA uses to authenticate users.')."
1627: ".&mt('3.')." ".&mt('Set-up the MySQL database.')."
1628: ".&mt('4.')." ".&mt('Set-up MySQL permissions.')."
1629: ".&mt('5.')." ".&mt('Configure Apache web server.')."
1.45.2.20 raeburn 1630: ".&mt('6.')." ".&mt('Configure systemd security settings for Apache web server.')."
1631: ".&mt('7.')." ".&mt('Configure start-up of services.')."
1632: ".&mt('8.')." ".&mt('Check firewall settings.')."
1633: ".&mt('9.')." ".&mt('Stop services not used by LON-CAPA,')."
1.1 raeburn 1634: ".&mt('i.e., services for a print server: [_1] daemon.',"'cups'")."
1.45.2.20 raeburn 1635: ".&mt('10.')." ".&mt('Download LON-CAPA source code in readiness for installation.')."
1.1 raeburn 1636:
1637: ".&mt('Typically, you will run this script only once, when you first install LON-CAPA.')."
1638:
1639: ".&mt('The script will analyze your system to determine which actions are recommended.')."
1640: ".&mt('The script will then prompt you to choose the actions you would like taken.')."
1641:
1642: ".&mt('For each the recommended action will be selected if you hit Enter/Return.')."
1643: ".&mt('To override the default, type the lower case option from the two options listed.')."
1644: ".&mt('So, if the default is "yes", ~[Y/n~] will be shown -- type n to override.')."
1645: ".&mt('Whereas if the default is "no", ~[y/N~] will be shown -- type y to override.')."
1646:
1647: ".&mt('To accept the default, simply hit Enter/Return on your keyboard.')."
1648: ".&mt('Otherwise type: y or n then hit the Enter/Return key.')."
1649:
1650: ".&mt('Once a choice has been entered for all nine actions, required changes will be made.')."
1651: ".&mt('Feedback will be displayed on screen, and also stored in: [_1].','loncapa_install.log')."
1652:
1653: ".&mt('Continue? ~[Y/n~] ');
1654:
1655: my $go_on = &get_user_selection(1);
1656: if (!$go_on) {
1657: exit;
1658: }
1659:
1660: my $instdir = `pwd`;
1661: chomp($instdir);
1662:
1663: my %callsub;
1.45.2.20 raeburn 1664: my @actions = ('wwwuser','pwauth','mysql','mysqlperms','apache','systemd',
1.1 raeburn 1665: 'runlevels','firewall','stopsrvcs','download');
1666: my %prompts = &texthash(
1667: wwwuser => "Create the 'www' user?",
1668: pwauth => 'Install the package LON-CAPA uses to authenticate users?',
1669: mysql => 'Set-up the MySQL database?',
1670: mysqlperms => 'Set-up MySQL permissions?',
1671: apache => 'Configure Apache web server?',
1.45.2.20 raeburn 1672: systemd => 'Configure systemd security settings for Apache web server?',
1.1 raeburn 1673: runlevels => 'Set overrides for start-up order of services?',
1674: firewall => 'Configure firewall settings for Apache',
1675: stopsrvcs => 'Stop extra services not required on a LON-CAPA server?',
1676: download => 'Download LON-CAPA source code in readiness for installation?',
1677: );
1678:
1679: print "\n".&mt('Checking system status ...')."\n";
1680:
1681: my $dsn = "DBI:mysql:database=mysql";
1.45.2.22 raeburn 1682: my ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart,
1.45.2.9 raeburn 1683: $recommended,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,$downloadstatus,
1684: $filetouse,$production,$testing,$apachefw,$uses_systemctl) = &check_required($instdir,$dsn);
1.1 raeburn 1685: if ($distro eq '') {
1686: print "\n".&mt('Linux distribution could not be verified as a supported distribution.')."\n".
1687: &mt('The following are supported: [_1].',
1688: 'CentOS, RedHat Enterprise, Fedora, Scientific Linux, '.
1.45.2.3 raeburn 1689: 'Oracle Linux, openSuSE, SLES, Ubuntu LTS, Debian')."\n\n".
1.1 raeburn 1690: &mt('Stopping execution.')."\n";
1691: exit;
1692: }
1.34 raeburn 1693: if ($mysqlrestart) {
1694: print "\n".&mt('The mysql daemon needs to be restarted using the following command:')."\n".
1695: $mysqlrestart."\n\n".
1696: &mt('Stopping execution of install.pl script.')."\n".
1697: &mt('Please run the install.pl script again, once you have restarted mysql.')."\n";
1698: exit;
1699: }
1.6 raeburn 1700: if ($localecmd ne '') {
1.45.2.22 raeburn 1701: print "\n".&mt('Although the LON-CAPA application itself is localized for a number of different languages,[_1]the default locale language for the Linux OS on which it runs should be US English.',"\n")."\n\n";
1702: if ($langcmd ne '') {
1703: print &mt('Use the following command(s) or action(s) to install a required language package.')."\n\n".
1704: "$langcmd\n";
1705: }
1706: print &mt('Run the following command from the command line to set the default language for your OS,[_1]and then run this LON-CAPA installation set-up script again.',"\n")."\n\n".
1.6 raeburn 1707: $localecmd."\n\n".
1708: &mt('Stopping execution.')."\n";
1709: exit;
1710: }
1.1 raeburn 1711: if (!$gotprereqs) {
1.12 raeburn 1712: print "\n".&mt('The LONCAPA-prerequisites package is not installed.')."\n".
1.1 raeburn 1713: &mt('The following command can be used to install the package (and dependencies):')."\n\n".
1714: $updatecmd."\n\n";
1715: if ($installnow eq '') {
1716: print &mt('Stopping execution.')."\n";
1717: exit;
1718: } else {
1719: print &mt('Run command? ~[Y/n~]');
1720: my $install_prereq = &get_user_selection(1);
1721: if ($install_prereq) {
1722: if (open(PIPE,'|-',$installnow)) {
1723: close(PIPE);
1724: $gotprereqs = &check_prerequisites($packagecmd,$distro);
1725: if (!$gotprereqs) {
1.12 raeburn 1726: print &mt('The LONCAPA-prerequisites package is not installed.')."\n".
1.1 raeburn 1727: &mt('Stopping execution.')."\n";
1728: exit;
1729: } else {
1.45.2.22 raeburn 1730: ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,
1.45.2.9 raeburn 1731: $mysqlrestart,$recommended,$dbh,$has_pass,$mysql_unix_socket,
1732: $has_lcdb,$downloadstatus,$filetouse,$production,$testing,$apachefw,
1733: $uses_systemctl) = &check_required($instdir,$dsn);
1.1 raeburn 1734: }
1735: } else {
1.12 raeburn 1736: print &mt('Failed to run command to install LONCAPA-prerequisites')."\n";
1.1 raeburn 1737: exit;
1738: }
1739: } else {
1740: print &mt('Stopping execution.')."\n";
1741: exit;
1742: }
1743: }
1744: }
1745: unless (ref($recommended) eq 'HASH') {
1746: print "\n".&mt('An error occurred determining which actions are recommended.')."\n\n".
1747: &mt('Stopping execution.')."\n";
1748: exit;
1749: }
1750:
1751: print "\n";
1752: my $num = 0;
1753: foreach my $action (@actions) {
1754: $num ++;
1755: my ($yesno,$defaultrun);
1756: if (ref($recommended) eq 'HASH') {
1.4 raeburn 1757: if (($action eq 'runlevels') || ($action eq 'stopsrvcs')) {
1.1 raeburn 1758: $yesno = '[y/N]';
1759: if (ref($recommended->{$action}) eq 'HASH') {
1760: if (keys(%{$recommended->{$action}}) > 0) {
1761: $yesno = &mt('~[Y/n~]');
1762: $defaultrun = 1;
1763: }
1764: }
1765: } else {
1766: if ($action eq 'download') {
1767: if ($downloadstatus) {
1768: print "\n$downloadstatus\n";
1769: }
1770: }
1771: if ($recommended->{$action}) {
1772: $yesno = mt('~[Y/n~]');
1773: $defaultrun = 1;
1774: } else {
1775: $yesno = &mt('~[y/N~]');
1776: }
1777: }
1778: print $num.'. '.$prompts{$action}." $yesno ";
1779: $callsub{$action} = &get_user_selection($defaultrun);
1780: }
1781: }
1782:
1783: my $lctarball = 'loncapa-current.tar.gz';
1784: my $sourcetarball = $lctarball;
1785: if ($callsub{'download'}) {
1786: my ($production,$testing,$sizes) = &download_versionslist();
1.45.2.16 raeburn 1787: my $homedir = '/root';
1788: if ($distro =~ /^ubuntu/) {
1789: if ($instdir ne $homedir) {
1790: ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});
1791: }
1792: }
1.1 raeburn 1793: if ($production && $testing) {
1794: if ($production ne $testing) {
1795: print &mt('Two recent LON-CAPA releases are available: ')."\n".
1.3 raeburn 1796: &mt('1.').' '.&mt('A production release - version: [_1].',$production)."\n".
1797: &mt('2.').' '.&mt('A testing release - version: [_1].',$testing)."\n\n".
1.45.2.16 raeburn 1798: &mt("After download, the tar.gz file will be extracted into $homedir")."\n\n".
1799: &mt("Download the production release into $instdir? ~[Y/n~]");
1.1 raeburn 1800: if (&get_user_selection(1)) {
1.4 raeburn 1801: $sourcetarball = 'loncapa-'.$production.'.tar.gz';
1.45.2.16 raeburn 1802: print "$sourcetarball will be downloaded into $instdir\n";
1.1 raeburn 1803: } else {
1804: print "\n".&mt('Download the testing release? ~[Y/n~]');
1805: if (&get_user_selection(1)) {
1.4 raeburn 1806: $sourcetarball = 'loncapa-'.$testing.'.tar.gz';
1.45.2.16 raeburn 1807: print "$sourcetarball will be downloaded into $instdir\n";
1808: } else {
1809: $callsub{'download'} = 0;
1.1 raeburn 1810: }
1811: }
1812: }
1813: } elsif ($production) {
1814: print &mt('The most recent LON-CAPA release is version: [_1].',$production)."\n".
1.45.2.16 raeburn 1815: &mt("After download, the tar.gz file will be extracted into $homedir")."\n\n".
1816: &mt("Download the production release into $instdir? ~[Y/n~]");
1.1 raeburn 1817: if (&get_user_selection(1)) {
1.20 raeburn 1818: $sourcetarball = 'loncapa-'.$production.'.tar.gz';
1.45.2.16 raeburn 1819: print "$sourcetarball will be downloaded into $instdir\n";
1820: } else {
1821: $callsub{'download'} = 0;
1.1 raeburn 1822: }
1823: }
1824: } elsif ($filetouse ne '') {
1825: $sourcetarball = $filetouse;
1826: }
1827:
1828: print_and_log("\n");
1829:
1830: # Each action: report if skipping, or perform action and provide feedback.
1831: if ($callsub{'wwwuser'}) {
1832: &setup_www();
1833: } else {
1834: &print_and_log(&mt('Skipping creation of user [_1].',"'www'")."\n");
1835: }
1836:
1837: if ($callsub{'pwauth'}) {
1.4 raeburn 1838: &build_and_install_mod_auth_external($instdir);
1.1 raeburn 1839: } else {
1840: &print_and_log(&mt('Skipping [_1] installation.',"'pwauth'")."\n");
1841: }
1842:
1843: if ($callsub{'mysql'}) {
1844: if ($dbh) {
1.45.2.9 raeburn 1845: &setup_mysql($callsub{'mysqlperms'},$dbh,$has_pass,
1.45.2.15 raeburn 1846: $mysql_unix_socket,$has_lcdb,$distro);
1.1 raeburn 1847: } else {
1848: print &mt('Unable to configure MySQL because access is denied.')."\n";
1849: }
1850: } else {
1851: &print_and_log(&mt('Skipping configuration of MySQL.')."\n");
1852: if ($callsub{'mysqlperms'}) {
1853: if ($dbh) {
1.45.2.9 raeburn 1854: &setup_mysql_permissions($dbh,$has_pass,$mysql_unix_socket);
1.1 raeburn 1855: } else {
1856: print &mt('Unable to configure MySQL because access is denied.')."\n";
1857: }
1858: } else {
1859: &print_and_log(&mt('Skipping MySQL permissions setup.')."\n");
1860: }
1861: }
1862:
1863: if ($dbh) {
1864: if (!$dbh->disconnect) {
1865: &print_and_log(&mt('Failed to disconnect from MySQL:')."\n".
1866: $dbh->errstr);
1867: }
1868: }
1869:
1870: if ($callsub{'apache'}) {
1871: if ($distro =~ /^(suse|sles)/) {
1.45.2.1 raeburn 1872: ©_apache2_suseconf($instdir,$distro);
1.1 raeburn 1873: } elsif ($distro =~ /^(debian|ubuntu)/) {
1.28 raeburn 1874: ©_apache2_debconf($instdir,$distro);
1.1 raeburn 1875: } else {
1.14 raeburn 1876: ©_httpd_conf($instdir,$distro);
1.45.2.5 raeburn 1877: ©_mpm_conf($instdir,$distro);
1.1 raeburn 1878: }
1879: } else {
1880: print_and_log(&mt('Skipping configuration of Apache web server.')."\n");
1881: }
1882:
1.45.2.20 raeburn 1883: if ($callsub{'systemd'}) {
1884: &check_systemd_update($distro);
1885: } else {
1886: print_and_log('Skipping systemd configuration update for web server');
1887: }
1888:
1.1 raeburn 1889: if ($callsub{'runlevels'}) {
1890: my $count = 0;
1891: if (ref($recommended) eq 'HASH') {
1892: if (ref($recommended->{'runlevels'}) eq 'HASH') {
1893: foreach my $type (keys(%{$recommended->{'runlevels'}})) {
1894: next if ($type eq 'insserv');
1895: $count ++;
1896: my $command = $recommended->{'runlevels'}{$type};
1897: if ($command ne '') {
1898: print_and_log(&mt('Runlevel update command run: [_1].',$command)."\n");
1899: system($command);
1900: }
1901: }
1902: if (!$count) {
1903: print_and_log(&mt('No runlevel updates required.')."\n");
1904: }
1905: }
1906: }
1.45.2.1 raeburn 1907: if ($distro =~ /^(suse|sles)(\d+)/) {
1908: unless(($1 eq 'sles') && ($2 >= 15)) {
1909: &update_SuSEfirewall2_setup($instdir);
1910: }
1.11 raeburn 1911: }
1.1 raeburn 1912: } else {
1913: &print_and_log(&mt('Skipping setting override for start-up order of services.')."\n");
1914: }
1915:
1916: if ($callsub{'firewall'}) {
1.45.2.3 raeburn 1917: my ($firewalld,$zone) = &uses_firewalld($distro);
1918: if ($firewalld) {
1.45.2.1 raeburn 1919: my (%current,%added);
1.45.2.3 raeburn 1920: if (open(PIPE,"firewall-cmd --permanent --zone=$zone --list-services |")) {
1.45.2.1 raeburn 1921: my $svc = <PIPE>;
1922: close(PIPE);
1923: chomp($svc);
1924: map { $current{$_} = 1; } (split(/\s+/,$svc));
1925: }
1926: foreach my $service ('http','https') {
1927: unless ($current{$service}) {
1.45.2.3 raeburn 1928: if (open(PIPE,"firewall-cmd --permanent --zone=$zone --add-service=$service |")) {
1.45.2.1 raeburn 1929: my $result = <PIPE>;
1930: if ($result =~ /^success/) {
1931: $added{$service} = 1;
1932: }
1933: }
1934: }
1935: }
1936: if (keys(%added) > 0) {
1937: print &mt('Firewall configured to allow access for: [_1].',
1938: join(', ',sort(keys(%added))))."\n";
1.45.2.13 raeburn 1939: system('firewall-cmd --reload');
1.45.2.1 raeburn 1940: }
1941: if ($current{'http'} || $current{'https'}) {
1942: print &mt('Firewall already configured to allow access for:[_1].',
1943: (($current{'http'})? ' http':'').(($current{'https'})? ' https':''))."\n";
1944: }
1945: unless ($current{'ssh'}) {
1.45.2.13 raeburn 1946: print &mt('If you would like to allow access to ssh from outside, use the commands:')."\n".
1947: "firewall-cmd --permanent --zone=$zone --add-service=ssh\n".
1948: "firewall-cmd --reload\n";
1.45.2.1 raeburn 1949: }
1950: } elsif ($distro =~ /^(suse|sles)/) {
1.5 raeburn 1951: print &mt('Use [_1] to configure the firewall to allow access for [_2].',
1952: 'yast -- Security and Users -> Firewall -> Interfaces',
1.45.2.1 raeburn 1953: 'ssh, http, https')."\n";
1.5 raeburn 1954: } elsif ($distro =~ /^(debian|ubuntu)(\d+)/) {
1955: if (($1 eq 'ubuntu') || ($2 > 5)) {
1956: print &mt('Use [_1] to configure the firewall to allow access for [_2].',
1957: 'ufw','ssh, http, https')."\n";
1958: } else {
1959: my $fwadded = &get_iptables_rules($distro,$instdir,$apachefw);
1960: if ($fwadded) {
1961: print &mt('Enable firewall? ~[Y/n~]');
1962: my $enable_iptables = &get_user_selection(1);
1963: if ($enable_iptables) {
1964: system('/etc/network/if-pre-up.d/iptables');
1965: print &mt('Firewall enabled using rules defined in [_1].',
1966: '/etc/iptables.loncapa.rules');
1967: }
1968: }
1969: }
1.45.2.3 raeburn 1970: } elsif ($distro =~ /^(scientific|oracle)/) {
1.11 raeburn 1971: print &mt('Use [_1] to configure the firewall to allow access for [_2].',
1972: 'system-config-firewall-tui -- Customize',
1973: 'ssh, http')."\n";
1.1 raeburn 1974: } else {
1.45.2.3 raeburn 1975: my $version;
1.45.2.18 raeburn 1976: if ($distro =~ /^(redhat|centos|rocky|alma)(\d+)/) {
1.45.2.3 raeburn 1977: $version = $1;
1978: }
1979: if ($version > 5) {
1980: print &mt('Use [_1] to configure the firewall to allow access for [_2].',
1981: 'system-config-firewall-tui -- Customize',
1982: 'ssh, http')."\n";
1983: } else {
1984: print &mt('Use [_1] to configure the firewall to allow access for [_2].',
1985: 'setup -- Firewall configuration -> Customize',
1986: 'ssh, http, https')."\n";
1987: }
1.1 raeburn 1988: }
1989: } else {
1.5 raeburn 1990: &print_and_log(&mt('Skipping Firewall configuration.')."\n");
1.1 raeburn 1991: }
1992:
1993: if ($callsub{'stopsrvcs'}) {
1.45 raeburn 1994: &kill_extra_services($distro,$recommended->{'stopsrvcs'},$uses_systemctl);
1.1 raeburn 1995: } else {
1.10 raeburn 1996: &print_and_log(&mt('Skipping stopping unnecessary service ([_1] daemons).',"'cups','memcached'")."\n");
1.1 raeburn 1997: }
1998:
1999: my ($have_tarball,$updateshown);
2000: if ($callsub{'download'}) {
2001: ($have_tarball,$updateshown) = &download_loncapa($instdir,$sourcetarball);
2002: } else {
2003: print_and_log(&mt('Skipping download of LON-CAPA tar file.')."\n\n");
2004: print &mt('LON-CAPA is available for download from: [_1]',
2005: 'http://install.loncapa.org/')."\n";
2006: if (!-e '/etc/loncapa-release') {
1.45.2.19 raeburn 2007: &print_and_log(&mt('LON-CAPA is not yet installed on your system.')."\n\n");
2008: unless ($filetouse) {
2009: &print_and_log(&mt('You may retrieve the source for LON-CAPA by executing:')."\n".
2010: "wget http://install.loncapa.org/versions/$lctarball\n");
2011: }
1.1 raeburn 2012: } else {
2013: my $currentversion;
2014: if (open(my $fh,"</etc/loncapa-release")) {
2015: my $version = <$fh>;
2016: chomp($version);
2017: if ($version =~ /^\QLON-CAPA release \E([\w\-.]+)$/) {
2018: $currentversion = $1;
2019: }
2020: }
2021: if ($currentversion ne '') {
2022: print &mt('Version of LON-CAPA currently installed on this server is: [_1].',
2023: $currentversion),"\n";
2024: if ($production) {
2025: print &mt('The latest production release of LON-CAPA is [_1].',$production)."\n";
2026: }
2027: if ($testing) {
2028: print &mt('The latest testing release of LON-CAPA is [_1].',$testing)."\n";
2029: }
2030: }
2031: }
2032: if ($filetouse ne '') {
2033: $have_tarball = 1;
2034: }
2035: }
2036:
2037: print "\n".&mt('Requested configuration complete.')."\n\n";
2038: if ($have_tarball && !$updateshown) {
2039: my ($lcdir) = ($sourcetarball =~ /^([\w.\-]+)\.tar.gz$/);
1.45.2.16 raeburn 2040: if ($lcdir eq 'loncapa-current') {
2041: $lcdir = "loncapa-X.Y.Z (X.Y.Z should correspond to a version number like '2.11.3')";
2042: }
1.45.2.14 raeburn 2043: my ($apachename,$lc_uses_systemctl,$uses_sudo);
1.45.2.12 raeburn 2044: if ($distro =~ /^(suse|sles|debian|ubuntu)([\d.]+)/) {
2045: if (($1 eq 'suse') && ($2 < 10)) {
2046: $apachename = 'apache';
2047: } else {
2048: $apachename = 'apache2';
2049: }
2050: } else {
2051: $apachename = 'httpd';
2052: }
2053: if ($distro =~ /^oracle(\d+)$/) {
2054: if ($1 > 6) {
2055: $lc_uses_systemctl = 1;
2056: }
1.45.2.18 raeburn 2057: } elsif ($distro =~ /^(?:rhes|centos|rocky|alma)(\d+)/) {
1.45.2.12 raeburn 2058: if ($1 > 7) {
2059: $lc_uses_systemctl = 1;
2060: }
2061: } elsif ($distro =~ /^ubuntu(\d+)$/) {
2062: if ($1 > 16) {
2063: $lc_uses_systemctl = 1;
2064: }
2065: $uses_sudo = 1;
1.45.2.19 raeburn 2066: } elsif ($distro =~ /^debian(\d+)$/) {
2067: if ($1 >= 10) {
2068: $lc_uses_systemctl = 1;
2069: }
1.45.2.12 raeburn 2070: } elsif ($distro =~ /^sles(\d+)$/) {
2071: if ($1 > 12) {
2072: $lc_uses_systemctl = 1;
2073: }
1.45.2.20 raeburn 2074: } elsif ($distro =~ /^fedora(\d+)$/) {
2075: if ($1 > 25) {
2076: $lc_uses_systemctl = 1;
2077: }
1.45.2.12 raeburn 2078: }
1.1 raeburn 2079: if (!-e '/etc/loncapa-release') {
2080: print &mt('If you are now ready to install LON-CAPA, enter the following commands:')."\n\n";
2081: } else {
1.45.2.12 raeburn 2082: my $lcstop = '/etc/init.d/loncontrol stop';
2083: if ($lc_uses_systemctl) {
2084: $lcstop = 'systemctl stop loncontrol';
2085: }
2086: my $apachestop = "/etc/init.d/$apachename stop";
2087: if ($uses_systemctl) {
2088: $apachestop = "systemctl stop $apachename";
2089: }
2090: if ($uses_sudo) {
1.45.2.16 raeburn 2091: $lcstop = 'sudo '.$lcstop;
1.45.2.12 raeburn 2092: $apachestop = 'sudo '.$apachestop;
1.1 raeburn 2093: }
1.45.2.12 raeburn 2094: print &mt('If you are now ready to update LON-CAPA, enter the following commands:').
2095: "\n\n$lcstop\n$apachestop\n";
1.1 raeburn 2096: }
1.45.2.16 raeburn 2097: my ($extract,$update);
2098: my $homedir = '/root';
2099: if ($uses_sudo) {
2100: $extract = 'sudo ';
2101: $update = 'sudo ';
2102: if ($instdir ne $homedir) {
2103: ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});
2104: }
2105: }
2106: $extract .= "tar zxf $sourcetarball --directory $homedir";
2107: $update .= './UPDATE';
2108: print "$extract\n".
2109: "cd $homedir/$lcdir\n".
2110: "$update\n";
1.1 raeburn 2111: if (-e '/etc/loncapa-release') {
1.45.2.19 raeburn 2112: my $lcstart = '/etc/init.d/loncontrol start';
1.45.2.12 raeburn 2113: if ($lc_uses_systemctl) {
2114: $lcstart = '/home/httpd/perl/loncontrol start';
2115: }
2116: my $apachestart = "/etc/init.d/$apachename start";
2117: if ($uses_systemctl) {
2118: $apachestart = "systemctl start $apachename";
2119: }
2120: if ($uses_sudo) {
2121: $lcstart = 'sudo '.$lcstart;
2122: $apachestart = 'sudo '.$apachestart;
2123: }
2124: print "$lcstart\n";
2125: print "$apachestart\n";
1.1 raeburn 2126: }
2127: }
2128: exit;
2129:
2130: #
2131: # End main script
2132: #
2133:
2134: #
2135: # Routines for the actions
2136: #
2137:
2138: sub setup_www {
2139: ##
2140: ## Set up www
2141: ##
2142: print_and_log(&mt('Creating user [_1]',"'www'")."\n");
2143: # -- Add group
2144:
2145: my $status = `/usr/sbin/groupadd www`;
2146: if ($status =~ /\QGroup `www' already exists.\E/) {
2147: print &mt('Group [_1] already exists.',"'www'")."\n";
2148: } elsif ($status ne '') {
2149: print &mt('Unable to add group [_1].',"'www'")."\n";
2150: }
2151:
2152: my $gid = getgrnam('www');
2153:
2154: if (open (PIPE, "/usr/sbin/useradd -c LONCAPA -g $gid www 2>&1 |")) {
2155: $status = <PIPE>;
2156: close(PIPE);
2157: chomp($status);
2158: if ($status =~ /\QAccount `www' already exists.\E/) {
2159: print &mt('Account [_1] already exists.',"'www'")."\n";
2160: } elsif ($status ne '') {
2161: print &mt('Unable to add user [_1].',"'www'")."\n";
2162: }
2163: } else {
2164: print &mt('Unable to run command to add user [_1].',"'www'")."\n";
2165: }
2166:
2167: my $uid = &uid_of_www();
2168: if (($gid ne '') && ($uid ne '')) {
2169: if (!-e '/home/www') {
2170: mkdir('/home/www',0755);
2171: system('chown www:www /home/www');
2172: }
2173: }
2174: writelog ($status);
2175: }
2176:
2177: sub uid_of_www {
2178: my ($num) = (getpwnam('www'))[2];
2179: return $num;
2180: }
2181:
2182: sub build_and_install_mod_auth_external {
2183: my ($instdir) = @_;
2184: my $num = &uid_of_www();
2185: # Patch pwauth
2186: print_and_log(&mt('Building authentication system for LON-CAPA users.')."\n");
2187: my $patch = <<"ENDPATCH";
2188: 148c148
2189: < #define SERVER_UIDS 99 /* user "nobody" */
2190: ---
2191: > #define SERVER_UIDS $num /* user "www" */
2192: ENDPATCH
2193:
1.45.2.19 raeburn 2194: my $patch_code = <<"ENDPATCH";
2195: 127a128
2196: > #include <string.h>
2197: 214a216
2198: > #include <time.h>
2199: 566c568
2200: < check_fails()
2201: ---
2202: > int check_fails()
2203: 589c591
2204: < log_failure()
2205: ---
2206: > void log_failure()
2207: 629c631
2208: < snooze(int seconds)
2209: ---
2210: > void snooze(int seconds)
2211: 653c655
2212: < main(int argc, char **argv)
2213: ---
2214: > int main(int argc, char **argv)
2215: ENDPATCH
2216:
1.1 raeburn 2217: if (! -e "/usr/bin/patch") {
2218: print_and_log(&mt('You must install the software development tools package: [_1], when installing Linux.',"'patch'")."\n");
2219: print_and_log(&mt('Authentication installation not completed.')."\n");
2220: return;
2221: }
2222: if (&skip_if_nonempty(`cd /tmp; tar zxf $instdir/pwauth-2.2.8.tar.gz`,
2223: &mt('Unable to extract pwauth')."\n")) {
2224: return;
2225: }
2226: my $dir = "/tmp/pwauth-2.2.8";
1.45.2.19 raeburn 2227: my $patchedok;
1.1 raeburn 2228: if (open(PATCH,"| patch $dir/config.h")) {
2229: print PATCH $patch;
2230: close(PATCH);
1.45.2.19 raeburn 2231: if (open(PATCH,"| patch $dir/pwauth.c")) {
2232: print PATCH $patch_code;
2233: close(PATCH);
2234: $patchedok = 1;
2235: }
2236: }
2237: if ($patchedok) {
1.1 raeburn 2238: print_and_log("\n");
2239: ##
2240: ## Compile patched pwauth
2241: ##
2242: print_and_log(&mt('Compiling pwauth')."\n");
1.12 raeburn 2243: my $result = `cd $dir/; make 2>/dev/null `;
1.1 raeburn 2244: my $expected = <<"END";
2245: gcc -g -c -o pwauth.o pwauth.c
2246: gcc -o pwauth -g pwauth.o -lcrypt
2247: END
2248: if ($result eq $expected) {
2249: print_and_log(&mt('Apparent success compiling pwauth:').
2250: "\n".$result );
2251: # Install patched pwauth
2252: print_and_log(&mt('Copying pwauth to [_1]',' /usr/local/sbin')."\n");
2253: if (copy "$dir/pwauth","/usr/local/sbin/pwauth") {
1.5 raeburn 2254: if (chmod(06755, "/usr/local/sbin/pwauth")) {
1.1 raeburn 2255: print_and_log(&mt('[_1] copied successfully',"'pwauth'").
2256: "\n");
2257: } else {
2258: print &mt('Unable to set permissions on [_1].'.
2259: "/usr/local/sbin/pwauth")."\n";
2260: }
2261: } else {
2262: print &mt('Unable to copy [_1] to [_2]',
2263: "'$dir/pwauth'","/usr/local/sbin/pwauth")."\n$!\n";
2264: }
2265: } else {
2266: print &mt('Unable to compile patched [_1].'."'pwauth'")."\n";
2267: }
2268: } else {
2269: print &mt('Unable to start patch for [_1]',"'pwauth'")."\n";
2270: }
2271: print_and_log("\n");
2272: }
2273:
2274: sub kill_extra_services {
1.45 raeburn 2275: my ($distro,$stopsrvcs,$uses_systemctl) = @_;
1.1 raeburn 2276: if (ref($stopsrvcs) eq 'HASH') {
2277: my @stopping = sort(keys(%{$stopsrvcs}));
2278: if (@stopping) {
1.6 raeburn 2279: my $kill_list = join("', '",@stopping);
1.1 raeburn 2280: if ($kill_list) {
2281: $kill_list = "'".$kill_list."'";
1.6 raeburn 2282: &print_and_log("\n".&mt('Killing unnecessary services ([_1] daemon(s)).',$kill_list)."\n");
2283: foreach my $service (@stopping) {
2284: my $daemon = $service;
2285: if ($service eq 'cups') {
2286: $daemon = 'cupsd';
2287: if ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
2288: my $version = $1;
2289: if (($distro =~ /^ubuntu/) && ($version <= 8)) {
2290: $daemon = 'cupsys';
2291: }
1.12 raeburn 2292: } else {
1.8 raeburn 2293: $daemon = 'cups';
1.6 raeburn 2294: }
2295: }
1.12 raeburn 2296: my $cmd = "ps -ef |grep '$daemon' |grep -v grep";
2297: if (open(PIPE,'-|',$cmd)) {
2298: my $daemonrunning = <PIPE>;
2299: chomp($daemonrunning);
2300: close(PIPE);
2301: if ($daemonrunning) {
2302: &print_and_log(`/etc/init.d/$daemon stop`);
2303: }
2304: }
1.1 raeburn 2305: &print_and_log(&mt('Removing [_1] from startup.',$service)."\n");
1.45 raeburn 2306: if ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
2307: my $version = $1;
1.45.2.19 raeburn 2308: if ((($distro =~ /^ubuntu/) && ($version > 16)) ||
2309: (($distro =~ /^debian/) && ($version >= 10))) {
1.45 raeburn 2310: if (ref($uses_systemctl) eq 'HASH') {
2311: if ($uses_systemctl->{$service}) {
2312: if (`systemctl is-enabled $service`) {
2313: &print_and_log(`systemctl disable $service`);
2314: }
2315: }
2316: }
2317: } else {
2318: &print_and_log(`update-rc.d -f $daemon remove`);
2319: }
1.1 raeburn 2320: } else {
1.35 raeburn 2321: if (ref($uses_systemctl) eq 'HASH') {
2322: if ($uses_systemctl->{$service}) {
2323: if (`systemctl is-enabled $service`) {
2324: &print_and_log(`systemctl disable $service`);
2325: }
2326: } else {
2327: &print_and_log(`/sbin/chkconfig --del $service`);
2328: }
2329: } else {
2330: &print_and_log(`/sbin/chkconfig --del $service`);
2331: }
1.1 raeburn 2332: }
2333: }
2334: }
2335: }
2336: }
2337: return;
2338: }
2339:
2340: sub setup_mysql {
1.45.2.15 raeburn 2341: my ($setup_mysql_permissions,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,$distro) = @_;
1.4 raeburn 2342: my @mysql_lc_commands;
1.1 raeburn 2343: unless ($has_lcdb) {
1.45.2.15 raeburn 2344: my $createcmd = 'CREATE DATABASE loncapa';
2345: if ($distro =~ /^sles(\d+)/) {
2346: if ($1 > 11) {
2347: $createcmd .= ' CHARACTER SET utf8 COLLATE utf8_general_ci';
2348: }
2349: } elsif ($distro =~ /^ubuntu(\d+)/) {
2350: if ($1 > 16) {
2351: $createcmd .= ' CHARACTER SET latin1 COLLATE latin1_swedish_ci';
2352: }
2353: }
2354: push(@mysql_lc_commands,$createcmd);
1.1 raeburn 2355: }
1.4 raeburn 2356: push(@mysql_lc_commands,"USE loncapa");
2357: push(@mysql_lc_commands,qq{
1.18 raeburn 2358: CREATE TABLE IF NOT EXISTS metadata (title TEXT, author TEXT, subject TEXT, url TEXT, keywords TEXT, version TEXT, notes TEXT, abstract TEXT, mime TEXT, language TEXT, creationdate DATETIME, lastrevisiondate DATETIME, owner TEXT, copyright TEXT, domain TEXT, dependencies TEXT, modifyinguser TEXT, authorspace TEXT, lowestgradelevel TEXT, highestgradelevel TEXT, standards TEXT, count INT, course INT, course_list TEXT, goto INT, goto_list TEXT, comefrom INT, comefrom_list TEXT, sequsage INT, sequsage_list TEXT, stdno INT, stdno_list TEXT, avetries FLOAT, avetries_list TEXT, difficulty FLOAT, difficulty_list TEXT, disc FLOAT, disc_list TEXT, clear FLOAT, technical FLOAT, correct FLOAT, helpful FLOAT, depth FLOAT, hostname TEXT, FULLTEXT idx_title (title), FULLTEXT idx_author (author), FULLTEXT idx_subject (subject), FULLTEXT idx_url (url), FULLTEXT idx_keywords (keywords), FULLTEXT idx_version (version), FULLTEXT idx_notes (notes), FULLTEXT idx_abstract (abstract), FULLTEXT idx_mime (mime), FULLTEXT idx_language (language), FULLTEXT idx_owner (owner), FULLTEXT idx_copyright (copyright)) ENGINE=MYISAM
1.4 raeburn 2359: });
1.1 raeburn 2360: if ($setup_mysql_permissions) {
1.45.2.9 raeburn 2361: &setup_mysql_permissions($dbh,$has_pass,$mysql_unix_socket,@mysql_lc_commands);
1.1 raeburn 2362: } else {
2363: print_and_log(&mt('Skipping MySQL permissions setup.')."\n");
2364: if ($dbh) {
1.4 raeburn 2365: if (@mysql_lc_commands) {
2366: foreach my $lccmd (@mysql_lc_commands) {
2367: $dbh->do($lccmd) || print $dbh->errstr."\n";
2368: }
2369: }
1.1 raeburn 2370: print_and_log(&mt('MySQL database set up complete.')."\n");
2371: } else {
2372: print_and_log(&mt('Problem accessing MySQL.')."\n");
2373: }
2374: }
2375: }
2376:
2377: sub setup_mysql_permissions {
1.45.2.9 raeburn 2378: my ($dbh,$has_pass,$mysql_unix_socket,@mysql_lc_commands) = @_;
1.45.2.19 raeburn 2379: my ($mysqlversion,$mysqlminorversion,$mysqlsubver,$mysqlname) = &get_mysql_version();
1.45.2.9 raeburn 2380: my ($usescreate,$usesauth,$is_mariadb,$hasauthcol,@mysql_commands);
1.38 raeburn 2381: if ($mysqlname =~ /^MariaDB/i) {
1.45.2.2 raeburn 2382: $is_mariadb = 1;
1.45.2.19 raeburn 2383: if ((($mysqlversion == 10) && ($mysqlminorversion >= 4)) || ($mysqlversion >= 11)) {
1.45.2.9 raeburn 2384: $usescreate = 1;
1.45.2.19 raeburn 2385: } elsif (($mysqlversion == 10) && ($mysqlminorversion >= 2)) {
1.38 raeburn 2386: $usesauth = 1;
1.45.2.19 raeburn 2387: } elsif (($mysqlversion == 5) && ($mysqlminorversion >= 5)) {
1.42 raeburn 2388: $hasauthcol = 1;
1.38 raeburn 2389: }
2390: } else {
1.45.2.19 raeburn 2391: if (($mysqlversion > 5) || (($mysqlminorversion == 5) && ($mysqlminorversion > 7)) ||
2392: (($mysqlversion == 5) && ($mysqlminorversion == 7) && ($mysqlsubver > 5))) {
1.38 raeburn 2393: $usesauth = 1;
1.45.2.19 raeburn 2394: } elsif (($mysqlversion == 5) &&
2395: (($mysqlminorversion >= 6) || (($mysqlminorversion == 5) && ($mysqlsubver >= 7)))) {
1.42 raeburn 2396: $hasauthcol = 1;
1.38 raeburn 2397: }
2398: }
1.45.2.9 raeburn 2399: if ($usescreate) {
2400: @mysql_commands = ("CREATE USER 'www'\@'localhost' IDENTIFIED BY 'localhostkey'");
2401: } elsif ($usesauth) {
1.45.2.15 raeburn 2402: @mysql_commands = ("INSERT user (Host, User, ssl_cipher, x509_issuer, x509_subject, authentication_string) VALUES('localhost','www','','','','')",
2403: "FLUSH PRIVILEGES");
1.45.2.2 raeburn 2404: if ($is_mariadb) {
2405: push(@mysql_commands,"ALTER USER 'www'\@'localhost' IDENTIFIED BY 'localhostkey'");
2406: } else {
2407: push(@mysql_commands,"ALTER USER 'www'\@'localhost' IDENTIFIED WITH mysql_native_password BY 'localhostkey'");
2408: }
1.42 raeburn 2409: } elsif ($hasauthcol) {
2410: @mysql_commands = ("INSERT user (Host, User, Password, ssl_cipher, x509_issuer, x509_subject, authentication_string) VALUES('localhost','www',password('localhostkey'),'','','','');");
1.36 raeburn 2411: } else {
1.42 raeburn 2412: @mysql_commands = ("INSERT user (Host, User, Password, ssl_cipher, x509_issuer, x509_subject) VALUES('localhost','www',password('localhostkey'),'','','');");
1.36 raeburn 2413: }
1.1 raeburn 2414: if ($mysqlversion < 4) {
1.4 raeburn 2415: push (@mysql_commands,"
2416: INSERT db (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Grant_priv,References_priv,Index_priv,Alter_priv) VALUES('localhost','loncapa','www','Y','Y','Y','Y','Y','Y','N','Y','Y','Y')");
2417: } else {
2418: push (@mysql_commands,"
2419: INSERT db (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Grant_priv,References_priv,Index_priv,Alter_priv,Create_tmp_table_priv,Lock_tables_priv) VALUES('localhost','loncapa','www','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y')");
1.1 raeburn 2420: }
1.4 raeburn 2421: push(@mysql_commands,"DELETE FROM user WHERE host<>'localhost'");
1.45.2.9 raeburn 2422: if (($has_pass) || ($mysql_unix_socket)) {
1.1 raeburn 2423: if ($dbh) {
1.4 raeburn 2424: push(@mysql_commands,"FLUSH PRIVILEGES");
2425: if (@mysql_commands) {
2426: foreach my $cmd (@mysql_commands) {
2427: $dbh->do($cmd) || print $dbh->errstr."\n";
2428: }
2429: }
2430: if (@mysql_lc_commands) {
2431: foreach my $lccmd (@mysql_lc_commands) {
2432: $dbh->do($lccmd) || print $dbh->errstr."\n";
2433: }
2434: }
1.1 raeburn 2435: print_and_log(&mt('Permissions set for LON-CAPA MySQL user: [_1]',"'www'")."\n");
2436: } else {
2437: print_and_log(&mt('Problem accessing MySQL.')."\n".
2438: &mt('Permissions not set.')."\n");
2439: }
2440: } else {
2441: my ($firstpass,$secondpass,$got_passwd,$newmysqlpass);
2442: print &mt('Please enter a root password for the mysql database.')."\n".
2443: &mt('It does not have to match your root account password, but you will need to remember it.')."\n";
2444: my $maxtries = 10;
2445: my $trial = 0;
2446: while ((!$got_passwd) && ($trial < $maxtries)) {
2447: $firstpass = &get_mysql_password(&mt('Enter password'));
2448: if (length($firstpass) > 5) {
2449: $secondpass = &get_mysql_password(&mt('Enter password a second time'));
2450: if ($firstpass eq $secondpass) {
2451: $got_passwd = 1;
2452: $newmysqlpass = $firstpass;
2453: } else {
2454: print(&mt('Passwords did not match. Please try again.')."\n");
2455: }
2456: $trial ++;
2457: } else {
2458: print(&mt('Password too short.')."\n".
2459: &mt('Please choose a password with at least six characters.')."\n");
2460: }
2461: }
2462: if ($got_passwd) {
1.45.2.2 raeburn 2463: my (@newpass_cmds) = &new_mysql_rootpasswd($newmysqlpass,$usesauth,$is_mariadb);
1.4 raeburn 2464: push(@mysql_commands,@newpass_cmds);
1.1 raeburn 2465: } else {
2466: print_and_log(&mt('Failed to get MySQL root password from user input.')."\n");
2467: }
2468: if ($dbh) {
1.4 raeburn 2469: if (@mysql_commands) {
2470: foreach my $cmd (@mysql_commands) {
2471: $dbh->do($cmd) || print $dbh->errstr."\n";
2472: }
2473: }
2474: if (@mysql_lc_commands) {
2475: foreach my $lccmd (@mysql_lc_commands) {
2476: $dbh->do($lccmd) || print $dbh->errstr."\n";
2477: }
2478: }
1.1 raeburn 2479: if ($got_passwd) {
2480: print_and_log(&mt('MySQL root password stored.')."\n".
2481: &mt('Permissions set for LON-CAPA MySQL user: [_1].',"'www'")."\n");
2482: } else {
2483: print_and_log(&mt('Permissions set for LON-CAPA MySQL user: [_1].',"'www'")."\n");
2484: }
2485: } else {
2486: print_and_log(&mt('Problem accessing MySQL.')."\n".
2487: &mt('Permissions not set.')."\n");
2488: }
2489: }
2490: }
2491:
2492: sub new_mysql_rootpasswd {
1.45.2.2 raeburn 2493: my ($currmysqlpass,$usesauth,$is_mariadb) = @_;
1.36 raeburn 2494: if ($usesauth) {
1.45.2.2 raeburn 2495: if ($is_mariadb) {
2496: return ("ALTER USER 'root'\@'localhost' IDENTIFIED BY '$currmysqlpass'",
2497: "FLUSH PRIVILEGES;");
2498: } else {
2499: return ("ALTER USER 'root'\@'localhost' IDENTIFIED WITH mysql_native_password BY '$currmysqlpass'",
2500: "FLUSH PRIVILEGES;");
2501: }
1.36 raeburn 2502: } else {
2503: return ("SET PASSWORD FOR 'root'\@'localhost'=PASSWORD('$currmysqlpass')",
2504: "FLUSH PRIVILEGES;");
2505: }
1.1 raeburn 2506: }
2507:
2508: sub get_mysql_version {
1.45.2.19 raeburn 2509: my ($version,$minorversion,$subversion,$name);
1.1 raeburn 2510: if (open(PIPE," mysql -V |")) {
2511: my $info = <PIPE>;
2512: chomp($info);
2513: close(PIPE);
1.45.2.19 raeburn 2514: ($version,$minorversion,$subversion,$name) = ($info =~ /(\d+)\.(\d+)\.(\d+)(?:\-?(\w*),|)/);
1.1 raeburn 2515: } else {
2516: print &mt('Could not determine which version of MySQL is installed.').
2517: "\n";
2518: }
1.45.2.19 raeburn 2519: return ($version,$minorversion,$subversion,$name);
1.1 raeburn 2520: }
2521:
1.45.2.20 raeburn 2522: sub check_systemd_update {
2523: my ($distro) = @_;
2524: my ($use_systemctl,$service);
2525: $service = 'apache2.service';
2526: if ($distro =~ /^ubuntu(\w+)/) {
2527: if ($1 >= 16) {
2528: $use_systemctl = 1;
2529: }
2530: } elsif ($distro =~ /^debian(\w+)/) {
2531: if ($1 >= 9) {
2532: $use_systemctl = 1;
2533: }
2534: } elsif ($distro =~ /^fedora(\d+)/) {
2535: $service = 'httpd.service';
2536: if ($1 >= 16) {
2537: $use_systemctl = 1;
2538: }
2539: } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
2540: $service = 'httpd.service';
2541: if ($1 >= 7) {
2542: $use_systemctl = 1;
2543: }
2544: } elsif ($distro =~ /^sles(\d+)/) {
2545: if ($1 >= 12) {
2546: $use_systemctl = 1;
2547: }
2548: } elsif ($distro =~ /^suse(\d+)/) {
2549: if ($1 >= 13) {
2550: $use_systemctl = 1;
2551: }
2552: }
2553: if ($use_systemctl) {
2554: my $needsupdate = &check_systemd_security($distro);
2555: if ($needsupdate) {
2556: if (!-d '/etc/systemd/system/'.$service.'.d') {
2557: mkdir '/etc/systemd/system/'.$service.'.d', 0755;
2558: }
2559: if (-d '/etc/systemd/system/'.$service.'.d') {
2560: if (-e '/etc/systemd/system/'.$service.'.d/override.conf') {
2561: if (open(my $fh,'<','/etc/systemd/system/'.$service.'.d/override.conf')) {
2562: my ($inservice,$addservice,$protectoff,$linenum,$change,@lines);
2563: while (my $entry = <$fh>) {
2564: $linenum ++;
2565: chomp($entry);
2566: if ($entry eq '[Service]') {
2567: if (!$protectoff) {
2568: $inservice = $linenum;
2569: push(@lines,$entry);
2570: } else {
2571: $addservice = 1;
2572: next;
2573: }
2574: }
2575: if ($entry =~ /^ProtectHome\s*=\s*([\w-]+)\s*$/) {
2576: my $value = $1;
2577: if ($protectoff) {
2578: next;
2579: if (lc($value) eq 'no') {
2580: $protectoff = $linenum;
2581: push(@lines,$entry);
2582: } else {
2583: if ($protectoff) {
2584: next;
2585: } else {
2586: push(@lines,'ProtectHome=no');
2587: $protectoff = $linenum;
2588: $change = $linenum;
2589: }
2590: }
2591: }
2592: }
2593: }
2594: close($fh);
2595: if ($addservice || $change || !$protectoff) {
2596: if (open(my $fh,'>','/etc/systemd/system/'.$service.'.d/override.conf')) {
2597: if ($addservice) {
2598: print $fh "[Service]\n";
2599: }
2600: foreach my $entry (@lines) {
2601: print $fh "$entry\n";
2602: }
2603: close($fh);
2604: print_and_log('Updated /etc/systemd/system/'.$service.'.d/override.conf');
1.45.2.21 raeburn 2605: system('systemctl daemon-reload');
1.45.2.20 raeburn 2606: } else {
2607: print_and_log('Could not open /etc/systemd/system/'.$service.'.d/override.conf for writing.');
2608: }
2609: } else {
2610: print_and_log('No change needed in /etc/systemd/system/'.$service.'.d/override.conf');
2611: }
2612: } else {
2613: print_and_log('Could not open /etc/systemd/system/'.$service.'.d/override.conf for reading.');
2614: }
2615: } else {
2616: if (open(my $fh,'>','/etc/systemd/system/'.$service.'.d/override.conf')) {
2617: print $fh '[Service]'."\n".'ProtectHome=no'."\n";
2618: close($fh);
2619: print_and_log('Created /etc/systemd/system/'.$service.'.d/override.conf');
1.45.2.21 raeburn 2620: system('systemctl daemon-reload');
1.45.2.20 raeburn 2621: }
2622: }
2623: } else {
2624: print_and_log('No /etc/systemd/system/'.$service.'.d directory exists and creating one failed,');
2625: }
2626: } else {
2627: print_and_log('No update needed to systemd security settings for Apache web server.');
2628: }
2629: } else {
2630: print_and_log('No update needed to systemd, as this Linux distro does not use systemctl');
2631: }
2632: }
2633:
1.1 raeburn 2634: ###########################################################
2635: ##
2636: ## RHEL/CentOS/Fedora/Scientific Linux
2637: ## Copy LON-CAPA httpd.conf to /etc/httpd/conf
2638: ##
2639: ###########################################################
2640:
2641: sub copy_httpd_conf {
1.14 raeburn 2642: my ($instdir,$distro) = @_;
2643: my $configfile = 'httpd.conf';
1.45.2.18 raeburn 2644: if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.29 raeburn 2645: if ($1 >= 7) {
2646: $configfile = 'apache2.4/httpd.conf';
2647: } elsif ($1 > 5) {
1.14 raeburn 2648: $configfile = 'new/httpd.conf';
2649: }
2650: } elsif ($distro =~ /^fedora(\d+)$/) {
1.29 raeburn 2651: if ($1 > 17) {
2652: $configfile = 'apache2.4/httpd.conf';
2653: } elsif ($1 > 10) {
1.14 raeburn 2654: $configfile = 'new/httpd.conf';
2655: }
2656: }
1.1 raeburn 2657: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'httpd.conf'",
2658: "'/etc/httpd/conf/httpd.conf'")."\n");
2659: copy "/etc/httpd/conf/httpd.conf","/etc/httpd/conf/httpd.conf.original";
1.14 raeburn 2660: copy "$instdir/centos-rhes-fedora-sl/$configfile","/etc/httpd/conf/httpd.conf";
1.5 raeburn 2661: chmod(0444,"/etc/httpd/conf/httpd.conf");
1.1 raeburn 2662: print_and_log("\n");
2663: }
2664:
1.45.2.5 raeburn 2665: ###########################################################
2666: ##
2667: ## RHEL/CentOS/Fedora/Scientific Linux
2668: ## Copy LON-CAPA mpm.conf to /etc/httpd/conf.modules.d/00-mpm.conf
2669: ##
2670: ## The LON-CAPA mpm.conf enables the prefork MPM module in
2671: ## Apache. This is also the default for RHEL/CentOS/Oracle
2672: ## Linux 7 and earlier, and Fedora 26 and earlier. For more
2673: ## recent versions of those distros, the event MPM is enabled
2674: ## by default. After ©_mpm_conf() is run, the prefork MPM
2675: ## module will be enabled instead of the event MPM module.
2676: ##
2677: ###########################################################
2678:
2679: sub copy_mpm_conf {
2680: my ($instdir,$distro) = @_;
2681: my $mpmfile = 'mpm.conf';
2682: if ((-e "/etc/httpd/conf.modules.d/00-mpm.conf") &&
2683: (-e "$instdir/centos-rhes-fedora-sl/$mpmfile")) {
2684: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'mpm.conf'",
2685: "'/etc/httpd/conf.modules.d/00-mpm.conf'")."\n");
2686: copy "$instdir/centos-rhes-fedora-sl/$mpmfile","/etc/httpd/conf.modules.d/00-mpm.conf";
2687: chmod(0644,"/etc/httpd/conf.modules.d/00-mpm.conf");
2688: print_and_log("\n");
2689: } else {
2690: my $logfail;
1.45.2.18 raeburn 2691: if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.45.2.5 raeburn 2692: if ($1 > 7) {
2693: $logfail = 1;
2694: }
2695: } elsif ($distro =~ /^fedora(\d+)$/) {
2696: if ($1 > 26) {
2697: $logfail = 1;
2698: }
2699: }
2700: if ($logfail) {
2701: print_and_log(&mt('Warning: copying the LON-CAPA [_1] failed because [_2] and/or [_3] are missing.',
2702: $mpmfile,"'$instdir/centos-rhes-fedora-sl/$mpmfile'",
2703: "'/etc/httpd/conf.modules.d/00-mpm.conf'"));
2704: print_and_log("\n");
2705: }
2706: }
2707: }
2708:
1.1 raeburn 2709: #########################################################
2710: ##
1.17 raeburn 2711: ## Ubuntu/Debian -- copy our loncapa configuration file to
1.1 raeburn 2712: ## sites-available and set the symlink from sites-enabled.
2713: ##
2714: #########################################################
2715:
2716: sub copy_apache2_debconf {
1.28 raeburn 2717: my ($instdir,$distro) = @_;
1.6 raeburn 2718: my $apache2_mods_enabled_dir = '/etc/apache2/mods-enabled';
2719: my $apache2_mods_available_dir = '/etc/apache2/mods-available';
2720: foreach my $module ('headers.load','expires.load') {
2721: unless (-l "$apache2_mods_enabled_dir/$module") {
2722: symlink("$apache2_mods_available_dir/$module","$apache2_mods_enabled_dir/$module");
2723: print_and_log(&mt('Enabling "[_1]" Apache module.',$module)."\n");
2724: }
2725: }
1.28 raeburn 2726: my $apache2_sites_enabled_dir = '/etc/apache2/sites-enabled';
2727: my $apache2_sites_available_dir = '/etc/apache2/sites-available';
2728: my $defaultconfig = "$apache2_sites_enabled_dir/000-default";
1.45.2.10 raeburn 2729: my $defaultsite = "$apache2_sites_enabled_dir/loncapa.conf";
1.28 raeburn 2730: my ($distname,$version);
2731: if ($distro =~ /^(debian|ubuntu)(\d+)$/) {
2732: $distname = $1;
2733: $version = $2;
2734: }
1.45.2.19 raeburn 2735: if ((($distname eq 'ubuntu') && ($version > 12)) ||
2736: (($distname eq 'debian') && ($version >= 10))) {
1.28 raeburn 2737: $defaultconfig = "$apache2_sites_enabled_dir/000-default.conf";
2738: }
1.45.2.7 raeburn 2739: my ($skipconf,$skipsite,$skipstatus);
1.45.2.19 raeburn 2740: if ((($distname eq 'ubuntu') && ($version > 12)) ||
2741: (($distname eq 'debian') && ($version >= 10))) {
1.28 raeburn 2742: my $apache2_conf_enabled_dir = '/etc/apache2/conf-enabled';
2743: my $apache2_conf_available_dir = '/etc/apache2/conf-available';
1.33 raeburn 2744: my $defaultconf = $apache2_conf_enabled_dir.'/loncapa.conf';
1.45.2.7 raeburn 2745: if ((-e "$apache2_conf_available_dir/loncapa") && (-e "$instdir/debian-ubuntu/ubuntu14/loncapa_conf")) {
1.45.2.8 raeburn 2746: if (open(PIPE, "diff --brief $apache2_conf_available_dir/loncapa $instdir/debian-ubuntu/ubuntu14/loncapa_conf |")) {
1.45.2.7 raeburn 2747: my $diffres = <PIPE>;
2748: close(PIPE);
2749: chomp($diffres);
2750: if ($diffres) {
1.45.2.10 raeburn 2751: copy("$apache2_conf_available_dir/loncapa","$apache2_conf_available_dir/loncapa.conf.original");
2752: } else {
2753: copy("$apache2_conf_available_dir/loncapa","$apache2_conf_available_dir/loncapa.conf");
1.45.2.11 raeburn 2754: chdir($apache2_conf_enabled_dir);
2755: symlink('../conf-available/loncapa.conf','loncapa.conf');
2756: chdir($instdir);
1.45.2.7 raeburn 2757: }
2758: if (-l $defaultconf) {
2759: my $linkfname = readlink($defaultconf);
1.45.2.11 raeburn 2760: if ($linkfname ne '') {
2761: $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_conf_enabled_dir));
2762: }
1.45.2.7 raeburn 2763: if ($linkfname eq "$apache2_conf_available_dir/loncapa") {
1.45.2.10 raeburn 2764: unlink($defaultconf);
2765: }
2766: }
2767: unlink("$apache2_conf_available_dir/loncapa");
2768: }
2769: }
2770: if ((-e "$apache2_conf_available_dir/loncapa.conf") && (-e "$instdir/debian-ubuntu/ubuntu14/loncapa_conf")) {
2771: if (open(PIPE, "diff --brief $apache2_conf_available_dir/loncapa.conf $instdir/debian-ubuntu/ubuntu14/loncapa_conf |")) {
2772: my $diffres = <PIPE>;
2773: close(PIPE);
2774: chomp($diffres);
2775: if ($diffres) {
2776: copy("$apache2_conf_available_dir/loncapa.conf","$apache2_conf_available_dir/loncapa.conf.original");
2777: }
2778: if (-l $defaultconf) {
2779: my $linkfname = readlink($defaultconf);
1.45.2.11 raeburn 2780: if ($linkfname ne '') {
2781: $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_conf_enabled_dir));
2782: }
1.45.2.10 raeburn 2783: if ($linkfname eq "$apache2_conf_available_dir/loncapa.conf") {
1.45.2.7 raeburn 2784: unless ($diffres) {
2785: $skipconf = 1;
2786: }
2787: }
2788: }
2789: }
2790: }
2791: unless ($skipconf) {
2792: print_and_log(&mt('Copying loncapa [_1] config file to [_2] and pointing [_3] to it from conf-enabled.',"'apache2'","'/etc/apache2/conf-available'","'loncapa.conf symlink'")."\n");
1.45.2.10 raeburn 2793: copy("$instdir/debian-ubuntu/ubuntu14/loncapa_conf","$apache2_conf_available_dir/loncapa.conf");
2794: chmod(0444,"$apache2_conf_available_dir/loncapa.conf");
1.45.2.7 raeburn 2795: if (-l $defaultconf) {
2796: unlink($defaultconf);
2797: }
1.45.2.11 raeburn 2798: chdir($apache2_conf_enabled_dir);
2799: symlink('../conf-available/loncapa.conf','loncapa.conf');
2800: chdir($instdir);
1.45.2.7 raeburn 2801: }
2802: my $stdsite = "$instdir/debian-ubuntu/ubuntu14/loncapa_site";
2803: if ((-e $stdsite) && (-e "$apache2_sites_available_dir/loncapa")) {
2804: if (open(PIPE, "diff --brief $stdsite $apache2_sites_available_dir/loncapa |")) {
2805: my $diffres = <PIPE>;
2806: close(PIPE);
2807: chomp($diffres);
2808: if ($diffres) {
1.45.2.10 raeburn 2809: copy("$apache2_sites_available_dir/loncapa","$apache2_sites_available_dir/loncapa.conf.original");
2810: } else {
2811: copy("$apache2_sites_available_dir/loncapa","$apache2_sites_available_dir/loncapa.conf");
1.45.2.7 raeburn 2812: }
2813: if (-l $defaultconfig) {
2814: my $linkfname = readlink($defaultconfig);
1.45.2.11 raeburn 2815: if ($linkfname ne '') {
2816: $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_sites_enabled_dir));
2817: }
1.45.2.7 raeburn 2818: if ($linkfname eq "$apache2_sites_available_dir/loncapa") {
1.45.2.10 raeburn 2819: unlink($defaultconfig);
2820: }
2821: }
2822: unlink("$apache2_sites_available_dir/loncapa");
2823: }
2824: }
2825: if ((-e $stdsite) && (-e "$apache2_sites_available_dir/loncapa.conf")) {
2826: if (open(PIPE, "diff --brief $stdsite $apache2_sites_available_dir/loncapa.conf |")) {
2827: my $diffres = <PIPE>;
2828: close(PIPE);
2829: chomp($diffres);
2830: if ($diffres) {
2831: copy("$apache2_sites_available_dir/loncapa.conf","$apache2_sites_available_dir/loncapa.conf.original");
2832: }
2833: if (-l $defaultsite) {
2834: my $linkfname = readlink($defaultsite);
1.45.2.11 raeburn 2835: if ($linkfname ne '') {
2836: $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_sites_enabled_dir));
2837: }
2838: if ($linkfname eq "$apache2_sites_available_dir/loncapa.conf") {
1.45.2.7 raeburn 2839: unless ($diffres) {
2840: $skipsite = 1;
2841: }
2842: }
2843: }
2844: }
2845: }
2846: unless ($skipsite) {
1.45.2.10 raeburn 2847: print_and_log(&mt('Copying loncapa [_1] site file to [_2] and pointing [_3] to it from sites-enabled.',"'apache2'","'/etc/apache2/sites-available'","'loncapa.conf symlink'")."\n");
2848: copy("$instdir/debian-ubuntu/ubuntu14/loncapa_site","$apache2_sites_available_dir/loncapa.conf");
2849: chmod(0444,"$apache2_sites_available_dir/loncapa.conf");
1.45.2.11 raeburn 2850: chdir($apache2_sites_enabled_dir);
2851: symlink('../sites-available/loncapa.conf','loncapa.conf');
2852: chdir($instdir);
1.45.2.10 raeburn 2853: }
1.45.2.11 raeburn 2854: if (-l $defaultconfig) {
1.45.2.10 raeburn 2855: my $linkfname = readlink($defaultconfig);
1.45.2.11 raeburn 2856: if ($linkfname ne '') {
2857: $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_sites_enabled_dir));
2858: }
2859: if ($linkfname eq "$apache2_sites_available_dir/000-default.conf") {
1.45.2.10 raeburn 2860: unlink($defaultconfig);
2861: }
1.45.2.7 raeburn 2862: }
2863: } else {
2864: if ((-e "$instdir/debian-ubuntu/loncapa") && (-e "$apache2_sites_available_dir/loncapa")) {
2865: if (open(PIPE, "diff --brief $instdir/debian-ubuntu/loncapa $apache2_sites_available_dir/loncapa |")) {
2866: my $diffres = <PIPE>;
2867: close(PIPE);
2868: chomp($diffres);
2869: if ($diffres) {
2870: copy("$apache2_sites_available_dir/loncapa","$apache2_sites_available_dir/loncapa.original");
2871: }
2872: if (-l $defaultconfig) {
2873: my $linkfname = readlink($defaultconfig);
2874: if ($linkfname eq "$apache2_sites_available_dir/loncapa") {
2875: unless ($diffres) {
2876: $skipsite = 1;
2877: }
2878: }
2879: }
2880: }
2881: }
2882: unless ($skipsite) {
2883: if (-l $defaultconfig) {
2884: unlink($defaultconfig);
2885: }
2886: print_and_log(&mt('Copying loncapa [_1] config file to [_2] and pointing [_3] to it from sites-enabled.',"'apache2'","'/etc/apache2/sites-available'","'000-default symlink'")."\n");
2887: if (-e "$instdir/debian-ubuntu/loncapa") {
2888: copy("$instdir/debian-ubuntu/loncapa","$apache2_sites_available_dir/loncapa");
2889: chmod(0444,"$apache2_sites_available_dir/loncapa");
2890: symlink("$apache2_sites_available_dir/loncapa","$apache2_sites_enabled_dir/000-default");
2891: }
2892: }
2893: }
1.45.2.19 raeburn 2894: if (($distname eq 'ubuntu') || ($distname eq 'debian')) {
1.45.2.7 raeburn 2895: my $sitestatus = "$apache2_mods_available_dir/status.conf";
2896: my $stdstatus = "$instdir/debian-ubuntu/status.conf";
2897: if ((-e $sitestatus) && (-e $stdstatus)) {
2898: if (open(PIPE, "diff --brief $stdstatus $sitestatus |")) {
2899: my $diffres = <PIPE>;
2900: close(PIPE);
2901: chomp($diffres);
2902: if ($diffres) {
2903: copy("$apache2_mods_available_dir/status.conf","$apache2_mods_available_dir/status.conf.original");
2904: } else {
2905: $skipstatus = 1;
2906: }
2907: }
2908: }
2909: unless ($skipstatus) {
2910: if (-e $stdstatus) {
2911: print_and_log(&mt('Copying loncapa [_1] file to [_2],',"'status.conf'","'/etc/apache2/mods-available/status.conf'")."\n");
2912: copy($stdstatus,$sitestatus);
2913: chmod(0644,$sitestatus);
2914: }
2915: }
1.28 raeburn 2916: }
1.1 raeburn 2917: print_and_log("\n");
2918: }
2919:
2920: ###########################################################
2921: ##
2922: ## openSuSE/SLES Copy apache2 config files:
2923: ## default-server.conf, uid.conf, /etc/sysconfig/apache2
2924: ## and create symlink from /srv/www/conf to /etc/apache2
2925: ##
2926: ###########################################################
2927:
2928: sub copy_apache2_suseconf {
1.45.2.1 raeburn 2929: my ($instdir,$distro) = @_;
2930: my ($name,$version) = ($distro =~ /^(suse|sles)([\d\.]+)$/);
2931: my $conf_file = "$instdir/sles-suse/default-server.conf";
2932: if (($name eq 'sles') && ($version >= 12)) {
2933: $conf_file = "$instdir/sles-suse/apache2.4/default-server.conf";
2934: }
1.1 raeburn 2935: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',
2936: "'default-server.conf'",
2937: "'/etc/apache2/default-server.conf'")."\n");
2938: if (!-e "/etc/apache2/default-server.conf.original") {
2939: copy "/etc/apache2/default-server.conf","/etc/apache2/default-server.conf.original";
2940: }
1.45.2.1 raeburn 2941: copy $conf_file,"/etc/apache2/default-server.conf";
1.5 raeburn 2942: chmod(0444,"/etc/apache2/default-server.conf");
1.1 raeburn 2943: # Make symlink for conf directory (included in loncapa_apache.conf)
2944: my $can_symlink = (eval { symlink('/etc/apache2','/srv/www/conf'); }, $@ eq '');
2945: if ($can_symlink) {
2946: &print_and_log(&mt('Symlink created for [_1] to [_2].',
2947: "'/srv/www/conf'","'/etc/apache2'")."\n");
2948: } else {
2949: &print_and_log(&mt('Symlink creation failed for [_1] to [_2]. You will need to perform this action from the command line.',"'/srv/www/conf'","'/etc/apache2'")."\n");
2950: }
2951: ©_apache2_conf_files($instdir);
1.45.2.1 raeburn 2952: ©_sysconfig_apache2_file($instdir,$name,$version);
1.1 raeburn 2953: print_and_log("\n");
2954: }
2955:
2956: ###############################################
2957: ##
2958: ## Modify uid.conf
2959: ##
2960: ###############################################
2961: sub copy_apache2_conf_files {
2962: my ($instdir) = @_;
2963: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',
2964: "'uid.conf'","'/etc/apache2/uid.conf'")."\n");
2965: if (!-e "/etc/apache2/uid.conf.original") {
2966: copy "/etc/apache2/uid.conf","/etc/apache2/uid.conf.original";
2967: }
1.9 raeburn 2968: copy "$instdir/sles-suse/uid.conf","/etc/apache2/uid.conf";
1.5 raeburn 2969: chmod(0444,"/etc/apache2/uid.conf");
1.1 raeburn 2970: }
2971:
2972: ###############################################
2973: ##
2974: ## Modify /etc/sysconfig/apache2
2975: ##
2976: ###############################################
2977: sub copy_sysconfig_apache2_file {
1.45.2.1 raeburn 2978: my ($instdir,$name,$version) = @_;
1.1 raeburn 2979: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'sysconfig/apache2'","'/etc/sysconfig/apache2'")."\n");
2980: if (!-e "/etc/sysconfig/apache2.original") {
2981: copy "/etc/sysconfig/apache2","/etc/sysconfig/apache2.original";
2982: }
1.45.2.1 raeburn 2983: my $sysconf_file = "$instdir/sles-suse/sysconfig_apache2";
2984: if (($name eq 'sles') && ($version >= 12)) {
2985: $sysconf_file = "$instdir/sles-suse/apache2.4/sysconfig_apache2";
2986: }
2987: copy $sysconf_file,"/etc/sysconfig/apache2";
1.5 raeburn 2988: chmod(0444,"/etc/sysconfig/apache2");
1.1 raeburn 2989: }
2990:
2991: ###############################################
2992: ##
2993: ## Add/Modify /etc/insserv/overrides
2994: ##
2995: ###############################################
2996:
2997: sub update_SuSEfirewall2_setup {
2998: my ($instdir) = @_;
2999: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'SuSEfirewall2_setup'","'/etc/insserv/overrides/SuSEfirewall2_setup'")."\n");
3000: if (!-e "/etc/insserv/overrides/SuSEfirewall2_setup") {
3001: if (!-d "/etc/insserv") {
3002: mkdir("/etc/insserv",0755);
3003: }
3004: if (!-d "/etc/insserv/overrides") {
3005: mkdir("/etc/insserv/overrides",0755);
3006: }
3007: } elsif (!-e "/etc/insserv/overrides/SuSEfirewall2_setup.original") {
3008: copy "/etc/insserv/overrides/SuSEfirewall2_setup","/etc/insserv/overrides/SuSEfirewall2_setup.original"
3009: }
1.9 raeburn 3010: copy "$instdir/sles-suse/SuSEfirewall2_setup","/etc/insserv/overrides/SuSEfirewall2_setup";
1.5 raeburn 3011: chmod(0444,"/etc/insserv/overrides/SuSEfirewall2_setup");
3012: }
3013:
3014: sub get_iptables_rules {
3015: my ($distro,$instdir,$apachefw) = @_;
3016: my (@fwchains,@ports);
3017: if (&firewall_is_active()) {
3018: my $iptables = &get_pathto_iptables();
3019: if ($iptables ne '') {
3020: @fwchains = &get_fw_chains($iptables,$distro);
3021: }
3022: }
3023: if (ref($apachefw) eq 'HASH') {
3024: foreach my $service ('http','https') {
3025: unless ($apachefw->{$service}) {
3026: push (@ports,$service);
3027: }
3028: }
3029: } else {
3030: @ports = ('http','https');
3031: }
3032: if (@ports == 0) {
3033: return;
3034: }
3035: my $ask_to_enable;
3036: if (-e "/etc/iptables.loncapa.rules") {
1.9 raeburn 3037: if (open(PIPE, "diff --brief $instdir/debian-ubuntu/iptables.loncapa.rules /etc/iptables.loncapa.rules |")) {
1.5 raeburn 3038: my $diffres = <PIPE>;
3039: close(PIPE);
3040: chomp($diffres);
3041: if ($diffres) {
3042: print &mt('Warning: [_1] exists but differs from LON-CAPA supplied file.','/etc/iptables.loncapa.rules')."\n";
3043: }
3044: } else {
3045: print &mt('Error: unable to open [_1] to compare contents with LON-CAPA supplied file.','/etc/iptables.loncapa.rules')."\n";
3046: }
3047: } else {
1.9 raeburn 3048: if (-e "$instdir/debian-ubuntu/iptables.loncapa.rules") {
3049: copy "$instdir/debian-ubuntu/iptables.loncapa.rules","/etc/iptables.loncapa.rules";
1.5 raeburn 3050: chmod(0600,"/etc/iptables.loncapa.rules");
3051: }
3052: }
3053: if (-e "/etc/iptables.loncapa.rules") {
3054: if (-e "/etc/network/if-pre-up.d/iptables") {
1.9 raeburn 3055: if (open(PIPE, "diff --brief $instdir/debian-ubuntu/iptables /etc/network/if-pre-up/iptables |")) {
1.5 raeburn 3056: my $diffres = <PIPE>;
3057: close(PIPE);
3058: chomp($diffres);
3059: if ($diffres) {
3060: print &mt('Warning: [_1] exists but differs from LON-CAPA supplied file.','/etc/network/if-pre-up.d/iptables')."\n";
3061: }
3062: } else {
3063: print &mt('Error: unable to open [_1] to compare contents with LON-CAPA supplied file.','/etc/network/if-pre-up.d/iptables')."\n";
3064: }
3065: } else {
1.9 raeburn 3066: copy "$instdir/debian-ubuntu/iptables","/etc/network/if-pre-up.d/iptables";
1.5 raeburn 3067: chmod(0755,"/etc/network/if-pre-up.d/iptables");
3068: print_and_log(&mt('Installed script "[_1]" to add iptables rules to block all ports except 22, 80, and 443 when network is enabled during boot.','/etc/network/if-pre-up.d/iptables'));
3069: $ask_to_enable = 1;
3070: }
3071: }
3072: return $ask_to_enable;
1.1 raeburn 3073: }
3074:
3075: sub download_loncapa {
3076: my ($instdir,$lctarball) = @_;
3077: my ($have_tarball,$updateshown);
3078: if (! -e "$instdir/$lctarball") {
3079: print_and_log(&mt('Retrieving LON-CAPA source files from: [_1]',
3080: 'http://install.loncapa.org')."\n");
3081: system("wget http://install.loncapa.org/versions/$lctarball ".
3082: "2>/dev/null 1>/dev/null");
3083: if (! -e "./$lctarball") {
3084: print &mt('Unable to retrieve LON-CAPA source files from: [_1].',
3085: "http://install.loncapa.org/versions/$lctarball")."\n";
3086: } else {
3087: $have_tarball = 1;
3088: }
3089: print_and_log("\n");
3090: } else {
3091: $have_tarball = 1;
3092: print_and_log("
3093: ------------------------------------------------------------------------
3094:
1.45.2.16 raeburn 3095: ".&mt('You seem to have a version of [_1] in [_2]',$lctarball,$instdir)."\n".
1.1 raeburn 3096: &mt('This copy will be used and a new version will NOT be downloaded.')."\n".
3097: &mt('If you wish, you may download a new version by executing:')."
3098:
1.45.2.16 raeburn 3099: wget http://install.loncapa.org/versions/$lctarball
1.1 raeburn 3100:
3101: ------------------------------------------------------------------------
3102: ");
3103: }
3104:
3105: ##
1.45.2.16 raeburn 3106: ## untar loncapa-X.Y.Z.tar.gz
1.1 raeburn 3107: ##
3108: if ($have_tarball) {
1.45.2.16 raeburn 3109: my $homedir = '/root';
3110: my ($targetdir,$chdircmd,$updatecmd);
3111: if (($distro =~ /^ubuntu/) && ($instdir ne $homedir)) {
3112: ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});
3113: $updatecmd = 'sudo ./UPDATE';
3114: } else {
3115: $updatecmd = './UPDATE';
3116: }
1.1 raeburn 3117: print_and_log(&mt('Extracting LON-CAPA source files')."\n");
1.45.2.16 raeburn 3118: if (-e $homedir) {
3119: writelog(`tar zxf $instdir/$lctarball --directory $homedir`);
3120: $targetdir = $homedir;
3121: } else {
3122: writelog(`tar zxf $instdir/$lctarball`);
3123: $targetdir = $instdir;
3124: }
3125: if ($lctarball =~ /^loncapa\-(\d+\.\d+\.\d+(?:|[^.]+))\.tar\.gz$/) {
3126: $chdircmd = "cd $targetdir/loncapa-".$1;
3127: } else {
3128: $chdircmd = "cd $targetdir/loncapa-X.Y.Z (X.Y.Z should correspond to a version number like '2.11.3')";
3129: }
1.1 raeburn 3130: print_and_log("\n");
3131: print &mt('LON-CAPA source files extracted.')."\n".
1.45.2.16 raeburn 3132: &mt('It remains for you to execute the following commands:').
3133: "\n$chdircmd\n$updatecmd\n".
3134: &mt('If you have any trouble, please see [_1] and [_2]',
3135: 'http://install.loncapa.org/','http://help.loncapa.org/')."\n";
1.1 raeburn 3136: $updateshown = 1;
3137: }
3138: return ($have_tarball,$updateshown);
3139: }
3140:
3141: close LOG;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>