From cd91e59d897b1359dd91b2b9e5e7e008d2dbd9ed Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 7 Nov 2010 05:30:12 +0000 Subject: [PATCH] certificates ala communigate, RT#7515 --- FS/FS/svc_cert.pm | 76 ++++++++++++-- httemplate/edit/process/svc_cert.cgi | 8 +- httemplate/edit/svc_cert.cgi | 174 ++++++++++++++++++--------------- httemplate/misc/svc_cert-generate.html | 25 +++++ httemplate/view/svc_cert.cgi | 41 +++++++- 5 files changed, 234 insertions(+), 90 deletions(-) create mode 100644 httemplate/misc/svc_cert-generate.html diff --git a/FS/FS/svc_cert.pm b/FS/FS/svc_cert.pm index 08bb8c094..e3ef3256f 100644 --- a/FS/FS/svc_cert.pm +++ b/FS/FS/svc_cert.pm @@ -79,9 +79,9 @@ state country -=item contact +=item cert_contact -contact +contact email =back @@ -124,7 +124,7 @@ sub table_info { 'city' => { label=>'City', %dis, }, 'state' => { label=>'State', %dis, }, 'country' => { label=>'Country', %dis, }, - 'cert_contact' => { label=>'Contact', %dis, }, + 'cert_contact' => { label=>'Contact email', %dis, }, #'another_field' => { # 'label' => 'Description', @@ -213,7 +213,7 @@ sub check { || $self->ut_textn('city') || $self->ut_textn('state') || $self->ut_textn('country') #XXX char(2) or NULL - || $self->ut_textn('contact') + || $self->ut_textn('cert_contact') ; return $error if $error; @@ -271,14 +271,23 @@ sub subj { ); } -sub generate_csr { +sub _file { my $self = shift; - my $in = $self->privatekey; + my $field = shift; my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc; #XXX actual cache dir my $fh = new File::Temp( - TEMPLATE => 'certkey.'. '.XXXXXXXX', + TEMPLATE => 'cert.'. '.XXXXXXXX', DIR => $dir, ) or die "can't open temp file: $!\n"; + print $fh $self->$field; + close $fh; + $fh; +} + +sub generate_csr { + my $self = shift; + + my $fh = $self->_file('privatekey'); run( [qw( openssl req -new -key ), $fh->filename, '-subj', $self->subj ], '>pipe'=>\*OUT, '2>'=>'/dev/null' @@ -289,6 +298,59 @@ sub generate_csr { $self->csr($csr); } +#sub check_csr { +# my $self = shift; +#} + +sub generate_selfsigned { + my $self = shift; + + my $days = 730; + + my $key = $self->_file('privatekey'); + my $csr = $self->_file('csr'); + + run( [qw( openssl req -x509 -nodes ), + '-days' => $days, + '-key' => $key->filename, + '-in' => $csr->filename, + ], + '>pipe'=>\*OUT, '2>'=>'/dev/null' + ) + or die "error running openssl: $!"; + #XXX error checking + my $csr = join('', ); + $self->certificate($csr); +} + +#openssl x509 -in cert -noout -subject -issuer -dates -serial +#subject= /CN=cn.example.com/ST=AK/O=Tofuy/OU=Soybean dept./C=US/L=Tofutown +#issuer= /CN=cn.example.com/ST=AK/O=Tofuy/OU=Soybean dept./C=US/L=Tofutown +#notBefore=Nov 7 05:07:42 2010 GMT +#notAfter=Nov 6 05:07:42 2012 GMT +#serial=B1DBF1A799EF207B + +sub check_certificate { + my $self = shift; + + my $in = $self->certificate; + run( [qw( openssl x509 -noout -subject -issuer -dates -serial )], + '<'=>\$in, + '>pipe'=>\*OUT, '2>'=>'/dev/null' + ) + or die "error running openssl: $!"; + #XXX error checking + + my %hash = (); + while () { + warn $_; + /^\s*(\w+)=\s*(.*)\s*$/ or next; + $hash{$1} = $2; + } + + %hash; +} + =back =head1 BUGS diff --git a/httemplate/edit/process/svc_cert.cgi b/httemplate/edit/process/svc_cert.cgi index 1bf749f96..58b95a6e9 100644 --- a/httemplate/edit/process/svc_cert.cgi +++ b/httemplate/edit/process/svc_cert.cgi @@ -17,9 +17,7 @@ % $cgi->param('error', $error); <% $cgi->redirect(popurl(2). "svc_cert.cgi?". $cgi->query_string ) %> %} else { -%#change link when we make a non-generic view -%#<% $cgi->redirect(popurl(3). "view/svc_cert.cgi?$svcnum") %> -<% $cgi->redirect(popurl(3). "view/svc_Common.html?svcdb=svc_cert;svcnum=$svcnum") %> +<% $cgi->redirect(popurl(3). "view/svc_cert.cgi?$svcnum") %> % } <%init> @@ -39,7 +37,7 @@ my $old = ''; if ( $svcnum ) { $old = qsearchs('svc_cert', { 'svcnum' => $svcnum } ) #agent virt; or die 'unknown svcnum'; - $new->$_( $old->$_ ) for grep $old->$_, qw( privatekey ); + $new->$_( $old->$_ ) for grep $old->$_, qw( privatekey csr certificate cacert ); } my $popup = 0; @@ -58,7 +56,7 @@ if ( $cgi->param('privatekey') eq '_generate' ) { #generate $new->privatekey( $cgi->param('privatekey') ); -} #elsif ( $cgi->param('privatekey') eq '_clear' ) { #import +} #elsif ( $cgi->param('privatekey') eq '_clear' ) { #clear my $error = ''; if ($cgi->param('svcnum')) { diff --git a/httemplate/edit/svc_cert.cgi b/httemplate/edit/svc_cert.cgi index 89460f3e3..93194228e 100644 --- a/httemplate/edit/svc_cert.cgi +++ b/httemplate/edit/svc_cert.cgi @@ -12,92 +12,112 @@ Private key -% if ( $svc_cert->privatekey && $svc_cert->check_privatekey ) { - Verification OK -% # remove key & cert link? just unprovision? - - -% my $cust_main = $svc_cert->cust_svc->cust_pkg->cust_main; +% if ( $svc_cert->privatekey && $svc_cert->check_privatekey ) { - - Organization - - + Verification OK +% # remove key & cert link? just unprovision? - - Organization Unit - - + - - City - <% include('/elements/city.html', - 'city' => $svc_cert->city || $cust_main->city, - 'state' => $svc_cert->state || $cust_main->state, - 'country' => $svc_cert->country || $cust_main->country, - ) - %> - - +% if (0) { #( $svc_cert->csr_submitted ) { #XXX add field? date? } - - State - <% include('/elements/select-state.html', - 'city' => $svc_cert->city || $cust_main->city, - 'state' => $svc_cert->state || $cust_main->state, - 'country' => $svc_cert->country || $cust_main->country, - ) - %> - - - - - City - <% include('/elements/select-country.html', - 'city' => $svc_cert->city || $cust_main->city, - 'state' => $svc_cert->state || $cust_main->state, - 'country' => $svc_cert->country || $cust_main->country, - ) - %> - - +% # just show the fields once the csr has been submitted % } else { -% my $re = ''; -% if ( $svc_cert->privatekey ) { - Verification error -% $re = 'Clear and Re-'; -% } - <% include('/elements/popup_link.html', { - 'action' => "svc_cert/generate_privatekey.html$link_query", - 'label' => $re.'Generate', - 'actionlabel' => 'Generate private key', - #opt - 'width' => '350', - 'height' => '150' - #'color' => '#ff0000', - #'closetext' => 'Go Away', # the value '' removes the link - })%> - - or - - <% include('/elements/popup_link.html', { - 'action' => "svc_cert/import_privatekey.html$link_query", - 'label' => $re.'Import', - 'actionlabel' => 'Import private key', - #opt - 'width' => '544', - 'height' => '368', - #'color' => '#ff0000', - #'closetext' => 'Go Away', # the value '' removes the link - })%> -% if ( $svc_cert->privatekey ) { -
<% $svc_cert->privatekey |h %>
-% } + +% my $cust_main = $svc_cert->cust_svc->cust_pkg->cust_main; + + + Common name + + + + + Organization + + + + + Organization Unit + + + + + City + <% include('/elements/city.html', + 'city' => $svc_cert->city || $cust_main->city, + 'state' => $svc_cert->state || $cust_main->state, + 'country' => $svc_cert->country || $cust_main->country, + ) + %> + + + + + State + <% include('/elements/select-state.html', + 'city' => $svc_cert->city || $cust_main->city, + 'state' => $svc_cert->state || $cust_main->state, + 'country' => $svc_cert->country || $cust_main->country, + ) + %> + + + + + Country + <% include('/elements/select-country.html', + 'city' => $svc_cert->city || $cust_main->city, + 'state' => $svc_cert->state || $cust_main->state, + 'country' => $svc_cert->country || $cust_main->country, + ) + %> + + + + + Contact email + + + +% } + +% } else { +% my $re = ''; +% if ( $svc_cert->privatekey ) { + Verification error +% $re = 'Clear and Re-'; +% } + <% include('/elements/popup_link.html', { + 'action' => "svc_cert/generate_privatekey.html$link_query", + 'label' => $re.'Generate', + 'actionlabel' => 'Generate private key', + #opt + 'width' => '350', + 'height' => '150' + #'color' => '#ff0000', + #'closetext' => 'Go Away', # the value '' removes the link + })%> + + or + + <% include('/elements/popup_link.html', { + 'action' => "svc_cert/import_privatekey.html$link_query", + 'label' => $re.'Import', + 'actionlabel' => 'Import private key', + #opt + 'width' => '544', + 'height' => '368', + #'color' => '#ff0000', + #'closetext' => 'Go Away', # the value '' removes the link + })%> +% if ( $svc_cert->privatekey ) { +
<% $svc_cert->privatekey |h %>
+% } -% } +% }
diff --git a/httemplate/misc/svc_cert-generate.html b/httemplate/misc/svc_cert-generate.html new file mode 100644 index 000000000..10e8ab4e9 --- /dev/null +++ b/httemplate/misc/svc_cert-generate.html @@ -0,0 +1,25 @@ +% if ($error) { +% errorpage($error); +%} else { +<% $cgi->redirect($p."view/svc_cert.cgi?$svcnum") %> +%} +<%init> + +$cgi->param('svcnum') =~ /^(\d+)$/ or die 'illegal svcnum'; +my $svcnum = $1; + +my $svc_cert = qsearchs('svc_cert', { 'svcnum' => $svcnum } ) + or die 'unknown svcnum'; + +my $error = ''; +if ( $cgi->param('action') eq 'generate_csr' ) { + $svc_cert->generate_csr; + $error = $svc_cert->replace; +} elsif ( $cgi->param('action') eq 'generate_selfsigned' ) { + $svc_cert->generate_selfsigned; + $error = $svc_cert->replace; +} else { + die 'unknown action'; +} + + diff --git a/httemplate/view/svc_cert.cgi b/httemplate/view/svc_cert.cgi index 92902d6d2..36f598b9a 100644 --- a/httemplate/view/svc_cert.cgi +++ b/httemplate/view/svc_cert.cgi @@ -28,7 +28,46 @@ my @fields = ( } }, }, - qw( organization organization_unit city state country cert_contact ) + qw( common_name organization organization_unit city state country cert_contact + ), + { 'field'=>'csr', + 'value'=> sub { + my $svc_cert = shift; + if ( $svc_cert->csr ) { #display the subject etc? + '
'. $svc_cert->csr.
+        '
'; + } elsif ( $svc_cert->common_name ) { + my $svcnum = $svc_cert->svcnum; + qq(Generate); + } else { + ''; + } + }, + }, + { 'field'=>'certificate', + 'value'=> sub { + my $svc_cert = shift; + if ( $svc_cert->certificate ) { + + my %hash = $svc_cert->check_certificate; + my $out = ''; #XXX better formatting + foreach my $key ( keys %hash ) { + $out .= ""; + } + $out .= '
$key$hash{$key}
'; + + $out .= '
'.
+                $svc_cert->certificate.
+                '
'; + $out; + } elsif ( $svc_cert->csr ) { + my $svcnum = $svc_cert->svcnum; + qq(Generate self-signed); + } else { + ''; + } + }, + }, ); -- 2.11.0