various: add read-only mode support
[girocco.git] / Girocco / Validator.pm
blobb6fc1020306f088406676d23f7b6b937dcdc41d2
1 # This install-only package contains validation, sanity and default
2 # checks for the values set in Girocco::Config.
4 # It's only used during the install process.
5 # Normally the Girocco::Config file will "require" this module
6 # at the end (before it's frozen during installation).
7 # However, the install process specifically "use"s this module to
8 # guarantee the checks always run even if that "require" is removed.
10 package Girocco::Validator;
12 BEGIN {
13 # This check MUST NOT be inside the Girocco::Config package
14 scalar(eval 'keys %Girocco::Config::') or
15 die "Girocco::Config must already be 'use'd before ".__PACKAGE__." is 'use'd.\n";
18 use Girocco::ValidUtil ();
20 package Girocco::Config;
22 use strict;
23 use warnings;
24 no strict 'vars'; # required since Config.pm declares the variables
26 BEGIN {
27 # Makes non-Config modules work with non-default Config
28 exists($INC{'Girocco/Config.pm'}) or
29 $INC{'Girocco/Config.pm'} = $INC{'Girocco/Validator.pm'};
33 ## ------------------------
34 ## Sanity checks & defaults
35 ## ------------------------
37 # Changing anything in this section can result in unexpected breakage
39 # Couple of sanity checks and default settings (do not change these)
40 require Digest::MD5;
41 require MIME::Base64;
42 defined($name) or $name = "";
43 $name =~ s/\s+/_/gs;
44 $nickname = lc((split(/[.]/, $name))[0]) unless defined($nickname) && $nickname ne "";
45 $nickname =~ s/\s+/_/gs;
46 our $tmpsuffix = substr(MIME::Base64::encode_base64(Digest::MD5::md5($name.':'.$nickname)),0,6);
47 $tmpsuffix =~ tr,+/,=_,;
48 defined($mirror_user) && $mirror_user ne "" or
49 die "Girocco::Config: \$mirror_user must be set even if to current user";
50 defined($basedir) && $basedir ne "" or
51 die "Girocco::Config: \$basedir must be set";
52 defined($sendmail_bin) && $sendmail_bin ne "" or
53 die "Girocco::Config: \$sendmail_bin must be set";
54 $sendmail_bin eq "sendmail.pl" and $sendmail_bin = "$basedir/bin/sendmail.pl";
55 defined($screen_acl_file) && $screen_acl_file ne "" or
56 $screen_acl_file = "$basedir/screen/giroccoacl";
57 defined($jailreporoot) or $jailreporoot = "";
58 $jailreporoot =~ s,^/+,,;
59 $reporoot ne "" or die "Girocco::Config: \$reporoot must be set";
60 $jailreporoot ne "" or die "Girocco::Config: \$jailreporoot must be set";
61 $disable_jailsetup = $disable_jailsetup ? 1 : '';
62 $notify_single_level = $notify_single_level ? 1 : '';
63 $fetch_stash_refs = $fetch_stash_refs ? 1 : '';
64 !$mob || $mob eq 'mob' or die "Girocco::Config: \$mob must be undef (or '') or 'mob'";
65 !defined($protect_fields) || ref($protect_fields) eq 'HASH' or
66 die "Girocco::Config: \$protect_fields must be a HASH ref or undefined";
67 ref($protect_fields) eq 'HASH' or $protect_fields = {};
68 $project_edit_timeout =~ /^[1-9][0-9]*$/ or
69 die "Girocco::Config: \$project_edit_timeout must be a positive integer";
70 5 <= $project_edit_timeout && $project_edit_timeout <= 86400 or
71 die "Girocco::Config: \$project_edit_timeout seems unreasonable: $project_edit_timeout";
72 !$min_key_length || $min_key_length =~ /^[1-9][0-9]*$/ or
73 die "Girocco::Config: \$min_key_length must be undef or numeric";
74 !defined($max_readme_size) || $max_readme_size =~ /^[0-9]+$/ or
75 die "Girocco::Config: \$max_readme_size must be a whole number";
76 defined($mailsh_sizelimit) && $mailsh_sizelimit =~ /^[1-9][0-9]*$/ or
77 die "Girocco::Config: \$mailsh_sizelimit must be a positive number";
78 !defined($initial_branch) || $initial_branch eq "" ||
79 Girocco::ValidUtil::valid_branch_name($initial_branch) or
80 die "Girocco::Config: \$initial_branch grossly invalid: $initial_branch";
81 if (defined($empty_commit_message)) {
82 $empty_commit_message =~ s/^\s+//;
83 $empty_commit_message =~ s/\s+$//;
85 $admincc = $admincc ? 1 : 0;
86 $rootcert = "$certsdir/girocco_root_crt.pem" if $httpspushurl && !$rootcert;
87 $clientcert = "$certsdir/girocco_client_crt.pem" if $httpspushurl && !$clientcert;
88 $clientkey = "$certsdir/girocco_client_key.pem" if $httpspushurl && !$clientkey;
89 $clientcertsuffix = "$certsdir/girocco_client_suffix.pem" if $httpspushurl && !$clientcertsuffix;
90 $mobusercert = "$certsdir/girocco_mob_user_crt.pem" if $httpspushurl && $mob && !$mobusercert;
91 $mobuserkey = "$certsdir/girocco_mob_user_key.pem" if $httpspushurl && $mob && !$mobuserkey;
92 our $mobpushurl = $pushurl;
93 $mobpushurl =~ s,^ssh://,ssh://mob@,i if $mobpushurl;
94 $disable_dsa = 1 unless $pushurl;
95 $disable_dsa = $disable_dsa ? 1 : '';
96 our $httpdnsname = ($gitweburl =~ m,https?://([A-Za-z0-9.-]+),i) ? lc($1) : undef if $gitweburl;
97 our $httpsdnsname = ($httpspushurl =~ m,https://([A-Za-z0-9.-]+),i) ? lc($1) : undef if $httpspushurl;
98 $SmartHTTPOnly = $SmartHTTPOnly ? 1 : '';
99 $TLSHost = $TLSHost ? 1 : '';
100 $pretrustedroot = $pretrustedroot ? 1 : '';
101 $suppress_git_ssh_logging = $suppress_git_ssh_logging ? 1 : '';
102 $git_daemon_any_host = $git_daemon_any_host ? 1 : '';
103 if ((!defined($git_daemon_host_list) || $git_daemon_host_list =~ /^\s*$/) &&
104 (defined($gitpullurl) && $gitpullurl =~ m{^git://\[?[A-Za-z0-9.-:]}i)) {
105 if ($gitpullurl =~ m{^[gG][iI][tT]://([A-Za-z0-9.-]+)(?:[/:]|$)} ||
106 $gitpullurl =~ m{^[gG][iI][tT]://\[([0-9a-zA-Z.:%]+)\](?:[/:]|$)}) {
107 my $gdhn = lc($1);
108 $gdhn ne "." and $gdhn =~ s/\.$//;
109 my $gdhnl = $gdhn; $gdhnl =~ s/(?<!^)(?<!\.)\..*$//;
110 $git_daemon_host_list="$gdhn";
111 do {$git_daemon_host_list.=" $_" unless index(" $git_daemon_host_list "," $_ ")>=0}
112 foreach $gdhnl, qw"localhost ::1 127.0.0.1";
115 if (defined($git_daemon_host_list)) {
116 $git_daemon_host_list = lc($git_daemon_host_list);
117 $git_daemon_host_list =~ s/^\s+//;
118 $git_daemon_host_list =~ s/\s+$//;
119 $git_daemon_host_list = undef if $git_daemon_host_list eq "";
121 $mirror || $push or
122 die "Girocco::Config: neither \$mirror nor \$push is set?!";
123 !$push || ($pushurl || $httpspushurl || $gitpullurl || $httppullurl) or
124 die "Girocco::Config: no pull URL is set";
125 !$push || ($pushurl || $httpspushurl) or
126 die "Girocco::Config: \$push set but \$pushurl and \$httpspushurl are undef";
127 !$mirror || $mirror_user or
128 die "Girocco::Config: \$mirror set but \$mirror_user is undef";
129 $TLSHost = $TLSHost ? 1 : '';
130 $manage_users = $manage_users ? 1 : 0;
131 $chrooted = $chrooted ? 1 : 0;
132 $manage_users == $chrooted or
133 die "Girocco::Config: \$manage_users and \$chrooted must be set to the same value";
134 !$chrooted || uc($permission_control) ne 'ACL' or
135 die "Girocco::Config: resolving uids for ACL not supported when using chroot";
136 defined($permission_control) or $permission_control = '';
137 $permission_control = ucfirst(lc($permission_control));
138 (grep { $permission_control eq $_ } qw(Group Hooks)) or
139 die "Girocco::Config: \$permission_control must be set to Group or Hooks";
140 $chrooted || !$mob or
141 die "Girocco::Config: mob user supported only in the chrooted mode";
142 !$httpspushurl || $httpsdnsname or
143 die "Girocco::Config: \$httpspushurl invalid does not start with https://domainname";
144 !$svn_log_window_size || $svn_log_window_size =~ /^[1-9][0-9]*$/ or
145 die "Girocco::Config: \$svn_log_window_size must be undef or numeric";
146 defined($max_file_size512) && !$max_file_size512 and $max_file_size512 = undef;
147 !defined($max_file_size512) || $max_file_size512 =~ /^[1-9][0-9]*$/ && $max_file_size512 <= 2147483647 or
148 die "Girocco::Config: \$max_file_size512 must be undef or a positive integer <= 2147483647";
149 defined($max_clone_objects) && !$max_clone_objects and $max_clone_objects = undef;
150 !defined($max_clone_objects) || $max_clone_objects =~ /^[1-9][0-9]*$/ or
151 die "Girocco::Config: \$max_clone_objects must be undef or a positive integer";
152 !defined($posix_sh_bin) || $posix_sh_bin !~ /\s/ or
153 die "Girocco::Config: \$posix_sh_bin must not contain any whitespace";
154 !defined($perl_bin) || $perl_bin !~ /\s/ or
155 die "Girocco::Config: \$perl_bin must not contain any whitespace";
156 !$delay_gfi_redelta and $delay_gfi_redelta = undef;
157 !$git_no_mmap and $git_no_mmap = undef;
158 !$suppress_x_girocco and $suppress_x_girocco = undef;
159 !$jgit_compatible_bitmaps and $jgit_compatible_bitmaps = undef;
160 !$autogchack and $autogchack = undef;
161 !$reflogs_lifetime || $reflogs_lifetime !~ /^[1-9][0-9]*$/ and $reflogs_lifetime = 1;
162 $reflogs_lifetime = 0 + $reflogs_lifetime;
163 $reflogs_lifetime >= 0 or $reflogs_lifetime = 1;
164 $reflogs_lifetime <= 30 or $reflogs_lifetime = 30;
165 !defined $upload_pack_window || $upload_pack_window =~ /^[1-9][0-9]*$/ or
166 die "Girocco::Config: \$upload_pack_window must be undef or numeric";
167 !defined $upload_pack_window || (2 <= $upload_pack_window && $upload_pack_window <= 50) or
168 die "Girocco::Config: \$upload_pack_window must be in range 2..50";
169 !defined $max_receive_size || $max_receive_size =~ /^\d+[kKmMgG]?$/ or
170 die "Girocco::Config: \$max_receive_size setting is invalid";
171 defined $git_shared_repository_setting or $git_shared_repository_setting = 2;
172 $git_shared_repository_setting = lc($git_shared_repository_setting);
174 $git_shared_repository_setting =~ /^(?:false|umask|00*)$/ and do {
175 $git_shared_repository_setting = 0;
176 $var_umask = '0177';
177 $var_umask_ug = $var_umask;
178 last;
180 $git_shared_repository_setting =~ /^(?:true|group|1|00*1)$/ and do {
181 $git_shared_repository_setting = 1;
182 $var_umask = '0117';
183 $var_umask_ug = $var_umask;
184 last;
186 $git_shared_repository_setting =~ /^(?:all|world|everybody|2|00*2)$/ and do {
187 $git_shared_repository_setting = 2;
188 $var_umask = '0113';
189 $var_umask_ug = '0117';
190 last;
192 $git_shared_repository_setting =~ /^0[0-7]{1,3}$/ and do {
193 my $p = oct($git_shared_repository_setting);
194 $p &= ~0111;
195 $p |= 0600;
196 $git_shared_repository_setting = sprintf("0%03o", $p);
197 $var_umask = sprintf("0%03o", $p ^ 0777);
198 $var_umask_ug = sprintf("0%03o", ($p ^ 0777) | 007);
199 last;
201 die "Invalid \$Girocco::Config::git_shared_repository_setting setting ($git_shared_repository_setting)\n";
203 $var_umask_perm = $permission_control eq 'Group' ? $var_umask : '0';
204 defined($ENV{'SENDMAIL_PL_HOST'}) and eval 'our $sendmail_pl_host = $ENV{"SENDMAIL_PL_HOST"}';
205 defined($ENV{'SENDMAIL_PL_PORT'}) and eval 'our $sendmail_pl_port = $ENV{"SENDMAIL_PL_PORT"}';
206 defined($ENV{'SENDMAIL_PL_NCBIN'}) and eval 'our $sendmail_pl_ncbin = $ENV{"SENDMAIL_PL_NCBIN"}';
207 defined($ENV{'SENDMAIL_PL_NCOPT'}) and eval 'our $sendmail_pl_ncopt = $ENV{"SENDMAIL_PL_NCOPT"}';
208 defined($ENV{'PYTHON'}) and eval 'our $python = $ENV{"PYTHON"}';
210 # jailreporoot MUST NOT be absolute
211 defined($jailreporoot) && substr($jailreporoot, 0, 1) ne "/" or
212 die "Girocco::Config: \$jailreporoot MUST NOT be an absolute path\n";
214 # webreporoot can be undef
215 !defined($webreporoot) || substr($webreporoot, 0, 1) eq "/" or
216 die "Girocco::Config: \$webreporoot MUST be an absolute path if not undef\n";
218 # All these MUST be absolute paths
220 no strict 'refs';
221 defined(${$_}) && substr(${$_}, 0, 1) eq "/" or
222 die "Girocco::Config: \$$_ MUST be an absolute path\n"
223 foreach qw(basedir certsdir reporoot chroot webroot cgiroot projlist_cache_dir);
226 # Make sure Git has a consistent and reproducible environment
228 $ENV{'XDG_CONFIG_HOME'} = $chroot.'/var/empty';
229 $ENV{'HOME'} = $chroot.'/etc/girocco';
230 $ENV{'TMPDIR'} = '/tmp';
231 $ENV{'GIT_CONFIG_NOSYSTEM'} = 1;
232 $ENV{'GIT_ATTR_NOSYSTEM'} = 1;
233 $ENV{'GIT_NO_REPLACE_OBJECTS'} = 1;
234 $ENV{'GIT_TERMINAL_PROMPT'} = 0;
235 $ENV{'GIT_ASKPASS'} = $basedir.'/bin/git-askpass-password';
236 delete $ENV{'GIT_USER_AGENT'};
237 $ENV{'GIT_USER_AGENT'} = $git_client_ua if defined($git_client_ua);
238 delete $ENV{'GIT_HTTP_USER_AGENT'};
239 delete $ENV{'GIT_CONFIG_PARAMETERS'};
240 delete $ENV{'GIT_ALTERNATE_OBJECT_DIRECTORIES'};
241 delete $ENV{'GIT_CONFIG'};
242 delete $ENV{'GIT_DIR'};
243 delete $ENV{'GIT_GRAFT_FILE'};
244 delete $ENV{'GIT_INDEX_FILE'};
245 delete $ENV{'GIT_OBJECT_DIRECTORY'};
246 delete $ENV{'GIT_NAMESPACE'};
248 # Guarantee a sane umask for Girocco
250 umask(umask() & ~0770);