From 1aefd926555beac5d7618c2375727df0c4470504 Mon Sep 17 00:00:00 2001 From: jake Date: Thu, 22 Sep 2022 17:48:50 -0400 Subject: Add server_alias config option. Add map_server_alias. Modifed auto_cert to generate certs for the alias. Changed some logic for detecting server_alias'. Update the sample config file. --- TO_FIX.md | 5 ++++ config.toml.sample | 4 +++ gmi.pl | 77 +++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 76 insertions(+), 10 deletions(-) diff --git a/TO_FIX.md b/TO_FIX.md index 611c3c9..a2942eb 100644 --- a/TO_FIX.md +++ b/TO_FIX.md @@ -25,3 +25,8 @@ reduce complexity in cert_req() permission denied when the file is readable (MAC permissions) use GetOpt::Long in a reasonable manner + +map_server_alias() perhaps should not exist. +In general, I am unsatisfied with the program keeping the configuration file in memory and constantly referring to it. map_server_alias() literally just copies it's vhost's config and keeps it in the config hash. + +reduce complexity in listen_config() diff --git a/config.toml.sample b/config.toml.sample index c1962c7..a668491 100644 --- a/config.toml.sample +++ b/config.toml.sample @@ -80,6 +80,10 @@ assume_index = true # A more realistic example #['example.com'] +# Listen to more than just 'example.com' with server_alias. No need two vhost configurations. +# server_alias can just be a single string, e.g. "server_alias='www.example.com'". An array allows +# for more than one alias. If auto_cert is true, then *ON CREATION OF THE CERT* the server_alias's will be added to it. +#server_alias=['www.example.com', 'example.org'] # bind can be set to a string or a list or 'no' which will not be accessible via IP address. #bind = ['172.16.0.53', '10.43.14.32'] #ports = [10000,10001,10002] diff --git a/gmi.pl b/gmi.pl index d3237c4..2029cc3 100755 --- a/gmi.pl +++ b/gmi.pl @@ -7,7 +7,7 @@ use warnings; use 5.010; #use diagnostics; -our $VERSION = 'v0.19.0'; +our $VERSION = 'v0.20.0'; # Modules use IO::Socket::SSL; # CPAN @@ -68,7 +68,7 @@ const our @VALID_DEFAULT_SETTINGS => unix redirection redirect gone/; const our @VALID_VHOST_SETTINGS => qw/auto_cert assume_index dir_listing root cert key default_mime bind ports - unix redirection redirect cert_req gone/; + unix redirection redirect cert_req gone server_alias/; my $config_path = './config.toml'; if ($ARGV[0]) { @@ -96,9 +96,12 @@ my @srv = ip_config($listen_config); my %ssl_config = ssl_config($config); ssl_vhost_cert_key(\%ssl_config); +### %ssl_config my $fork_toggled = fork_toggle($config); +map_server_alias($config); + # let the user know if an invalid option was used check_config_keys($config); @@ -142,6 +145,7 @@ while (my @ready = $sel->can_read) { my $fh = shift @ready; $cl = $fh->accept; get_fh_data($fh, $cl, \%data); + ### %data maybe_fork() and next; @@ -165,6 +169,7 @@ while (my @ready = $sel->can_read) { speak($cl, 'proxy_req_refused'); goto CLOSE; } + ### %data my $url; my $path; @@ -267,7 +272,7 @@ sub respond_to_client { if (not $data{cl_path_translated} = get_request_in_vhost_root($vhost, $path)) { goto FAILURE; } - ### $doc_loc + ## $doc_loc # checking if the path already has .gone for 'some reason' if (substr($data{cl_path_translated}, -5, 5) eq '.gone') { ## no critic (MagicNumbers) @@ -380,6 +385,11 @@ sub gen_cert { 'not_before' => $not_before, 'not_after' => $not_after, ); + if (exists $config->{$hostname}{server_alias}) { + for my $alias (give_array($config->{$hostname}{server_alias})) { + push @{ $cert{subjectAltNames} }, ['DNS', $alias]; + } + } my ($cert, $key) = CERT_create(%cert); my $old_umask = umask oct $UMASK_FOR_CERTS_KEYS; @@ -737,6 +747,12 @@ sub ssl_vhost_cert_key { my $cert_loc; my $key_loc; + my @hosts; + push @hosts, $vhost; + if (exists $config->{$vhost}{server_alias}) { + push @hosts, give_array($config->{$vhost}{server_alias}); + } + if (exists $config->{$vhost}{cert} and exists $config->{$vhost}{key}) { $cert_loc = accurate_path($config->{$vhost}{cert}, $cert_key_dir); if (! -e $cert_loc) { @@ -771,8 +787,10 @@ sub ssl_vhost_cert_key { } if ($error_free) { - $ssl_ref->{SSL_cert_file}{$vhost} = $cert_loc; - $ssl_ref->{SSL_key_file}{$vhost} = $key_loc; + for my $host (@hosts) { + $ssl_ref->{SSL_cert_file}{$host} = $cert_loc; + $ssl_ref->{SSL_key_file}{$host} = $key_loc; + } } else { serr("$vhost: will not listen for incoming requests."); @@ -898,6 +916,7 @@ sub timeout_secs { } } +## no critic (Complex) sub listen_config { my ($conf_ref, $ssl_ref, $ip_ref) = @_; my %listen; @@ -951,21 +970,45 @@ sub listen_config { for my $port (give_array($ports)) { for my $bind (give_array($binds)) { push @{ $listen{$bind}{$port} }, $vhost; + if (exists $conf_ref->{$vhost}{server_alias}) { + push @{ $listen{$bind}{$port} }, give_array($conf_ref->{$vhost}{server_alias}); + } } } # check vhost unix socket otherwise check for default unix socket - if (exists $conf_ref->{$vhost}{unix} and $conf_ref->{$vhost}{unix} ne 'no') { - $listen{unix}{path}{$vhost} = $conf_ref->{$vhost}{unix}; - push @{ $listen{unix}{listen} }, $vhost; + if (exists $conf_ref->{$vhost}{unix}) { + if ($conf_ref->{$vhost}{unix} ne 'no') { + my @hosts; + push @hosts, $vhost; + if (exists $conf_ref->{$vhost}{server_alias}) { + for my $alias (give_array($conf_ref->{$vhost}{server_alias})) { + push @hosts, $alias; + } + } + for my $host (@hosts) { + $listen{unix}{path}{$host} = $conf_ref->{$vhost}{unix}; + push @{ $listen{unix}{listen} }, $host; + } + } } elsif (exists $listen{unix}{path}{default}) { - push @{ $listen{unix}{listen} }, $vhost; + my @hosts; + push @hosts, $vhost; + if (exists $conf_ref->{$vhost}{server_alias}) { + for my $alias (give_array($conf_ref->{$vhost}{server_alias})) { + push @hosts, $alias; + } + } + for my $host (@hosts) { + push @{ $listen{unix}{listen} }, $host; + } } } # ## %listen return \%listen; } +## use critic sub give_array { my ($ref) = @_; @@ -1127,7 +1170,7 @@ sub verify_cert_callback { #6. The depth of the certificate in the chain. Depth 0 is the leaf certificate. ## $pem $data{cl_cert} = CERT_asHash(PEM_string2cert(Net::SSLeay::PEM_get_string_X509($_[4]))); - ### $cl_cert + ## $cl_cert return 1; } ## use critic @@ -1297,3 +1340,17 @@ sub undef_data { undef $data{cl_query_string}; return 1; } + +sub map_server_alias { + my ($conf_ref) = @_; + for my $vhost ( keys %{ $conf_ref } ) { + next if ($vhost eq 'default'); + + if (exists $conf_ref->{$vhost}{server_alias}) { + for my $host ( give_array($conf_ref->{$vhost}{server_alias}) ) { + # not a deep copy, thankfully. + $conf_ref->{$host} = $conf_ref->{$vhost}; + } + } + } +} -- cgit v1.2.3