sample-scripts/verify-cn
6fbf66fa
 #!/usr/bin/perl
 
 # verify-cn -- a sample OpenVPN tls-verify script
 #
 # Return 0 if cn matches the common name component of
 # X509_NAME_oneline, 1 otherwise.
 #
 # For example in OpenVPN, you could use the directive:
 #
060e8818
 #   tls-verify "./verify-cn /etc/openvpn/allowed_clients"
6fbf66fa
 #
 # This would cause the connection to be dropped unless
060e8818
 # the client common name is listed on a line in the
 # allowed_clients file.
6fbf66fa
 
060e8818
 die "usage: verify-cn cnfile certificate_depth X509_NAME_oneline" if (@ARGV != 3);
6fbf66fa
 
 # Parse out arguments:
060e8818
 #   cnfile -- The file containing the list of common names, one per
 #             line, which the client is required to have,
 #             taken from the argument to the tls-verify directive
 #             in the OpenVPN config file.
 #             The file can have blank lines and comment lines that begin
 #             with the # character.
 #   depth  -- The current certificate chain depth.  In a typical
 #             bi-level chain, the root certificate will be at level
 #             1 and the client certificate will be at level 0.
 #             This script will be called separately for each level.
 #   x509   -- the X509 subject string as extracted by OpenVPN from
 #             the client's provided certificate.
 ($cnfile, $depth, $x509) = @ARGV;
6fbf66fa
 
 if ($depth == 0) {
     # If depth is zero, we know that this is the final
     # certificate in the chain (i.e. the client certificate),
     # and the one we are interested in examining.
     # If so, parse out the common name substring in
     # the X509 subject string.
 
     if ($x509 =~ /\/CN=([^\/]+)/) {
060e8818
         $cn = $1;
6fbf66fa
 	# Accept the connection if the X509 common name
 	# string matches the passed cn argument.
060e8818
 	open(FH, '<', $cnfile) or exit 1; # can't open, nobody authenticates!
         while (defined($line = <FH>)) {
 	    if ($line !~ /^[[:space:]]*(#|$)/o) {
 		chop($line);
 		if ($line eq $cn) {
 		    exit 0;
 		}
 	    }
6fbf66fa
 	}
060e8818
 	close(FH);
6fbf66fa
     }
 
     # Authentication failed -- Either we could not parse
     # the X509 subject string, or the common name in the
     # subject string didn't match the passed cn argument.
     exit 1;
 }
 
 # If depth is nonzero, tell OpenVPN to continue processing
 # the certificate chain.
 exit 0;