[openssl] master update

dev at ddvo.net dev at ddvo.net
Thu Sep 10 10:08:44 UTC 2020


The branch master has been updated
       via  5a0991d0d94b966e0621b8123873b132877dc9d3 (commit)
       via  5fdcde816f6ee9ef048977c14427e2b0b63f47b6 (commit)
       via  a8e2a9f569c60dbbc180672b0fce16ab7dd6ca72 (commit)
       via  bc64c5a69b95d45c314ec6ac40a865228cf230cd (commit)
       via  2aa91df406a8c907b53d01773b1b860117542c48 (commit)
       via  115786793c2521af9dcf20a6114e9904e0c206aa (commit)
      from  388f2d9f6c3faebc72722ba6bb76df12146ad988 (commit)


- Log -----------------------------------------------------------------
commit 5a0991d0d94b966e0621b8123873b132877dc9d3
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Sep 2 13:52:23 2020 +0200

    Add/harmonize multi-valued RDN support and doc of ca, cmp, req, storeutl, and x509 apps
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12769)

commit 5fdcde816f6ee9ef048977c14427e2b0b63f47b6
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Sep 2 13:50:04 2020 +0200

    X509_NAME_cmp(): Clearly document its semantics, referencing relevant RFCs
    
    Fixes #12765
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12769)

commit a8e2a9f569c60dbbc180672b0fce16ab7dd6ca72
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Fri Sep 4 18:31:46 2020 +0200

    X509_NAME_add_entry_by_txt.pod: Improve documentation w.r.t. multi-valued RDNs (containing sets of AVAs)
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12769)

commit bc64c5a69b95d45c314ec6ac40a865228cf230cd
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Sep 2 13:12:22 2020 +0200

    X509_NAME_cmp: restrict normal return values to {-1,0,1} to avoid confusion with -2 for error
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12769)

commit 2aa91df406a8c907b53d01773b1b860117542c48
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Sep 2 14:18:34 2020 +0200

    X509_NAME_oneline(): Fix output of multi-valued RDNs, escaping '/' and '+' in values
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12769)

commit 115786793c2521af9dcf20a6114e9904e0c206aa
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Sep 2 12:56:49 2020 +0200

    X509_NAME_print_ex.pod: re-format lines to fit within 80 chars limit
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12769)

-----------------------------------------------------------------------

Summary of changes:
 apps/ca.c                               |  6 +--
 apps/cmp.c                              |  2 +-
 apps/lib/apps.c                         |  7 ++-
 apps/req.c                              |  6 +--
 apps/x509.c                             |  2 +-
 crypto/x509/x509_cmp.c                  | 38 ++++++++---------
 crypto/x509/x509_obj.c                  | 26 +++++++-----
 doc/man1/openssl-ca.pod.in              | 20 +++++----
 doc/man1/openssl-cmp.pod.in             | 23 +++++-----
 doc/man1/openssl-req.pod.in             | 22 +++++-----
 doc/man1/openssl-storeutl.pod.in        | 10 ++++-
 doc/man1/openssl-x509.pod.in            | 12 ++++--
 doc/man3/X509_NAME_add_entry_by_txt.pod | 12 +++---
 doc/man3/X509_NAME_print_ex.pod         | 75 ++++++++++++++++++---------------
 doc/man3/X509_cmp.pod                   | 19 +++++----
 15 files changed, 159 insertions(+), 121 deletions(-)

diff --git a/apps/ca.c b/apps/ca.c
index 8a5104f488..ff40a13d31 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -200,7 +200,7 @@ const OPTIONS ca_options[] = {
     {"rand_serial", OPT_RAND_SERIAL, '-',
      "Always create a random serial; do not store it"},
     {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
-     "Enable support for multivalued RDNs"},
+     "Deprecated; multi-valued RDNs support is always on."},
     {"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"},
     {"enddate", OPT_ENDDATE, 's',
      "YYMMDDHHMMSSZ cert notAfter (overrides -days)"},
@@ -288,7 +288,7 @@ int ca_main(int argc, char **argv)
     size_t outdirlen = 0;
     int create_ser = 0, free_passin = 0, total = 0, total_done = 0;
     int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE;
-    int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0;
+    int keyformat = FORMAT_PEM, multirdn = 1, notext = 0, output_der = 0;
     int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0;
     int rand_ser = 0, i, j, selfsign = 0, def_nid, def_ret;
     long crldays = 0, crlhours = 0, crlsec = 0, days = 0;
@@ -344,7 +344,7 @@ opthelp:
             create_ser = 1;
             break;
         case OPT_MULTIVALUE_RDN:
-            multirdn = 1;
+            /* obsolete */
             break;
         case OPT_STARTDATE:
             startdate = opt_arg();
diff --git a/apps/cmp.c b/apps/cmp.c
index 1c3b592f7f..ce2513bd0d 100644
--- a/apps/cmp.c
+++ b/apps/cmp.c
@@ -893,7 +893,7 @@ static int set_name(const char *str,
                     OSSL_CMP_CTX *ctx, const char *desc)
 {
     if (str != NULL) {
-        X509_NAME *n = parse_name(str, MBSTRING_ASC, 0, desc);
+        X509_NAME *n = parse_name(str, MBSTRING_ASC, 1, desc);
 
         if (n == NULL)
             return 0;
diff --git a/apps/lib/apps.c b/apps/lib/apps.c
index 878ec18f0b..d3f3f6d2b6 100644
--- a/apps/lib/apps.c
+++ b/apps/lib/apps.c
@@ -1647,7 +1647,8 @@ int parse_yesno(const char *str, int def)
 
 /*
  * name is expected to be in the format /type0=value0/type1=value1/type2=...
- * where characters may be escaped by \
+ * where + can be used instead of / to form multi-valued RDNs if canmulti
+ * and characters may be escaped by \
  */
 X509_NAME *parse_name(const char *cp, int chtype, int canmulti,
                       const char *desc)
@@ -1700,6 +1701,7 @@ X509_NAME *parse_name(const char *cp, int chtype, int canmulti,
         /* Collect the value. */
         valstr = (unsigned char *)bp;
         for (; *cp != '\0' && *cp != '/'; *bp++ = *cp++) {
+            /* unescaped '+' symbol string signals further member of multiRDN */
             if (canmulti && *cp == '+') {
                 nextismulti = 1;
                 break;
@@ -1723,6 +1725,9 @@ X509_NAME *parse_name(const char *cp, int chtype, int canmulti,
             BIO_printf(bio_err,
                        "%s: Skipping unknown %s name attribute \"%s\"\n",
                        opt_getprog(), desc, typestr);
+            if (ismulti)
+                BIO_printf(bio_err,
+                           "Hint: a '+' in a value string needs be escaped using '\\' else a new member of a multi-valued RDN is expected\n");
             continue;
         }
         if (*valstr == '\0') {
diff --git a/apps/req.c b/apps/req.c
index 46739554bd..2cc9ebf43d 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -127,7 +127,7 @@ const OPTIONS req_options[] = {
     {"subj", OPT_SUBJ, 's', "Set or modify request subject"},
     {"subject", OPT_SUBJECT, '-', "Output the request's subject"},
     {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
-     "Enable support for multivalued RDNs"},
+     "Deprecated; multi-valued RDNs support is always on."},
     {"days", OPT_DAYS, 'p', "Number of days cert is valid for"},
     {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
     {"addext", OPT_ADDEXT, 's',
@@ -257,7 +257,7 @@ int req_main(int argc, char **argv)
     int ret = 1, x509 = 0, days = 0, i = 0, newreq = 0, verbose = 0;
     int pkey_type = -1, private = 0;
     int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyform = FORMAT_PEM;
-    int modulus = 0, multirdn = 0, verify = 0, noout = 0, text = 0;
+    int modulus = 0, multirdn = 1, verify = 0, noout = 0, text = 0;
     int noenc = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0;
     long newkey = -1;
     unsigned long chtype = MBSTRING_ASC, reqflag = 0;
@@ -421,7 +421,7 @@ int req_main(int argc, char **argv)
             subj = opt_arg();
             break;
         case OPT_MULTIVALUE_RDN:
-            multirdn = 1;
+            /* obsolete */
             break;
         case OPT_ADDEXT:
             p = opt_arg();
diff --git a/apps/x509.c b/apps/x509.c
index 64a1cadc97..169530f6d6 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -179,7 +179,7 @@ int x509_main(int argc, char **argv)
     char *subj = NULL;
     X509_NAME *fsubj = NULL;
     const unsigned long chtype = MBSTRING_ASC;
-    const int multirdn = 0;
+    const int multirdn = 1;
     STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
     STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL;
     X509 *x = NULL, *xca = NULL;
diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c
index 0e770de11d..32e15682b1 100644
--- a/crypto/x509/x509_cmp.c
+++ b/crypto/x509/x509_cmp.c
@@ -30,8 +30,8 @@ int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
     ai = &a->cert_info;
     bi = &b->cert_info;
     i = ASN1_INTEGER_cmp(&ai->serialNumber, &bi->serialNumber);
-    if (i)
-        return i;
+    if (i != 0)
+        return i < 0 ? -1 : 1;
     return X509_NAME_cmp(ai->issuer, bi->issuer);
 }
 
@@ -83,7 +83,9 @@ int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
 
 int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
 {
-    return memcmp(a->sha1_hash, b->sha1_hash, 20);
+    int rv = memcmp(a->sha1_hash, b->sha1_hash, 20);
+
+    return rv < 0 ? -1 : rv > 0;
 }
 
 X509_NAME *X509_get_issuer_name(const X509 *a)
@@ -149,18 +151,18 @@ int X509_cmp(const X509 *a, const X509 *b)
         return -2;
 
     rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
-    if (rv)
-        return rv;
+    if (rv != 0)
+        return rv < 0 ? -1 : 1;
     /* Check for match against stored encoding too */
     if (!a->cert_info.enc.modified && !b->cert_info.enc.modified) {
         if (a->cert_info.enc.len < b->cert_info.enc.len)
             return -1;
         if (a->cert_info.enc.len > b->cert_info.enc.len)
             return 1;
-        return memcmp(a->cert_info.enc.enc, b->cert_info.enc.enc,
-                      a->cert_info.enc.len);
+        rv = memcmp(a->cert_info.enc.enc,
+                    b->cert_info.enc.enc, a->cert_info.enc.len);
     }
-    return rv;
+    return rv < 0 ? -1 : rv > 0;
 }
 
 int X509_add_cert_new(STACK_OF(X509) **sk, X509 *cert, int flags)
@@ -208,7 +210,7 @@ int X509_add_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs, int flags)
 {
     int n = sk_X509_num(certs); /* certs may be NULL */
     int i;
- 
+
     for (i = 0; i < n; i++) {
         int j = (flags & X509_ADD_FLAG_PREPEND) == 0 ? i : n - 1 - i;
         /* if prepend, add certs in reverse order to keep original order */
@@ -242,12 +244,10 @@ int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
     }
 
     ret = a->canon_enclen - b->canon_enclen;
+    if (ret == 0 && a->canon_enclen != 0)
+        ret = memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
 
-    if (ret != 0 || a->canon_enclen == 0)
-        return ret;
-
-    return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
-
+    return ret < 0 ? -1 : ret > 0;
 }
 
 unsigned long X509_NAME_hash(const X509_NAME *x)
@@ -410,9 +410,9 @@ static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
             return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
         if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY))
             return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
-    } else
+    } else {
         return X509_V_ERR_SUITE_B_INVALID_CURVE;
-
+    }
     return X509_V_OK;
 }
 
@@ -430,9 +430,9 @@ int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
     if (x == NULL) {
         x = sk_X509_value(chain, 0);
         i = 1;
-    } else
+    } else {
         i = 0;
-
+    }
     pk = X509_get0_pubkey(x);
 
     /*
@@ -533,7 +533,7 @@ STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain)
     return ret;
  err:
     while (i-- > 0)
-        X509_free (sk_X509_value(ret, i));
+        X509_free(sk_X509_value(ret, i));
     sk_X509_free(ret);
     return NULL;
 }
diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c
index c1e893bf13..7bed79a2d5 100644
--- a/crypto/x509/x509_obj.c
+++ b/crypto/x509/x509_obj.c
@@ -13,6 +13,7 @@
 #include <openssl/x509.h>
 #include <openssl/buffer.h>
 #include "crypto/x509.h"
+#include "crypto/ctype.h"
 
 DEFINE_STACK_OF(X509_NAME_ENTRY)
 
@@ -28,6 +29,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
     const X509_NAME_ENTRY *ne;
     int i;
     int n, lold, l, l1, l2, num, j, type;
+    int prev_set = -1;
     const char *s;
     char *p;
     unsigned char *q;
@@ -109,14 +111,11 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
             if (!gs_doit[j & 3])
                 continue;
             l2++;
-#ifndef CHARSET_EBCDIC
-            if ((q[j] < ' ') || (q[j] > '~'))
-                l2 += 3;
-#else
-            if ((os_toascii[q[j]] < os_toascii[' ']) ||
-                (os_toascii[q[j]] > os_toascii['~']))
+            if (q[j] == '/' || q[j] == '+')
+                l2++; /* char needs to be escaped */
+            else if ((ossl_toascii(q[j]) < ossl_toascii(' ')) ||
+                     (ossl_toascii(q[j]) > ossl_toascii('~')))
                 l2 += 3;
-#endif
         }
 
         lold = l;
@@ -133,7 +132,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
             break;
         } else
             p = &(buf[lold]);
-        *(p++) = '/';
+        *(p++) = prev_set == ne->set ? '+' : '/';
         memcpy(p, s, (unsigned int)l1);
         p += l1;
         *(p++) = '=';
@@ -152,8 +151,11 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
                 *(p++) = 'x';
                 *(p++) = hex[(n >> 4) & 0x0f];
                 *(p++) = hex[n & 0x0f];
-            } else
+            } else {
+                if (n == '/' || n == '+')
+                    *(p++) = '\\';
                 *(p++) = n;
+            }
 #else
             n = os_toascii[q[j]];
             if ((n < os_toascii[' ']) || (n > os_toascii['~'])) {
@@ -161,11 +163,15 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
                 *(p++) = 'x';
                 *(p++) = hex[(n >> 4) & 0x0f];
                 *(p++) = hex[n & 0x0f];
-            } else
+            } else {
+                if (n == os_toascii['/'] || n == os_toascii['+'])
+                    *(p++) = '\\';
                 *(p++) = q[j];
+            }
 #endif
         }
         *p = '\0';
+        prev_set = ne->set;
     }
     if (b != NULL) {
         p = b->data;
diff --git a/doc/man1/openssl-ca.pod.in b/doc/man1/openssl-ca.pod.in
index 7d7f0752f3..d196565422 100644
--- a/doc/man1/openssl-ca.pod.in
+++ b/doc/man1/openssl-ca.pod.in
@@ -285,11 +285,17 @@ used).
 =item B<-subj> I<arg>
 
 Supersedes subject name given in the request.
+
 The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
-Keyword characters may be escaped by C<\> (backslash), and whitespace is
-retained.
+Special characters may be escaped by C<\> (backslash), whitespace is retained.
 Empty values are permitted, but the corresponding type will not be included
 in the resulting certificate.
+Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
+Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
+between the AttributeValueAssertions (AVAs) that specify the members of the set.
+Example:
+
+C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
 
 =item B<-utf8>
 
@@ -313,12 +319,7 @@ This overrides any option or configuration to use a serial number file.
 
 =item B<-multivalue-rdn>
 
-This option causes the -subj argument to be interpreted with full
-support for multivalued RDNs. Example:
-
-C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
-
-If B<-multi-rdn> is not used then the UID value is C<123456+CN=John Doe>.
+This option has been deprecated and has no effect.
 
 {- $OpenSSL::safe::opt_r_item -}
 
@@ -791,7 +792,8 @@ retained mainly for compatibility reasons.
 
 The B<-section> option was added in OpenSSL 3.0.0.
 
-The B<-certform> option has become obsolete in OpenSSL 3.0.0 and has no effect.
+The B<-certform> and B<-multivalue-rdn> options
+have become obsolete in OpenSSL 3.0.0 and have no effect.
 
 All B<-keyform> values except B<ENGINE> have become obsolete in OpenSSL 3.0.0
 and have no effect.
diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in
index 9389701893..44f71b8358 100644
--- a/doc/man1/openssl-cmp.pod.in
+++ b/doc/man1/openssl-cmp.pod.in
@@ -268,20 +268,24 @@ For KUR, it defaults to the subject DN of the reference certificate
 (see B<-oldcert>).
 This default is used for IR and CR only if no SANs are set.
 
-The argument must be formatted as I</type0=value0/type1=value1/type2=...>,
-characters may be escaped by C<\>E<nbsp>(backslash), no spaces are skipped.
-
 The subject DN is also used as fallback sender of outgoing CMP messages
 if no B<-cert> and no B<-oldcert> are given.
 
+The argument must be formatted as I</type0=value0/type1=value1/type2=...>.
+Special characters may be escaped by C<\> (backslash), whitespace is retained.
+Empty values are permitted, but the corresponding type will not be included.
+Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
+Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
+between the AttributeValueAssertions (AVAs) that specify the members of the set.
+Example:
+
+C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
+
 =item B<-issuer> I<name>
 
 X509 issuer Distinguished Name (DN) of the CA server
 to place in the requested certificate template in IR/CR/KUR.
 
-The argument must be formatted as I</type0=value0/type1=value1/type2=...>,
-characters may be escaped by C<\>E<nbsp>(backslash), no spaces are skipped.
-
 If neither B<-srvcert> nor B<-recipient> is available,
 the name given in this option is also set as the recipient of the CMP message.
 
@@ -519,10 +523,6 @@ and as default value for the expected sender of incoming CMP messages.
 Distinguished Name (DN) to use in the recipient field of CMP request messages,
 i.e., the CMP server (usually the addressed CA).
 
-The argument must be formatted as I</type0=value0/type1=value1/type2=...>,
-characters may be escaped by C<\>E<nbsp>(backslash), no spaces are skipped.
-The empty name (NULL-DN) can be given explicitly as a single slash: 'I</>'.
-
 The recipient field in the header of a CMP message is mandatory.
 If not given explicitly the recipient is determined in the following order:
 the subject of the CMP server certificate given with the B<-srvcert> option,
@@ -536,9 +536,6 @@ as far as any of those is present, else the NULL-DN as last resort.
 Distinguished Name (DN) expected in the sender field of incoming CMP messages.
 Defaults to the subject DN of the pinned B<-srvcert>, if any.
 
-The argument must be formatted as I</type0=value0/type1=value1/type2=...>,
-characters may be escaped by C<\>E<nbsp>(backslash), no spaces are skipped.
-
 This can be used to make sure that only a particular entity is accepted as
 CMP message signer, and attackers are not able to use arbitrary certificates
 of a trusted PKI hierarchy to fraudulently pose as a CMP server.
diff --git a/doc/man1/openssl-req.pod.in b/doc/man1/openssl-req.pod.in
index 1af355b5b3..52b2326d78 100644
--- a/doc/man1/openssl-req.pod.in
+++ b/doc/man1/openssl-req.pod.in
@@ -32,7 +32,6 @@ B<openssl> B<req>
 [B<-I<digest>>]
 [B<-config> I<filename>]
 [B<-section> I<name>]
-[B<-multivalue-rdn>]
 [B<-x509>]
 [B<-days> I<n>]
 [B<-set_serial> I<n>]
@@ -45,6 +44,7 @@ B<openssl> B<req>
 [B<-reqopt>]
 [B<-subject>]
 [B<-subj> I<arg>]
+[B<-multivalue-rdn>]
 [B<-sigopt> I<nm>:I<v>]
 [B<-vfyopt> I<nm>:I<v>]
 [B<-batch>]
@@ -233,19 +233,21 @@ Specifies the name of the section to use; the default is B<req>.
 
 Sets subject name for new request or supersedes the subject name
 when processing a request.
+
 The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
-Keyword characters may be escaped by \ (backslash), and whitespace is retained.
+Special characters may be escaped by C<\> (backslash), whitespace is retained.
 Empty values are permitted, but the corresponding type will not be included
 in the request.
-
-=item B<-multivalue-rdn>
-
-This option causes the -subj argument to be interpreted with full
-support for multivalued RDNs. Example:
+Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
+Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
+between the AttributeValueAssertions (AVAs) that specify the members of the set.
+Example:
 
 C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
 
-If -multi-rdn is not used then the UID value is C<123456+CN=John Doe>.
+=item B<-multivalue-rdn>
+
+This option has been deprecated and has no effect.
 
 =item B<-x509>
 
@@ -697,8 +699,8 @@ L<x509v3_config(5)>
 
 The B<-section> option was added in OpenSSL 3.0.0.
 
-All B<-keyform> values except B<ENGINE> have become obsolete in OpenSSL 3.0.0
-and have no effect.
+All B<-keyform> values except B<ENGINE> and the B<-multivalue-rdn> option
+have become obsolete in OpenSSL 3.0.0 and have no effect.
 
 The B<-engine> option was deprecated in OpenSSL 3.0.
 The <-nodes> option was deprecated in OpenSSL 3.0, too; use B<-noenc> instead.
diff --git a/doc/man1/openssl-storeutl.pod.in b/doc/man1/openssl-storeutl.pod.in
index 2c92f825a0..bc2eec17f7 100644
--- a/doc/man1/openssl-storeutl.pod.in
+++ b/doc/man1/openssl-storeutl.pod.in
@@ -80,11 +80,19 @@ returned.
 =item B<-subject> I<arg>
 
 Search for an object having the subject name I<arg>.
+
 The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
-Keyword characters may be escaped by \ (backslash), and whitespace is retained.
+Special characters may be escaped by C<\> (backslash), whitespace is retained.
 Empty values are permitted but are ignored for the search.  That is,
 a search with an empty value will have the same effect as not specifying
 the type at all.
+Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
+Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
+between the AttributeValueAssertions (AVAs) that specify the members of the set.
+
+Example:
+
+C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
 
 =item B<-issuer> I<arg>
 
diff --git a/doc/man1/openssl-x509.pod.in b/doc/man1/openssl-x509.pod.in
index 8eb35e537e..fb4be2c264 100644
--- a/doc/man1/openssl-x509.pod.in
+++ b/doc/man1/openssl-x509.pod.in
@@ -517,11 +517,17 @@ generate a certificate containing any desired public key.
 =item B<-subj> I<arg>
 
 When a certificate is created set its subject name to the given value.
+
 The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
-Keyword characters may be escaped by \ (backslash), and whitespace is retained.
+Special characters may be escaped by C<\> (backslash), whitespace is retained.
 Empty values are permitted, but the corresponding type will not be included
-in the certificate. Giving a single C</> will lead to an empty sequence of RDNs
-(a NULL subject DN).
+in the certificate.
+Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
+Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
+between the AttributeValueAssertions (AVAs) that specify the members of the set.
+Example:
+
+C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
 
 Unless the B<-CA> option is given the issuer is set to the same value.
 
diff --git a/doc/man3/X509_NAME_add_entry_by_txt.pod b/doc/man3/X509_NAME_add_entry_by_txt.pod
index ce8bf3ef29..8b17a016de 100644
--- a/doc/man3/X509_NAME_add_entry_by_txt.pod
+++ b/doc/man3/X509_NAME_add_entry_by_txt.pod
@@ -66,13 +66,13 @@ RelativeDistinguishedName (RDN).
 B<loc> actually determines the index where the new entry is inserted:
 if it is -1 it is appended.
 
-B<set> determines how the new type is added. If it is zero a
-new RDN is created.
+B<set> determines how the new type is added.
+If it is zero a new RDN is created.
 
-If B<set> is -1 or 1 it is added to the previous or next RDN
-structure respectively. This will then be a multivalued RDN:
-since multivalues RDNs are very seldom used B<set> is almost
-always set to zero.
+If B<set> is -1 or 1 it is added as a new set member
+to the previous or next RDN structure, respectively.
+This will then become part of a multi-valued RDN (containing a set of AVAs).
+Since multi-valued RDNs are very rarely used B<set> typically will be zero.
 
 =head1 RETURN VALUES
 
diff --git a/doc/man3/X509_NAME_print_ex.pod b/doc/man3/X509_NAME_print_ex.pod
index a9532b1853..ccb4b5629a 100644
--- a/doc/man3/X509_NAME_print_ex.pod
+++ b/doc/man3/X509_NAME_print_ex.pod
@@ -9,34 +9,37 @@ X509_NAME_oneline - X509_NAME printing routines
 
  #include <openssl/x509.h>
 
- int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, unsigned long flags);
- int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent, unsigned long flags);
+ int X509_NAME_print_ex(BIO *out, const X509_NAME *nm,
+                        int indent, unsigned long flags);
+ int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm,
+                           int indent, unsigned long flags);
  char *X509_NAME_oneline(const X509_NAME *a, char *buf, int size);
  int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase);
 
 =head1 DESCRIPTION
 
-X509_NAME_print_ex() prints a human readable version of B<nm> to BIO B<out>. Each
-line (for multiline formats) is indented by B<indent> spaces. The output format
-can be extensively customised by use of the B<flags> parameter.
+X509_NAME_print_ex() prints a human readable version of I<nm> to BIO I<out>.
+Each line (for multiline formats) is indented by I<indent> spaces. The
+output format can be extensively customised by use of the I<flags> parameter.
 
-X509_NAME_print_ex_fp() is identical to X509_NAME_print_ex() except the output is
-written to FILE pointer B<fp>.
+X509_NAME_print_ex_fp() is identical to X509_NAME_print_ex()
+except the output is written to FILE pointer I<fp>.
 
-X509_NAME_oneline() prints an ASCII version of B<a> to B<buf>.
-If B<buf> is B<NULL> then a buffer is dynamically allocated and returned, and
-B<size> is ignored.
-Otherwise, at most B<size> bytes will be written, including the ending '\0',
-and B<buf> is returned.
+X509_NAME_oneline() prints an ASCII version of I<a> to I<buf>.
+This supports multi-valued RDNs and escapes B</> and B<+> characters in values.
+If I<buf> is B<NULL> then a buffer is dynamically allocated and returned, and
+I<size> is ignored.
+Otherwise, at most I<size> bytes will be written, including the ending '\0',
+and I<buf> is returned.
 
-X509_NAME_print() prints out B<name> to B<bp> indenting each line by B<obase>
+X509_NAME_print() prints out I<name> to I<bp> indenting each line by I<obase>
 characters. Multiple lines are used if the output (including indent) exceeds
 80 characters.
 
 =head1 NOTES
 
 The functions X509_NAME_oneline() and X509_NAME_print()
-produce a non standard output form, they don't handle multi character fields and
+produce a non standard output form, they don't handle multi-character fields and
 have various quirks and inconsistencies.
 Their use is strongly discouraged in new applications and they could
 be deprecated in a future release.
@@ -52,15 +55,18 @@ The complete set of the flags supported by X509_NAME_print_ex() is listed below.
 Several options can be ored together.
 
 The options B<XN_FLAG_SEP_COMMA_PLUS>, B<XN_FLAG_SEP_CPLUS_SPC>,
-B<XN_FLAG_SEP_SPLUS_SPC> and B<XN_FLAG_SEP_MULTILINE> determine the field separators
-to use. Two distinct separators are used between distinct RelativeDistinguishedName
-components and separate values in the same RDN for a multi-valued RDN. Multi-valued
-RDNs are currently very rare so the second separator will hardly ever be used.
-
-B<XN_FLAG_SEP_COMMA_PLUS> uses comma and plus as separators. B<XN_FLAG_SEP_CPLUS_SPC>
-uses comma and plus with spaces: this is more readable that plain comma and plus.
-B<XN_FLAG_SEP_SPLUS_SPC> uses spaced semicolon and plus. B<XN_FLAG_SEP_MULTILINE> uses
-spaced newline and plus respectively.
+B<XN_FLAG_SEP_SPLUS_SPC> and B<XN_FLAG_SEP_MULTILINE>
+determine the field separators to use.
+Two distinct separators are used between distinct RelativeDistinguishedName
+components and separate values in the same RDN for a multi-valued RDN.
+Multi-valued RDNs are currently very rare
+so the second separator will hardly ever be used.
+
+B<XN_FLAG_SEP_COMMA_PLUS> uses comma and plus as separators.
+B<XN_FLAG_SEP_CPLUS_SPC> uses comma and plus with spaces:
+this is more readable that plain comma and plus.
+B<XN_FLAG_SEP_SPLUS_SPC> uses spaced semicolon and plus.
+B<XN_FLAG_SEP_MULTILINE> uses spaced newline and plus respectively.
 
 If B<XN_FLAG_DN_REV> is set the whole DN is printed in reversed order.
 
@@ -84,18 +90,21 @@ control how each field value is displayed.
 
 In addition a number options can be set for commonly used formats.
 
-B<XN_FLAG_RFC2253> sets options which produce an output compatible with RFC2253 it
-is equivalent to:
- C<ASN1_STRFLGS_RFC2253 | XN_FLAG_SEP_COMMA_PLUS | XN_FLAG_DN_REV | XN_FLAG_FN_SN | XN_FLAG_DUMP_UNKNOWN_FIELDS>
-
+B<XN_FLAG_RFC2253> sets options which produce an output compatible with RFC2253.
+It is equivalent to:
+ C<ASN1_STRFLGS_RFC2253 | XN_FLAG_SEP_COMMA_PLUS | XN_FLAG_DN_REV
+   | XN_FLAG_FN_SN | XN_FLAG_DUMP_UNKNOWN_FIELDS>
 
 B<XN_FLAG_ONELINE> is a more readable one line format which is the same as:
- C<ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE | XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_SPC_EQ | XN_FLAG_FN_SN>
+ C<ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE | XN_FLAG_SEP_CPLUS_SPC
+   | XN_FLAG_SPC_EQ | XN_FLAG_FN_SN>
 
 B<XN_FLAG_MULTILINE> is a multiline format which is the same as:
- C<ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB | XN_FLAG_SEP_MULTILINE | XN_FLAG_SPC_EQ | XN_FLAG_FN_LN | XN_FLAG_FN_ALIGN>
+ C<ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB | XN_FLAG_SEP_MULTILINE
+   | XN_FLAG_SPC_EQ | XN_FLAG_FN_LN | XN_FLAG_FN_ALIGN>
 
-B<XN_FLAG_COMPAT> uses a format identical to X509_NAME_print(): in fact it calls X509_NAME_print() internally.
+B<XN_FLAG_COMPAT> uses a format identical to X509_NAME_print():
+in fact it calls X509_NAME_print() internally.
 
 =head1 RETURN VALUES
 
@@ -103,9 +112,9 @@ X509_NAME_oneline() returns a valid string on success or NULL on error.
 
 X509_NAME_print() returns 1 on success or 0 on error.
 
-X509_NAME_print_ex() and X509_NAME_print_ex_fp() return 1 on success or 0 on error
-if the B<XN_FLAG_COMPAT> is set, which is the same as X509_NAME_print(). Otherwise,
-it returns -1 on error or other values on success.
+X509_NAME_print_ex() and X509_NAME_print_ex_fp() return 1 on success or 0 on
+error if the B<XN_FLAG_COMPAT> is set, which is the same as X509_NAME_print().
+Otherwise, it returns -1 on error or other values on success.
 
 =head1 SEE ALSO
 
diff --git a/doc/man3/X509_cmp.pod b/doc/man3/X509_cmp.pod
index 3cb16b2a81..7460d901db 100644
--- a/doc/man3/X509_cmp.pod
+++ b/doc/man3/X509_cmp.pod
@@ -25,16 +25,20 @@ This set of functions are used to compare X509 objects, including X509
 certificates, X509 CRL objects and various values in an X509 certificate.
 
 The X509_cmp() function compares two B<X509> objects indicated by parameters
-B<a> and B<b>. The comparison is based on the B<memcmp> result of the hash
+I<a> and I<b>. The comparison is based on the B<memcmp> result of the hash
 values of two B<X509> objects and the canonical (DER) encoding values.
 
 The X509_NAME_cmp() function compares two B<X509_NAME> objects indicated by
-parameters B<a> and B<b>. The comparison is based on the B<memcmp> result of
-the canonical (DER) encoding values of the two objects. L<i2d_X509_NAME(3)>
-has a more detailed description of the DER encoding of the B<X509_NAME> structure.
+parameters I<a> and I<b>. The comparison is based on the B<memcmp> result of the
+canonical (DER) encoding values of the two objects using L<i2d_X509_NAME(3)>.
+This procedure adheres to the matching rules for Distinguished Names (DN)
+given in RFC 4517 section 4.2.15 and RFC 5280 section 7.1.
+In particular, the order of Relative Distinguished Names (RDNs) is relevant.
+On the other hand, if an RDN is multi-valued, i.e., it contains a set of
+AttributeValueAssertions (AVAs), its members are effectively not ordered.
 
 The X509_issuer_and_serial_cmp() function compares the serial number and issuer
-values in the given B<X509> objects B<a> and B<b>.
+values in the given B<X509> objects I<a> and I<b>.
 
 The X509_issuer_name_cmp(), X509_subject_name_cmp() and X509_CRL_cmp() functions
 are effectively wrappers of the X509_NAME_cmp() function. These functions compare
@@ -47,9 +51,8 @@ of just the issuer name.
 
 =head1 RETURN VALUES
 
-Like common memory comparison functions, the B<X509> comparison functions return
-an integer less than, equal to, or greater than zero if object B<a> is found to
-be less than, to match, or be greater than object B<b>, respectively.
+The B<X509> comparison functions return B<-1>, B<0>, or B<1> if object I<a> is
+found to be less than, to match, or be greater than object I<b>, respectively.
 
 X509_NAME_cmp(), X509_issuer_and_serial_cmp(), X509_issuer_name_cmp(),
 X509_subject_name_cmp() and X509_CRL_cmp() may return B<-2> to indicate an error.


More information about the openssl-commits mailing list