#!/usr/bin/perl -w
# This expects input of the form:
# type filenameprefix commonname emailaddress password
# user path/joeuser Joe User joeuser@org.com 8gfBl@#9
# host path/twizzle twizzle.org.com joeuser@org.com
#
# Fiields are separated by tabs. Users have passwords but
# hosts do not.
use strict;
my($ca_pass_file) = "capassfile.txt";
# This is necessary because if you do this with large input files,
# your machine will run out of randomness.
print STDERR "Running find to get randomness.\n";
my(@files) = grep(!/\'/, (`find /Users/ian/src`));
chomp @files;
print STDERR "Validating.\n";
my(@lines);
# Input validation pass
while(<>) {
chomp;
my($type,$filename,$commonname,$email,$password) = split /\t/;
if(not ($type eq 'user' or $type eq 'host')) {
die "Error in input: first field should be type, either 'user' or 'host'.";
}
my $input_file = "$filename.txt";
my $key_file = "$filename.key";
my $req_file = "$filename.req";
my $cert_file = "$filename.crt";
if(-e $key_file) {
die "Key file exists: '$key_file'";
}
if(-e $req_file) {
die "Request file exists: '$req_file'";
}
if(-e $cert_file) {
die "Certificate file exists: '$cert_file'";
}
# How to validate common name?
# Stronger validation of email addresses?
# See: http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html
# see also perlfaq9
if(not $email =~ /^[\w.-]+\@(?:[\w-]+\.)+\w+$/) {
die "Invalid email address: '$email'";
}
if($type eq 'user' and $password eq '') {
die "User can't have null password.";
}
if($type eq 'host' and $password ne '') {
die "Host must have null password.";
}
push @lines, $_;
}
print STDERR "Running.\n";
foreach (@lines) {
chomp;
my($type,$filename,$commonname,$email,$password) = split /\t/;
my $input_file = "$filename.txt";
my $key_file = "$filename.key";
my $req_file = "$filename.req";
my $cert_file = "$filename.crt";
my $pass_file = "$filename.pass";
# create input file
open FF, ">$input_file" or die "Can't open '$input_file': $!";
print FF "\n\n\n\n\n\n$commonname\n$email\n";
close FF;
# make the reqs and keys
my $files = "'".$files[int(rand($#files))]."':'".$files[int(rand($#files))]."':'".$files[int(rand($#files))]."'";
if($type eq 'user') {
# create password file
open FF, ">$pass_file" or die "Can't open '$pass_file': $!";
print FF "$password\n";
close FF;
&docmd("openssl req -newkey rsa:1024 -keyout $key_file -passout file:$pass_file -config openssl.cnf -out $req_file -rand $files < $input_file");
unlink($pass_file) or die "Can't delete '$pass_file': $!";
} else {
&docmd("openssl req -newkey rsa:1024 -keyout $key_file -nodes -config openssl.cnf -out $req_file -rand $files < $input_file");
}
&docmd("openssl ca -config openssl.cnf -passin file:$ca_pass_file -batch -out $cert_file -infiles $req_file");
}
sub docmd {
my($cmd) = @_;
print "$cmd\n";
print `$cmd`;
}