-/* $OpenBSD: x509_constraints.c,v 1.31 2022/12/26 07:18:53 jmc Exp $ */
+/* $OpenBSD: x509_constraints.c,v 1.32 2023/09/29 15:53:59 beck Exp $ */
/*
* Copyright (c) 2020 Bob Beck <beck@openbsd.org>
*
#define MAX_IP_ADDRESS_LENGTH (size_t)46
static int
-cbs_is_ip_address(CBS *cbs)
+cbs_is_ip_address(CBS *cbs, int *is_ip)
{
struct sockaddr_in6 sin6;
struct sockaddr_in sin4;
char *name = NULL;
- int ret = 0;
+ *is_ip = 0;
if (CBS_len(cbs) > MAX_IP_ADDRESS_LENGTH)
- return 0;
+ return 1;
if (!CBS_strdup(cbs, &name))
return 0;
if (inet_pton(AF_INET, name, &sin4) == 1 ||
inet_pton(AF_INET6, name, &sin6) == 1)
- ret = 1;
+ *is_ip = 1;
free(name);
- return ret;
+ return 1;
}
struct x509_constraints_name *
}
int
-x509_constraints_valid_host(CBS *cbs)
+x509_constraints_valid_host(CBS *cbs, int permit_ip)
{
uint8_t first;
+ int is_ip;
if (!CBS_peek_u8(cbs, &first))
return 0;
if (first == '.')
- return 0; /* leading . not allowed in a host name */
- if (cbs_is_ip_address(cbs))
- return 0;
+ return 0; /* leading . not allowed in a host name or IP */
+ if (!permit_ip) {
+ if (!cbs_is_ip_address(cbs, &is_ip))
+ return 0;
+ if (is_ip)
+ return 0;
+ }
return x509_constraints_valid_domain_internal(cbs, 0);
}
if (candidate_local == NULL || candidate_domain == NULL)
goto bad;
CBS_init(&domain_cbs, candidate_domain, strlen(candidate_domain));
- if (!x509_constraints_valid_host(&domain_cbs))
+ if (!x509_constraints_valid_host(&domain_cbs, 0))
goto bad;
if (name != NULL) {
if (host == NULL)
host = authority;
CBS_init(&host_cbs, host, hostlen);
- if (!x509_constraints_valid_host(&host_cbs))
+ if (!x509_constraints_valid_host(&host_cbs, 1))
return 0;
if (hostpart != NULL && !CBS_strdup(&host_cbs, hostpart))
return 0;
goto err;
}
CBS_init(&cbs, aname->data, aname->length);
- if (!x509_constraints_valid_host(&cbs))
+ if (!x509_constraints_valid_host(&cbs, 0))
continue; /* ignore it if not a hostname */
if ((vname = x509_constraints_name_new()) == NULL) {
*error = X509_V_ERR_OUT_OF_MEM;
-/* $OpenBSD: x509_internal.h,v 1.25 2023/01/28 19:08:09 tb Exp $ */
+/* $OpenBSD: x509_internal.h,v 1.26 2023/09/29 15:53:59 beck Exp $ */
/*
* Copyright (c) 2020 Bob Beck <beck@openbsd.org>
*
int x509_constraints_general_to_bytes(GENERAL_NAME *name, uint8_t **bytes,
size_t *len);
void x509_constraints_names_free(struct x509_constraints_names *names);
-int x509_constraints_valid_host(CBS *cbs);
+int x509_constraints_valid_host(CBS *cbs, int permit_ip);
int x509_constraints_valid_sandns(CBS *cbs);
int x509_constraints_domain(char *domain, size_t dlen, char *constraint,
size_t len);
-/* $OpenBSD: constraints.c,v 1.15 2022/11/28 07:24:03 tb Exp $ */
+/* $OpenBSD: constraints.c,v 1.16 2023/09/29 15:53:59 beck Exp $ */
/*
* Copyright (c) 2020 Bob Beck <beck@openbsd.org>
*
"https://.www.openbsd.org/",
"https://www.ope|nbsd.org%",
"https://www.openbsd.org.#",
+ "https://192.168.1.1./",
+ "https://192.168.1.1|/",
+ "https://.192.168.1.1/",
+ "https://192.168..1.1/",
+ "https://.2001:0DB8:AC10:FE01::/",
+ "https://.2001:0DB8:AC10:FE01::|/",
"///",
"//",
"/",
NULL,
};
+unsigned char *validuri[] = {
+ "https://www.openbsd.org/meep/meep/meep/",
+ "https://192.168.1.1/",
+ "https://2001:0DB8:AC10:FE01::/",
+ "https://192.168.1/", /* Not an IP, but valid component */
+ "https://999.999.999.999/", /* Not an IP, but valid component */
+ NULL,
+};
+
static int
test_valid_hostnames(void)
{
for (i = 0; valid_hostnames[i] != NULL; i++) {
CBS cbs;
CBS_init(&cbs, valid_hostnames[i], strlen(valid_hostnames[i]));
- if (!x509_constraints_valid_host(&cbs)) {
+ if (!x509_constraints_valid_host(&cbs, 0)) {
FAIL("Valid hostname '%s' rejected\n",
valid_hostnames[i]);
failure = 1;
goto done;
}
}
+
done:
return failure;
}
goto done;
}
}
+
done:
return failure;
}
goto done;
}
}
+
done:
return failure;
}
free(name.local);
name.local = NULL;
}
+
done:
return failure;
}
for (i = 0; invalid_hostnames[i] != NULL; i++) {
CBS_init(&cbs, invalid_hostnames[i],
strlen(invalid_hostnames[i]));
- if (x509_constraints_valid_host(&cbs)) {
+ if (x509_constraints_valid_host(&cbs, 0)) {
FAIL("Invalid hostname '%s' accepted\n",
invalid_hostnames[i]);
failure = 1;
}
}
CBS_init(&cbs, nulhost, strlen(nulhost) + 1);
- if (x509_constraints_valid_host(&cbs)) {
+ if (x509_constraints_valid_host(&cbs, 0)) {
FAIL("hostname with NUL byte accepted\n");
failure = 1;
goto done;
failure = 1;
goto done;
}
+
done:
return failure;
}
goto done;
}
}
+
done:
return failure;
}
free(name.local);
name.local = NULL;
}
+
done:
return failure;
}
goto done;
}
}
+
done:
return failure;
}
done:
return failure;
}
+static int
+test_valid_uri(void)
+{
+ int j, failure = 0;
+ char *hostpart = NULL;
+
+ for (j = 0; validuri[j] != NULL; j++) {
+ if (x509_constraints_uri_host(validuri[j],
+ strlen(invaliduri[j]), &hostpart) == 0) {
+ FAIL("Valid URI '%s' NOT accepted\n",
+ validuri[j]);
+ failure = 1;
+ goto done;
+ }
+ free(hostpart);
+ hostpart = NULL;
+ }
+
+ done:
+ return failure;
+}
static int
test_constraints1(void)
failure = 1;
goto done;
}
+
done:
return failure;
}
failed |= test_valid_domain_constraints();
failed |= test_invalid_domain_constraints();
failed |= test_invalid_uri();
+ failed |= test_valid_uri();
failed |= test_constraints1();
return (failed);