aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2018-02-09 12:11:18 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2018-02-09 12:18:16 +0200
commitc95c16005cb6ffafd27e884c405b839e049384a6 (patch)
tree536c2895b923e4eb539d254a4ba7b5568bdb513f
parent70922eff7611175811958174e0c5ba45948bb118 (diff)
downloadacmeman-c95c16005cb6ffafd27e884c405b839e049384a6.tar.gz
acmeman-c95c16005cb6ffafd27e884c405b839e049384a6.tar.bz2
Use configurable key length.
* acmeman: (syntax) New configuration settings: core.key-size and domain.*.key-size. (make_csr): Take the key size as 2nd argument. (domain_cert_expires): Determine key size from the configuration. Include it in the debug output. (coalesce): Bugfix. * lib/App/Acmeman/Apache/Layout.pm (apache_layout_tab): Additional tests to resolve ambuguities. (new): Use the _test field to resolve ambiguities. * lib/App/Acmeman/Source/Apache.pm (server_root): New method. (http_include): Determine the server root by probing the server, unless it is set explicitly in the configuration. (probe): New method.
-rwxr-xr-xacmeman43
-rw-r--r--lib/App/Acmeman/Apache/Layout.pm5
-rw-r--r--lib/App/Acmeman/Source/Apache.pm54
3 files changed, 84 insertions, 18 deletions
diff --git a/acmeman b/acmeman
index d166a88..bd01b52 100755
--- a/acmeman
+++ b/acmeman
@@ -233,6 +233,10 @@ underlying X509 module, and therefore is not enabled by default.
Valid values for I<BOOL> are: B<1>, B<on>, B<true>, or B<yes>, for
true, and B<0>, B<off>, B<false>, or B<no> for false (all values
case-insensitive).
+
+=item B<key-size=>I<N>
+
+Size of the RSA key to use, in bits. Default is 4096.
=back
@@ -254,6 +258,11 @@ statement from the B<[core]> section will be used.
Defines alternative name for the certificate. Multiple B<alt> statements
are allowed.
+
+=item B<key-size=>I<N>
+
+Size of the RSA key to use, in bits. If not set, the B<core.key-size>
+setting is used.
=back
@@ -598,8 +607,8 @@ sub debug_to_loglevel {
}
sub make_csr {
- my $dom = shift;
- my $req = Crypt::OpenSSL::PKCS10->new(4096);
+ my ($dom, $keysize) = @_;
+ my $req = Crypt::OpenSSL::PKCS10->new($keysize);
$req->set_subject("/CN=".$dom->cn);
$req->add_ext(Crypt::OpenSSL::PKCS10::NID_subject_alt_name,
join(',', map { "DNS:$_" } $dom->alt))
@@ -698,17 +707,22 @@ sub domain_cert_expires {
sub register_domain_certificate {
my $domain = shift;
+ my $key_size = $config->get('domain', $domain, 'key-size')
+ || $config->get('core', 'key-size');
+
if ($debug) {
my $crt = $domain->certificate_file;
my $alt = join(',', $domain->alt);
if (-f $crt) {
- debug(1, "renewing $crt: CN=$domain, alternatives=$alt");
+ debug(1, "renewing $crt: CN=$domain, alternatives=$alt, key_size=$key_size");
} else {
- debug(1, "issuing $crt: CN=$domain, alternatives=$alt");
+ debug(1, "issuing $crt: CN=$domain, alternatives=$alt, key_size=$key_size");
}
}
+
return 1 if $dry_run;
-
+ $account_key = Crypt::OpenSSL::RSA->generate_key($key_size);
+
my $acme = Protocol::ACME->new(
host => $acme_endpoint{$acme_host},
account_key => { buffer => $account_key->get_private_key_string(), format => 'PEM' },
@@ -727,7 +741,7 @@ sub register_domain_certificate {
$acme->cleanup_challenge($challenge);
}
- my $csr = make_csr($domain);
+ my $csr = make_csr($domain, $key_size);
my $cert = $acme->sign({ format => 'PEM', buffer => $csr->get_pem_req() });
my $chain = $acme->chain();
@@ -826,7 +840,7 @@ sub coalesce {
my @domlist;
foreach my $ent (sort { $a->{domain} cmp $b->{domain} }
map { { ord => $i++, domain => $_ } } @{$ref}) {
- if (@domlist && $domlist[-1]->cn eq $ent->cn) {
+ if (@domlist && $domlist[-1]->{domain}->cn eq $ent->{domain}->cn) {
$domlist[-1] += $ent;
} else {
push @domlist, $ent;
@@ -842,7 +856,7 @@ sub collect {
while (my ($k, $v) = each %{$config->get('domain')}) {
my $dom;
my $ft;
-
+
if (exists($v->{files})) {
if (my $fref = $config->get('files', $v->{files})) {
$dom = new App::Acmeman::Domain(
@@ -917,8 +931,9 @@ my %syntax = (
rootdir => { default => '/var/www/acme' },
files => 1,
'time-delta' => { default => 86400 },
- source => 1,
- 'check-alt-names' => { default => 0, parser => \&cb_check_bool }
+ source => { default => 'apache' },
+ 'check-alt-names' => { default => 0, parser => \&cb_parse_bool },
+ 'key-size' => { re => '^\d+$', default => 4096 }
}
},
files => {
@@ -939,7 +954,8 @@ my %syntax = (
'*' => {
section => {
alt => { array => 1 },
- files => 1
+ files => 1,
+ 'key-size' => { re => '^\d+$' }
}
}
}
@@ -1013,8 +1029,10 @@ my @domlist;
$config = new App::Acmeman::Config($config_file,
syntax => \%syntax,
defaults => {
- 'core.source' => 'apache'
+ 'core.source' => 'apache',
+ 'core.key-size' => 4096,
});
+
if ($config->success) {
if (my $source = $config->get(qw(core source))) {
my ($name, @args) = quotewords('\s+', 0, $source);
@@ -1057,7 +1075,6 @@ prep_dir($config->get(qw(core rootdir)).'/file');
# abend(EX_CONFIG, "filename patterns not defined")
# unless (defined($filename_arg) && defined($filename_pattern{cert}));
-$account_key = Crypt::OpenSSL::RSA->generate_key(4096);
$challenge = Protocol::ACME::Challenge::LocalFile->new({
www_root => $config->get(qw(core rootdir))
});
diff --git a/lib/App/Acmeman/Apache/Layout.pm b/lib/App/Acmeman/Apache/Layout.pm
index 77e2f8f..44d5e3d 100644
--- a/lib/App/Acmeman/Apache/Layout.pm
+++ b/lib/App/Acmeman/Apache/Layout.pm
@@ -10,6 +10,7 @@ our @ISA = qw(Exporter);
my %apache_layout_tab = (
slackware => {
+ _test => sub { -d '/etc/httpd/extra' },
_config_file => '/etc/httpd/httpd.conf',
_incdir => '/etc/httpd/extra',
_restart => '/etc/rc.d/rc.httpd restart'
@@ -42,6 +43,7 @@ my %apache_layout_tab = (
},
suse => {
_config_file => '/etc/apache2/httpd.conf',
+ _test => sub { ! -f '/etc/apache2/apache2.conf' },
_incdir => '/etc/apache2/conf.d',
_restart => 'service httpd restart'
# or systemctl restart apache2.service
@@ -59,6 +61,9 @@ sub new {
# Autodetect
while (my ($n, $layout) = each %apache_layout_tab) {
if (-f $layout->{_config_file}) {
+ if (exists($layout->{_test}) && !&{$layout->{_test}}) {
+ next;
+ }
debug(2, "assuming Apache layout \"$n\"");
$name = $n;
last;
diff --git a/lib/App/Acmeman/Source/Apache.pm b/lib/App/Acmeman/Source/Apache.pm
index f86c02f..c4a0570 100644
--- a/lib/App/Acmeman/Source/Apache.pm
+++ b/lib/App/Acmeman/Source/Apache.pm
@@ -5,6 +5,8 @@ use warnings;
use Carp;
use feature 'state';
use File::Path qw(make_path);
+use File::Spec;
+use IPC::Open3;
require App::Acmeman::Apache::Layout;
our @ISA = qw(App::Acmeman::Apache::Layout);
@@ -84,7 +86,7 @@ sub examine_http_config {
s/^\s+//;
next if /^(#.*)?$/;
if (/^include(optional)?\s+(.+?)\s*$/i) {
-# debug(3, "$file:$line: state $state: Include$1 $2");
+ #debug(3, "$file:$line: state $state: Include".($1||'')." $2");
$self->http_include($self->dequote($2), defined($1));
next;
}
@@ -96,7 +98,7 @@ sub examine_http_config {
@server_aliases = ();
$reference = undef;
} elsif (/^ServerRoot\s+(.+)/i) {
- $self->{_server_root} = $self->dequote($1);
+ $self->server_root($self->dequote($1));
} elsif (/^<(?:(?i)Macro)\s+LetsEncryptChallenge/) {
$state = STATE_MACRO_CHALLENGE;
} elsif (/^<(?:(?i)Macro)\s+LetsEncryptSSL\s+(.+?)\s*>/) {
@@ -181,11 +183,25 @@ sub examine_http_config {
return 1;
}
+sub server_root {
+ my $self = shift;
+ if (my $v = shift) {
+ croak "too many arguments" if $@;
+ $self->{_server_root} = $v;
+ }
+ return $self->{_server_root};
+}
+
sub http_include {
my ($self, $pattern, $optional) = @_;
- $pattern = "$self->{_server_root}/$pattern" unless $pattern =~ m{^/};
- $pattern =~ s{/*$}{};
- $pattern .= '/*' if -d $pattern;
+
+ unless ($self->server_root) {
+ $self->probe;
+ }
+
+ $pattern = File::Spec->catfile($self->{_server_root}, $pattern)
+ unless $pattern =~ m{^/};
+ $pattern = File::Spec->catfile($pattern, '*') if -d $pattern;
foreach my $file (glob $pattern) {
if ($optional && ! -e $file) {
debug(1, "optional include file \"$file\" doesn't exist");
@@ -281,4 +297,32 @@ EOT
return 1;
}
+sub probe {
+ my ($self, @servlist) = @_;
+ @servlist = qw(/usr/sbin/httpd /usr/sbin/apache2)
+ unless (@servlist);
+ open(my $nullout, '>', File::Spec->devnull);
+ open(my $nullin, '<', File::Spec->devnull);
+ foreach my $serv (@servlist) {
+ use Symbol 'gensym';
+ my $fd = gensym;
+ eval {
+ if (my $pid = open3($nullin, $fd, $nullout, $serv, '-V')) {
+ while (<$fd>) {
+ chomp;
+ if (/^\s+-D\s+HTTPD_ROOT=(.+)\s*$/) {
+ $self->server_root($self->dequote($1));
+ last;
+ }
+ }
+ }
+ };
+ close $fd;
+ last unless ($@)
+ }
+ close $nullin;
+ close $nullout;
+}
+
+
1;

Return to:

Send suggestions and report system problems to the System administrator.