There are several people already doing this, including myself
and the Papyrus people at Georgia Tech.  What I do is just to
supply the non-secret information in a configuration file,
and add the secret information via Unix pipes.

There is some variance depending on if you're using the
"openssl ca" or if you are using a lower level API like
"openssl req" or "openssl x509".  Here is an example
configuration file for lower-level calling:


# OpenSSL configuration file for signing Internet Server Certificates


extensions = extend

  [req] # openssl req params
  prompt = no
  distinguished_name = dn-param

  [dn-param] # DN fields
  C = US
  ST = Maryland
  O = University of Maryland
  OU = College Park Campus
  CN = $ENV::CERTHOST
  1.DC = umd
  2.DC = edu
  emailAddress = $ENV::CERTMAIL

  [extend] # openssl extensions
  subjectAltName = email:$ENV::CERTMAIL # no double quotes here!
  issuerAltName = "DNS:umd.edu","email:[EMAIL PROTECTED]"
  subjectKeyIdentifier = hash
  authorityKeyIdentifier = keyid:always
  basicConstraints = critical,CA:false
  keyUsage = critical,Key Encipherment
  extendedKeyUsage = serverAuth, clientAuth
  nsCertType = SSL Server
  nsComment = "See http://cert.umd.edu/server for details."
  certificatePolicies = ia5org,@policy

  [policy] # certificate policy extension data
  policyIdentifier = 1.3.6.1.4.1.4305.1.2.1
  CPS = "http://cert.umd.edu/certpolicy";

# sconfig


This configuration file is entirely static; the varying parts are supplied by environment variable substitution (see the $ENV stores in the example code below). It is passed to "openssl req" to create a request and also to "openssl x509" to sign the request. Here is some example Perl code.


# ##### CSRQMAKE #####


# Generate a Certificate Signing Request (CSR)

# csrqmake(vault,vkey,openssl,hostname,email)

   # If the requestor did not supply a CSR
   # this routine generates a private key and a CSR.

   sub csrqmake {
      my ($vault,$vkey,$openssl,$certhost,$certmail) = @_;

my $pid, $error, $csr, $pkey; # PID, error, result

      $ENV{'CERTHOST'} = $certhost;        # Add server to config
      $ENV{'CERTMAIL'} = $certmail;        # Add email to config

      {
         $^F = 99;                         # FORCE CLOSE-ON-WRITE OFF!!!
         pipe KCR,KCW;                     # Kid Code Read/Write
         pipe KPR,KPW;                     # Kid Private Key Read/Write
      }

# Copy passphrase from the vault into the KC pipe.

      if ( !forkcode(sub{                  # Run this in forked process
         close KCR;                        # Close parent's pipe end
         open STDOUT,'>&KCW';              # Bind std out to the KC pipe
         exec $vault,$vkey;                # Send passphrase to KCW
         die "Could not EXEC vault (csrqmake): $!"; # NOT REACHED
      }) ) {
         htmlfail "Could not FORK (csrqmake): $!";
      }
      close KCW;                           # Close kid's pipe end

# Run OpenSSL req to generate the private key and CSR

      pipe KOR,KOW;                        # Kid (std) Output Read/Write
      pipe KER,KEW;                        # Kid (err) Output Read/Write
      if ( !($pid=forkcode(sub{            # Run in forked process
         close KER;                        # Close parent's pipe end
         close KOR;                        # Close parent's pipe end
         open STDOUT,'>&KOW';              # Bind pipe to standard out
         open STDERR,'>&KEW';              # Bind pipe to standard err
         exec $openssl.' req -config ../config/sconfig'.
            ' -newkey rsa:2048 -keyout /dev/fd/'.fileno(KPW).
            ' -passout fd:'.fileno(KCR);
         die "Could not EXEC OpenSSL (csrqmake): $!"; # NOT REACHED
      })) ) {
         htmlfail "Could not FORK (csrqmake): $!";
      }
      close KCR;                           # Close pipe from vault
      close KPW;                           # Close kid's pipe end
      close KOW;                           # Close kid's pipe end
      close KEW;                           # Close kid's pipe end
      read KER,$error,4096;                # Read any errors from kid
      read KOR,$csr,4096;                  # Read any output from kid
      read KPR,$pkey,4096;                 # Read private key from kid
      waitpid($pid,0);                     # Wait for kid to terminate
      if ($?) {                            # If error in kid
         htmlfail "OpenSSL req failed (gencsr):\n".$error;
      }
      close KOR;                           # Close pipe from kid
      close KER;                           # Close pipe from kid
      close KPR;                           # Close pipe from kid

      return ($csr,$pkey);                 # Return CSR and private key
   }


# ##### CERTSIGN #####


# Generate a signed certificate

# certsign(vault,vkey,openssl,serialno,signreq,lifetime,email);

   sub certsign {
      my ($vault,$vkey,$openssl,$serial,$csr,$certlife,$certmail) = @_;

my $pid, $error, $cert; # PID, error, result

      $ENV{'CERTMAIL'} = $certmail;        # Add altname to extension
      $ENV{'CERTHOST'} = 'placeholder';    # Kluge

      {
         $^F = 99;                         # FORCE CLOSE-ON-WRITE OFF!!!
         pipe KDR,KDW;                     # Kid Decode passphr R/W
         pipe KSR,KSW;                     # Kid Serial number R/W
      }

      my $hex = sprintf("%lx",$serial);    # Convert serial to hex
      if ( length($hex)%2 ) {
         $hex = '0'.$hex;                  # Even num digits required!
      }
      print KSW $hex;                      # Write serial number to pipe
      close KSW;                           # Make EOF

# Copy passphrase from the vault into the KD pipe.

      if ( !forkcode(sub{                  # Run in forked process
         close KDR;                        # Close parent's end of pipe
         open STDOUT,'>&KDW';              # Bind std out to the KD pipe
         exec $vault,$vkey;                # Send passphrase to KDW
         die "Could not EXEC vault (certsign): $!"; # NOT REACHED
      }) ) {
         htmlfail "Could not FORK (certsign): $!";
      }
      close KDW;                           # Close kid's pipe end

# Run OpenSSL x509 to sign the certificate

      pipe KIR,KIW;                        # Kid (std) Input Read/Write
      pipe KOR,KOW;                        # Kid (std) Output Read/Write
      pipe KER,KEW;                        # Kid Error (output) R/W
      if ( !($pid=forkcode(sub{            # Run in forked process
         close KIW;                        # Close parent's end of pipe
         close KOR;                        # Close parent's end of pipe
         close KER;                        # Close parent's end of pipe
         open STDIN, '<&KIR';              # Bind pipe to standard in
         open STDOUT,'>&KOW';              # Bind pipe to standard out
         open STDERR,'>&KEW';              # Bind pipe to standard err
         exec $openssl.' x509 -req -sha1 -extfile ../config/sconfig'.
            ' -CA ../certs/ssign.cert.pem'.
            ' -CAkey /usr/local/nobackup/umcpca/ssign.key.pem'.
            ' -CAserial /dev/fd/'.fileno(KSR).
            ' -days '.$certlife.
            ' -passin fd:'.fileno(KDR);
         die "Could not EXEC OpenSSL (certsign): $!"; # NOT REACHED
      })) ) {
         htmlfail "Could not FORK (certsign): $!" ;
      }
      close KDR;                           # Close pipe from vault
      close KIR;                           # Close kid's pipe end
      close KOW;                           # Close kid's pipe end
      close KEW;                           # Close kid's pipe end
      print KIW $csr;                      # Send input to kid
      close KIW;                           # Cause an end of file
      read KER,$error,4096;                # Read any errors from kid
      read KOR,$cert,4096;                 # Read any output from kid
      waitpid($pid,0);                     # Wait for kid to terminate
      if ($?) {
         htmlfail "OpenSSL x509 failed (certsign):\n".$error;
      }
      close KOR;                           # Close pipe from kid
      close KER;                           # Close pipe from kid

      return $cert;                        # Return cert to caller
   }


# Run a new forked process (passed as an anonymous subroutine)


# $pid = forkcode(sub{code});

   # Returns zero if the fork failed
   # If return is nonzero then
   #  The code passed is running in the child process
   #  The return value is the process ID of the child

   sub forkcode {
      my $pid;                             # Process ID
      my $childcode = @_[0];               # Code to run as child
      while ( !defined($pid=fork) ) {      # Retry until fork succeeds
         if ($! !~ /No more process/) {    # Under some conditions retry
            return 0;                      # Return failure
         }
         sleep 5;                          # Delay between retries
      }
      if ($pid) {                          # If fork succeed and parent
         return $pid;                      # Return PID to parent
      }
      &$childcode;                         # Child runs passed code
      exit;                                # Child does NOT return
   }

These examples are for SSL Server certificates.  I have some
minor skeletal code for identity and privacy certificates,
which uses "openssl ca" instead.  I have posted that code on
this list before.  Contact me via direct email if you want a
copy.

BTW I've started to work on this code several times, and each
time a SSL Server CA emergency has forced me to back-burner it,
so I'm not picking the work up again until after August when
our old root expires.  When the sturm und drang from that dies
down I will look at the identity and privacy CA stuff again.


[EMAIL PROTECTED] wrote:
Hi,

I want to create a request automatically with an webapplication. So the
persons enter the details into a form an I write a temporary config-file to
create request. But how does the content of the config-file look, that it contains
the details (cn, o, ou,...) and how does the command look, what I have to
execute?

Hope anybody can help me..

Thanx a lot for help!!!!

Carsten



--
Charles B (Ben) Cranston
mailto: [EMAIL PROTECTED]
http://www.wam.umd.edu/~zben

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to