Annotation of doc/install/linux/install.pl, revision 1.45.2.24
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.24! raeburn 79: print LOG '$Id: install.pl,v 1.45.2.23 2024/08/05 13:42:44 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");
1.45.2.24! raeburn 904: if (open(PIPE,"systemctl show $service --property=ProtectHome --property=RestrictSUIDSGID 2>/dev/null |")) {
! 905: my ($protecthome,$suidsgid);
! 906: while (my $line = <PIPE>) {
! 907: chomp($line);
! 908: if ($line =~ /^ProtectHome=(read-only|yes)$/i) {
! 909: $protecthome = 1;
! 910: } elsif ($line =~ /^RestrictSUIDSGID=yes$/i) {
! 911: $suidsgid = 1;
! 912: }
! 913: }
1.45.2.20 raeburn 914: close(PIPE);
1.45.2.24! raeburn 915: if ($protecthome) {
! 916: return 1;
! 917: }
! 918: if ($suidsgid) {
1.45.2.20 raeburn 919: return 1;
920: }
921: } else {
922: print &mt('Could not check systemctl configuration for Apache')."\n";
923: }
924: return 0;
925: }
926:
1.45.2.1 raeburn 927: sub uses_firewalld {
928: my ($distro) = @_;
1.45.2.3 raeburn 929: my ($inuse,$checkfirewalld,$zone);
1.45.2.1 raeburn 930: if ($distro =~ /^(suse|sles)([\d\.]+)$/) {
931: if (($1 eq 'sles') && ($2 >= 15)) {
932: $checkfirewalld = 1;
933: }
934: } elsif ($distro =~ /^fedora(\d+)$/) {
935: if ($1 >= 18) {
936: $checkfirewalld = 1;
937: }
1.45.2.18 raeburn 938: } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.45.2.1 raeburn 939: if ($1 >= 7) {
940: $checkfirewalld = 1;
941: }
942: }
943: if ($checkfirewalld) {
944: my ($loaded,$active);
1.45.2.15 raeburn 945: if (open(PIPE,"systemctl status firewalld 2>/dev/null |")) {
1.45.2.1 raeburn 946: while (<PIPE>) {
947: chomp();
948: if (/^\s*Loaded:\s+(\w+)/) {
949: $loaded = $1;
950: }
1.45.2.15 raeburn 951: if (/^\s*Active:\s+(\w+)/) {
1.45.2.1 raeburn 952: $active = $1;
953: }
954: }
955: close(PIPE);
956: }
957: if (($loaded eq 'loaded') || ($active eq 'active')) {
958: $inuse = 1;
1.45.2.3 raeburn 959: my $cmd = 'firewall-cmd --get-default-zone';
960: if (open(PIPE,"$cmd |")) {
961: my $result = <PIPE>;
962: chomp($result);
963: close(PIPE);
964: if ($result =~ /^\w+$/) {
965: $zone = $result;
966: }
967: }
1.45.2.1 raeburn 968: }
969: }
1.45.2.3 raeburn 970: return ($inuse,$zone);
1.45.2.1 raeburn 971: }
972:
1.1 raeburn 973: sub chkfirewall {
1.5 raeburn 974: my ($distro) = @_;
1.1 raeburn 975: my $configfirewall = 1;
976: my %ports = (
977: http => 80,
978: https => 443,
979: );
1.5 raeburn 980: my %activefw;
1.45.2.3 raeburn 981: my ($firewalld,$zone) = &uses_firewalld($distro);
982: if ($firewalld) {
983: my %current;
984: if (open(PIPE,'firewall-cmd --permanent --zone='.$zone.' --list-services |')) {
985: my $svc = <PIPE>;
986: close(PIPE);
987: chomp($svc);
988: map { $current{$_} = 1; } (split(/\s+/,$svc));
989: }
990: if ($current{'http'} && $current{'https'}) {
991: $configfirewall = 0;
992: }
993: } else {
994: if (&firewall_is_active()) {
1.45.2.1 raeburn 995: my $iptables = &get_pathto_iptables();
996: if ($iptables eq '') {
997: print &mt('Firewall not checked as path to iptables not determined.')."\n";
998: } else {
999: my @fwchains = &get_fw_chains($iptables,$distro);
1000: if (@fwchains) {
1001: foreach my $service ('http','https') {
1002: foreach my $fwchain (@fwchains) {
1003: if (&firewall_is_port_open($iptables,$fwchain,$ports{$service})) {
1004: $activefw{$service} = 1;
1005: last;
1006: }
1.1 raeburn 1007: }
1008: }
1.45.2.1 raeburn 1009: if ($activefw{'http'}) {
1010: $configfirewall = 0;
1011: }
1012: } else {
1013: print &mt('Firewall not checked as iptables Chains not identified.')."\n";
1.1 raeburn 1014: }
1015: }
1.45.2.3 raeburn 1016: } else {
1017: print &mt('Firewall not enabled.')."\n";
1.1 raeburn 1018: }
1019: }
1.5 raeburn 1020: return ($configfirewall,\%activefw);
1.1 raeburn 1021: }
1022:
1023: sub chkapache {
1024: my ($distro,$instdir) = @_;
1025: my $fixapache = 1;
1.28 raeburn 1026: if ($distro =~ /^(debian|ubuntu)(\d+)$/) {
1027: my $distname = $1;
1028: my $version = $2;
1.33 raeburn 1029: my ($stdconf,$stdsite);
1.45.2.19 raeburn 1030: if ((($distname eq 'ubuntu') && ($version > 12)) ||
1031: (($distname eq 'debian') && ($version >= 10))) {
1.33 raeburn 1032: $stdconf = "$instdir/debian-ubuntu/ubuntu14/loncapa_conf";
1033: $stdsite = "$instdir/debian-ubuntu/ubuntu14/loncapa_sites";
1034: } else {
1035: $stdconf = "$instdir/debian-ubuntu/loncapa";
1036: }
1037: if (!-e $stdconf) {
1.1 raeburn 1038: $fixapache = 0;
1039: print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";
1.28 raeburn 1040: } else {
1.33 raeburn 1041: my ($configfile,$sitefile);
1.45.2.19 raeburn 1042: if ((($distname eq 'ubuntu') && ($version > 12)) ||
1043: (($distname eq 'debian') && ($version >= 10))) {
1.45.2.10 raeburn 1044: $sitefile = '/etc/apache2/sites-available/loncapa.conf';
1045: $configfile = '/etc/apache2/conf-available/loncapa.conf';
1.33 raeburn 1046: } else {
1.45.2.10 raeburn 1047: $configfile = '/etc/apache2/sites-available/loncapa';
1.28 raeburn 1048: }
1.33 raeburn 1049: if (($configfile ne '') && (-e $configfile) && (-e $stdconf)) {
1050: if (open(PIPE, "diff --brief $stdconf $configfile |")) {
1.28 raeburn 1051: my $diffres = <PIPE>;
1052: close(PIPE);
1053: chomp($diffres);
1054: unless ($diffres) {
1055: $fixapache = 0;
1056: }
1.1 raeburn 1057: }
1058: }
1.45.2.19 raeburn 1059: if ((!$fixapache) && ((($distname eq 'ubuntu') && ($version > 12)) ||
1060: (($distname eq 'debian') && ($version >= 10)))) {
1.33 raeburn 1061: if (($sitefile ne '') && (-e $sitefile) && (-e $stdsite)) {
1062: if (open(PIPE, "diff --brief $stdsite $sitefile |")) {
1063: my $diffres = <PIPE>;
1064: close(PIPE);
1065: chomp($diffres);
1.45.2.20 raeburn 1066: if ($diffres) {
1067: $fixapache = 1;
1068: } else {
1.33 raeburn 1069: $fixapache = 0;
1070: }
1071: }
1072: }
1073: }
1.1 raeburn 1074: }
1.6 raeburn 1075: if (!$fixapache) {
1076: foreach my $module ('headers.load','expires.load') {
1077: unless (-l "/etc/apache2/mods-enabled/$module") {
1078: $fixapache = 1;
1079: }
1080: }
1081: }
1.45.2.19 raeburn 1082: if ((!$fixapache) && (($distname eq 'ubuntu') || ($distname eq 'debian'))) {
1.45.2.7 raeburn 1083: my $sitestatus = "/etc/apache2/mods-available/status.conf";
1084: my $stdstatus = "$instdir/debian-ubuntu/status.conf";
1085: if ((-e $stdstatus) && (-e $sitestatus)) {
1086: if (open(PIPE, "diff --brief $stdstatus $sitestatus |")) {
1087: my $diffres = <PIPE>;
1088: close(PIPE);
1089: chomp($diffres);
1090: if ($diffres) {
1091: $fixapache = 1;
1092: }
1093: }
1094: }
1095: }
1.45.2.1 raeburn 1096: } elsif ($distro =~ /^(suse|sles)([\d\.]+)$/) {
1097: my ($name,$version) = ($1,$2);
1.1 raeburn 1098: my $apache = 'apache';
1.45.2.1 raeburn 1099: my $conf_file = "$instdir/sles-suse/default-server.conf";
1100: if ($version >= 10) {
1.8 raeburn 1101: $apache = 'apache2';
1.1 raeburn 1102: }
1.45.2.1 raeburn 1103: if (($name eq 'sles') && ($version >= 12)) {
1104: $conf_file = "$instdir/sles-suse/apache2.4/default-server.conf";
1105: }
1106: if (!-e $conf_file) {
1.1 raeburn 1107: $fixapache = 0;
1108: print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";
1.45.2.1 raeburn 1109: } elsif (-e "/etc/$apache/default-server.conf") {
1110: if (open(PIPE, "diff --brief $conf_file /etc/$apache/default-server.conf |")) {
1.9 raeburn 1111: my $diffres = <PIPE>;
1112: close(PIPE);
1113: chomp($diffres);
1114: unless ($diffres) {
1115: $fixapache = 0;
1116: }
1117: }
1118: }
1119: } elsif ($distro eq 'rhes4') {
1120: if (!-e "$instdir/rhes4/httpd.conf") {
1121: $fixapache = 0;
1122: print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";
1123: } elsif ((-e "/etc/httpd/conf/httpd.conf") && (-e "$instdir/rhes4/httpd.conf")) {
1124: if (open(PIPE, "diff --brief $instdir/rhes4/httpd.conf /etc/httpd/conf/httpd.conf |")) {
1.1 raeburn 1125: my $diffres = <PIPE>;
1126: close(PIPE);
1127: chomp($diffres);
1128: unless ($diffres) {
1129: $fixapache = 0;
1130: }
1131: }
1132: }
1133: } else {
1.14 raeburn 1134: my $configfile = 'httpd.conf';
1.45.2.5 raeburn 1135: my $mpmfile = 'mpm.conf';
1.45.2.18 raeburn 1136: if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.29 raeburn 1137: if ($1 >= 7) {
1138: $configfile = 'apache2.4/httpd.conf';
1139: } elsif ($1 > 5) {
1.14 raeburn 1140: $configfile = 'new/httpd.conf';
1141: }
1142: } elsif ($distro =~ /^fedora(\d+)$/) {
1.29 raeburn 1143: if ($1 > 17) {
1.45.2.5 raeburn 1144: $configfile = 'apache2.4/httpd.conf';
1.29 raeburn 1145: } elsif ($1 > 10) {
1.15 raeburn 1146: $configfile = 'new/httpd.conf';
1.14 raeburn 1147: }
1148: }
1149: if (!-e "$instdir/centos-rhes-fedora-sl/$configfile") {
1.1 raeburn 1150: $fixapache = 0;
1151: print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";
1.14 raeburn 1152: } elsif ((-e "/etc/httpd/conf/httpd.conf") && (-e "$instdir/centos-rhes-fedora-sl/$configfile")) {
1153: if (open(PIPE, "diff --brief $instdir/centos-rhes-fedora-sl/$configfile /etc/httpd/conf/httpd.conf |")) {
1.1 raeburn 1154: my $diffres = <PIPE>;
1155: close(PIPE);
1156: chomp($diffres);
1157: unless ($diffres) {
1158: $fixapache = 0;
1159: }
1160: }
1161: }
1.45.2.5 raeburn 1162: if (-e "/etc/httpd/conf.modules.d/00-mpm.conf") {
1163: if (!-e "$instdir/centos-rhes-fedora-sl/$mpmfile") {
1164: print &mt('Warning: No LON-CAPA Apache MPM configuration file found for installation check.')."\n";
1165: } elsif ((-e "/etc/httpd/conf.modules.d/00-mpm.conf") && (-e "$instdir/centos-rhes-fedora-sl/$mpmfile")) {
1166: if (open(PIPE, "diff --brief $instdir/centos-rhes-fedora-sl/$mpmfile /etc/httpd/conf.modules.d/00-mpm.conf |")) {
1167: my $diffres = <PIPE>;
1168: close(PIPE);
1169: chomp($diffres);
1170: if ($diffres) {
1171: $fixapache = 1;
1172: }
1173: }
1174: }
1175: }
1.1 raeburn 1176: }
1177: return $fixapache;
1178: }
1179:
1180: sub chksrvcs {
1181: my ($distro,$tostop) = @_;
1182: my %stopsrvcs;
1183: if (ref($tostop) eq 'HASH') {
1184: %stopsrvcs = %{$tostop};
1185: }
1.6 raeburn 1186: foreach my $service ('cups','memcached') {
1.1 raeburn 1187: next if (exists($stopsrvcs{$service}));
1188: my $daemon = $service;
1189: if ($service eq 'cups') {
1190: $daemon = 'cupsd';
1191: }
1192: my $cmd = "ps -ef |grep '$daemon' |grep -v grep";
1193: if (open(PIPE,'-|',$cmd)) {
1194: my $daemonrunning = <PIPE>;
1195: chomp($daemonrunning);
1196: close(PIPE);
1197: if ($daemonrunning) {
1.12 raeburn 1198: if ($service eq 'memcached') {
1.16 raeburn 1199: my $cmd = '/usr/bin/memcached';
1200: if ($distro =~ /^(suse|sles)/) {
1201: $cmd = '/usr/sbin/memcached';
1202: }
1.12 raeburn 1203: unless ($daemonrunning =~ m{^www[^/]+\Q$cmd -m 400 -v\E$}) {
1.10 raeburn 1204: $stopsrvcs{$service} = 1;
1205: }
1206: } else {
1207: $stopsrvcs{$service} = 1;
1208: }
1.1 raeburn 1209: }
1210: }
1.10 raeburn 1211: }
1.1 raeburn 1212: return \%stopsrvcs;
1213: }
1214:
1215: sub need_download {
1.45.2.16 raeburn 1216: my ($distro,$instdir) = @_;
1.1 raeburn 1217: my $needs_download = 1;
1218: my ($production,$testing,$stdsizes) = &download_versionslist();
1.45.2.16 raeburn 1219: my ($localcurrent,$localtesting,%tarball,%localsize,%bymodtime,
1.1 raeburn 1220: %bysize,$filetouse,$downloadstatus);
1.45.2.16 raeburn 1221: if (opendir(my $dir,$instdir)) {
1.1 raeburn 1222: my (@lcdownloads,$version);
1223: foreach my $file (readdir($dir)) {
1224: if ($file =~ /^loncapa\-([\w\-.]+)\.tar\.gz$/) {
1225: $version = $1;
1226: } else {
1227: next;
1228: }
1229: if (ref($stdsizes) eq 'HASH') {
1230: if ($version eq 'current') {
1.45.2.16 raeburn 1231: my @stats = stat("$instdir/$file");
1.1 raeburn 1232: $localcurrent = $stats[7];
1.4 raeburn 1233: if ($localcurrent == $stdsizes->{$production}) {
1.1 raeburn 1234: $needs_download = 0;
1235: $filetouse = $file;
1236: }
1237: } elsif ($version eq 'testing') {
1.45.2.16 raeburn 1238: my @stats = stat("$instdir/$file");
1.1 raeburn 1239: $localtesting = $stats[7];
1.4 raeburn 1240: if ($localtesting == $stdsizes->{$testing}) {
1.1 raeburn 1241: $needs_download = 0;
1242: $filetouse = $file;
1243: }
1244: }
1245: }
1246: $tarball{$version} = $file;
1247: push(@lcdownloads,$version);
1248: }
1249: if ($needs_download) {
1250: if (@lcdownloads > 0) {
1251: foreach my $version (@lcdownloads) {
1.45.2.16 raeburn 1252: my @stats = stat("$instdir/$tarball{$version}");
1.1 raeburn 1253: my $mtime = $stats[9];
1254: $localsize{$version} = $stats[7];
1255: if ($mtime) {
1256: push(@{$bymodtime{$mtime}},$version);
1257: }
1258: if ($localsize{$version}) {
1259: push(@{$bysize{$localsize{$version}}},$version);
1260: }
1261: }
1262: if ($testing) {
1263: if (exists($localsize{$testing})) {
1264: if ($stdsizes->{$testing} == $localsize{$testing}) {
1265: $needs_download = 0;
1266: $filetouse = 'loncapa-'.$testing.'.tar.gz';
1267: }
1268: }
1269: }
1270: if ($needs_download) {
1271: if ($production) {
1272: if (exists($localsize{$production})) {
1273: if ($stdsizes->{$production} == $localsize{$production}) {
1274: $needs_download = 0;
1275: $filetouse = 'loncapa-'.$production.'.tar.gz';
1276: }
1277: }
1278: }
1279: }
1280: if ($needs_download) {
1281: my @sorted = sort { $b <=> $a } keys(%bymodtime);
1282: my $newest = $sorted[0];
1283: if (ref($bymodtime{$newest}) eq 'ARRAY') {
1284: $downloadstatus =
1.45.2.16 raeburn 1285: "Latest LON-CAPA source download in $instdir is: ".
1.1 raeburn 1286: join(',',@{$bymodtime{$newest}})." (downloaded ".
1287: localtime($newest).")\n";
1288: }
1289: } else {
1290: $downloadstatus =
1.45.2.16 raeburn 1291: "The $instdir directory already contains the latest LON-CAPA version:".
1.1 raeburn 1292: "\n".$filetouse."\n"."which can be used for installation.\n";
1293: }
1294: } else {
1.45.2.16 raeburn 1295: $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 1296: }
1297: }
1298: } else {
1.45.2.16 raeburn 1299: $downloadstatus = "Could not open $instdir directory to look for existing downloads of LON-CAPA source code.\n";
1.1 raeburn 1300: }
1301: return ($needs_download,$downloadstatus,$filetouse,$production,$testing);
1302: }
1303:
1304: sub check_mysql_setup {
1.45.2.12 raeburn 1305: my ($instdir,$dsn,$distro) = @_;
1306: my ($mysqlsetup,$has_pass,$mysql_unix_socket,$mysql_has_wwwuser);
1.1 raeburn 1307: my $dbh = DBI->connect($dsn,'root','',{'PrintError'=>0});
1.45.2.19 raeburn 1308: my ($mysqlversion,$mysqlminorversion,$mysqlsubver,$mysqlname) = &get_mysql_version();
1309: if (($mysqlname =~ /^MariaDB/i) && (($mysqlversion == 10 && $mysqlminorversion >= 4) || ($mysqlversion >= 11))) {
1.45.2.9 raeburn 1310: if ($dbh) {
1311: my $sth = $dbh->prepare("SELECT Priv FROM mysql.global_priv WHERE (User = 'root' AND Host ='localhost')");
1312: $sth->execute();
1313: while (my $priv = $sth->fetchrow_array) {
1.45.2.14 raeburn 1314: if ($priv =~ /unix_socket/) {
1.45.2.9 raeburn 1315: $mysql_unix_socket = 1;
1316: last;
1317: }
1318: }
1319: $sth->finish();
1320: if ($mysql_unix_socket) {
1321: print_and_log(&mt('MariaDB using unix_socket for root access from localhost.')."\n");
1322: $mysqlsetup = 'rootok';
1.45.2.12 raeburn 1323: $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.45.2.9 raeburn 1324: return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser,$mysql_unix_socket);
1325: }
1326: }
1327: }
1.1 raeburn 1328: if ($dbh) {
1.45.2.12 raeburn 1329: $mysqlsetup = 'noroot';
1.45.2.19 raeburn 1330: if (($mysqlname !~ /^MariaDB/i) && (($mysqlversion == 5 && $mysqlminorversion >= 7) || ($mysqlversion >= 6))) {
1.45.2.12 raeburn 1331: my $sth = $dbh->prepare("SELECT plugin from mysql.user where User='root'");
1332: $sth->execute();
1333: while (my $priv = $sth->fetchrow_array) {
1334: if ($priv =~ /auth_socket/) {
1335: $mysql_unix_socket = 1;
1336: last;
1337: }
1338: }
1339: $sth->finish();
1340: if ($mysql_unix_socket) {
1341: print_and_log(&mt('MySQL using unix_socket for root access from localhost.')."\n");
1342: $mysqlsetup = 'rootok';
1343: $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1344: return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser,$mysql_unix_socket);
1345: }
1.45.2.14 raeburn 1346: }
1.1 raeburn 1347: } elsif ($DBI::err =~ /1045/) {
1348: $has_pass = 1;
1.34 raeburn 1349: } elsif ($distro =~ /^ubuntu(\d+)$/) {
1350: my $version = $1;
1351: if ($1 > 12) {
1352: print_and_log(&mt('Restarting mysql, please be patient')."\n");
1353: if (open (PIPE, "service mysql restart 2>&1 |")) {
1354: while (<PIPE>) {
1355: print $_;
1356: }
1357: close(PIPE);
1358: }
1359: $dbh = DBI->connect($dsn,'root','',{'PrintError'=>0});
1360: if ($dbh) {
1361: $mysqlsetup = 'noroot';
1.45.2.12 raeburn 1362: $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.34 raeburn 1363: } elsif ($DBI::err =~ /1045/) {
1364: $has_pass = 1;
1365: } else {
1366: $mysqlsetup = 'needsrestart';
1.45.2.16 raeburn 1367: $mysql_has_wwwuser = &check_mysql_wwwuser();
1.34 raeburn 1368: return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser);
1369: }
1370: }
1.1 raeburn 1371: }
1372: if ($has_pass) {
1373: print &mt('You have already set a root password for the MySQL database.')."\n";
1374: my $currpass = &get_mysql_password(&mt('Please enter the password now'));
1375: $dbh = DBI->connect($dsn,'root',$currpass,{'PrintError'=>0});
1376: if ($dbh) {
1377: $mysqlsetup = 'rootok';
1378: print_and_log(&mt('Password accepted.')."\n");
1.45.2.12 raeburn 1379: $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.1 raeburn 1380: } else {
1381: $mysqlsetup = 'rootfail';
1382: print_and_log(&mt('Problem accessing MySQL.')."\n");
1383: if ($DBI::err =~ /1045/) {
1384: print_and_log(&mt('Perhaps the password was incorrect?')."\n");
1385: print &mt('Try again?').' ';
1386: $currpass = &get_mysql_password(&mt('Re-enter password now'));
1387: $dbh = DBI->connect($dsn,'root',$currpass,{'PrintError'=>0});
1388: if ($dbh) {
1389: $mysqlsetup = 'rootok';
1390: print_and_log(&mt('Password accepted.')."\n");
1.45.2.12 raeburn 1391: $mysql_has_wwwuser = &check_mysql_wwwuser($dbh);
1.1 raeburn 1392: } else {
1393: if ($DBI::err =~ /1045/) {
1394: print_and_log(&mt('Incorrect password.')."\n");
1395: }
1.45.2.16 raeburn 1396: $mysql_has_wwwuser = &check_mysql_wwwuser();
1.1 raeburn 1397: }
1398: }
1399: }
1.34 raeburn 1400: } elsif ($mysqlsetup ne 'noroot') {
1.1 raeburn 1401: print_and_log(&mt('Problem accessing MySQL.')."\n");
1402: $mysqlsetup = 'rootfail';
1.45.2.16 raeburn 1403: $mysql_has_wwwuser = &check_mysql_wwwuser();
1.1 raeburn 1404: }
1.34 raeburn 1405: return ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser);
1.1 raeburn 1406: }
1407:
1408: sub check_mysql_wwwuser {
1.45.2.12 raeburn 1409: my ($dbh) = @_;
1.1 raeburn 1410: my $mysql_wwwuser;
1.45.2.12 raeburn 1411: if ($dbh) {
1412: $mysql_wwwuser = $dbh->selectrow_array("SELECT COUNT(User) FROM mysql.user WHERE (User = 'www' AND Host ='localhost')");
1413: } else {
1414: my $dbhn = DBI->connect("DBI:mysql:database=information_schema",'www','localhostkey',
1415: {PrintError => +0}) || return;
1416: if ($dbhn) {
1417: $mysql_wwwuser = 1;
1418: $dbhn->disconnect;
1419: }
1.1 raeburn 1420: }
1421: return $mysql_wwwuser;
1422: }
1423:
1424: sub check_loncapa_mysqldb {
1425: my ($dbh) = @_;
1426: my $has_lcdb;
1427: if (ref($dbh)) {
1428: my $sth = $dbh->prepare("SHOW DATABASES");
1429: $sth->execute();
1430: while (my $dbname = $sth->fetchrow_array) {
1431: if ($dbname eq 'loncapa') {
1432: $has_lcdb = 1;
1433: last;
1434: }
1435: }
1436: $sth->finish();
1437: }
1438: return $has_lcdb;
1439: }
1440:
1441: sub get_pathto_iptables {
1442: my $iptables;
1443: if (-e '/sbin/iptables') {
1444: $iptables = '/sbin/iptables';
1445: } elsif (-e '/usr/sbin/iptables') {
1446: $iptables = '/usr/sbin/iptables';
1447: } else {
1448: print &mt('Unable to find iptables command.')."\n";
1449: }
1450: return $iptables;
1451: }
1452:
1453: sub firewall_is_active {
1454: if (-e '/proc/net/ip_tables_names') {
1.45.2.19 raeburn 1455: my $status;
1.45.2.1 raeburn 1456: if (open(PIPE,'cat /proc/net/ip_tables_names |grep filter |')) {
1.45.2.19 raeburn 1457: $status = <PIPE>;
1.45.2.1 raeburn 1458: close(PIPE);
1459: chomp($status);
1460: if ($status eq 'filter') {
1461: return 1;
1462: }
1463: }
1.45.2.19 raeburn 1464: unless ($status) {
1465: if (open(PIPE,'nft list tables |')) {
1466: while(<PIPE>) {
1467: chomp();
1468: if (/filter$/) {
1469: $status = 1;
1470: last;
1471: }
1472: }
1473: close(PIPE);
1474: if ($status) {
1475: return 1;
1476: }
1477: }
1478: }
1.1 raeburn 1479: }
1.45.2.1 raeburn 1480: return 0;
1.1 raeburn 1481: }
1482:
1483: sub get_fw_chains {
1.5 raeburn 1484: my ($iptables,$distro) = @_;
1.1 raeburn 1485: my @fw_chains;
1486: my $suse_config = "/etc/sysconfig/SuSEfirewall2";
1487: my $ubuntu_config = "/etc/ufw/ufw.conf";
1488: if (-e $suse_config) {
1489: push(@fw_chains,'input_ext');
1490: } else {
1491: my @posschains;
1492: if (-e $ubuntu_config) {
1493: @posschains = ('ufw-user-input','INPUT');
1.5 raeburn 1494: } elsif ($distro =~ /^debian5/) {
1495: @posschains = ('INPUT');
1.45.2.1 raeburn 1496: } elsif ($distro =~ /^(suse|sles)(\d+)/) {
1497: @posschains = ('IN_public');
1.1 raeburn 1498: } else {
1499: @posschains = ('RH-Firewall-1-INPUT','INPUT');
1500: if (!-e '/etc/sysconfig/iptables') {
1501: if (!-e '/var/lib/iptables') {
1502: print &mt('Unable to find iptables file containing static definitions.')."\n";
1503: }
1504: push(@fw_chains,'RH-Firewall-1-INPUT');
1505: }
1506: }
1507: if ($iptables eq '') {
1508: $iptables = &get_pathto_iptables();
1509: }
1510: my %counts;
1511: if (open(PIPE,"$iptables -L -n |")) {
1512: while(<PIPE>) {
1513: foreach my $chain (@posschains) {
1514: if (/(\Q$chain\E)/) {
1515: $counts{$1} ++;
1516: }
1517: }
1518: }
1519: close(PIPE);
1520: }
1521: foreach my $fw_chain (@posschains) {
1522: if ($counts{$fw_chain}) {
1523: unless(grep(/^\Q$fw_chain\E$/,@fw_chains)) {
1524: push(@fw_chains,$fw_chain);
1525: }
1526: }
1527: }
1528: }
1529: return @fw_chains;
1530: }
1531:
1532: sub firewall_is_port_open {
1533: my ($iptables,$fw_chain,$port) = @_;
1534: # returns 1 if the firewall port is open, 0 if not.
1535: #
1536: # check if firewall is active or installed
1537: return if (! &firewall_is_active());
1538: my $count = 0;
1539: if (open(PIPE,"$iptables -L $fw_chain -n |")) {
1540: while(<PIPE>) {
1541: if (/tcp dpt\:\Q$port\E/) {
1542: $count ++;
1543: last;
1544: }
1545: }
1546: close(PIPE);
1547: } else {
1548: print &mt('Firewall status not checked: unable to run [_1].','iptables -L')."\n";
1549: }
1550: return $count;
1551: }
1552:
1553: sub get_mysql_password {
1554: my ($prompt) = @_;
1555: local $| = 1;
1556: print $prompt.': ';
1557: my $newpasswd = '';
1558: ReadMode 'raw';
1559: my $key;
1560: while(ord($key = ReadKey(0)) != 10) {
1561: if(ord($key) == 127 || ord($key) == 8) {
1562: chop($newpasswd);
1563: print "\b \b";
1564: } elsif(!ord($key) < 32) {
1565: $newpasswd .= $key;
1566: print '*';
1567: }
1568: }
1569: ReadMode 'normal';
1570: print "\n";
1571: return $newpasswd;
1572: }
1573:
1574: sub check_SuSEfirewall2_setup {
1575: my ($instdir) = @_;
1576: my $need_override = 1;
1.9 raeburn 1577: if ((-e "/etc/insserv/overrides/SuSEfirewall2_setup") && (-e "$instdir/sles-suse/SuSEfirewall2_setup")) {
1578: if (open(PIPE, "diff --brief $instdir/sles-suse/SuSEfirewall2_setup /etc/insserv/overrides/SuSEfirewall2_setup |")) {
1.1 raeburn 1579: my $diffres = <PIPE>;
1580: close(PIPE);
1581: chomp($diffres);
1582: unless ($diffres) {
1583: $need_override = 0;
1584: }
1585: }
1586: }
1587: return $need_override;
1588: }
1589:
1590: sub download_versionslist {
1591: my ($production,$testing,%sizes);
1592: if (-e "latest.txt") {
1593: unlink("latest.txt");
1594: }
1595: my $rtncode = system("wget http://install.loncapa.org/versions/latest.txt ".
1596: "> /dev/null 2>&1");
1597: if (!$rtncode) {
1598: if (open(my $fh,"<latest.txt")) {
1599: my @info = <$fh>;
1600: close($fh);
1601: foreach my $line (@info) {
1602: chomp();
1603: if ($line =~ /^\QLATEST-IS: \E([\w\-.]+):(\d+)$/) {
1604: $production = $1;
1605: $sizes{$1} = $2;
1606: } elsif ($line =~ /^LATEST-TESTING-IS: \E([\w\-.]+):(\d+)$/) {
1607: $testing = $1;
1608: $sizes{$1} = $2;
1609: }
1610: }
1611: }
1612: }
1613: return ($production,$testing,\%sizes);
1614: }
1615:
1616: #
1617: # End helper routines.
1618: # Main script starts here
1619: #
1620:
1621: print "
1622: ********************************************************************
1623:
1624: ".&mt('Welcome to LON-CAPA')."
1625:
1626: ".&mt('This script will configure your system for installation of LON-CAPA.')."
1627:
1628: ********************************************************************
1629:
1630: ".&mt('The following actions are available:')."
1631:
1.4 raeburn 1632: ".&mt('1.')." ".&mt('Create the www user/group.')."
1.1 raeburn 1633: ".&mt('This is the user/group ownership under which Apache child processes run.')."
1634: ".&mt('It also owns most directories within the /home/httpd directory.')."
1635: ".&mt('This directory is where most LON-CAPA files and directories are stored.')."
1.4 raeburn 1636: ".&mt('2.')." ".&mt('Install the package LON-CAPA uses to authenticate users.')."
1637: ".&mt('3.')." ".&mt('Set-up the MySQL database.')."
1638: ".&mt('4.')." ".&mt('Set-up MySQL permissions.')."
1639: ".&mt('5.')." ".&mt('Configure Apache web server.')."
1.45.2.20 raeburn 1640: ".&mt('6.')." ".&mt('Configure systemd security settings for Apache web server.')."
1641: ".&mt('7.')." ".&mt('Configure start-up of services.')."
1642: ".&mt('8.')." ".&mt('Check firewall settings.')."
1643: ".&mt('9.')." ".&mt('Stop services not used by LON-CAPA,')."
1.1 raeburn 1644: ".&mt('i.e., services for a print server: [_1] daemon.',"'cups'")."
1.45.2.20 raeburn 1645: ".&mt('10.')." ".&mt('Download LON-CAPA source code in readiness for installation.')."
1.1 raeburn 1646:
1647: ".&mt('Typically, you will run this script only once, when you first install LON-CAPA.')."
1648:
1649: ".&mt('The script will analyze your system to determine which actions are recommended.')."
1650: ".&mt('The script will then prompt you to choose the actions you would like taken.')."
1651:
1652: ".&mt('For each the recommended action will be selected if you hit Enter/Return.')."
1653: ".&mt('To override the default, type the lower case option from the two options listed.')."
1654: ".&mt('So, if the default is "yes", ~[Y/n~] will be shown -- type n to override.')."
1655: ".&mt('Whereas if the default is "no", ~[y/N~] will be shown -- type y to override.')."
1656:
1657: ".&mt('To accept the default, simply hit Enter/Return on your keyboard.')."
1658: ".&mt('Otherwise type: y or n then hit the Enter/Return key.')."
1659:
1660: ".&mt('Once a choice has been entered for all nine actions, required changes will be made.')."
1661: ".&mt('Feedback will be displayed on screen, and also stored in: [_1].','loncapa_install.log')."
1662:
1663: ".&mt('Continue? ~[Y/n~] ');
1664:
1665: my $go_on = &get_user_selection(1);
1666: if (!$go_on) {
1667: exit;
1668: }
1669:
1670: my $instdir = `pwd`;
1671: chomp($instdir);
1672:
1673: my %callsub;
1.45.2.20 raeburn 1674: my @actions = ('wwwuser','pwauth','mysql','mysqlperms','apache','systemd',
1.1 raeburn 1675: 'runlevels','firewall','stopsrvcs','download');
1676: my %prompts = &texthash(
1677: wwwuser => "Create the 'www' user?",
1678: pwauth => 'Install the package LON-CAPA uses to authenticate users?',
1679: mysql => 'Set-up the MySQL database?',
1680: mysqlperms => 'Set-up MySQL permissions?',
1681: apache => 'Configure Apache web server?',
1.45.2.20 raeburn 1682: systemd => 'Configure systemd security settings for Apache web server?',
1.1 raeburn 1683: runlevels => 'Set overrides for start-up order of services?',
1684: firewall => 'Configure firewall settings for Apache',
1685: stopsrvcs => 'Stop extra services not required on a LON-CAPA server?',
1686: download => 'Download LON-CAPA source code in readiness for installation?',
1687: );
1688:
1689: print "\n".&mt('Checking system status ...')."\n";
1690:
1691: my $dsn = "DBI:mysql:database=mysql";
1.45.2.22 raeburn 1692: my ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart,
1.45.2.9 raeburn 1693: $recommended,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,$downloadstatus,
1694: $filetouse,$production,$testing,$apachefw,$uses_systemctl) = &check_required($instdir,$dsn);
1.1 raeburn 1695: if ($distro eq '') {
1696: print "\n".&mt('Linux distribution could not be verified as a supported distribution.')."\n".
1697: &mt('The following are supported: [_1].',
1698: 'CentOS, RedHat Enterprise, Fedora, Scientific Linux, '.
1.45.2.3 raeburn 1699: 'Oracle Linux, openSuSE, SLES, Ubuntu LTS, Debian')."\n\n".
1.1 raeburn 1700: &mt('Stopping execution.')."\n";
1701: exit;
1702: }
1.34 raeburn 1703: if ($mysqlrestart) {
1704: print "\n".&mt('The mysql daemon needs to be restarted using the following command:')."\n".
1705: $mysqlrestart."\n\n".
1706: &mt('Stopping execution of install.pl script.')."\n".
1707: &mt('Please run the install.pl script again, once you have restarted mysql.')."\n";
1708: exit;
1709: }
1.6 raeburn 1710: if ($localecmd ne '') {
1.45.2.22 raeburn 1711: 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";
1712: if ($langcmd ne '') {
1713: print &mt('Use the following command(s) or action(s) to install a required language package.')."\n\n".
1714: "$langcmd\n";
1715: }
1716: 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 1717: $localecmd."\n\n".
1718: &mt('Stopping execution.')."\n";
1719: exit;
1720: }
1.1 raeburn 1721: if (!$gotprereqs) {
1.12 raeburn 1722: print "\n".&mt('The LONCAPA-prerequisites package is not installed.')."\n".
1.1 raeburn 1723: &mt('The following command can be used to install the package (and dependencies):')."\n\n".
1724: $updatecmd."\n\n";
1725: if ($installnow eq '') {
1726: print &mt('Stopping execution.')."\n";
1727: exit;
1728: } else {
1729: print &mt('Run command? ~[Y/n~]');
1730: my $install_prereq = &get_user_selection(1);
1731: if ($install_prereq) {
1732: if (open(PIPE,'|-',$installnow)) {
1733: close(PIPE);
1734: $gotprereqs = &check_prerequisites($packagecmd,$distro);
1735: if (!$gotprereqs) {
1.12 raeburn 1736: print &mt('The LONCAPA-prerequisites package is not installed.')."\n".
1.1 raeburn 1737: &mt('Stopping execution.')."\n";
1738: exit;
1739: } else {
1.45.2.22 raeburn 1740: ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,
1.45.2.9 raeburn 1741: $mysqlrestart,$recommended,$dbh,$has_pass,$mysql_unix_socket,
1742: $has_lcdb,$downloadstatus,$filetouse,$production,$testing,$apachefw,
1743: $uses_systemctl) = &check_required($instdir,$dsn);
1.1 raeburn 1744: }
1745: } else {
1.12 raeburn 1746: print &mt('Failed to run command to install LONCAPA-prerequisites')."\n";
1.1 raeburn 1747: exit;
1748: }
1749: } else {
1750: print &mt('Stopping execution.')."\n";
1751: exit;
1752: }
1753: }
1754: }
1755: unless (ref($recommended) eq 'HASH') {
1756: print "\n".&mt('An error occurred determining which actions are recommended.')."\n\n".
1757: &mt('Stopping execution.')."\n";
1758: exit;
1759: }
1760:
1761: print "\n";
1762: my $num = 0;
1763: foreach my $action (@actions) {
1764: $num ++;
1765: my ($yesno,$defaultrun);
1766: if (ref($recommended) eq 'HASH') {
1.4 raeburn 1767: if (($action eq 'runlevels') || ($action eq 'stopsrvcs')) {
1.1 raeburn 1768: $yesno = '[y/N]';
1769: if (ref($recommended->{$action}) eq 'HASH') {
1770: if (keys(%{$recommended->{$action}}) > 0) {
1771: $yesno = &mt('~[Y/n~]');
1772: $defaultrun = 1;
1773: }
1774: }
1775: } else {
1776: if ($action eq 'download') {
1777: if ($downloadstatus) {
1778: print "\n$downloadstatus\n";
1779: }
1780: }
1781: if ($recommended->{$action}) {
1782: $yesno = mt('~[Y/n~]');
1783: $defaultrun = 1;
1784: } else {
1785: $yesno = &mt('~[y/N~]');
1786: }
1787: }
1788: print $num.'. '.$prompts{$action}." $yesno ";
1789: $callsub{$action} = &get_user_selection($defaultrun);
1790: }
1791: }
1792:
1793: my $lctarball = 'loncapa-current.tar.gz';
1794: my $sourcetarball = $lctarball;
1795: if ($callsub{'download'}) {
1796: my ($production,$testing,$sizes) = &download_versionslist();
1.45.2.16 raeburn 1797: my $homedir = '/root';
1798: if ($distro =~ /^ubuntu/) {
1799: if ($instdir ne $homedir) {
1800: ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});
1801: }
1802: }
1.1 raeburn 1803: if ($production && $testing) {
1804: if ($production ne $testing) {
1805: print &mt('Two recent LON-CAPA releases are available: ')."\n".
1.3 raeburn 1806: &mt('1.').' '.&mt('A production release - version: [_1].',$production)."\n".
1807: &mt('2.').' '.&mt('A testing release - version: [_1].',$testing)."\n\n".
1.45.2.16 raeburn 1808: &mt("After download, the tar.gz file will be extracted into $homedir")."\n\n".
1809: &mt("Download the production release into $instdir? ~[Y/n~]");
1.1 raeburn 1810: if (&get_user_selection(1)) {
1.4 raeburn 1811: $sourcetarball = 'loncapa-'.$production.'.tar.gz';
1.45.2.16 raeburn 1812: print "$sourcetarball will be downloaded into $instdir\n";
1.1 raeburn 1813: } else {
1814: print "\n".&mt('Download the testing release? ~[Y/n~]');
1815: if (&get_user_selection(1)) {
1.4 raeburn 1816: $sourcetarball = 'loncapa-'.$testing.'.tar.gz';
1.45.2.16 raeburn 1817: print "$sourcetarball will be downloaded into $instdir\n";
1818: } else {
1819: $callsub{'download'} = 0;
1.1 raeburn 1820: }
1821: }
1822: }
1823: } elsif ($production) {
1824: print &mt('The most recent LON-CAPA release is version: [_1].',$production)."\n".
1.45.2.16 raeburn 1825: &mt("After download, the tar.gz file will be extracted into $homedir")."\n\n".
1826: &mt("Download the production release into $instdir? ~[Y/n~]");
1.1 raeburn 1827: if (&get_user_selection(1)) {
1.20 raeburn 1828: $sourcetarball = 'loncapa-'.$production.'.tar.gz';
1.45.2.16 raeburn 1829: print "$sourcetarball will be downloaded into $instdir\n";
1830: } else {
1831: $callsub{'download'} = 0;
1.1 raeburn 1832: }
1833: }
1834: } elsif ($filetouse ne '') {
1835: $sourcetarball = $filetouse;
1836: }
1837:
1838: print_and_log("\n");
1839:
1840: # Each action: report if skipping, or perform action and provide feedback.
1841: if ($callsub{'wwwuser'}) {
1842: &setup_www();
1843: } else {
1844: &print_and_log(&mt('Skipping creation of user [_1].',"'www'")."\n");
1845: }
1846:
1847: if ($callsub{'pwauth'}) {
1.4 raeburn 1848: &build_and_install_mod_auth_external($instdir);
1.1 raeburn 1849: } else {
1850: &print_and_log(&mt('Skipping [_1] installation.',"'pwauth'")."\n");
1851: }
1852:
1853: if ($callsub{'mysql'}) {
1854: if ($dbh) {
1.45.2.9 raeburn 1855: &setup_mysql($callsub{'mysqlperms'},$dbh,$has_pass,
1.45.2.15 raeburn 1856: $mysql_unix_socket,$has_lcdb,$distro);
1.1 raeburn 1857: } else {
1858: print &mt('Unable to configure MySQL because access is denied.')."\n";
1859: }
1860: } else {
1861: &print_and_log(&mt('Skipping configuration of MySQL.')."\n");
1862: if ($callsub{'mysqlperms'}) {
1863: if ($dbh) {
1.45.2.9 raeburn 1864: &setup_mysql_permissions($dbh,$has_pass,$mysql_unix_socket);
1.1 raeburn 1865: } else {
1866: print &mt('Unable to configure MySQL because access is denied.')."\n";
1867: }
1868: } else {
1869: &print_and_log(&mt('Skipping MySQL permissions setup.')."\n");
1870: }
1871: }
1872:
1873: if ($dbh) {
1874: if (!$dbh->disconnect) {
1875: &print_and_log(&mt('Failed to disconnect from MySQL:')."\n".
1876: $dbh->errstr);
1877: }
1878: }
1879:
1880: if ($callsub{'apache'}) {
1881: if ($distro =~ /^(suse|sles)/) {
1.45.2.1 raeburn 1882: ©_apache2_suseconf($instdir,$distro);
1.1 raeburn 1883: } elsif ($distro =~ /^(debian|ubuntu)/) {
1.28 raeburn 1884: ©_apache2_debconf($instdir,$distro);
1.1 raeburn 1885: } else {
1.14 raeburn 1886: ©_httpd_conf($instdir,$distro);
1.45.2.5 raeburn 1887: ©_mpm_conf($instdir,$distro);
1.1 raeburn 1888: }
1889: } else {
1890: print_and_log(&mt('Skipping configuration of Apache web server.')."\n");
1891: }
1892:
1.45.2.20 raeburn 1893: if ($callsub{'systemd'}) {
1894: &check_systemd_update($distro);
1895: } else {
1896: print_and_log('Skipping systemd configuration update for web server');
1897: }
1898:
1.1 raeburn 1899: if ($callsub{'runlevels'}) {
1900: my $count = 0;
1901: if (ref($recommended) eq 'HASH') {
1902: if (ref($recommended->{'runlevels'}) eq 'HASH') {
1903: foreach my $type (keys(%{$recommended->{'runlevels'}})) {
1904: next if ($type eq 'insserv');
1905: $count ++;
1906: my $command = $recommended->{'runlevels'}{$type};
1907: if ($command ne '') {
1908: print_and_log(&mt('Runlevel update command run: [_1].',$command)."\n");
1909: system($command);
1910: }
1911: }
1912: if (!$count) {
1913: print_and_log(&mt('No runlevel updates required.')."\n");
1914: }
1915: }
1916: }
1.45.2.1 raeburn 1917: if ($distro =~ /^(suse|sles)(\d+)/) {
1918: unless(($1 eq 'sles') && ($2 >= 15)) {
1919: &update_SuSEfirewall2_setup($instdir);
1920: }
1.11 raeburn 1921: }
1.1 raeburn 1922: } else {
1923: &print_and_log(&mt('Skipping setting override for start-up order of services.')."\n");
1924: }
1925:
1926: if ($callsub{'firewall'}) {
1.45.2.3 raeburn 1927: my ($firewalld,$zone) = &uses_firewalld($distro);
1928: if ($firewalld) {
1.45.2.1 raeburn 1929: my (%current,%added);
1.45.2.3 raeburn 1930: if (open(PIPE,"firewall-cmd --permanent --zone=$zone --list-services |")) {
1.45.2.1 raeburn 1931: my $svc = <PIPE>;
1932: close(PIPE);
1933: chomp($svc);
1934: map { $current{$_} = 1; } (split(/\s+/,$svc));
1935: }
1936: foreach my $service ('http','https') {
1937: unless ($current{$service}) {
1.45.2.3 raeburn 1938: if (open(PIPE,"firewall-cmd --permanent --zone=$zone --add-service=$service |")) {
1.45.2.1 raeburn 1939: my $result = <PIPE>;
1940: if ($result =~ /^success/) {
1941: $added{$service} = 1;
1942: }
1943: }
1944: }
1945: }
1946: if (keys(%added) > 0) {
1947: print &mt('Firewall configured to allow access for: [_1].',
1948: join(', ',sort(keys(%added))))."\n";
1.45.2.13 raeburn 1949: system('firewall-cmd --reload');
1.45.2.1 raeburn 1950: }
1951: if ($current{'http'} || $current{'https'}) {
1952: print &mt('Firewall already configured to allow access for:[_1].',
1953: (($current{'http'})? ' http':'').(($current{'https'})? ' https':''))."\n";
1954: }
1955: unless ($current{'ssh'}) {
1.45.2.13 raeburn 1956: print &mt('If you would like to allow access to ssh from outside, use the commands:')."\n".
1957: "firewall-cmd --permanent --zone=$zone --add-service=ssh\n".
1958: "firewall-cmd --reload\n";
1.45.2.1 raeburn 1959: }
1960: } elsif ($distro =~ /^(suse|sles)/) {
1.5 raeburn 1961: print &mt('Use [_1] to configure the firewall to allow access for [_2].',
1962: 'yast -- Security and Users -> Firewall -> Interfaces',
1.45.2.1 raeburn 1963: 'ssh, http, https')."\n";
1.5 raeburn 1964: } elsif ($distro =~ /^(debian|ubuntu)(\d+)/) {
1965: if (($1 eq 'ubuntu') || ($2 > 5)) {
1966: print &mt('Use [_1] to configure the firewall to allow access for [_2].',
1967: 'ufw','ssh, http, https')."\n";
1968: } else {
1969: my $fwadded = &get_iptables_rules($distro,$instdir,$apachefw);
1970: if ($fwadded) {
1971: print &mt('Enable firewall? ~[Y/n~]');
1972: my $enable_iptables = &get_user_selection(1);
1973: if ($enable_iptables) {
1974: system('/etc/network/if-pre-up.d/iptables');
1975: print &mt('Firewall enabled using rules defined in [_1].',
1976: '/etc/iptables.loncapa.rules');
1977: }
1978: }
1979: }
1.45.2.3 raeburn 1980: } elsif ($distro =~ /^(scientific|oracle)/) {
1.11 raeburn 1981: print &mt('Use [_1] to configure the firewall to allow access for [_2].',
1982: 'system-config-firewall-tui -- Customize',
1983: 'ssh, http')."\n";
1.1 raeburn 1984: } else {
1.45.2.3 raeburn 1985: my $version;
1.45.2.18 raeburn 1986: if ($distro =~ /^(redhat|centos|rocky|alma)(\d+)/) {
1.45.2.3 raeburn 1987: $version = $1;
1988: }
1989: if ($version > 5) {
1990: print &mt('Use [_1] to configure the firewall to allow access for [_2].',
1991: 'system-config-firewall-tui -- Customize',
1992: 'ssh, http')."\n";
1993: } else {
1994: print &mt('Use [_1] to configure the firewall to allow access for [_2].',
1995: 'setup -- Firewall configuration -> Customize',
1996: 'ssh, http, https')."\n";
1997: }
1.1 raeburn 1998: }
1999: } else {
1.5 raeburn 2000: &print_and_log(&mt('Skipping Firewall configuration.')."\n");
1.1 raeburn 2001: }
2002:
2003: if ($callsub{'stopsrvcs'}) {
1.45 raeburn 2004: &kill_extra_services($distro,$recommended->{'stopsrvcs'},$uses_systemctl);
1.1 raeburn 2005: } else {
1.10 raeburn 2006: &print_and_log(&mt('Skipping stopping unnecessary service ([_1] daemons).',"'cups','memcached'")."\n");
1.1 raeburn 2007: }
2008:
2009: my ($have_tarball,$updateshown);
2010: if ($callsub{'download'}) {
2011: ($have_tarball,$updateshown) = &download_loncapa($instdir,$sourcetarball);
2012: } else {
2013: print_and_log(&mt('Skipping download of LON-CAPA tar file.')."\n\n");
2014: print &mt('LON-CAPA is available for download from: [_1]',
2015: 'http://install.loncapa.org/')."\n";
2016: if (!-e '/etc/loncapa-release') {
1.45.2.19 raeburn 2017: &print_and_log(&mt('LON-CAPA is not yet installed on your system.')."\n\n");
2018: unless ($filetouse) {
2019: &print_and_log(&mt('You may retrieve the source for LON-CAPA by executing:')."\n".
2020: "wget http://install.loncapa.org/versions/$lctarball\n");
2021: }
1.1 raeburn 2022: } else {
2023: my $currentversion;
2024: if (open(my $fh,"</etc/loncapa-release")) {
2025: my $version = <$fh>;
2026: chomp($version);
2027: if ($version =~ /^\QLON-CAPA release \E([\w\-.]+)$/) {
2028: $currentversion = $1;
2029: }
2030: }
2031: if ($currentversion ne '') {
2032: print &mt('Version of LON-CAPA currently installed on this server is: [_1].',
2033: $currentversion),"\n";
2034: if ($production) {
2035: print &mt('The latest production release of LON-CAPA is [_1].',$production)."\n";
2036: }
2037: if ($testing) {
2038: print &mt('The latest testing release of LON-CAPA is [_1].',$testing)."\n";
2039: }
2040: }
2041: }
2042: if ($filetouse ne '') {
2043: $have_tarball = 1;
2044: }
2045: }
2046:
2047: print "\n".&mt('Requested configuration complete.')."\n\n";
2048: if ($have_tarball && !$updateshown) {
2049: my ($lcdir) = ($sourcetarball =~ /^([\w.\-]+)\.tar.gz$/);
1.45.2.16 raeburn 2050: if ($lcdir eq 'loncapa-current') {
2051: $lcdir = "loncapa-X.Y.Z (X.Y.Z should correspond to a version number like '2.11.3')";
2052: }
1.45.2.14 raeburn 2053: my ($apachename,$lc_uses_systemctl,$uses_sudo);
1.45.2.12 raeburn 2054: if ($distro =~ /^(suse|sles|debian|ubuntu)([\d.]+)/) {
2055: if (($1 eq 'suse') && ($2 < 10)) {
2056: $apachename = 'apache';
2057: } else {
2058: $apachename = 'apache2';
2059: }
2060: } else {
2061: $apachename = 'httpd';
2062: }
2063: if ($distro =~ /^oracle(\d+)$/) {
2064: if ($1 > 6) {
2065: $lc_uses_systemctl = 1;
2066: }
1.45.2.18 raeburn 2067: } elsif ($distro =~ /^(?:rhes|centos|rocky|alma)(\d+)/) {
1.45.2.12 raeburn 2068: if ($1 > 7) {
2069: $lc_uses_systemctl = 1;
2070: }
2071: } elsif ($distro =~ /^ubuntu(\d+)$/) {
2072: if ($1 > 16) {
2073: $lc_uses_systemctl = 1;
2074: }
2075: $uses_sudo = 1;
1.45.2.19 raeburn 2076: } elsif ($distro =~ /^debian(\d+)$/) {
2077: if ($1 >= 10) {
2078: $lc_uses_systemctl = 1;
2079: }
1.45.2.12 raeburn 2080: } elsif ($distro =~ /^sles(\d+)$/) {
2081: if ($1 > 12) {
2082: $lc_uses_systemctl = 1;
2083: }
1.45.2.20 raeburn 2084: } elsif ($distro =~ /^fedora(\d+)$/) {
2085: if ($1 > 25) {
2086: $lc_uses_systemctl = 1;
2087: }
1.45.2.12 raeburn 2088: }
1.1 raeburn 2089: if (!-e '/etc/loncapa-release') {
2090: print &mt('If you are now ready to install LON-CAPA, enter the following commands:')."\n\n";
2091: } else {
1.45.2.12 raeburn 2092: my $lcstop = '/etc/init.d/loncontrol stop';
2093: if ($lc_uses_systemctl) {
2094: $lcstop = 'systemctl stop loncontrol';
2095: }
2096: my $apachestop = "/etc/init.d/$apachename stop";
2097: if ($uses_systemctl) {
2098: $apachestop = "systemctl stop $apachename";
2099: }
2100: if ($uses_sudo) {
1.45.2.16 raeburn 2101: $lcstop = 'sudo '.$lcstop;
1.45.2.12 raeburn 2102: $apachestop = 'sudo '.$apachestop;
1.1 raeburn 2103: }
1.45.2.12 raeburn 2104: print &mt('If you are now ready to update LON-CAPA, enter the following commands:').
2105: "\n\n$lcstop\n$apachestop\n";
1.1 raeburn 2106: }
1.45.2.16 raeburn 2107: my ($extract,$update);
2108: my $homedir = '/root';
2109: if ($uses_sudo) {
2110: $extract = 'sudo ';
2111: $update = 'sudo ';
2112: if ($instdir ne $homedir) {
2113: ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});
2114: }
2115: }
2116: $extract .= "tar zxf $sourcetarball --directory $homedir";
2117: $update .= './UPDATE';
2118: print "$extract\n".
2119: "cd $homedir/$lcdir\n".
2120: "$update\n";
1.1 raeburn 2121: if (-e '/etc/loncapa-release') {
1.45.2.19 raeburn 2122: my $lcstart = '/etc/init.d/loncontrol start';
1.45.2.12 raeburn 2123: if ($lc_uses_systemctl) {
2124: $lcstart = '/home/httpd/perl/loncontrol start';
2125: }
2126: my $apachestart = "/etc/init.d/$apachename start";
2127: if ($uses_systemctl) {
2128: $apachestart = "systemctl start $apachename";
2129: }
2130: if ($uses_sudo) {
2131: $lcstart = 'sudo '.$lcstart;
2132: $apachestart = 'sudo '.$apachestart;
2133: }
2134: print "$lcstart\n";
2135: print "$apachestart\n";
1.1 raeburn 2136: }
2137: }
2138: exit;
2139:
2140: #
2141: # End main script
2142: #
2143:
2144: #
2145: # Routines for the actions
2146: #
2147:
2148: sub setup_www {
2149: ##
2150: ## Set up www
2151: ##
2152: print_and_log(&mt('Creating user [_1]',"'www'")."\n");
2153: # -- Add group
2154:
2155: my $status = `/usr/sbin/groupadd www`;
2156: if ($status =~ /\QGroup `www' already exists.\E/) {
2157: print &mt('Group [_1] already exists.',"'www'")."\n";
2158: } elsif ($status ne '') {
2159: print &mt('Unable to add group [_1].',"'www'")."\n";
2160: }
2161:
2162: my $gid = getgrnam('www');
2163:
2164: if (open (PIPE, "/usr/sbin/useradd -c LONCAPA -g $gid www 2>&1 |")) {
2165: $status = <PIPE>;
2166: close(PIPE);
2167: chomp($status);
2168: if ($status =~ /\QAccount `www' already exists.\E/) {
2169: print &mt('Account [_1] already exists.',"'www'")."\n";
2170: } elsif ($status ne '') {
2171: print &mt('Unable to add user [_1].',"'www'")."\n";
2172: }
2173: } else {
2174: print &mt('Unable to run command to add user [_1].',"'www'")."\n";
2175: }
2176:
2177: my $uid = &uid_of_www();
2178: if (($gid ne '') && ($uid ne '')) {
2179: if (!-e '/home/www') {
2180: mkdir('/home/www',0755);
2181: system('chown www:www /home/www');
2182: }
2183: }
2184: writelog ($status);
2185: }
2186:
2187: sub uid_of_www {
2188: my ($num) = (getpwnam('www'))[2];
2189: return $num;
2190: }
2191:
2192: sub build_and_install_mod_auth_external {
2193: my ($instdir) = @_;
2194: my $num = &uid_of_www();
2195: # Patch pwauth
2196: print_and_log(&mt('Building authentication system for LON-CAPA users.')."\n");
2197: my $patch = <<"ENDPATCH";
2198: 148c148
2199: < #define SERVER_UIDS 99 /* user "nobody" */
2200: ---
2201: > #define SERVER_UIDS $num /* user "www" */
2202: ENDPATCH
2203:
1.45.2.19 raeburn 2204: my $patch_code = <<"ENDPATCH";
2205: 127a128
2206: > #include <string.h>
2207: 214a216
2208: > #include <time.h>
2209: 566c568
2210: < check_fails()
2211: ---
2212: > int check_fails()
2213: 589c591
2214: < log_failure()
2215: ---
2216: > void log_failure()
2217: 629c631
2218: < snooze(int seconds)
2219: ---
2220: > void snooze(int seconds)
2221: 653c655
2222: < main(int argc, char **argv)
2223: ---
2224: > int main(int argc, char **argv)
2225: ENDPATCH
2226:
1.1 raeburn 2227: if (! -e "/usr/bin/patch") {
2228: print_and_log(&mt('You must install the software development tools package: [_1], when installing Linux.',"'patch'")."\n");
2229: print_and_log(&mt('Authentication installation not completed.')."\n");
2230: return;
2231: }
2232: if (&skip_if_nonempty(`cd /tmp; tar zxf $instdir/pwauth-2.2.8.tar.gz`,
2233: &mt('Unable to extract pwauth')."\n")) {
2234: return;
2235: }
2236: my $dir = "/tmp/pwauth-2.2.8";
1.45.2.19 raeburn 2237: my $patchedok;
1.1 raeburn 2238: if (open(PATCH,"| patch $dir/config.h")) {
2239: print PATCH $patch;
2240: close(PATCH);
1.45.2.19 raeburn 2241: if (open(PATCH,"| patch $dir/pwauth.c")) {
2242: print PATCH $patch_code;
2243: close(PATCH);
2244: $patchedok = 1;
2245: }
2246: }
2247: if ($patchedok) {
1.1 raeburn 2248: print_and_log("\n");
2249: ##
2250: ## Compile patched pwauth
2251: ##
2252: print_and_log(&mt('Compiling pwauth')."\n");
1.12 raeburn 2253: my $result = `cd $dir/; make 2>/dev/null `;
1.1 raeburn 2254: my $expected = <<"END";
2255: gcc -g -c -o pwauth.o pwauth.c
2256: gcc -o pwauth -g pwauth.o -lcrypt
2257: END
2258: if ($result eq $expected) {
2259: print_and_log(&mt('Apparent success compiling pwauth:').
2260: "\n".$result );
2261: # Install patched pwauth
2262: print_and_log(&mt('Copying pwauth to [_1]',' /usr/local/sbin')."\n");
2263: if (copy "$dir/pwauth","/usr/local/sbin/pwauth") {
1.5 raeburn 2264: if (chmod(06755, "/usr/local/sbin/pwauth")) {
1.1 raeburn 2265: print_and_log(&mt('[_1] copied successfully',"'pwauth'").
2266: "\n");
2267: } else {
2268: print &mt('Unable to set permissions on [_1].'.
2269: "/usr/local/sbin/pwauth")."\n";
2270: }
2271: } else {
2272: print &mt('Unable to copy [_1] to [_2]',
2273: "'$dir/pwauth'","/usr/local/sbin/pwauth")."\n$!\n";
2274: }
2275: } else {
2276: print &mt('Unable to compile patched [_1].'."'pwauth'")."\n";
2277: }
2278: } else {
2279: print &mt('Unable to start patch for [_1]',"'pwauth'")."\n";
2280: }
2281: print_and_log("\n");
2282: }
2283:
2284: sub kill_extra_services {
1.45 raeburn 2285: my ($distro,$stopsrvcs,$uses_systemctl) = @_;
1.1 raeburn 2286: if (ref($stopsrvcs) eq 'HASH') {
2287: my @stopping = sort(keys(%{$stopsrvcs}));
2288: if (@stopping) {
1.6 raeburn 2289: my $kill_list = join("', '",@stopping);
1.1 raeburn 2290: if ($kill_list) {
2291: $kill_list = "'".$kill_list."'";
1.6 raeburn 2292: &print_and_log("\n".&mt('Killing unnecessary services ([_1] daemon(s)).',$kill_list)."\n");
2293: foreach my $service (@stopping) {
2294: my $daemon = $service;
2295: if ($service eq 'cups') {
2296: $daemon = 'cupsd';
2297: if ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
2298: my $version = $1;
2299: if (($distro =~ /^ubuntu/) && ($version <= 8)) {
2300: $daemon = 'cupsys';
2301: }
1.12 raeburn 2302: } else {
1.8 raeburn 2303: $daemon = 'cups';
1.6 raeburn 2304: }
2305: }
1.12 raeburn 2306: my $cmd = "ps -ef |grep '$daemon' |grep -v grep";
2307: if (open(PIPE,'-|',$cmd)) {
2308: my $daemonrunning = <PIPE>;
2309: chomp($daemonrunning);
2310: close(PIPE);
2311: if ($daemonrunning) {
2312: &print_and_log(`/etc/init.d/$daemon stop`);
2313: }
2314: }
1.1 raeburn 2315: &print_and_log(&mt('Removing [_1] from startup.',$service)."\n");
1.45 raeburn 2316: if ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
2317: my $version = $1;
1.45.2.19 raeburn 2318: if ((($distro =~ /^ubuntu/) && ($version > 16)) ||
2319: (($distro =~ /^debian/) && ($version >= 10))) {
1.45 raeburn 2320: if (ref($uses_systemctl) eq 'HASH') {
2321: if ($uses_systemctl->{$service}) {
2322: if (`systemctl is-enabled $service`) {
2323: &print_and_log(`systemctl disable $service`);
2324: }
2325: }
2326: }
2327: } else {
2328: &print_and_log(`update-rc.d -f $daemon remove`);
2329: }
1.1 raeburn 2330: } else {
1.35 raeburn 2331: if (ref($uses_systemctl) eq 'HASH') {
2332: if ($uses_systemctl->{$service}) {
2333: if (`systemctl is-enabled $service`) {
2334: &print_and_log(`systemctl disable $service`);
2335: }
2336: } else {
2337: &print_and_log(`/sbin/chkconfig --del $service`);
2338: }
2339: } else {
2340: &print_and_log(`/sbin/chkconfig --del $service`);
2341: }
1.1 raeburn 2342: }
2343: }
2344: }
2345: }
2346: }
2347: return;
2348: }
2349:
2350: sub setup_mysql {
1.45.2.15 raeburn 2351: my ($setup_mysql_permissions,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,$distro) = @_;
1.4 raeburn 2352: my @mysql_lc_commands;
1.1 raeburn 2353: unless ($has_lcdb) {
1.45.2.15 raeburn 2354: my $createcmd = 'CREATE DATABASE loncapa';
2355: if ($distro =~ /^sles(\d+)/) {
2356: if ($1 > 11) {
2357: $createcmd .= ' CHARACTER SET utf8 COLLATE utf8_general_ci';
2358: }
2359: } elsif ($distro =~ /^ubuntu(\d+)/) {
2360: if ($1 > 16) {
2361: $createcmd .= ' CHARACTER SET latin1 COLLATE latin1_swedish_ci';
2362: }
2363: }
2364: push(@mysql_lc_commands,$createcmd);
1.1 raeburn 2365: }
1.4 raeburn 2366: push(@mysql_lc_commands,"USE loncapa");
2367: push(@mysql_lc_commands,qq{
1.18 raeburn 2368: 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 2369: });
1.1 raeburn 2370: if ($setup_mysql_permissions) {
1.45.2.9 raeburn 2371: &setup_mysql_permissions($dbh,$has_pass,$mysql_unix_socket,@mysql_lc_commands);
1.1 raeburn 2372: } else {
2373: print_and_log(&mt('Skipping MySQL permissions setup.')."\n");
2374: if ($dbh) {
1.4 raeburn 2375: if (@mysql_lc_commands) {
2376: foreach my $lccmd (@mysql_lc_commands) {
2377: $dbh->do($lccmd) || print $dbh->errstr."\n";
2378: }
2379: }
1.1 raeburn 2380: print_and_log(&mt('MySQL database set up complete.')."\n");
2381: } else {
2382: print_and_log(&mt('Problem accessing MySQL.')."\n");
2383: }
2384: }
2385: }
2386:
2387: sub setup_mysql_permissions {
1.45.2.9 raeburn 2388: my ($dbh,$has_pass,$mysql_unix_socket,@mysql_lc_commands) = @_;
1.45.2.19 raeburn 2389: my ($mysqlversion,$mysqlminorversion,$mysqlsubver,$mysqlname) = &get_mysql_version();
1.45.2.9 raeburn 2390: my ($usescreate,$usesauth,$is_mariadb,$hasauthcol,@mysql_commands);
1.38 raeburn 2391: if ($mysqlname =~ /^MariaDB/i) {
1.45.2.2 raeburn 2392: $is_mariadb = 1;
1.45.2.19 raeburn 2393: if ((($mysqlversion == 10) && ($mysqlminorversion >= 4)) || ($mysqlversion >= 11)) {
1.45.2.9 raeburn 2394: $usescreate = 1;
1.45.2.19 raeburn 2395: } elsif (($mysqlversion == 10) && ($mysqlminorversion >= 2)) {
1.38 raeburn 2396: $usesauth = 1;
1.45.2.19 raeburn 2397: } elsif (($mysqlversion == 5) && ($mysqlminorversion >= 5)) {
1.42 raeburn 2398: $hasauthcol = 1;
1.38 raeburn 2399: }
2400: } else {
1.45.2.19 raeburn 2401: if (($mysqlversion > 5) || (($mysqlminorversion == 5) && ($mysqlminorversion > 7)) ||
2402: (($mysqlversion == 5) && ($mysqlminorversion == 7) && ($mysqlsubver > 5))) {
1.38 raeburn 2403: $usesauth = 1;
1.45.2.19 raeburn 2404: } elsif (($mysqlversion == 5) &&
2405: (($mysqlminorversion >= 6) || (($mysqlminorversion == 5) && ($mysqlsubver >= 7)))) {
1.42 raeburn 2406: $hasauthcol = 1;
1.38 raeburn 2407: }
2408: }
1.45.2.9 raeburn 2409: if ($usescreate) {
2410: @mysql_commands = ("CREATE USER 'www'\@'localhost' IDENTIFIED BY 'localhostkey'");
2411: } elsif ($usesauth) {
1.45.2.15 raeburn 2412: @mysql_commands = ("INSERT user (Host, User, ssl_cipher, x509_issuer, x509_subject, authentication_string) VALUES('localhost','www','','','','')",
2413: "FLUSH PRIVILEGES");
1.45.2.2 raeburn 2414: if ($is_mariadb) {
2415: push(@mysql_commands,"ALTER USER 'www'\@'localhost' IDENTIFIED BY 'localhostkey'");
2416: } else {
2417: push(@mysql_commands,"ALTER USER 'www'\@'localhost' IDENTIFIED WITH mysql_native_password BY 'localhostkey'");
2418: }
1.42 raeburn 2419: } elsif ($hasauthcol) {
2420: @mysql_commands = ("INSERT user (Host, User, Password, ssl_cipher, x509_issuer, x509_subject, authentication_string) VALUES('localhost','www',password('localhostkey'),'','','','');");
1.36 raeburn 2421: } else {
1.42 raeburn 2422: @mysql_commands = ("INSERT user (Host, User, Password, ssl_cipher, x509_issuer, x509_subject) VALUES('localhost','www',password('localhostkey'),'','','');");
1.36 raeburn 2423: }
1.1 raeburn 2424: if ($mysqlversion < 4) {
1.4 raeburn 2425: push (@mysql_commands,"
2426: 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')");
2427: } else {
2428: push (@mysql_commands,"
2429: 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 2430: }
1.4 raeburn 2431: push(@mysql_commands,"DELETE FROM user WHERE host<>'localhost'");
1.45.2.9 raeburn 2432: if (($has_pass) || ($mysql_unix_socket)) {
1.1 raeburn 2433: if ($dbh) {
1.4 raeburn 2434: push(@mysql_commands,"FLUSH PRIVILEGES");
2435: if (@mysql_commands) {
2436: foreach my $cmd (@mysql_commands) {
2437: $dbh->do($cmd) || print $dbh->errstr."\n";
2438: }
2439: }
2440: if (@mysql_lc_commands) {
2441: foreach my $lccmd (@mysql_lc_commands) {
2442: $dbh->do($lccmd) || print $dbh->errstr."\n";
2443: }
2444: }
1.1 raeburn 2445: print_and_log(&mt('Permissions set for LON-CAPA MySQL user: [_1]',"'www'")."\n");
2446: } else {
2447: print_and_log(&mt('Problem accessing MySQL.')."\n".
2448: &mt('Permissions not set.')."\n");
2449: }
2450: } else {
2451: my ($firstpass,$secondpass,$got_passwd,$newmysqlpass);
2452: print &mt('Please enter a root password for the mysql database.')."\n".
2453: &mt('It does not have to match your root account password, but you will need to remember it.')."\n";
2454: my $maxtries = 10;
2455: my $trial = 0;
2456: while ((!$got_passwd) && ($trial < $maxtries)) {
2457: $firstpass = &get_mysql_password(&mt('Enter password'));
2458: if (length($firstpass) > 5) {
2459: $secondpass = &get_mysql_password(&mt('Enter password a second time'));
2460: if ($firstpass eq $secondpass) {
2461: $got_passwd = 1;
2462: $newmysqlpass = $firstpass;
2463: } else {
2464: print(&mt('Passwords did not match. Please try again.')."\n");
2465: }
2466: $trial ++;
2467: } else {
2468: print(&mt('Password too short.')."\n".
2469: &mt('Please choose a password with at least six characters.')."\n");
2470: }
2471: }
2472: if ($got_passwd) {
1.45.2.2 raeburn 2473: my (@newpass_cmds) = &new_mysql_rootpasswd($newmysqlpass,$usesauth,$is_mariadb);
1.4 raeburn 2474: push(@mysql_commands,@newpass_cmds);
1.1 raeburn 2475: } else {
2476: print_and_log(&mt('Failed to get MySQL root password from user input.')."\n");
2477: }
2478: if ($dbh) {
1.4 raeburn 2479: if (@mysql_commands) {
2480: foreach my $cmd (@mysql_commands) {
2481: $dbh->do($cmd) || print $dbh->errstr."\n";
2482: }
2483: }
2484: if (@mysql_lc_commands) {
2485: foreach my $lccmd (@mysql_lc_commands) {
2486: $dbh->do($lccmd) || print $dbh->errstr."\n";
2487: }
2488: }
1.1 raeburn 2489: if ($got_passwd) {
2490: print_and_log(&mt('MySQL root password stored.')."\n".
2491: &mt('Permissions set for LON-CAPA MySQL user: [_1].',"'www'")."\n");
2492: } else {
2493: print_and_log(&mt('Permissions set for LON-CAPA MySQL user: [_1].',"'www'")."\n");
2494: }
2495: } else {
2496: print_and_log(&mt('Problem accessing MySQL.')."\n".
2497: &mt('Permissions not set.')."\n");
2498: }
2499: }
2500: }
2501:
2502: sub new_mysql_rootpasswd {
1.45.2.2 raeburn 2503: my ($currmysqlpass,$usesauth,$is_mariadb) = @_;
1.36 raeburn 2504: if ($usesauth) {
1.45.2.2 raeburn 2505: if ($is_mariadb) {
2506: return ("ALTER USER 'root'\@'localhost' IDENTIFIED BY '$currmysqlpass'",
2507: "FLUSH PRIVILEGES;");
2508: } else {
2509: return ("ALTER USER 'root'\@'localhost' IDENTIFIED WITH mysql_native_password BY '$currmysqlpass'",
2510: "FLUSH PRIVILEGES;");
2511: }
1.36 raeburn 2512: } else {
2513: return ("SET PASSWORD FOR 'root'\@'localhost'=PASSWORD('$currmysqlpass')",
2514: "FLUSH PRIVILEGES;");
2515: }
1.1 raeburn 2516: }
2517:
2518: sub get_mysql_version {
1.45.2.19 raeburn 2519: my ($version,$minorversion,$subversion,$name);
1.1 raeburn 2520: if (open(PIPE," mysql -V |")) {
2521: my $info = <PIPE>;
2522: chomp($info);
2523: close(PIPE);
1.45.2.19 raeburn 2524: ($version,$minorversion,$subversion,$name) = ($info =~ /(\d+)\.(\d+)\.(\d+)(?:\-?(\w*),|)/);
1.1 raeburn 2525: } else {
2526: print &mt('Could not determine which version of MySQL is installed.').
2527: "\n";
2528: }
1.45.2.19 raeburn 2529: return ($version,$minorversion,$subversion,$name);
1.1 raeburn 2530: }
2531:
1.45.2.20 raeburn 2532: sub check_systemd_update {
2533: my ($distro) = @_;
2534: my ($use_systemctl,$service);
2535: $service = 'apache2.service';
2536: if ($distro =~ /^ubuntu(\w+)/) {
2537: if ($1 >= 16) {
2538: $use_systemctl = 1;
2539: }
2540: } elsif ($distro =~ /^debian(\w+)/) {
2541: if ($1 >= 9) {
2542: $use_systemctl = 1;
2543: }
2544: } elsif ($distro =~ /^fedora(\d+)/) {
2545: $service = 'httpd.service';
2546: if ($1 >= 16) {
2547: $use_systemctl = 1;
2548: }
2549: } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
2550: $service = 'httpd.service';
2551: if ($1 >= 7) {
2552: $use_systemctl = 1;
2553: }
2554: } elsif ($distro =~ /^sles(\d+)/) {
2555: if ($1 >= 12) {
2556: $use_systemctl = 1;
2557: }
2558: } elsif ($distro =~ /^suse(\d+)/) {
2559: if ($1 >= 13) {
2560: $use_systemctl = 1;
2561: }
2562: }
2563: if ($use_systemctl) {
2564: my $needsupdate = &check_systemd_security($distro);
2565: if ($needsupdate) {
2566: if (!-d '/etc/systemd/system/'.$service.'.d') {
2567: mkdir '/etc/systemd/system/'.$service.'.d', 0755;
2568: }
2569: if (-d '/etc/systemd/system/'.$service.'.d') {
2570: if (-e '/etc/systemd/system/'.$service.'.d/override.conf') {
2571: if (open(my $fh,'<','/etc/systemd/system/'.$service.'.d/override.conf')) {
1.45.2.24! raeburn 2572: my ($category,$addservice,$needs_update,$linenum,%is_no,%lines,
! 2573: @move,@nocat,@ordered);
! 2574: $linenum = 0;
1.45.2.20 raeburn 2575: while (my $entry = <$fh>) {
2576: $linenum ++;
2577: chomp($entry);
1.45.2.24! raeburn 2578: if ($entry =~ /^\s*\[([^\]]+)\]\s*$/) {
! 2579: $category = $1;
! 2580: if ($category =~ /^Service$/i) {
! 2581: unless (grep(/^Service$/,@ordered)) {
! 2582: push(@ordered,'Service');
! 2583: }
1.45.2.20 raeburn 2584: } else {
1.45.2.24! raeburn 2585: unless (grep(/^\Q$category\E$/,@ordered)) {
! 2586: push(@ordered,$category);
! 2587: }
1.45.2.20 raeburn 2588: }
1.45.2.24! raeburn 2589: } elsif ($entry =~ /^(ProtectHome|RestrictSUIDSGID)\s*=\s*([\w-]+)\s*$/) {
! 2590: my ($key,$value) = ($1,$2);
! 2591: next if ($is_no{$key});
! 2592: if (lc($value) eq 'no') {
! 2593: if ($category =~ /^Service$/i) {
! 2594: push(@{$lines{'Service'}},$entry);
1.45.2.20 raeburn 2595: } else {
1.45.2.24! raeburn 2596: push(@move,$entry);
! 2597: $needs_update = 1;
! 2598: }
! 2599: } else {
! 2600: my $offstr = $key.'=no';
! 2601: if ($category =~ /^Service$/i) {
! 2602: push(@{$lines{'Service'}},$offstr);
! 2603: } else {
! 2604: push(@move,$offstr);
1.45.2.20 raeburn 2605: }
1.45.2.24! raeburn 2606: $needs_update = 1;
! 2607: }
! 2608: $is_no{$key} = $linenum;
! 2609: } else {
! 2610: next if ($entry =~ /^\s*$/);
! 2611: if ($category =~ /^Service$/i) {
! 2612: push(@{$lines{'Service'}},$entry);
! 2613: } elsif ($category ne '') {
! 2614: push(@{$lines{$category}},$entry);
! 2615: } else {
! 2616: push(@nocat,$entry);
1.45.2.20 raeburn 2617: }
2618: }
2619: }
2620: close($fh);
1.45.2.24! raeburn 2621: unless (grep(/^Service$/,@ordered)) {
! 2622: $addservice = 1;
! 2623: unshift(@ordered,'Service');
! 2624: }
! 2625: foreach my $item ('ProtectHome','RestrictSUIDSGID') {
! 2626: unless (exists($is_no{$item})) {
! 2627: push(@{$lines{'Service'}},$item.'=no');
! 2628: $needs_update = 1;
! 2629: }
! 2630: }
! 2631: if ($addservice || $needs_update) {
1.45.2.20 raeburn 2632: if (open(my $fh,'>','/etc/systemd/system/'.$service.'.d/override.conf')) {
1.45.2.24! raeburn 2633: if (@ordered) {
! 2634: foreach my $category (@ordered) {
! 2635: print $fh "[$category]\n";
! 2636: if (ref($lines{$category}) eq 'ARRAY') {
! 2637: foreach my $item (@{$lines{$category}}) {
! 2638: print $fh "$item\n";
! 2639: }
! 2640: }
! 2641: if ($category eq 'Service') {
! 2642: if (@move) {
! 2643: foreach my $item (@move) {
! 2644: if ($item =~ /^(ProtectHome|RestrictSUIDSGID)\s*=\s*no\s*$/i) {
! 2645: my $key = $1;
! 2646: unless (grep/^$key\s*=\s*no\s*$/i,@{$lines{$category}}) {
! 2647: print $fh "$item\n";
! 2648: }
! 2649: } else {
! 2650: print $fh "$item\n";
! 2651: }
! 2652: }
! 2653: }
! 2654: }
! 2655: print $fh "\n";
! 2656: }
1.45.2.20 raeburn 2657: }
1.45.2.24! raeburn 2658: if (@nocat) {
! 2659: foreach my $item (@nocat) {
! 2660: print $fh "$item\n";
! 2661: }
1.45.2.20 raeburn 2662: }
2663: close($fh);
2664: print_and_log('Updated /etc/systemd/system/'.$service.'.d/override.conf');
1.45.2.21 raeburn 2665: system('systemctl daemon-reload');
1.45.2.20 raeburn 2666: } else {
2667: print_and_log('Could not open /etc/systemd/system/'.$service.'.d/override.conf for writing.');
2668: }
2669: } else {
2670: print_and_log('No change needed in /etc/systemd/system/'.$service.'.d/override.conf');
2671: }
2672: } else {
2673: print_and_log('Could not open /etc/systemd/system/'.$service.'.d/override.conf for reading.');
2674: }
2675: } else {
2676: if (open(my $fh,'>','/etc/systemd/system/'.$service.'.d/override.conf')) {
1.45.2.24! raeburn 2677: print $fh '[Service]'."\n".'ProtectHome=no'."\n".'RestrictSUIDSGID=no'."\n";
1.45.2.20 raeburn 2678: close($fh);
2679: print_and_log('Created /etc/systemd/system/'.$service.'.d/override.conf');
1.45.2.21 raeburn 2680: system('systemctl daemon-reload');
1.45.2.24! raeburn 2681: } else {
! 2682: print_and_log('Could not open /etc/systemd/system/'.$service.'.d/override.conf for writing.');
1.45.2.20 raeburn 2683: }
2684: }
2685: } else {
2686: print_and_log('No /etc/systemd/system/'.$service.'.d directory exists and creating one failed,');
2687: }
2688: } else {
2689: print_and_log('No update needed to systemd security settings for Apache web server.');
2690: }
2691: } else {
2692: print_and_log('No update needed to systemd, as this Linux distro does not use systemctl');
2693: }
2694: }
2695:
1.1 raeburn 2696: ###########################################################
2697: ##
2698: ## RHEL/CentOS/Fedora/Scientific Linux
2699: ## Copy LON-CAPA httpd.conf to /etc/httpd/conf
2700: ##
2701: ###########################################################
2702:
2703: sub copy_httpd_conf {
1.14 raeburn 2704: my ($instdir,$distro) = @_;
2705: my $configfile = 'httpd.conf';
1.45.2.18 raeburn 2706: if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.29 raeburn 2707: if ($1 >= 7) {
2708: $configfile = 'apache2.4/httpd.conf';
2709: } elsif ($1 > 5) {
1.14 raeburn 2710: $configfile = 'new/httpd.conf';
2711: }
2712: } elsif ($distro =~ /^fedora(\d+)$/) {
1.29 raeburn 2713: if ($1 > 17) {
2714: $configfile = 'apache2.4/httpd.conf';
2715: } elsif ($1 > 10) {
1.14 raeburn 2716: $configfile = 'new/httpd.conf';
2717: }
2718: }
1.1 raeburn 2719: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'httpd.conf'",
2720: "'/etc/httpd/conf/httpd.conf'")."\n");
2721: copy "/etc/httpd/conf/httpd.conf","/etc/httpd/conf/httpd.conf.original";
1.14 raeburn 2722: copy "$instdir/centos-rhes-fedora-sl/$configfile","/etc/httpd/conf/httpd.conf";
1.5 raeburn 2723: chmod(0444,"/etc/httpd/conf/httpd.conf");
1.1 raeburn 2724: print_and_log("\n");
2725: }
2726:
1.45.2.5 raeburn 2727: ###########################################################
2728: ##
2729: ## RHEL/CentOS/Fedora/Scientific Linux
2730: ## Copy LON-CAPA mpm.conf to /etc/httpd/conf.modules.d/00-mpm.conf
2731: ##
2732: ## The LON-CAPA mpm.conf enables the prefork MPM module in
2733: ## Apache. This is also the default for RHEL/CentOS/Oracle
2734: ## Linux 7 and earlier, and Fedora 26 and earlier. For more
2735: ## recent versions of those distros, the event MPM is enabled
2736: ## by default. After ©_mpm_conf() is run, the prefork MPM
2737: ## module will be enabled instead of the event MPM module.
2738: ##
2739: ###########################################################
2740:
2741: sub copy_mpm_conf {
2742: my ($instdir,$distro) = @_;
2743: my $mpmfile = 'mpm.conf';
2744: if ((-e "/etc/httpd/conf.modules.d/00-mpm.conf") &&
2745: (-e "$instdir/centos-rhes-fedora-sl/$mpmfile")) {
2746: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'mpm.conf'",
2747: "'/etc/httpd/conf.modules.d/00-mpm.conf'")."\n");
2748: copy "$instdir/centos-rhes-fedora-sl/$mpmfile","/etc/httpd/conf.modules.d/00-mpm.conf";
2749: chmod(0644,"/etc/httpd/conf.modules.d/00-mpm.conf");
2750: print_and_log("\n");
2751: } else {
2752: my $logfail;
1.45.2.18 raeburn 2753: if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {
1.45.2.5 raeburn 2754: if ($1 > 7) {
2755: $logfail = 1;
2756: }
2757: } elsif ($distro =~ /^fedora(\d+)$/) {
2758: if ($1 > 26) {
2759: $logfail = 1;
2760: }
2761: }
2762: if ($logfail) {
2763: print_and_log(&mt('Warning: copying the LON-CAPA [_1] failed because [_2] and/or [_3] are missing.',
2764: $mpmfile,"'$instdir/centos-rhes-fedora-sl/$mpmfile'",
2765: "'/etc/httpd/conf.modules.d/00-mpm.conf'"));
2766: print_and_log("\n");
2767: }
2768: }
2769: }
2770:
1.1 raeburn 2771: #########################################################
2772: ##
1.17 raeburn 2773: ## Ubuntu/Debian -- copy our loncapa configuration file to
1.1 raeburn 2774: ## sites-available and set the symlink from sites-enabled.
2775: ##
2776: #########################################################
2777:
2778: sub copy_apache2_debconf {
1.28 raeburn 2779: my ($instdir,$distro) = @_;
1.6 raeburn 2780: my $apache2_mods_enabled_dir = '/etc/apache2/mods-enabled';
2781: my $apache2_mods_available_dir = '/etc/apache2/mods-available';
2782: foreach my $module ('headers.load','expires.load') {
2783: unless (-l "$apache2_mods_enabled_dir/$module") {
2784: symlink("$apache2_mods_available_dir/$module","$apache2_mods_enabled_dir/$module");
2785: print_and_log(&mt('Enabling "[_1]" Apache module.',$module)."\n");
2786: }
2787: }
1.28 raeburn 2788: my $apache2_sites_enabled_dir = '/etc/apache2/sites-enabled';
2789: my $apache2_sites_available_dir = '/etc/apache2/sites-available';
2790: my $defaultconfig = "$apache2_sites_enabled_dir/000-default";
1.45.2.10 raeburn 2791: my $defaultsite = "$apache2_sites_enabled_dir/loncapa.conf";
1.28 raeburn 2792: my ($distname,$version);
2793: if ($distro =~ /^(debian|ubuntu)(\d+)$/) {
2794: $distname = $1;
2795: $version = $2;
2796: }
1.45.2.19 raeburn 2797: if ((($distname eq 'ubuntu') && ($version > 12)) ||
2798: (($distname eq 'debian') && ($version >= 10))) {
1.28 raeburn 2799: $defaultconfig = "$apache2_sites_enabled_dir/000-default.conf";
2800: }
1.45.2.7 raeburn 2801: my ($skipconf,$skipsite,$skipstatus);
1.45.2.19 raeburn 2802: if ((($distname eq 'ubuntu') && ($version > 12)) ||
2803: (($distname eq 'debian') && ($version >= 10))) {
1.28 raeburn 2804: my $apache2_conf_enabled_dir = '/etc/apache2/conf-enabled';
2805: my $apache2_conf_available_dir = '/etc/apache2/conf-available';
1.33 raeburn 2806: my $defaultconf = $apache2_conf_enabled_dir.'/loncapa.conf';
1.45.2.7 raeburn 2807: if ((-e "$apache2_conf_available_dir/loncapa") && (-e "$instdir/debian-ubuntu/ubuntu14/loncapa_conf")) {
1.45.2.8 raeburn 2808: if (open(PIPE, "diff --brief $apache2_conf_available_dir/loncapa $instdir/debian-ubuntu/ubuntu14/loncapa_conf |")) {
1.45.2.7 raeburn 2809: my $diffres = <PIPE>;
2810: close(PIPE);
2811: chomp($diffres);
2812: if ($diffres) {
1.45.2.10 raeburn 2813: copy("$apache2_conf_available_dir/loncapa","$apache2_conf_available_dir/loncapa.conf.original");
2814: } else {
2815: copy("$apache2_conf_available_dir/loncapa","$apache2_conf_available_dir/loncapa.conf");
1.45.2.11 raeburn 2816: chdir($apache2_conf_enabled_dir);
2817: symlink('../conf-available/loncapa.conf','loncapa.conf');
2818: chdir($instdir);
1.45.2.7 raeburn 2819: }
2820: if (-l $defaultconf) {
2821: my $linkfname = readlink($defaultconf);
1.45.2.11 raeburn 2822: if ($linkfname ne '') {
2823: $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_conf_enabled_dir));
2824: }
1.45.2.7 raeburn 2825: if ($linkfname eq "$apache2_conf_available_dir/loncapa") {
1.45.2.10 raeburn 2826: unlink($defaultconf);
2827: }
2828: }
2829: unlink("$apache2_conf_available_dir/loncapa");
2830: }
2831: }
2832: if ((-e "$apache2_conf_available_dir/loncapa.conf") && (-e "$instdir/debian-ubuntu/ubuntu14/loncapa_conf")) {
2833: if (open(PIPE, "diff --brief $apache2_conf_available_dir/loncapa.conf $instdir/debian-ubuntu/ubuntu14/loncapa_conf |")) {
2834: my $diffres = <PIPE>;
2835: close(PIPE);
2836: chomp($diffres);
2837: if ($diffres) {
2838: copy("$apache2_conf_available_dir/loncapa.conf","$apache2_conf_available_dir/loncapa.conf.original");
2839: }
2840: if (-l $defaultconf) {
2841: my $linkfname = readlink($defaultconf);
1.45.2.11 raeburn 2842: if ($linkfname ne '') {
2843: $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_conf_enabled_dir));
2844: }
1.45.2.10 raeburn 2845: if ($linkfname eq "$apache2_conf_available_dir/loncapa.conf") {
1.45.2.7 raeburn 2846: unless ($diffres) {
2847: $skipconf = 1;
2848: }
2849: }
2850: }
2851: }
2852: }
2853: unless ($skipconf) {
2854: 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 2855: copy("$instdir/debian-ubuntu/ubuntu14/loncapa_conf","$apache2_conf_available_dir/loncapa.conf");
2856: chmod(0444,"$apache2_conf_available_dir/loncapa.conf");
1.45.2.7 raeburn 2857: if (-l $defaultconf) {
2858: unlink($defaultconf);
2859: }
1.45.2.11 raeburn 2860: chdir($apache2_conf_enabled_dir);
2861: symlink('../conf-available/loncapa.conf','loncapa.conf');
2862: chdir($instdir);
1.45.2.7 raeburn 2863: }
2864: my $stdsite = "$instdir/debian-ubuntu/ubuntu14/loncapa_site";
2865: if ((-e $stdsite) && (-e "$apache2_sites_available_dir/loncapa")) {
2866: if (open(PIPE, "diff --brief $stdsite $apache2_sites_available_dir/loncapa |")) {
2867: my $diffres = <PIPE>;
2868: close(PIPE);
2869: chomp($diffres);
2870: if ($diffres) {
1.45.2.10 raeburn 2871: copy("$apache2_sites_available_dir/loncapa","$apache2_sites_available_dir/loncapa.conf.original");
2872: } else {
2873: copy("$apache2_sites_available_dir/loncapa","$apache2_sites_available_dir/loncapa.conf");
1.45.2.7 raeburn 2874: }
2875: if (-l $defaultconfig) {
2876: my $linkfname = readlink($defaultconfig);
1.45.2.11 raeburn 2877: if ($linkfname ne '') {
2878: $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_sites_enabled_dir));
2879: }
1.45.2.7 raeburn 2880: if ($linkfname eq "$apache2_sites_available_dir/loncapa") {
1.45.2.10 raeburn 2881: unlink($defaultconfig);
2882: }
2883: }
2884: unlink("$apache2_sites_available_dir/loncapa");
2885: }
2886: }
2887: if ((-e $stdsite) && (-e "$apache2_sites_available_dir/loncapa.conf")) {
2888: if (open(PIPE, "diff --brief $stdsite $apache2_sites_available_dir/loncapa.conf |")) {
2889: my $diffres = <PIPE>;
2890: close(PIPE);
2891: chomp($diffres);
2892: if ($diffres) {
2893: copy("$apache2_sites_available_dir/loncapa.conf","$apache2_sites_available_dir/loncapa.conf.original");
2894: }
2895: if (-l $defaultsite) {
2896: my $linkfname = readlink($defaultsite);
1.45.2.11 raeburn 2897: if ($linkfname ne '') {
2898: $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_sites_enabled_dir));
2899: }
2900: if ($linkfname eq "$apache2_sites_available_dir/loncapa.conf") {
1.45.2.7 raeburn 2901: unless ($diffres) {
2902: $skipsite = 1;
2903: }
2904: }
2905: }
2906: }
2907: }
2908: unless ($skipsite) {
1.45.2.10 raeburn 2909: 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");
2910: copy("$instdir/debian-ubuntu/ubuntu14/loncapa_site","$apache2_sites_available_dir/loncapa.conf");
2911: chmod(0444,"$apache2_sites_available_dir/loncapa.conf");
1.45.2.11 raeburn 2912: chdir($apache2_sites_enabled_dir);
2913: symlink('../sites-available/loncapa.conf','loncapa.conf');
2914: chdir($instdir);
1.45.2.10 raeburn 2915: }
1.45.2.11 raeburn 2916: if (-l $defaultconfig) {
1.45.2.10 raeburn 2917: my $linkfname = readlink($defaultconfig);
1.45.2.11 raeburn 2918: if ($linkfname ne '') {
2919: $linkfname = Cwd::abs_path(File::Spec->rel2abs($linkfname,$apache2_sites_enabled_dir));
2920: }
2921: if ($linkfname eq "$apache2_sites_available_dir/000-default.conf") {
1.45.2.10 raeburn 2922: unlink($defaultconfig);
2923: }
1.45.2.7 raeburn 2924: }
2925: } else {
2926: if ((-e "$instdir/debian-ubuntu/loncapa") && (-e "$apache2_sites_available_dir/loncapa")) {
2927: if (open(PIPE, "diff --brief $instdir/debian-ubuntu/loncapa $apache2_sites_available_dir/loncapa |")) {
2928: my $diffres = <PIPE>;
2929: close(PIPE);
2930: chomp($diffres);
2931: if ($diffres) {
2932: copy("$apache2_sites_available_dir/loncapa","$apache2_sites_available_dir/loncapa.original");
2933: }
2934: if (-l $defaultconfig) {
2935: my $linkfname = readlink($defaultconfig);
2936: if ($linkfname eq "$apache2_sites_available_dir/loncapa") {
2937: unless ($diffres) {
2938: $skipsite = 1;
2939: }
2940: }
2941: }
2942: }
2943: }
2944: unless ($skipsite) {
2945: if (-l $defaultconfig) {
2946: unlink($defaultconfig);
2947: }
2948: 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");
2949: if (-e "$instdir/debian-ubuntu/loncapa") {
2950: copy("$instdir/debian-ubuntu/loncapa","$apache2_sites_available_dir/loncapa");
2951: chmod(0444,"$apache2_sites_available_dir/loncapa");
2952: symlink("$apache2_sites_available_dir/loncapa","$apache2_sites_enabled_dir/000-default");
2953: }
2954: }
2955: }
1.45.2.19 raeburn 2956: if (($distname eq 'ubuntu') || ($distname eq 'debian')) {
1.45.2.7 raeburn 2957: my $sitestatus = "$apache2_mods_available_dir/status.conf";
2958: my $stdstatus = "$instdir/debian-ubuntu/status.conf";
2959: if ((-e $sitestatus) && (-e $stdstatus)) {
2960: if (open(PIPE, "diff --brief $stdstatus $sitestatus |")) {
2961: my $diffres = <PIPE>;
2962: close(PIPE);
2963: chomp($diffres);
2964: if ($diffres) {
2965: copy("$apache2_mods_available_dir/status.conf","$apache2_mods_available_dir/status.conf.original");
2966: } else {
2967: $skipstatus = 1;
2968: }
2969: }
2970: }
2971: unless ($skipstatus) {
2972: if (-e $stdstatus) {
2973: print_and_log(&mt('Copying loncapa [_1] file to [_2],',"'status.conf'","'/etc/apache2/mods-available/status.conf'")."\n");
2974: copy($stdstatus,$sitestatus);
2975: chmod(0644,$sitestatus);
2976: }
2977: }
1.28 raeburn 2978: }
1.1 raeburn 2979: print_and_log("\n");
2980: }
2981:
2982: ###########################################################
2983: ##
2984: ## openSuSE/SLES Copy apache2 config files:
2985: ## default-server.conf, uid.conf, /etc/sysconfig/apache2
2986: ## and create symlink from /srv/www/conf to /etc/apache2
2987: ##
2988: ###########################################################
2989:
2990: sub copy_apache2_suseconf {
1.45.2.1 raeburn 2991: my ($instdir,$distro) = @_;
2992: my ($name,$version) = ($distro =~ /^(suse|sles)([\d\.]+)$/);
2993: my $conf_file = "$instdir/sles-suse/default-server.conf";
2994: if (($name eq 'sles') && ($version >= 12)) {
2995: $conf_file = "$instdir/sles-suse/apache2.4/default-server.conf";
2996: }
1.1 raeburn 2997: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',
2998: "'default-server.conf'",
2999: "'/etc/apache2/default-server.conf'")."\n");
3000: if (!-e "/etc/apache2/default-server.conf.original") {
3001: copy "/etc/apache2/default-server.conf","/etc/apache2/default-server.conf.original";
3002: }
1.45.2.1 raeburn 3003: copy $conf_file,"/etc/apache2/default-server.conf";
1.5 raeburn 3004: chmod(0444,"/etc/apache2/default-server.conf");
1.1 raeburn 3005: # Make symlink for conf directory (included in loncapa_apache.conf)
3006: my $can_symlink = (eval { symlink('/etc/apache2','/srv/www/conf'); }, $@ eq '');
3007: if ($can_symlink) {
3008: &print_and_log(&mt('Symlink created for [_1] to [_2].',
3009: "'/srv/www/conf'","'/etc/apache2'")."\n");
3010: } else {
3011: &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");
3012: }
3013: ©_apache2_conf_files($instdir);
1.45.2.1 raeburn 3014: ©_sysconfig_apache2_file($instdir,$name,$version);
1.1 raeburn 3015: print_and_log("\n");
3016: }
3017:
3018: ###############################################
3019: ##
3020: ## Modify uid.conf
3021: ##
3022: ###############################################
3023: sub copy_apache2_conf_files {
3024: my ($instdir) = @_;
3025: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',
3026: "'uid.conf'","'/etc/apache2/uid.conf'")."\n");
3027: if (!-e "/etc/apache2/uid.conf.original") {
3028: copy "/etc/apache2/uid.conf","/etc/apache2/uid.conf.original";
3029: }
1.9 raeburn 3030: copy "$instdir/sles-suse/uid.conf","/etc/apache2/uid.conf";
1.5 raeburn 3031: chmod(0444,"/etc/apache2/uid.conf");
1.1 raeburn 3032: }
3033:
3034: ###############################################
3035: ##
3036: ## Modify /etc/sysconfig/apache2
3037: ##
3038: ###############################################
3039: sub copy_sysconfig_apache2_file {
1.45.2.1 raeburn 3040: my ($instdir,$name,$version) = @_;
1.1 raeburn 3041: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'sysconfig/apache2'","'/etc/sysconfig/apache2'")."\n");
3042: if (!-e "/etc/sysconfig/apache2.original") {
3043: copy "/etc/sysconfig/apache2","/etc/sysconfig/apache2.original";
3044: }
1.45.2.1 raeburn 3045: my $sysconf_file = "$instdir/sles-suse/sysconfig_apache2";
3046: if (($name eq 'sles') && ($version >= 12)) {
3047: $sysconf_file = "$instdir/sles-suse/apache2.4/sysconfig_apache2";
3048: }
3049: copy $sysconf_file,"/etc/sysconfig/apache2";
1.5 raeburn 3050: chmod(0444,"/etc/sysconfig/apache2");
1.1 raeburn 3051: }
3052:
3053: ###############################################
3054: ##
3055: ## Add/Modify /etc/insserv/overrides
3056: ##
3057: ###############################################
3058:
3059: sub update_SuSEfirewall2_setup {
3060: my ($instdir) = @_;
3061: print_and_log(&mt('Copying the LON-CAPA [_1] to [_2].',"'SuSEfirewall2_setup'","'/etc/insserv/overrides/SuSEfirewall2_setup'")."\n");
3062: if (!-e "/etc/insserv/overrides/SuSEfirewall2_setup") {
3063: if (!-d "/etc/insserv") {
3064: mkdir("/etc/insserv",0755);
3065: }
3066: if (!-d "/etc/insserv/overrides") {
3067: mkdir("/etc/insserv/overrides",0755);
3068: }
3069: } elsif (!-e "/etc/insserv/overrides/SuSEfirewall2_setup.original") {
3070: copy "/etc/insserv/overrides/SuSEfirewall2_setup","/etc/insserv/overrides/SuSEfirewall2_setup.original"
3071: }
1.9 raeburn 3072: copy "$instdir/sles-suse/SuSEfirewall2_setup","/etc/insserv/overrides/SuSEfirewall2_setup";
1.5 raeburn 3073: chmod(0444,"/etc/insserv/overrides/SuSEfirewall2_setup");
3074: }
3075:
3076: sub get_iptables_rules {
3077: my ($distro,$instdir,$apachefw) = @_;
3078: my (@fwchains,@ports);
3079: if (&firewall_is_active()) {
3080: my $iptables = &get_pathto_iptables();
3081: if ($iptables ne '') {
3082: @fwchains = &get_fw_chains($iptables,$distro);
3083: }
3084: }
3085: if (ref($apachefw) eq 'HASH') {
3086: foreach my $service ('http','https') {
3087: unless ($apachefw->{$service}) {
3088: push (@ports,$service);
3089: }
3090: }
3091: } else {
3092: @ports = ('http','https');
3093: }
3094: if (@ports == 0) {
3095: return;
3096: }
3097: my $ask_to_enable;
3098: if (-e "/etc/iptables.loncapa.rules") {
1.9 raeburn 3099: if (open(PIPE, "diff --brief $instdir/debian-ubuntu/iptables.loncapa.rules /etc/iptables.loncapa.rules |")) {
1.5 raeburn 3100: my $diffres = <PIPE>;
3101: close(PIPE);
3102: chomp($diffres);
3103: if ($diffres) {
3104: print &mt('Warning: [_1] exists but differs from LON-CAPA supplied file.','/etc/iptables.loncapa.rules')."\n";
3105: }
3106: } else {
3107: print &mt('Error: unable to open [_1] to compare contents with LON-CAPA supplied file.','/etc/iptables.loncapa.rules')."\n";
3108: }
3109: } else {
1.9 raeburn 3110: if (-e "$instdir/debian-ubuntu/iptables.loncapa.rules") {
3111: copy "$instdir/debian-ubuntu/iptables.loncapa.rules","/etc/iptables.loncapa.rules";
1.5 raeburn 3112: chmod(0600,"/etc/iptables.loncapa.rules");
3113: }
3114: }
3115: if (-e "/etc/iptables.loncapa.rules") {
3116: if (-e "/etc/network/if-pre-up.d/iptables") {
1.9 raeburn 3117: if (open(PIPE, "diff --brief $instdir/debian-ubuntu/iptables /etc/network/if-pre-up/iptables |")) {
1.5 raeburn 3118: my $diffres = <PIPE>;
3119: close(PIPE);
3120: chomp($diffres);
3121: if ($diffres) {
3122: print &mt('Warning: [_1] exists but differs from LON-CAPA supplied file.','/etc/network/if-pre-up.d/iptables')."\n";
3123: }
3124: } else {
3125: print &mt('Error: unable to open [_1] to compare contents with LON-CAPA supplied file.','/etc/network/if-pre-up.d/iptables')."\n";
3126: }
3127: } else {
1.9 raeburn 3128: copy "$instdir/debian-ubuntu/iptables","/etc/network/if-pre-up.d/iptables";
1.5 raeburn 3129: chmod(0755,"/etc/network/if-pre-up.d/iptables");
3130: 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'));
3131: $ask_to_enable = 1;
3132: }
3133: }
3134: return $ask_to_enable;
1.1 raeburn 3135: }
3136:
3137: sub download_loncapa {
3138: my ($instdir,$lctarball) = @_;
3139: my ($have_tarball,$updateshown);
3140: if (! -e "$instdir/$lctarball") {
3141: print_and_log(&mt('Retrieving LON-CAPA source files from: [_1]',
3142: 'http://install.loncapa.org')."\n");
3143: system("wget http://install.loncapa.org/versions/$lctarball ".
3144: "2>/dev/null 1>/dev/null");
3145: if (! -e "./$lctarball") {
3146: print &mt('Unable to retrieve LON-CAPA source files from: [_1].',
3147: "http://install.loncapa.org/versions/$lctarball")."\n";
3148: } else {
3149: $have_tarball = 1;
3150: }
3151: print_and_log("\n");
3152: } else {
3153: $have_tarball = 1;
3154: print_and_log("
3155: ------------------------------------------------------------------------
3156:
1.45.2.16 raeburn 3157: ".&mt('You seem to have a version of [_1] in [_2]',$lctarball,$instdir)."\n".
1.1 raeburn 3158: &mt('This copy will be used and a new version will NOT be downloaded.')."\n".
3159: &mt('If you wish, you may download a new version by executing:')."
3160:
1.45.2.16 raeburn 3161: wget http://install.loncapa.org/versions/$lctarball
1.1 raeburn 3162:
3163: ------------------------------------------------------------------------
3164: ");
3165: }
3166:
3167: ##
1.45.2.16 raeburn 3168: ## untar loncapa-X.Y.Z.tar.gz
1.1 raeburn 3169: ##
3170: if ($have_tarball) {
1.45.2.16 raeburn 3171: my $homedir = '/root';
3172: my ($targetdir,$chdircmd,$updatecmd);
3173: if (($distro =~ /^ubuntu/) && ($instdir ne $homedir)) {
3174: ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});
3175: $updatecmd = 'sudo ./UPDATE';
3176: } else {
3177: $updatecmd = './UPDATE';
3178: }
1.1 raeburn 3179: print_and_log(&mt('Extracting LON-CAPA source files')."\n");
1.45.2.16 raeburn 3180: if (-e $homedir) {
3181: writelog(`tar zxf $instdir/$lctarball --directory $homedir`);
3182: $targetdir = $homedir;
3183: } else {
3184: writelog(`tar zxf $instdir/$lctarball`);
3185: $targetdir = $instdir;
3186: }
3187: if ($lctarball =~ /^loncapa\-(\d+\.\d+\.\d+(?:|[^.]+))\.tar\.gz$/) {
3188: $chdircmd = "cd $targetdir/loncapa-".$1;
3189: } else {
3190: $chdircmd = "cd $targetdir/loncapa-X.Y.Z (X.Y.Z should correspond to a version number like '2.11.3')";
3191: }
1.1 raeburn 3192: print_and_log("\n");
3193: print &mt('LON-CAPA source files extracted.')."\n".
1.45.2.16 raeburn 3194: &mt('It remains for you to execute the following commands:').
3195: "\n$chdircmd\n$updatecmd\n".
3196: &mt('If you have any trouble, please see [_1] and [_2]',
3197: 'http://install.loncapa.org/','http://help.loncapa.org/')."\n";
1.1 raeburn 3198: $updateshown = 1;
3199: }
3200: return ($have_tarball,$updateshown);
3201: }
3202:
3203: close LOG;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>