ikectl ca certificate create fails due to invalid subjectAltName

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

ikectl ca certificate create fails due to invalid subjectAltName

Andrei-Marius Radu
Hello,

I'm running the latest snapshot and I've found that I cannot create
certificates with ikectl. It fails due to the fact that the request
contains an invalid subjectAltName of only 'IP:' or 'DNS:'. In turn this
is due to the fact that in the OpenSSL config file the variable names
are 'IP:$ENV::CERTIP' and 'DNS:$ENV::CERTFQDN' but in ikeca.c they
appear as only '$ENV::CERTIP' and '$ENV::CERTFQDN'.

I don't know exactly the last working version but I think that this
issue was introduced in rev 1.41 .

With the patch below creating certificates works again. If the correct
string is built in ca_request() (prefixed with 'IP:' or 'DNS:') then it
must not be deallocated at the return of ca_request(). So I thought it's
better to change ca_setenv() to make sure that any strings it puts in
ca_env will not be deallocated too soon. But I didn't want to leave any
allocations not freed so this is the reason for also changing
ca_crlenv(). Any memory leak is irrelevant since ikectl exits
immediately but in the interest of correctness ca_crlenv() should be
called if any ca_setenv() is present in the code path. If this is not
the best way to handle this situation please let me know and I can try
to redo the patch in a different manner.

Best regards,
Andrei.

IKECTL tests with the latest snapshot version:
======================================================================
root@server1 ~ $ sysctl kern.version
kern.version=OpenBSD 6.1-current (GENERIC.MP) #4: Mon Aug 14 18:51:58 MDT 2017
    [hidden email]:/usr/src/sys/arch/amd64/compile/GENERIC.MP

root@server1 ~ $ ls -lsah /usr/sbin/ikectl
104 -r-xr-xr-x  1 root  bin  50.3K Aug 15 03:42 /usr/sbin/ikectl

root@server1 ~ $ ikectl ca test-vpn create
CA passphrase:
Retype CA passphrase:
Generating RSA private key, 2048 bit long modulus
.............................................................................................................................................................+++
.+++
e is 65537 (0x10001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [DE]:
State or Province Name (full name) [Lower Saxony]:
Locality Name (eg, city) [Hanover]:
Organization Name (eg, company) [OpenBSD]:
Organizational Unit Name (eg, section) [iked]:
Common Name (eg, fully qualified host name) [VPN CA]:
Email Address [[hidden email]]:
Signature ok
subject=/C=DE/ST=Lower Saxony/L=Hanover/O=OpenBSD/OU=iked/CN=VPN CA/emailAddress=[hidden email]
Getting Private key
Using configuration from /etc/ssl/test-vpn/ca-revoke-ssl.cnf

root@server1 ~ $ ikectl ca test-vpn certificate 10.1.2.3 create
Generating RSA private key, 2048 bit long modulus
..+++
.....+++
e is 65537 (0x10001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [DE]:
State or Province Name (full name) [Lower Saxony]:
Locality Name (eg, city) [Hanover]:
Organization Name (eg, company) [OpenBSD]:
Organizational Unit Name (eg, section) [iked]:
Common Name (eg, fully qualified host name) [10.1.2.3]:
Email Address [[hidden email]]:
Using configuration from /etc/ssl/test-vpn/10.1.2.3-ssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'DE'
stateOrProvinceName   :ASN.1 12:'Lower Saxony'
localityName          :ASN.1 12:'Hanover'
organizationName      :ASN.1 12:'OpenBSD'
organizationalUnitName:ASN.1 12:'iked'
commonName            :ASN.1 12:'10.1.2.3'
emailAddress          :IA5STRING:'[hidden email]'
ERROR: adding extensions in section x509v3_IPAddr
13531723566432:error:22FFF06D:X509 V3 routines:func(4095):invalid null value:/usr/src/lib/libcrypto/x509v3/v3_utl.c:355:
13531723566432:error:22FFF069:X509 V3 routines:func(4095):invalid extension string:/usr/src/lib/libcrypto/x509v3/v3_conf.c:143:name=subjectAltName,section=IP:
13531723566432:error:22FFF080:X509 V3 routines:func(4095):error in extension:/usr/src/lib/libcrypto/x509v3/v3_conf.c:96:name=subjectAltName, value=IP:

root@server1 ~ $ ikectl ca test-vpn certificate test-client.test-vpn.net create
Generating RSA private key, 2048 bit long modulus
.................................+++
....................+++
e is 65537 (0x10001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [DE]:
State or Province Name (full name) [Lower Saxony]:
Locality Name (eg, city) [Hanover]:
Organization Name (eg, company) [OpenBSD]:
Organizational Unit Name (eg, section) [iked]:
Common Name (eg, fully qualified host name) [test-client.test-vpn.net]:
Email Address [[hidden email]]:
Using configuration from /etc/ssl/test-vpn/test-client.test-vpn.net-ssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'DE'
stateOrProvinceName   :ASN.1 12:'Lower Saxony'
localityName          :ASN.1 12:'Hanover'
organizationName      :ASN.1 12:'OpenBSD'
organizationalUnitName:ASN.1 12:'iked'
commonName            :ASN.1 12:'test-client.test-vpn.net'
emailAddress          :IA5STRING:'[hidden email]'
ERROR: adding extensions in section x509v3_FQDN
32032597429408:error:22FFF06D:X509 V3 routines:func(4095):invalid null value:/usr/src/lib/libcrypto/x509v3/v3_utl.c:355:
32032597429408:error:22FFF069:X509 V3 routines:func(4095):invalid extension string:/usr/src/lib/libcrypto/x509v3/v3_conf.c:143:name=subjectAltName,section=DNS:
32032597429408:error:22FFF080:X509 V3 routines:func(4095):error in extension:/usr/src/lib/libcrypto/x509v3/v3_conf.c:96:name=subjectAltName, value=DNS:


IKECTL tests with the proposed patch:
======================================================================
root@server1 ~ $ rm /etc/ssl/test-vpn/private/*                                
root@server1 ~ $ rmdir /etc/ssl/test-vpn/private/                              
root@server1 ~ $ rm /etc/ssl/test-vpn/*          
root@server1 ~ $ rmdir /etc/ssl/test-vpn/        

root@server1 ~ $ /usr/src/usr.sbin/ikectl/ikectl ca test-vpn create
CA passphrase:
Retype CA passphrase:
Generating RSA private key, 2048 bit long modulus
..........................+++
....+++
e is 65537 (0x10001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [DE]:
State or Province Name (full name) [Lower Saxony]:
Locality Name (eg, city) [Hanover]:
Organization Name (eg, company) [OpenBSD]:
Organizational Unit Name (eg, section) [iked]:
Common Name (eg, fully qualified host name) [VPN CA]:
Email Address [[hidden email]]:
Signature ok
subject=/C=DE/ST=Lower Saxony/L=Hanover/O=OpenBSD/OU=iked/CN=VPN CA/emailAddress=[hidden email]
Getting Private key
Using configuration from /etc/ssl/test-vpn/ca-revoke-ssl.cnf

root@server1 ~ $ /usr/src/usr.sbin/ikectl/ikectl ca test-vpn certificate 10.1.2.3 create
Generating RSA private key, 2048 bit long modulus
........................................................................................................+++
.....................................................................................................+++
e is 65537 (0x10001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [DE]:
State or Province Name (full name) [Lower Saxony]:
Locality Name (eg, city) [Hanover]:
Organization Name (eg, company) [OpenBSD]:
Organizational Unit Name (eg, section) [iked]:
Common Name (eg, fully qualified host name) [10.1.2.3]:
Email Address [[hidden email]]:
Using configuration from /etc/ssl/test-vpn/10.1.2.3-ssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'DE'
stateOrProvinceName   :ASN.1 12:'Lower Saxony'
localityName          :ASN.1 12:'Hanover'
organizationName      :ASN.1 12:'OpenBSD'
organizationalUnitName:ASN.1 12:'iked'
commonName            :ASN.1 12:'10.1.2.3'
emailAddress          :IA5STRING:'[hidden email]'
Certificate is to be certified until Aug 15 21:53:56 2018 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

root@server1 ~ $ /usr/src/usr.sbin/ikectl/ikectl ca test-vpn certificate test-client.test-vpn.net create
Generating RSA private key, 2048 bit long modulus
.....................................................+++
............................+++
e is 65537 (0x10001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [DE]:
State or Province Name (full name) [Lower Saxony]:
Locality Name (eg, city) [Hanover]:
Organization Name (eg, company) [OpenBSD]:
Organizational Unit Name (eg, section) [iked]:
Common Name (eg, fully qualified host name) [test-client.test-vpn.net]:
Email Address [[hidden email]]:
Using configuration from /etc/ssl/test-vpn/test-client.test-vpn.net-ssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'DE'
stateOrProvinceName   :ASN.1 12:'Lower Saxony'
localityName          :ASN.1 12:'Hanover'
organizationName      :ASN.1 12:'OpenBSD'
organizationalUnitName:ASN.1 12:'iked'
commonName            :ASN.1 12:'test-client.test-vpn.net'
emailAddress          :IA5STRING:'[hidden email]'
Certificate is to be certified until Aug 15 21:54:22 2018 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

root@server1 ~ $ openssl x509 -text -in /etc/ssl/test-vpn/ca.crt                                        
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 12210187129990035033 (0xa9734c809c1a3659)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=DE, ST=Lower Saxony, L=Hanover, O=OpenBSD, OU=iked, CN=VPN CA/emailAddress=[hidden email]
        Validity
            Not Before: Aug 15 21:53:18 2017 GMT
            Not After : Aug 15 21:53:18 2018 GMT
        Subject: C=DE, ST=Lower Saxony, L=Hanover, O=OpenBSD, OU=iked, CN=VPN CA/emailAddress=[hidden email]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:b3:9a:4a:06:ac:23:9d:ff:99:26:3f:f3:28:49:
                        < ......................... >
                    e2:f1
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:1
            X509v3 Key Usage:
                Digital Signature, Certificate Sign, CRL Sign
    Signature Algorithm: sha256WithRSAEncryption
         43:0d:9c:01:3b:e9:2c:2f:d0:de:54:30:d7:7d:d4:bc:ef:e9:
                < ......................... >
         6d:ce:5f:71
-----BEGIN CERTIFICATE-----
< ......................... >
-----END CERTIFICATE-----

root@server1 ~ $ openssl x509 -text -in /etc/ssl/test-vpn/10.1.2.3.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=DE, ST=Lower Saxony, L=Hanover, O=OpenBSD, OU=iked, CN=VPN CA/emailAddress=[hidden email]
        Validity
            Not Before: Aug 15 21:53:56 2017 GMT
            Not After : Aug 15 21:53:56 2018 GMT
        Subject: C=DE, ST=Lower Saxony, L=Hanover, O=OpenBSD, OU=iked, CN=10.1.2.3/emailAddress=[hidden email]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:b2:86:04:4c:aa:8b:b8:1d:4b:fe:06:b9:7b:6b:
                        < ......................... >
                    13:81
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage:
                Digital Signature, Certificate Sign, CRL Sign
            Netscape Cert Type:
                SSL Client, SSL Server
            X509v3 Subject Alternative Name:
                IP Address:10.1.2.3
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
    Signature Algorithm: sha256WithRSAEncryption
         aa:84:95:0e:e5:a0:a5:85:3e:65:10:a8:43:36:ea:de:53:d0:
                < ......................... >
         a7:b5:00:b0
-----BEGIN CERTIFICATE-----
< ......................... >
-----END CERTIFICATE-----

root@server1 ~ $ openssl x509 -text -in /etc/ssl/test-vpn/test-client.test-vpn.net.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 2 (0x2)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=DE, ST=Lower Saxony, L=Hanover, O=OpenBSD, OU=iked, CN=VPN CA/emailAddress=[hidden email]
        Validity
            Not Before: Aug 15 21:54:22 2017 GMT
            Not After : Aug 15 21:54:22 2018 GMT
        Subject: C=DE, ST=Lower Saxony, L=Hanover, O=OpenBSD, OU=iked, CN=test-client.test-vpn.net/emailAddress=[hidden email]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:e0:39:71:50:3c:4d:de:45:48:62:8f:ef:b6:25:
< ......................... >
                    16:0f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage:
                Digital Signature, Certificate Sign, CRL Sign
            Netscape Cert Type:
                SSL Client, SSL Server
            X509v3 Subject Alternative Name:
                DNS:test-client.test-vpn.net
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
    Signature Algorithm: sha256WithRSAEncryption
         3d:ee:34:0d:7a:a1:58:b0:f6:72:ef:df:92:41:ed:d6:ae:21:
< ......................... >
         27:b3:11:4f
-----BEGIN CERTIFICATE-----
< ......................... >
-----END CERTIFICATE-----


Proposed patch:
======================================================================
diff --git a/usr.sbin/ikectl/ikeca.c b/usr.sbin/ikectl/ikeca.c
index 3dacac9e83e..9fce2d4f04c 100644
--- a/usr.sbin/ikectl/ikeca.c
+++ b/usr.sbin/ikectl/ikeca.c
@@ -88,8 +88,8 @@ struct {
 const char *ca_env[][2] = {
  { "$ENV::CADB", NULL },
  { "$ENV::CASERIAL", NULL },
- { "$ENV::CERTFQDN", NULL },
- { "$ENV::CERTIP", NULL },
+ { "DNS:$ENV::CERTFQDN", NULL },
+ { "IP:$ENV::CERTIP", NULL },
  { "$ENV::CERTPATHLEN", NULL },
  { "$ENV::CERTUSAGE", NULL },
  { "$ENV::CERT_C", NULL },
@@ -202,23 +202,27 @@ ca_request(struct ca *ca, char *keyname, int type)
 {
  char cmd[PATH_MAX * 2];
  char hostname[HOST_NAME_MAX+1];
- char name[128];
+ char subjaltname[HOST_NAME_MAX+5];
  char path[PATH_MAX];
 
  ca_setenv("$ENV::CERT_CN", keyname);
 
- strlcpy(name, keyname, sizeof(name));
-
  if (type == HOST_IPADDR) {
- ca_setenv("$ENV::CERTIP", name);
+ snprintf(subjaltname, sizeof(subjaltname), "IP:%s", keyname);
+ ca_setenv("IP:$ENV::CERTIP", subjaltname);
  ca_setenv("$ENV::REQ_EXT", "x509v3_IPAddr");
  } else if (type == HOST_FQDN) {
  if (!strcmp(keyname, "local")) {
  if (gethostname(hostname, sizeof(hostname)))
  err(1, "gethostname");
- strlcpy(name, hostname, sizeof(name));
+ snprintf(subjaltname, sizeof(subjaltname), "DNS:%s",
+ hostname);
+ }
+ else {
+ snprintf(subjaltname, sizeof(subjaltname), "DNS:%s",
+ keyname);
  }
- ca_setenv("$ENV::CERTFQDN", name);
+ ca_setenv("DNS:$ENV::CERTFQDN", subjaltname);
  ca_setenv("$ENV::REQ_EXT", "x509v3_FQDN");
  } else {
  errx(1, "unknown host type %d", type);
@@ -306,6 +310,9 @@ ca_certificate(struct ca *ca, char *keyname, int type, int action)
  ca_request(ca, keyname, type);
  ca_sign(ca, keyname, type);
 
+ /* call ca_clrenv again to free the char*'s allocated by ca_setenv */
+ ca_clrenv();
+
  return (0);
 }
 
@@ -440,6 +447,9 @@ ca_create(struct ca *ca)
  /* Create the CRL revocation list */
  ca_revoke(ca, NULL);
 
+ /* call ca_clrenv again to free the char*'s allocated by ca_setenv */
+ ca_clrenv();
+
  return (0);
 }
 
@@ -892,6 +902,11 @@ ca_revoke(struct ca *ca, char *keyname)
     ca->passfile, ca->sslpath, ca->sslpath);
  system(cmd);
 
+ if (keyname) {
+ /* ca_revoke() called directly from ca_opt() so free char *'s */
+ ca_clrenv();
+ }
+
  return (0);
 }
 
@@ -899,20 +914,26 @@ void
 ca_clrenv(void)
 {
  int i;
- for (i = 0; ca_env[i][0] != NULL; i++)
+ for (i = 0; ca_env[i][0] != NULL; i++) {
+ free((char *) ca_env[i][1]);
  ca_env[i][1] = NULL;
+ }
 }
 
 void
 ca_setenv(const char *key, const char *value)
 {
  int i;
+ char *p = NULL;
 
  for (i = 0; ca_env[i][0] != NULL; i++) {
  if (strcmp(ca_env[i][0], key) == 0) {
  if (ca_env[i][1] != NULL)
  errx(1, "env %s already set: %s", key, value);
- ca_env[i][1] = value;
+ p = strdup(value);
+ if (p == NULL)
+ err(1, NULL);
+ ca_env[i][1] = p;
  return;
  }
  }

ikectl_subjaltname.patch (2K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: ikectl ca certificate create fails due to invalid subjectAltName

damageg
I'm seeing the same thing in 6.2.



--
Sent from: http://openbsd-archive.7691.n7.nabble.com/openbsd-dev-bugs-f183916.html

Reply | Threaded
Open this post in threaded view
|

Re: ikectl ca certificate create fails due to invalid subjectAltName

jes@posteo.de
The patched submitted by Andrei fixed it for me.
There are some style issues, I fixed the ones I saw and reattached the
patch.

Index: ikeca.c
===================================================================
RCS file: /cvs/src/usr.sbin/ikectl/ikeca.c,v
retrieving revision 1.46
diff -u -p -r1.46 ikeca.c
--- ikeca.c 8 Jun 2017 11:45:44 -0000 1.46
+++ ikeca.c 25 Oct 2017 12:51:59 -0000
@@ -85,11 +85,11 @@ struct {
 };
 
 /* explicitly list allowed variables */
-const char *ca_env[][2] = {
+char *ca_env[][2] = {
  { "$ENV::CADB", NULL },
  { "$ENV::CASERIAL", NULL },
- { "$ENV::CERTFQDN", NULL },
- { "$ENV::CERTIP", NULL },
+ { "DNS:$ENV::CERTFQDN", NULL },
+ { "IP:$ENV::CERTIP", NULL },
  { "$ENV::CERTPATHLEN", NULL },
  { "$ENV::CERTUSAGE", NULL },
  { "$ENV::CERT_C", NULL },
@@ -202,23 +202,26 @@ ca_request(struct ca *ca, char *keyname,
 {
  char cmd[PATH_MAX * 2];
  char hostname[HOST_NAME_MAX+1];
- char name[128];
+ char subjaltname[HOST_NAME_MAX+5];
  char path[PATH_MAX];
 
  ca_setenv("$ENV::CERT_CN", keyname);
 
- strlcpy(name, keyname, sizeof(name));
-
  if (type == HOST_IPADDR) {
- ca_setenv("$ENV::CERTIP", name);
+ snprintf(subjaltname, sizeof(subjaltname), "IP:%s", keyname);
+ ca_setenv("IP:$ENV::CERTIP", subjaltname);
  ca_setenv("$ENV::REQ_EXT", "x509v3_IPAddr");
  } else if (type == HOST_FQDN) {
  if (!strcmp(keyname, "local")) {
  if (gethostname(hostname, sizeof(hostname)))
  err(1, "gethostname");
- strlcpy(name, hostname, sizeof(name));
+ snprintf(subjaltname, sizeof(subjaltname), "DNS:%s",
+    hostname);
+ } else {
+ snprintf(subjaltname, sizeof(subjaltname), "DNS:%s",
+        keyname);
  }
- ca_setenv("$ENV::CERTFQDN", name);
+ ca_setenv("DNS:$ENV::CERTFQDN", subjaltname);
  ca_setenv("$ENV::REQ_EXT", "x509v3_FQDN");
  } else {
  errx(1, "unknown host type %d", type);
@@ -306,6 +309,9 @@ ca_certificate(struct ca *ca, char *keyn
  ca_request(ca, keyname, type);
  ca_sign(ca, keyname, type);
 
+ /* call ca_clrenv again to free the char*'s allocated by ca_setenv */
+ ca_clrenv();
+
  return (0);
 }
 
@@ -440,6 +446,9 @@ ca_create(struct ca *ca)
  /* Create the CRL revocation list */
  ca_revoke(ca, NULL);
 
+ /* call ca_clrenv again to free the char*'s allocated by ca_setenv */
+ ca_clrenv();
+
  return (0);
 }
 
@@ -892,6 +901,11 @@ ca_revoke(struct ca *ca, char *keyname)
     ca->passfile, ca->sslpath, ca->sslpath);
  system(cmd);
 
+ if (keyname) {
+ /* ca_revoke() called directly from ca_opt() so free char *'s */
+ ca_clrenv();
+ }
+
  return (0);
 }
 
@@ -899,20 +913,26 @@ void
 ca_clrenv(void)
 {
  int i;
- for (i = 0; ca_env[i][0] != NULL; i++)
+ for (i = 0; ca_env[i][0] != NULL; i++) {
+ free((char *) ca_env[i][1]);
  ca_env[i][1] = NULL;
+ }
 }
 
 void
 ca_setenv(const char *key, const char *value)
 {
  int i;
+ char *p = NULL;
 
  for (i = 0; ca_env[i][0] != NULL; i++) {
  if (strcmp(ca_env[i][0], key) == 0) {
  if (ca_env[i][1] != NULL)
  errx(1, "env %s already set: %s", key, value);
- ca_env[i][1] = value;
+ p = strdup(value);
+ if (p == NULL)
+ err(1, NULL);
+ ca_env[i][1] = p;
  return;
  }
  }



--
Sent from: http://openbsd-archive.7691.n7.nabble.com/openbsd-dev-bugs-f183916.html

Reply | Threaded
Open this post in threaded view
|

Re: ikectl ca certificate create fails due to invalid subjectAltName

Patrick Wildt-4
On Wed, Oct 25, 2017 at 06:03:44AM -0700, [hidden email] wrote:

> The patched submitted by Andrei fixed it for me.
> There are some style issues, I fixed the ones I saw and reattached the
> patch.
>
> Index: ikeca.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ikectl/ikeca.c,v
> retrieving revision 1.46
> diff -u -p -r1.46 ikeca.c
> --- ikeca.c 8 Jun 2017 11:45:44 -0000 1.46
> +++ ikeca.c 25 Oct 2017 12:51:59 -0000
> @@ -85,11 +85,11 @@ struct {
>  };
>  
>  /* explicitly list allowed variables */
> -const char *ca_env[][2] = {
> +char *ca_env[][2] = {
>   { "$ENV::CADB", NULL },
>   { "$ENV::CASERIAL", NULL },
> - { "$ENV::CERTFQDN", NULL },
> - { "$ENV::CERTIP", NULL },
> + { "DNS:$ENV::CERTFQDN", NULL },
> + { "IP:$ENV::CERTIP", NULL },
>   { "$ENV::CERTPATHLEN", NULL },
>   { "$ENV::CERTUSAGE", NULL },
>   { "$ENV::CERT_C", NULL },
> @@ -202,23 +202,26 @@ ca_request(struct ca *ca, char *keyname,
>  {
>   char cmd[PATH_MAX * 2];
>   char hostname[HOST_NAME_MAX+1];
> - char name[128];
> + char subjaltname[HOST_NAME_MAX+5];
>   char path[PATH_MAX];
>  
>   ca_setenv("$ENV::CERT_CN", keyname);
>  
> - strlcpy(name, keyname, sizeof(name));
> -
>   if (type == HOST_IPADDR) {
> - ca_setenv("$ENV::CERTIP", name);
> + snprintf(subjaltname, sizeof(subjaltname), "IP:%s", keyname);
> + ca_setenv("IP:$ENV::CERTIP", subjaltname);
>   ca_setenv("$ENV::REQ_EXT", "x509v3_IPAddr");
>   } else if (type == HOST_FQDN) {
>   if (!strcmp(keyname, "local")) {
>   if (gethostname(hostname, sizeof(hostname)))
>   err(1, "gethostname");
> - strlcpy(name, hostname, sizeof(name));
> + snprintf(subjaltname, sizeof(subjaltname), "DNS:%s",
> +    hostname);
> + } else {
> + snprintf(subjaltname, sizeof(subjaltname), "DNS:%s",
> +        keyname);
>   }
> - ca_setenv("$ENV::CERTFQDN", name);
> + ca_setenv("DNS:$ENV::CERTFQDN", subjaltname);
>   ca_setenv("$ENV::REQ_EXT", "x509v3_FQDN");
>   } else {
>   errx(1, "unknown host type %d", type);
> @@ -306,6 +309,9 @@ ca_certificate(struct ca *ca, char *keyn
>   ca_request(ca, keyname, type);
>   ca_sign(ca, keyname, type);
>  
> + /* call ca_clrenv again to free the char*'s allocated by ca_setenv */
> + ca_clrenv();
> +
>   return (0);
>  }
>  
> @@ -440,6 +446,9 @@ ca_create(struct ca *ca)
>   /* Create the CRL revocation list */
>   ca_revoke(ca, NULL);
>  
> + /* call ca_clrenv again to free the char*'s allocated by ca_setenv */
> + ca_clrenv();
> +
>   return (0);
>  }
>  
> @@ -892,6 +901,11 @@ ca_revoke(struct ca *ca, char *keyname)
>      ca->passfile, ca->sslpath, ca->sslpath);
>   system(cmd);
>  
> + if (keyname) {
> + /* ca_revoke() called directly from ca_opt() so free char *'s */
> + ca_clrenv();
> + }
> +
>   return (0);
>  }
>  
> @@ -899,20 +913,26 @@ void
>  ca_clrenv(void)
>  {
>   int i;
> - for (i = 0; ca_env[i][0] != NULL; i++)
> + for (i = 0; ca_env[i][0] != NULL; i++) {
> + free((char *) ca_env[i][1]);
>   ca_env[i][1] = NULL;
> + }
>  }
>  
>  void
>  ca_setenv(const char *key, const char *value)
>  {
>   int i;
> + char *p = NULL;
>  
>   for (i = 0; ca_env[i][0] != NULL; i++) {
>   if (strcmp(ca_env[i][0], key) == 0) {
>   if (ca_env[i][1] != NULL)
>   errx(1, "env %s already set: %s", key, value);
> - ca_env[i][1] = value;
> + p = strdup(value);
> + if (p == NULL)
> + err(1, NULL);
> + ca_env[i][1] = p;
>   return;
>   }
>   }

Good find by Andrei, I will have a look!

Reply | Threaded
Open this post in threaded view
|

Re: ikectl ca certificate create fails due to invalid subjectAltName

Patrick Wildt-4
On Sun, Nov 05, 2017 at 09:19:04PM +0100, Patrick Wildt wrote:
> On Wed, Oct 25, 2017 at 06:03:44AM -0700, [hidden email] wrote:
> > The patched submitted by Andrei fixed it for me.
> > There are some style issues, I fixed the ones I saw and reattached the
> > patch.
>
> Good find by Andrei, I will have a look!
>

The diff can be massively reduced.  The expand_string() code looks for
$ENV::CERTFQDN and $ENV::CERTIP and replaces those in the config file.
Since IP: and DNS: is prepended in the config file already, there is
no need to do the dance as the prefix will still be there after the
$ENV::STUFF has been replaced.

The issue though is that due to the rework, we store a pointer to the
stack in the "CA config" struct.  The function returns, and another
function then uses that pointer.  But it's the stack, so it's already
garbage.  The important thing from the diff is the strdup().

diff --git a/usr.sbin/ikectl/ikeca.c b/usr.sbin/ikectl/ikeca.c
index 3dacac9e83e..0bf2bbd5738 100644
--- a/usr.sbin/ikectl/ikeca.c
+++ b/usr.sbin/ikectl/ikeca.c
@@ -85,7 +85,7 @@ struct {
 };
 
 /* explicitly list allowed variables */
-const char *ca_env[][2] = {
+char *ca_env[][2] = {
  { "$ENV::CADB", NULL },
  { "$ENV::CASERIAL", NULL },
  { "$ENV::CERTFQDN", NULL },
@@ -899,20 +899,26 @@ void
 ca_clrenv(void)
 {
  int i;
- for (i = 0; ca_env[i][0] != NULL; i++)
+ for (i = 0; ca_env[i][0] != NULL; i++) {
+ free(ca_env[i][1]);
  ca_env[i][1] = NULL;
+ }
 }
 
 void
 ca_setenv(const char *key, const char *value)
 {
  int i;
+ char *p = NULL;
 
  for (i = 0; ca_env[i][0] != NULL; i++) {
  if (strcmp(ca_env[i][0], key) == 0) {
  if (ca_env[i][1] != NULL)
  errx(1, "env %s already set: %s", key, value);
- ca_env[i][1] = value;
+ p = strdup(value);
+ if (p == NULL)
+ err(1, NULL);
+ ca_env[i][1] = p;
  return;
  }
  }