On 06/13/2011 10:08 PM, Scott Schaefer wrote:
On 06/13/2011 06:10 AM, Kurt Roeckx wrote:
On Fri, May 06, 2011 at 08:35:57AM -0400, Scott Schaefer wrote:
See attached.  Prints "completion" message only on successful return.

Also fixes bug which prevents executing -newreq-nodes option, and
includes newer options in usage message.
Can you also check the CA.sh script for the same problems?


Kurt

I will be glad to submit patch for CA.sh, since, on quick review, it indeed has same two problems as CA.pl; i.e. 1) It prints "success" messages, even on failure of underlying SSL command(s), and
   2) The usage message in lacking the newer, added valid arguments,

This will probably require 24-48 hours, since I have travel commitment tomorrow.

OTOH, my assertion that my original patch for CA.pl 'fixes bug which prevents executing -newreq-nodes option' is WRONG. I badly misread that code in order to conclude what I did; i.e. the original code does execute both -newreq and -newreq-nodes options correctly.

Note the patch still correctly executes both options, and both did incorrectly print "success" message even on failure of underlying SSL command. For this reason, I would prefer to leave the patch intact, and simply change the second part of the description to only "Also includes newer options in usage message". If you prefer, I can submit revised patch file that does not re-order the testing of command-args vs patterns /^-newreq$/ and/^-newreq-nodes$/.


Attached are two patches. The first is a replacement for the original and applies to CA.pl. The second is new, and applies to CA.sh.

Please note that both of these are less-than-thoroughly tested. I have verified most of the functionality, but not all of the boundary cases which I would normally test before releasing as production code. In addition, the original(s) had some inconsistencies and unclear design choices which I am not certain I understand the rationale for.

However, I am starting my first vacation of more than three days in over six years tomorrow morning, and will be unable to test any more until my return.

diff --git a/apps/CA.pl b/apps/CA.pl
--- a/apps/CA.pl
+++ b/apps/CA.pl
@@ -44,6 +44,26 @@
 	$ENV{OPENSSL} = $openssl;
 }
 
+sub system_command() {
+    my $cmd = shift;
+    my $ret = 2;
+    if ($cmd) {
+        system($cmd);
+        if ($? == -1) {
+            print "ERROR: Failed to execute: $cmd\n";
+            exit 1; 
+        }
+        elsif ($? & 127) {
+            printf "ERROR: Process died with signal %d, %s coredump\n",($? & 127),(($? & 128) ? 'with' : 'without');
+            exit 1; 
+        }
+        else {
+            $ret = $? >> 8;
+        }
+    }
+    $ret;
+}
+    
 $SSLEAY_CONFIG=$ENV{"SSLEAY_CONFIG"};
 $DAYS="-days 365";	# 1 year
 $CADAYS="-days 1095";	# 3 years
@@ -62,25 +82,39 @@
 
 $RET = 0;
 
+$USAGE = <<"_USAGE_";
+usage: $0  -newcert | -newreq | -newreq-nodes | -newca |
+       -sign | -signreq | -signCA | -signcert | -xsign | pkcs12 | -verify
+_USAGE_
+$HELP_USAGE = <<"_HELP_USAGE_";
+usage: $0 option
+  Valid options
+    -newca : Create local CA directory structure
+    -newcert : Create certficate
+    -newreq|-newreq-nodes : Create certficate request
+    -sign|-signreq|-signCA|-signcert|-xsign : Sign cert/request
+    -pkcs12 name (default='My Certificate') : Create PKCS-12 certificate
+    -verify [file [file]]: Verifiy certificate(s); newcert.pem if no file(s)
+_HELP_USAGE_
+
+
 foreach (@ARGV) {
+        $result='';
 	if ( /^(-\?|-h|-help)$/ ) {
-	    print STDERR "usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify\n";
+	    print STDERR $HELP_USAGE;
 	    exit 0;
 	} elsif (/^-newcert$/) {
 	    # create a certificate
-	    system ("$REQ -new -x509 -keyout newkey.pem -out newcert.pem $DAYS");
-	    $RET=$?;
-	    print "Certificate is in newcert.pem, private key is in newkey.pem\n"
+	    $RET=&system_command("$REQ -new -x509 -keyout newkey.pem -out newcert.pem $DAYS");
+	    $result="Certificate is in newcert.pem, private key is in newkey.pem";
 	} elsif (/^-newreq$/) {
 	    # create a certificate request
-	    system ("$REQ -new -keyout newkey.pem -out newreq.pem $DAYS");
-	    $RET=$?;
-	    print "Request is in newreq.pem, private key is in newkey.pem\n";
+	    $RET=&system_command("$REQ -new -keyout newkey.pem -out newreq.pem $DAYS");
+	    $result="Request is in newreq.pem, private key is in newkey.pem";
 	} elsif (/^-newreq-nodes$/) {
 	    # create a certificate request
-	    system ("$REQ -new -nodes -keyout newkey.pem -out newreq.pem $DAYS");
-	    $RET=$?;
-	    print "Request is in newreq.pem, private key is in newkey.pem\n";
+	    $RET=&system_command("$REQ -new -nodes -keyout newkey.pem -out newreq.pem $DAYS");
+	    $result="Request is in newreq.pem, private key is in newkey.pem";
 	} elsif (/^-newca$/) {
 		# if explicitly asked for or it doesn't exist then setup the
 		# directory structure that Eric likes to manage things 
@@ -111,62 +145,60 @@
 		    $RET=$?;
 		} else {
 		    print "Making CA certificate ...\n";
-		    system ("$REQ -new -keyout " .
+		    $RET=&system_command("$REQ -new -keyout " .
 			"${CATOP}/private/$CAKEY -out ${CATOP}/$CAREQ");
-		    system ("$CA -create_serial " .
-			"-out ${CATOP}/$CACERT $CADAYS -batch " . 
-			"-keyfile ${CATOP}/private/$CAKEY -selfsign " .
-			"-extensions v3_ca " .
-			"-infiles ${CATOP}/$CAREQ ");
-		    $RET=$?;
+                    if ($RET==0) {
+		        $RET=&system_command("$CA -create_serial " .
+		    	    "-out ${CATOP}/$CACERT $CADAYS -batch " . 
+			    "-keyfile ${CATOP}/private/$CAKEY -selfsign " .
+			    "-extensions v3_ca " .
+			    "-infiles ${CATOP}/$CAREQ ");
+                    }
 		}
 	    }
 	} elsif (/^-pkcs12$/) {
 	    my $cname = $ARGV[1];
 	    $cname = "My Certificate" unless defined $cname;
-	    system ("$PKCS12 -in newcert.pem -inkey newkey.pem " .
-			"-certfile ${CATOP}/$CACERT -out newcert.p12 " .
-			"-export -name \"$cname\"");
-	    $RET=$?;
-	    print "PKCS #12 file is in newcert.p12\n";
+	    $RET=&system_command("$PKCS12 -in newcert.pem -inkey newkey.pem " .
+					"-certfile ${CATOP}/$CACERT -out newcert.p12 " .
+					"-export -name \"$cname\"");
+	    print "PKCS #12 file is in newcert.p12\n" if ($RET==0);
 	    exit $RET;
 	} elsif (/^-xsign$/) {
-	    system ("$CA -policy policy_anything -infiles newreq.pem");
-	    $RET=$?;
+	    $RET=&system_command("$CA -policy policy_anything -infiles newreq.pem");
 	} elsif (/^(-sign|-signreq)$/) {
-	    system ("$CA -policy policy_anything -out newcert.pem " .
-							"-infiles newreq.pem");
-	    $RET=$?;
-	    print "Signed certificate is in newcert.pem\n";
+	    $RET=&system_command("$CA -policy policy_anything -out newcert.pem " .
+					"-infiles newreq.pem");
+	    $result="Signed certificate is in newcert.pem";
 	} elsif (/^(-signCA)$/) {
-	    system ("$CA -policy policy_anything -out newcert.pem " .
+	    $RET=&system_command("$CA -policy policy_anything -out newcert.pem " .
 					"-extensions v3_ca -infiles newreq.pem");
-	    $RET=$?;
-	    print "Signed CA certificate is in newcert.pem\n";
+	    $result="Signed CA certificate is in newcert.pem";
 	} elsif (/^-signcert$/) {
-	    system ("$X509 -x509toreq -in newreq.pem -signkey newreq.pem " .
-								"-out tmp.pem");
-	    system ("$CA -policy policy_anything -out newcert.pem " .
-							"-infiles tmp.pem");
-	    $RET = $?;
-	    print "Signed certificate is in newcert.pem\n";
+	    $RET=&system_command("$X509 -x509toreq -in newreq.pem -signkey newreq.pem " .
+					"-out tmp.pem");
+            if ($RET==0) {
+	        $RET=&system_command("$CA -policy policy_anything -out newcert.pem " .
+					"-infiles tmp.pem");
+            }
+	    $result="Signed certificate is in newcert.pem";
 	} elsif (/^-verify$/) {
+	    shift;
 	    if (shift) {
+                $RET = 0;
 		foreach $j (@ARGV) {
-		    system ("$VERIFY -CAfile $CATOP/$CACERT $j");
-		    $RET=$? if ($? != 0);
+		    my $v_ret=&system_command("$VERIFY -CAfile $CATOP/$CACERT $j");
+		    $RET=$v_ret if ($v_ret != 0);
 		}
-		exit $RET;
 	    } else {
-		    system ("$VERIFY -CAfile $CATOP/$CACERT newcert.pem");
-		    $RET=$?;
-	    	    exit 0;
+		    $RET=&system_command("$VERIFY -CAfile $CATOP/$CACERT newcert.pem");
 	    }
 	} else {
 	    print STDERR "Unknown arg $_\n";
-	    print STDERR "usage: CA -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify\n";
+	    print STDERR $USAGE; 
 	    exit 1;
 	}
+        print "$result\n" if (($result) && ($RET==0));
 }
 
 exit $RET;
diff --git a/apps/CA.sh b/apps/CA.sh
--- a/apps/CA.sh
+++ b/apps/CA.sh
@@ -55,7 +55,18 @@
 }
 
 usage() {
- echo "usage: $0 -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify" >&2
+ echo "usage: $0  -newcert | -newreq | -newreq-nodes | -newca |" >&2
+ echo "       -sign | -signreq | -signCA | -signcert | -xsign | pkcs12 | -verify" >&2
+}
+help_usage() {
+ echo "usage: $0 option" >&2
+ echo "  Valid options" >&2
+ echo "    -newca : Create local CA directory structure" >&2
+ echo "    -newcert : Create certficate" >&2
+ echo "    -newreq|-newreq-nodes : Create certficate request" >&2
+ echo "    -sign|-signreq|-signCA|-signcert|-xsign : Sign cert/request" >&2
+ echo "    -pkcs12 name (default='My Certificate') : Create PKCS#12 certificate" >&2
+ echo "    -verify [file [file]]: Verifiy certificate(s); newcert.pem if no file(s)" >&2
 }
 
 if [ -z "$OPENSSL" ]; then OPENSSL=openssl; fi
@@ -78,26 +89,32 @@
 while [ "$1" != "" ] ; do
 case $1 in
 -\?|-h|-help)
-    usage
+    help_usage
     exit 0
     ;;
 -newcert)
     # create a certificate
     $REQ -new -x509 -keyout newkey.pem -out newcert.pem $DAYS
     RET=$?
-    echo "Certificate is in newcert.pem, private key is in newkey.pem"
+    if [ $RET -eq 0 ]; then
+        echo "Certificate is in newcert.pem, private key is in newkey.pem"
+    fi
     ;;
 -newreq)
     # create a certificate request
     $REQ -new -keyout newkey.pem -out newreq.pem $DAYS
     RET=$?
-    echo "Request is in newreq.pem, private key is in newkey.pem"
+    if [ $RET -eq 0 ]; then
+        echo "Request is in newreq.pem, private key is in newkey.pem"
+    fi
     ;;
 -newreq-nodes) 
     # create a certificate request
     $REQ -new -nodes -keyout newreq.pem -out newreq.pem $DAYS
     RET=$?
-    echo "Request (and private key) is in newreq.pem"
+    if [ $RET -eq 0 ]; then
+        echo "Request (and private key) is in newreq.pem"
+    fi
     ;;
 -newca)
     # if explicitly asked for or it doesn't exist then setup the directory
@@ -150,18 +167,24 @@
     $PKCS12 -in newcert.pem -inkey newreq.pem -certfile ${CATOP}/$CACERT \
 	    -out newcert.p12 -export -name "$CNAME"
     RET=$?
-    exit $RET
+    if [ $RET -eq 0 ]; then
+        echo "PKCS#12 file is in newcert.p12"
+    fi
     ;;
 -sign|-signreq)
     $CA -policy policy_anything -out newcert.pem -infiles newreq.pem
     RET=$?
     cat newcert.pem
-    echo "Signed certificate is in newcert.pem"
+    if [ $RET -eq 0 ]; then
+        echo "Signed certificate is in newcert.pem"
+    fi
     ;;
 -signCA)
     $CA -policy policy_anything -out newcert.pem -extensions v3_ca -infiles newreq.pem
     RET=$?
-    echo "Signed CA certificate is in newcert.pem"
+    if [ $RET -eq 0 ]; then
+        echo "Signed CA certificate is in newcert.pem"
+    fi
     ;;
 -signcert)
     echo "Cert passphrase will be requested twice - bug?"
@@ -169,7 +192,9 @@
     $CA -policy policy_anything -out newcert.pem -infiles tmp.pem
     RET=$?
     cat newcert.pem
-    echo "Signed certificate is in newcert.pem"
+    if [ $RET -eq 0 ]; then
+        echo "Signed certificate is in newcert.pem"
+    fi
     ;;
 -verify)
     shift
@@ -177,6 +202,7 @@
 	    $VERIFY -CAfile $CATOP/$CACERT newcert.pem
 	    RET=$?
     else
+        RET=0
 	for j
 	do
 	    $VERIFY -CAfile $CATOP/$CACERT $j
@@ -188,7 +214,7 @@
     exit $RET
     ;;
 *)
-    echo "Unknown arg $i" >&2
+    echo "Unknown arg $1" >&2
     usage
     exit 1
     ;;

Reply via email to