/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
#include <stdio.h>
#include <string.h>
#include "internal/cryptlib.h"
+#include "internal/asn1_int.h"
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/asn1.h>
* even 4 byte forms.
*/
-static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes,
+static int do_esc_char(unsigned long c, unsigned short flags, char *do_quotes,
char_io *io_ch, void *arg)
{
unsigned short chflgs;
if (c > 0xffffffffL)
return -1;
if (c > 0xffff) {
- BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
+ BIO_snprintf(tmphex, sizeof(tmphex), "\\W%08lX", c);
if (!io_ch(arg, tmphex, 10))
return -1;
return 10;
}
if (c > 0xff) {
- BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
+ BIO_snprintf(tmphex, sizeof(tmphex), "\\U%04lX", c);
if (!io_ch(arg, tmphex, 6))
return -1;
return 6;
* If we get this far and do any escaping at all must escape the escape
* character itself: backslash.
*/
- if (chtmp == '\\' && flags & ESC_FLAGS) {
+ if (chtmp == '\\' && (flags & ESC_FLAGS)) {
if (!io_ch(arg, "\\\\", 2))
return -1;
return 2;
unsigned short orflags;
unsigned char *p, *q;
unsigned long c;
+
p = buf;
q = buf + buflen;
outlen = 0;
if (type & BUF_TYPE_CONVUTF8) {
unsigned char utfbuf[6];
int utflen;
- utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
+ utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c);
for (i = 0; i < utflen; i++) {
/*
* We don't need to worry about setting orflags correctly
* otherwise each character will be > 0x7f and so the
* character will never be escaped on first and last.
*/
- len =
- do_esc_char(utfbuf[i], (unsigned short)(flags | orflags),
- quotes, io_ch, arg);
+ len = do_esc_char(utfbuf[i], flags | orflags, quotes,
+ io_ch, arg);
if (len < 0)
return -1;
outlen += len;
}
} else {
- len =
- do_esc_char(c, (unsigned short)(flags | orflags), quotes,
- io_ch, arg);
+ len = do_esc_char(c, flags | orflags, quotes,
+ io_ch, arg);
if (len < 0)
return -1;
outlen += len;
*/
static int do_dump(unsigned long lflags, char_io *io_ch, void *arg,
- ASN1_STRING *str)
+ const ASN1_STRING *str)
{
/*
* Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to
t.type = str->type;
t.value.ptr = (char *)str;
der_len = i2d_ASN1_TYPE(&t, NULL);
- der_buf = OPENSSL_malloc(der_len);
- if (der_buf == NULL)
+ if ((der_buf = OPENSSL_malloc(der_len)) == NULL) {
+ ASN1err(ASN1_F_DO_DUMP, ERR_R_MALLOC_FAILURE);
return -1;
+ }
p = der_buf;
i2d_ASN1_TYPE(&t, &p);
outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
static const signed char tag2nbyte[] = {
-1, -1, -1, -1, -1, /* 0-4 */
-1, -1, -1, -1, -1, /* 5-9 */
- -1, -1, 0, -1, /* 10-13 */
- -1, -1, -1, -1, /* 15-17 */
- 1, 1, 1, /* 18-20 */
- -1, 1, 1, 1, /* 21-24 */
- -1, 1, -1, /* 25-27 */
- 4, -1, 2 /* 28-30 */
+ -1, -1, /* 10-11 */
+ 0, /* 12 V_ASN1_UTF8STRING */
+ -1, -1, -1, -1, -1, /* 13-17 */
+ 1, /* 18 V_ASN1_NUMERICSTRING */
+ 1, /* 19 V_ASN1_PRINTABLESTRING */
+ 1, /* 20 V_ASN1_T61STRING */
+ -1, /* 21 */
+ 1, /* 22 V_ASN1_IA5STRING */
+ 1, /* 23 V_ASN1_UTCTIME */
+ 1, /* 24 V_ASN1_GENERALIZEDTIME */
+ -1, /* 25 */
+ 1, /* 26 V_ASN1_ISO64STRING */
+ -1, /* 27 */
+ 4, /* 28 V_ASN1_UNIVERSALSTRING */
+ -1, /* 29 */
+ 2 /* 30 V_ASN1_BMPSTRING */
};
/*
*/
static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
- ASN1_STRING *str)
+ const ASN1_STRING *str)
{
int outlen, len;
int type;
#define FN_WIDTH_LN 25
#define FN_WIDTH_SN 10
-static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n,
+static int do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n,
int indent, unsigned long flags)
{
int i, prev = -1, orflags, cnt;
int fn_opt, fn_nid;
ASN1_OBJECT *fn;
- ASN1_STRING *val;
- X509_NAME_ENTRY *ent;
+ const ASN1_STRING *val;
+ const X509_NAME_ENTRY *ent;
char objtmp[80];
const char *objbuf;
int outlen, len;
if (fn_opt != XN_FLAG_FN_NONE) {
int objlen, fld_len;
if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) {
- OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
+ OBJ_obj2txt(objtmp, sizeof(objtmp), fn, 1);
fld_len = 0; /* XXX: what should this be? */
objbuf = objtmp;
} else {
/* Wrappers round the main functions */
-int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent,
+int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
unsigned long flags)
{
if (flags == XN_FLAG_COMPAT)
}
#ifndef OPENSSL_NO_STDIO
-int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent,
+int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
unsigned long flags)
{
if (flags == XN_FLAG_COMPAT) {
}
#endif
-int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags)
+int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags)
{
return do_print_ex(send_bio_chars, out, flags, str);
}
#ifndef OPENSSL_NO_STDIO
-int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags)
+int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags)
{
return do_print_ex(send_fp_chars, fp, flags, str);
}
* in output string or a negative error code
*/
-int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in)
+int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in)
{
ASN1_STRING stmp, *str = &stmp;
int mbflag, type, ret;
*out = stmp.data;
return stmp.length;
}
+
+/* Return 1 if host is a valid hostname and 0 otherwise */
+int asn1_valid_host(const ASN1_STRING *host)
+{
+ int hostlen = host->length;
+ const unsigned char *hostptr = host->data;
+ int type = host->type;
+ int i;
+ signed char width = -1;
+ unsigned short chflags = 0, prevchflags;
+
+ if (type > 0 && type < 31)
+ width = tag2nbyte[type];
+ if (width == -1 || hostlen == 0)
+ return 0;
+ /* Treat UTF8String as width 1 as any MSB set is invalid */
+ if (width == 0)
+ width = 1;
+ for (i = 0 ; i < hostlen; i+= width) {
+ prevchflags = chflags;
+ /* Value must be <= 0x7F: check upper bytes are all zeroes */
+ if (width == 4) {
+ if (*hostptr++ != 0 || *hostptr++ != 0 || *hostptr++ != 0)
+ return 0;
+ } else if (width == 2) {
+ if (*hostptr++ != 0)
+ return 0;
+ }
+ if (*hostptr > 0x7f)
+ return 0;
+ chflags = char_type[*hostptr++];
+ if (!(chflags & (CHARTYPE_HOST_ANY | CHARTYPE_HOST_WILD))) {
+ /* Nothing else allowed at start or end of string */
+ if (i == 0 || i == hostlen - 1)
+ return 0;
+ /* Otherwise invalid if not dot or hyphen */
+ if (!(chflags & (CHARTYPE_HOST_DOT | CHARTYPE_HOST_HYPHEN)))
+ return 0;
+ /*
+ * If previous is dot or hyphen then illegal unless both
+ * are hyphens: as .- -. .. are all illegal
+ */
+ if (prevchflags & (CHARTYPE_HOST_DOT | CHARTYPE_HOST_HYPHEN)
+ && ((prevchflags & CHARTYPE_HOST_DOT)
+ || (chflags & CHARTYPE_HOST_DOT)))
+ return 0;
+ }
+ }
+ return 1;
+}