From b3a754cd4561e908ee117849b82ef7bedffb4046 Mon Sep 17 00:00:00 2001 From: Gary Wong <gtw@cs.utah.edu> Date: Fri, 15 May 2009 21:57:46 +0000 Subject: [PATCH] Checkpointing work on URN support in certificates and credentials. URNs are now generated for new certificates. However, UUIDs and old HRNs are still used, for compatibility. --- account/mkusercert.in | 4 ++++ protogeni/etc/protogeni.sql | 1 + protogeni/lib/GeniCertificate.pm.in | 33 +++++++++++++++++++++++------ protogeni/lib/GeniCredential.pm.in | 2 ++ protogeni/test/showcredential.py | 16 +++++++------- protogeni/updates/3 | 18 ++++++++++++++++ ssl/usercert.cnf.in | 1 + 7 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 protogeni/updates/3 diff --git a/account/mkusercert.in b/account/mkusercert.in index 4e95030373..3755dad62b 100644 --- a/account/mkusercert.in +++ b/account/mkusercert.in @@ -256,6 +256,10 @@ else { } print TEMP "CN\t\t= $user_uuid\n"; print TEMP "emailAddress\t= $user_uid" . "\@" . "$OURDOMAIN\n"; + +print TEMP "\n[ req_altname ]\nURI=urn:publicid:IDN+$OURDOMAIN" . + "+user+$user_uid\nemail=$user_uid" . "\@" . "$OURDOMAIN\n"; + close(TEMP) or fatal("Could not close usercert.cnf: $!"); diff --git a/protogeni/etc/protogeni.sql b/protogeni/etc/protogeni.sql index fa014af3ee..9bc3cfe8fb 100644 --- a/protogeni/etc/protogeni.sql +++ b/protogeni/etc/protogeni.sql @@ -148,6 +148,7 @@ CREATE TABLE `geni_certificates` ( `cert` text, `DN` text, `privkey` text, + `uri` text, PRIMARY KEY (`uuid`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; diff --git a/protogeni/lib/GeniCertificate.pm.in b/protogeni/lib/GeniCertificate.pm.in index f249587c69..899b259875 100644 --- a/protogeni/lib/GeniCertificate.pm.in +++ b/protogeni/lib/GeniCertificate.pm.in @@ -66,7 +66,6 @@ sub Lookup($$) my $self = {}; $self->{'CERT'} = $query_result->fetchrow_hashref(); - $self->{'url'} = undef; $self->{'stored'} = 1; bless($self, $class); my $cert = $self->cert(); @@ -98,6 +97,7 @@ sub DN($) { return field($_[0], "DN"); } sub privkey($) { return field($_[0], "privkey"); } sub revoked($) { return field($_[0], "revoked"); } sub certfile($) { return field($_[0], "certfile"); } +sub uri($) { return field($_[0], "uri"); } sub GetCertificate($) { return $_[0]; } # @@ -315,7 +315,7 @@ sub LoadFromFile($$) $self->{'CERT'}->{'revoked'} = undef; $self->{'CERT'}->{'created'} = undef; $self->{'CERT'}->{'certfile'} = $filename; - $self->{'url'} = $url; + $self->{'CERT'}->{'uri'} = $url; return $self; } @@ -336,6 +336,8 @@ sub Store($) push(@inserts, "DN=" . DBQuoteSpecial($self->DN())); push(@inserts, "privkey=" . DBQuoteSpecial($self->privkey())) if (defined($self->privkey())); + push(@inserts, "uri=" . DBQuoteSpecial($self->uri())) + if (defined($self->uri())); return -1 if (!DBQueryWarn("replace into geni_certificates set ". @@ -374,7 +376,7 @@ sub WriteToFile($;$) sub URL($) { my ($self) = @_; - my $url = $self->{'url'}; + my $url = $self->uri(); return $url if (defined($url)); @@ -384,10 +386,21 @@ sub URL($) print STDERR "Could not start $OPENSSL on $filename\n"; return undef; } + my $altname = 0; while (<X509>) { - if ($_ =~ /^\s+URI:([-\w\.\/:]+)$/) { - $url = $1; - chomp($url); + if( /^\s+x509v3 Subject Alternative Name:\s*$/ ) { + $altname = 1; + } elsif( $altname ) { + # Gah! OpenSSL is horrible. Apparently the text output format + # for the subject alternative name is fixed, and neither + # -nameopt nor -certopt will help us. Worse still, the + # directory entries (e.g. URI, email) are comma separated... + # but commas are legal characters in URIs (see RFC 3986, section + # 2.2)! We'll have to assume the delimiter is the ", " (comma, + # space) pair... + m'^\s*URI:([-!#$%()*+,./0-9:;=?@A-Z_a-z~]+)\s*$' and $url = $1 + foreach split( /, / ); + $altname = 0; } } if (!close(X509) || !defined($url)) { @@ -395,7 +408,7 @@ sub URL($) return undef; } unlink($filename); - $self->{'url'} = $url; + $self->{'CERT'}->{'uri'} = $url; return $url; } @@ -456,9 +469,13 @@ sub StoreCRL($$$) # Wrapper for local users. # package GeniCertificate::LocalUser; +use GeniHRN; use English; use emdb; +# Configure variables +my $OURDOMAIN = "@OURDOMAIN@"; + # # Create a wrapper, with the same access names. # @@ -477,6 +494,8 @@ sub Create($$) my $self = {}; $self->{'CERT'} = $query_result->fetchrow_hashref(); + $self->{'CERT'}->{'uri'} = GeniHRN::Generate( $OURDOMAIN, "user", + $self->{'CERT'}->{'uid'} ); $self->{'stored'} = 1; bless($self, $class); diff --git a/protogeni/lib/GeniCredential.pm.in b/protogeni/lib/GeniCredential.pm.in index 4c2b68c184..560448f097 100644 --- a/protogeni/lib/GeniCredential.pm.in +++ b/protogeni/lib/GeniCredential.pm.in @@ -123,6 +123,8 @@ sub extensions($) { return field($_[0], "extensions"); } sub owner_cert($) { return $_[0]->{"owner_cert"}; } sub target_cert($) { return $_[0]->{"target_cert"}; } sub hrn($) { return $_[0]->{"target_cert"}->hrn(); } +sub target_uri($) { return $_[0]->{"target_cert"}->uri(); } +sub owner_uri($) { return $_[0]->{"owner_cert"}->uri(); } # # Stringify for output. diff --git a/protogeni/test/showcredential.py b/protogeni/test/showcredential.py index e7b219f9bf..71af339bf7 100755 --- a/protogeni/test/showcredential.py +++ b/protogeni/test/showcredential.py @@ -60,6 +60,12 @@ def Decode( gid ): f.close() return s +def SubjectName( cert ): + return ( re.search( r"X509v3 Subject Alternative Name:[ \t]*\n[ \t]*.*URI:" + "(urn:publicid:[-!$%()*+.0-9:;=?@A-Z_a-z~]+)", \ + cert ) or \ + re.search( r"Subject: .*OU=([-\w.]+)", cert ) ).group( 1 ) + def ShowCredential( cred, level ): if level == 0: @@ -79,14 +85,8 @@ def ShowCredential( cred, level ): owner = Decode( Text( Lookup( cred, "owner_gid" ) ) ) target = Decode( Text( Lookup( cred, "target_gid" ) ) ) - print " Owner:" - print " Subject:", re.search( r"Subject: (.+)", owner ).group( 1 ) - print " Issuer:", re.search( r"Issuer: (.+)", owner ).group( 1 ) - - print " Target:" - print " Subject:", re.search( r"Subject: (.+)", target ).group( 1 ) - print " Issuer:", re.search( r"Issuer: (.+)", target ).group( 1 ) - + print " Owner: " + SubjectName( owner ) + print " Target: " + SubjectName( target ) print " UUID: " + Text( Lookup( cred, "uuid" ) ) print " Expires: " + Text( Lookup( cred, "expires" ) ) diff --git a/protogeni/updates/3 b/protogeni/updates/3 new file mode 100644 index 0000000000..5d4e090d00 --- /dev/null +++ b/protogeni/updates/3 @@ -0,0 +1,18 @@ +# +# Add a URI column to the certificate table, for storing new GENI identifiers. +# +use strict; +use GeniDB; + +sub DoUpdate($$$) +{ + my ($dbhandle, $dbname, $version) = @_; + + DBSetDefault( $dbhandle ); + + DBQueryFatal( "ALTER TABLE `geni_certificates` ADD `uri` text" ) + unless DBSlotExists( "geni_certificates", "uri" ); + + return 0; +} +1; diff --git a/ssl/usercert.cnf.in b/ssl/usercert.cnf.in index 140bbe8472..5e3ad42a24 100644 --- a/ssl/usercert.cnf.in +++ b/ssl/usercert.cnf.in @@ -11,6 +11,7 @@ string_mask = nombstr [ request_extensions ] basicConstraints=critical,CA:TRUE subjectKeyIdentifier=hash +subjectAltName=@req_altname # This will be appended to by mkusercert. [ req_distinguished_name ] -- GitLab