Loading CHANGES +4 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,10 @@ Changes between 0.9.6d and 0.9.7 [XX xxx 2002] Changes between 0.9.6d and 0.9.7 [XX xxx 2002] *) Fix escaping of non-ASCII characters when using the -subj option of the "openssl req" command line tool. (Robert Joop <joop@fokus.gmd.de>) [Lutz Jaenicke] *) Make object definitions compliant to LDAP (RFC2256): SN is the short *) Make object definitions compliant to LDAP (RFC2256): SN is the short form for "surname", serialNumber has no short form. form for "surname", serialNumber has no short form. Use "mail" as the short name for "rfc822Mailbox" according to RFC2798; Use "mail" as the short name for "rfc822Mailbox" according to RFC2798; Loading apps/ca.c +94 −35 Original line number Original line Diff line number Diff line Loading @@ -3023,63 +3023,122 @@ int make_revoked(X509_REVOKED *rev, char *str) return ret; return ret; } } /* * subject is expected to be in the format /type0=value0/type1=value1/type2=... * where characters may be escaped by \ */ static X509_NAME *do_subject(char *subject) static X509_NAME *do_subject(char *subject) { { X509_NAME *n = NULL; size_t buflen = strlen (subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */ char *buf = malloc (buflen); size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */ char **ne_types = malloc (max_ne * sizeof (char *)); char **ne_values = malloc (max_ne * sizeof (char *)); int i, nid, ne_num=0; char *sp = subject, *bp = buf; int i, ne_num = 0; char *ne_name = NULL; char *ne_value = NULL; char *tmp = NULL; char *p[2]; char *str_list[256]; X509_NAME *n = NULL; int nid; p[0] = ",/"; p[1] = "="; n = X509_NAME_new(); tmp = strtok(subject, p[0]); if (!buf || !ne_types || !ne_values) while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list))) { { char *token = tmp; BIO_printf(bio_err, "malloc error\n"); goto error0; } while (token[0] == ' ') if (*subject != '/') token++; { str_list[ne_num] = token; BIO_printf(bio_err, "Subject does not start with '/'.\n"); goto error0; } sp++; /* skip leading / */ tmp = strtok(NULL, p[0]); while (*sp) { /* collect type */ ne_types[ne_num] = bp; while (*sp) { if (*sp == '\\') /* is there anything to escape in the type...? */ if (*++sp) *bp++ = *sp++; else { BIO_printf(bio_err, "escape character at end of string\n"); goto error0; } else if (*sp == '=') { sp++; *bp++ = '\0'; break; } else *bp++ = *sp++; } if (!*sp) { BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num); goto error0; } ne_values[ne_num] = bp; while (*sp) { if (*sp == '\\') if (*++sp) *bp++ = *sp++; else { BIO_printf(bio_err, "escape character at end of string\n"); goto error0; } else if (*sp == '/') { sp++; *bp++ = '\0'; break; } else *bp++ = *sp++; } *bp++ = '\0'; ne_num++; ne_num++; } } if (!(n = X509_NAME_new())) goto error0; for (i = 0; i < ne_num; i++) for (i = 0; i < ne_num; i++) { { ne_name = strtok(str_list[i], p[1]); if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef) ne_value = strtok(NULL, p[1]); if ((nid=OBJ_txt2nid(ne_name)) == NID_undef) { { BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name); BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]); continue; continue; } } if (ne_value == NULL) if (!*ne_values[i]) { { BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name); BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]); continue; continue; } } if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0)) if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_values[i], -1,-1,0)) { goto error1; X509_NAME_free(n); return NULL; } } } free (ne_values); free (ne_types); free (buf); return n; return n; error1: X509_NAME_free(n); error0: free (ne_values); free (ne_types); free (buf); return NULL; } } Loading apps/crl.c +9 −4 Original line number Original line Diff line number Diff line Loading @@ -87,6 +87,7 @@ static char *crl_usage[]={ " -noout - no CRL output\n", " -noout - no CRL output\n", " -CAfile name - verify CRL using certificates in file \"name\"\n", " -CAfile name - verify CRL using certificates in file \"name\"\n", " -CApath dir - verify CRL using certificates in \"dir\"\n", " -CApath dir - verify CRL using certificates in \"dir\"\n", " -nameopt arg - various certificate name options\n", NULL NULL }; }; Loading @@ -97,6 +98,7 @@ int MAIN(int, char **); int MAIN(int argc, char **argv) int MAIN(int argc, char **argv) { { unsigned long nmflag = 0; X509_CRL *x=NULL; X509_CRL *x=NULL; char *CAfile = NULL, *CApath = NULL; char *CAfile = NULL, *CApath = NULL; int ret=1,i,num,badops=0; int ret=1,i,num,badops=0; Loading @@ -105,7 +107,7 @@ int MAIN(int argc, char **argv) char *infile=NULL,*outfile=NULL; char *infile=NULL,*outfile=NULL; int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0; int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0; int fingerprint = 0; int fingerprint = 0; char **pp,buf[256]; char **pp; X509_STORE *store = NULL; X509_STORE *store = NULL; X509_STORE_CTX ctx; X509_STORE_CTX ctx; X509_LOOKUP *lookup = NULL; X509_LOOKUP *lookup = NULL; Loading Loading @@ -188,6 +190,11 @@ int MAIN(int argc, char **argv) text = 1; text = 1; else if (strcmp(*argv,"-hash") == 0) else if (strcmp(*argv,"-hash") == 0) hash= ++num; hash= ++num; else if (strcmp(*argv,"-nameopt") == 0) { if (--argc < 1) goto bad; if (!set_name_ex(&nmflag, *(++argv))) goto bad; } else if (strcmp(*argv,"-issuer") == 0) else if (strcmp(*argv,"-issuer") == 0) issuer= ++num; issuer= ++num; else if (strcmp(*argv,"-lastupdate") == 0) else if (strcmp(*argv,"-lastupdate") == 0) Loading Loading @@ -271,9 +278,7 @@ bad: { { if (issuer == i) if (issuer == i) { { X509_NAME_oneline(X509_CRL_get_issuer(x), print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); buf,256); BIO_printf(bio_out,"issuer= %s\n",buf); } } if (hash == i) if (hash == i) Loading apps/req.c +96 −35 Original line number Original line Diff line number Diff line Loading @@ -505,6 +505,7 @@ bad: BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n"); BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n"); BIO_printf(bio_err," -reqexts .. specify request extension section (override value in config file)\n"); BIO_printf(bio_err," -reqexts .. specify request extension section (override value in config file)\n"); BIO_printf(bio_err," -utf8 input characters are UTF8 (default ASCII)\n"); BIO_printf(bio_err," -utf8 input characters are UTF8 (default ASCII)\n"); BIO_printf(bio_err," -nameopt arg - various certificate name options\n"); goto end; goto end; } } Loading Loading @@ -1210,66 +1211,126 @@ err: return(ret); return(ret); } } /* * subject is expected to be in the format /type0=value0/type1=value1/type2=... * where characters may be escaped by \ */ static int build_subject(X509_REQ *req, char *subject, unsigned long chtype) static int build_subject(X509_REQ *req, char *subject, unsigned long chtype) { { X509_NAME *n = NULL; size_t buflen = strlen (subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */ char *buf = malloc (buflen); int i, nid, ne_num=0; size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */ char **ne_types = malloc (max_ne * sizeof (char *)); char *ne_name = NULL; char **ne_values = malloc (max_ne * sizeof (char *)); char *ne_value = NULL; char *tmp = NULL; char *p[2]; char *str_list[256]; char *sp = subject, *bp = buf; int i, ne_num = 0; p[0] = ",/"; X509_NAME *n = NULL; p[1] = "="; int nid; n = X509_NAME_new(); tmp = strtok(subject, p[0]); if (!buf || !ne_types || !ne_values) while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list))) { { char *token = tmp; BIO_printf(bio_err, "malloc error\n"); goto error0; } while (token[0] == ' ') if (*subject != '/') token++; { str_list[ne_num] = token; BIO_printf(bio_err, "Subject does not start with '/'.\n"); goto error0; } sp++; /* skip leading / */ tmp = strtok(NULL, p[0]); while (*sp) { /* collect type */ ne_types[ne_num] = bp; while (*sp) { if (*sp == '\\') /* is there anything to escape in the type...? */ if (*++sp) *bp++ = *sp++; else { BIO_printf(bio_err, "escape character at end of string\n"); goto error0; } else if (*sp == '=') { sp++; *bp++ = '\0'; break; } else *bp++ = *sp++; } if (!*sp) { BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num); goto error0; } ne_values[ne_num] = bp; while (*sp) { if (*sp == '\\') if (*++sp) *bp++ = *sp++; else { BIO_printf(bio_err, "escape character at end of string\n"); goto error0; } else if (*sp == '/') { sp++; *bp++ = '\0'; break; } else *bp++ = *sp++; } *bp++ = '\0'; ne_num++; ne_num++; } } if (!(n = X509_NAME_new())) goto error0; for(i = 0; i < ne_num; i++) for(i = 0; i < ne_num; i++) { { ne_name = strtok(str_list[i], p[1]); if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef) ne_value = strtok(NULL, p[1]); if ((nid=OBJ_txt2nid(ne_name)) == NID_undef) { { BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name); BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]); continue; continue; } } if (ne_value == NULL) if (!*ne_values[i]) { { BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name); BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]); continue; continue; } } if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_value, -1,-1,0)) if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,0)) { goto error1; X509_NAME_free(n); return 0; } } } if (!X509_REQ_set_subject_name(req, n)) if (!X509_REQ_set_subject_name(req, n)) return 0; goto error1; X509_NAME_free(n); X509_NAME_free(n); free (ne_values); free (ne_types); free (buf); return 1; return 1; error1: X509_NAME_free(n); error0: free (ne_values); free (ne_types); free (buf); return 0; } } Loading doc/apps/ca.pod +3 −1 Original line number Original line Diff line number Diff line Loading @@ -216,7 +216,9 @@ a filename containing a certificate to revoke. =item B<-subj arg> =item B<-subj arg> supersedes subject name given in the request supersedes subject name given in the request. The arg must be formatted as I</type0=value0/type1=value1/type2=...>, characters may be escaped by \ (backslash), no spaces are skipped. =item B<-crlexts section> =item B<-crlexts section> Loading Loading
CHANGES +4 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,10 @@ Changes between 0.9.6d and 0.9.7 [XX xxx 2002] Changes between 0.9.6d and 0.9.7 [XX xxx 2002] *) Fix escaping of non-ASCII characters when using the -subj option of the "openssl req" command line tool. (Robert Joop <joop@fokus.gmd.de>) [Lutz Jaenicke] *) Make object definitions compliant to LDAP (RFC2256): SN is the short *) Make object definitions compliant to LDAP (RFC2256): SN is the short form for "surname", serialNumber has no short form. form for "surname", serialNumber has no short form. Use "mail" as the short name for "rfc822Mailbox" according to RFC2798; Use "mail" as the short name for "rfc822Mailbox" according to RFC2798; Loading
apps/ca.c +94 −35 Original line number Original line Diff line number Diff line Loading @@ -3023,63 +3023,122 @@ int make_revoked(X509_REVOKED *rev, char *str) return ret; return ret; } } /* * subject is expected to be in the format /type0=value0/type1=value1/type2=... * where characters may be escaped by \ */ static X509_NAME *do_subject(char *subject) static X509_NAME *do_subject(char *subject) { { X509_NAME *n = NULL; size_t buflen = strlen (subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */ char *buf = malloc (buflen); size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */ char **ne_types = malloc (max_ne * sizeof (char *)); char **ne_values = malloc (max_ne * sizeof (char *)); int i, nid, ne_num=0; char *sp = subject, *bp = buf; int i, ne_num = 0; char *ne_name = NULL; char *ne_value = NULL; char *tmp = NULL; char *p[2]; char *str_list[256]; X509_NAME *n = NULL; int nid; p[0] = ",/"; p[1] = "="; n = X509_NAME_new(); tmp = strtok(subject, p[0]); if (!buf || !ne_types || !ne_values) while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list))) { { char *token = tmp; BIO_printf(bio_err, "malloc error\n"); goto error0; } while (token[0] == ' ') if (*subject != '/') token++; { str_list[ne_num] = token; BIO_printf(bio_err, "Subject does not start with '/'.\n"); goto error0; } sp++; /* skip leading / */ tmp = strtok(NULL, p[0]); while (*sp) { /* collect type */ ne_types[ne_num] = bp; while (*sp) { if (*sp == '\\') /* is there anything to escape in the type...? */ if (*++sp) *bp++ = *sp++; else { BIO_printf(bio_err, "escape character at end of string\n"); goto error0; } else if (*sp == '=') { sp++; *bp++ = '\0'; break; } else *bp++ = *sp++; } if (!*sp) { BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num); goto error0; } ne_values[ne_num] = bp; while (*sp) { if (*sp == '\\') if (*++sp) *bp++ = *sp++; else { BIO_printf(bio_err, "escape character at end of string\n"); goto error0; } else if (*sp == '/') { sp++; *bp++ = '\0'; break; } else *bp++ = *sp++; } *bp++ = '\0'; ne_num++; ne_num++; } } if (!(n = X509_NAME_new())) goto error0; for (i = 0; i < ne_num; i++) for (i = 0; i < ne_num; i++) { { ne_name = strtok(str_list[i], p[1]); if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef) ne_value = strtok(NULL, p[1]); if ((nid=OBJ_txt2nid(ne_name)) == NID_undef) { { BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name); BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]); continue; continue; } } if (ne_value == NULL) if (!*ne_values[i]) { { BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name); BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]); continue; continue; } } if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0)) if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_values[i], -1,-1,0)) { goto error1; X509_NAME_free(n); return NULL; } } } free (ne_values); free (ne_types); free (buf); return n; return n; error1: X509_NAME_free(n); error0: free (ne_values); free (ne_types); free (buf); return NULL; } } Loading
apps/crl.c +9 −4 Original line number Original line Diff line number Diff line Loading @@ -87,6 +87,7 @@ static char *crl_usage[]={ " -noout - no CRL output\n", " -noout - no CRL output\n", " -CAfile name - verify CRL using certificates in file \"name\"\n", " -CAfile name - verify CRL using certificates in file \"name\"\n", " -CApath dir - verify CRL using certificates in \"dir\"\n", " -CApath dir - verify CRL using certificates in \"dir\"\n", " -nameopt arg - various certificate name options\n", NULL NULL }; }; Loading @@ -97,6 +98,7 @@ int MAIN(int, char **); int MAIN(int argc, char **argv) int MAIN(int argc, char **argv) { { unsigned long nmflag = 0; X509_CRL *x=NULL; X509_CRL *x=NULL; char *CAfile = NULL, *CApath = NULL; char *CAfile = NULL, *CApath = NULL; int ret=1,i,num,badops=0; int ret=1,i,num,badops=0; Loading @@ -105,7 +107,7 @@ int MAIN(int argc, char **argv) char *infile=NULL,*outfile=NULL; char *infile=NULL,*outfile=NULL; int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0; int hash=0,issuer=0,lastupdate=0,nextupdate=0,noout=0,text=0; int fingerprint = 0; int fingerprint = 0; char **pp,buf[256]; char **pp; X509_STORE *store = NULL; X509_STORE *store = NULL; X509_STORE_CTX ctx; X509_STORE_CTX ctx; X509_LOOKUP *lookup = NULL; X509_LOOKUP *lookup = NULL; Loading Loading @@ -188,6 +190,11 @@ int MAIN(int argc, char **argv) text = 1; text = 1; else if (strcmp(*argv,"-hash") == 0) else if (strcmp(*argv,"-hash") == 0) hash= ++num; hash= ++num; else if (strcmp(*argv,"-nameopt") == 0) { if (--argc < 1) goto bad; if (!set_name_ex(&nmflag, *(++argv))) goto bad; } else if (strcmp(*argv,"-issuer") == 0) else if (strcmp(*argv,"-issuer") == 0) issuer= ++num; issuer= ++num; else if (strcmp(*argv,"-lastupdate") == 0) else if (strcmp(*argv,"-lastupdate") == 0) Loading Loading @@ -271,9 +278,7 @@ bad: { { if (issuer == i) if (issuer == i) { { X509_NAME_oneline(X509_CRL_get_issuer(x), print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); buf,256); BIO_printf(bio_out,"issuer= %s\n",buf); } } if (hash == i) if (hash == i) Loading
apps/req.c +96 −35 Original line number Original line Diff line number Diff line Loading @@ -505,6 +505,7 @@ bad: BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n"); BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n"); BIO_printf(bio_err," -reqexts .. specify request extension section (override value in config file)\n"); BIO_printf(bio_err," -reqexts .. specify request extension section (override value in config file)\n"); BIO_printf(bio_err," -utf8 input characters are UTF8 (default ASCII)\n"); BIO_printf(bio_err," -utf8 input characters are UTF8 (default ASCII)\n"); BIO_printf(bio_err," -nameopt arg - various certificate name options\n"); goto end; goto end; } } Loading Loading @@ -1210,66 +1211,126 @@ err: return(ret); return(ret); } } /* * subject is expected to be in the format /type0=value0/type1=value1/type2=... * where characters may be escaped by \ */ static int build_subject(X509_REQ *req, char *subject, unsigned long chtype) static int build_subject(X509_REQ *req, char *subject, unsigned long chtype) { { X509_NAME *n = NULL; size_t buflen = strlen (subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */ char *buf = malloc (buflen); int i, nid, ne_num=0; size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */ char **ne_types = malloc (max_ne * sizeof (char *)); char *ne_name = NULL; char **ne_values = malloc (max_ne * sizeof (char *)); char *ne_value = NULL; char *tmp = NULL; char *p[2]; char *str_list[256]; char *sp = subject, *bp = buf; int i, ne_num = 0; p[0] = ",/"; X509_NAME *n = NULL; p[1] = "="; int nid; n = X509_NAME_new(); tmp = strtok(subject, p[0]); if (!buf || !ne_types || !ne_values) while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list))) { { char *token = tmp; BIO_printf(bio_err, "malloc error\n"); goto error0; } while (token[0] == ' ') if (*subject != '/') token++; { str_list[ne_num] = token; BIO_printf(bio_err, "Subject does not start with '/'.\n"); goto error0; } sp++; /* skip leading / */ tmp = strtok(NULL, p[0]); while (*sp) { /* collect type */ ne_types[ne_num] = bp; while (*sp) { if (*sp == '\\') /* is there anything to escape in the type...? */ if (*++sp) *bp++ = *sp++; else { BIO_printf(bio_err, "escape character at end of string\n"); goto error0; } else if (*sp == '=') { sp++; *bp++ = '\0'; break; } else *bp++ = *sp++; } if (!*sp) { BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num); goto error0; } ne_values[ne_num] = bp; while (*sp) { if (*sp == '\\') if (*++sp) *bp++ = *sp++; else { BIO_printf(bio_err, "escape character at end of string\n"); goto error0; } else if (*sp == '/') { sp++; *bp++ = '\0'; break; } else *bp++ = *sp++; } *bp++ = '\0'; ne_num++; ne_num++; } } if (!(n = X509_NAME_new())) goto error0; for(i = 0; i < ne_num; i++) for(i = 0; i < ne_num; i++) { { ne_name = strtok(str_list[i], p[1]); if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef) ne_value = strtok(NULL, p[1]); if ((nid=OBJ_txt2nid(ne_name)) == NID_undef) { { BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name); BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]); continue; continue; } } if (ne_value == NULL) if (!*ne_values[i]) { { BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name); BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]); continue; continue; } } if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_value, -1,-1,0)) if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,0)) { goto error1; X509_NAME_free(n); return 0; } } } if (!X509_REQ_set_subject_name(req, n)) if (!X509_REQ_set_subject_name(req, n)) return 0; goto error1; X509_NAME_free(n); X509_NAME_free(n); free (ne_values); free (ne_types); free (buf); return 1; return 1; error1: X509_NAME_free(n); error0: free (ne_values); free (ne_types); free (buf); return 0; } } Loading
doc/apps/ca.pod +3 −1 Original line number Original line Diff line number Diff line Loading @@ -216,7 +216,9 @@ a filename containing a certificate to revoke. =item B<-subj arg> =item B<-subj arg> supersedes subject name given in the request supersedes subject name given in the request. The arg must be formatted as I</type0=value0/type1=value1/type2=...>, characters may be escaped by \ (backslash), no spaces are skipped. =item B<-crlexts section> =item B<-crlexts section> Loading