^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_not_revealed
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed
#
-# Unicode tests
-#
-^samba\.tests\.krb5\.as_req_tests\.samba\.tests\.krb5\.as_req_tests\.AsReqKerberosTests\.test_as_req_unicode\(fl2008r2dc\)$
-^samba\.tests\.krb5\.as_req_tests\.samba\.tests\.krb5\.as_req_tests\.AsReqKerberosTests\.test_as_req_unicode\(fl2003dc\)$
-^samba\.tests\.krb5\.kdc_tgs_tests\.samba\.tests\.krb5\.kdc_tgs_tests\.KdcTgsTests\.test_fast_as_req_unicode\(ad_dc\)$
-^samba\.tests\.krb5\.kdc_tgs_tests\.samba\.tests\.krb5\.kdc_tgs_tests\.KdcTgsTests\.test_fast_unicode\(ad_dc\)$
-^samba\.tests\.krb5\.kdc_tgs_tests\.samba\.tests\.krb5\.kdc_tgs_tests\.KdcTgsTests\.test_renew_unicode\(ad_dc\)$
-^samba\.tests\.krb5\.kdc_tgs_tests\.samba\.tests\.krb5\.kdc_tgs_tests\.KdcTgsTests\.test_s4u2self_unicode\(ad_dc\)$
-^samba\.tests\.krb5\.kdc_tgs_tests\.samba\.tests\.krb5\.kdc_tgs_tests\.KdcTgsTests\.test_tgs_unicode\(ad_dc\)$
-^samba\.tests\.krb5\.kdc_tgs_tests\.samba\.tests\.krb5\.kdc_tgs_tests\.KdcTgsTests\.test_user2user_unicode\(ad_dc\)$
-^samba\.tests\.krb5\.kdc_tgs_tests\.samba\.tests\.krb5\.kdc_tgs_tests\.KdcTgsTests\.test_validate_unicode\(ad_dc\)$
-#
# Protected Users tests
#
# This test fails, which is fine, as we have an alternate test that considers a policy error as successful.
if ((tmp = realloc(res, alloced + (alloced > 1))) == NULL)
err(1, "Out of memory");
alloced += alloced > 1;
- p = tmp + (p - res);
+ p = tmp + len;
res = tmp;
end = res + alloced;
}
int ret;
if (hx509_request_count_unauthorized(req)) {
- hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ hx509_set_error_string(context, 0, EACCES,
+ "Some certificate features requested in the CSR were not authorized");
return EACCES;
}
}
command = {
name = "request-create"
+ option = {
+ long = "ca"
+ type = "flag"
+ help = "Request CA certificate"
+ }
+ option = {
+ long = "ca-path-length"
+ type = "integer"
+ help = "Path length constraint for CA certificate"
+ default = "-1"
+ }
+ option = {
+ long = "ee"
+ type = "flag"
+ help = "Include BasicConstraints w/ cA set to false"
+ }
option = {
long = "subject"
type = "string"
if (ret)
hx509_err(context, 1, ret, "Could not initialize CSR context");
+ if (opt->ca_flag && opt->ee_flag)
+ errx(1, "request-create --ca and --ee are mutually exclusive");
+
+ if (opt->ca_flag) {
+ unsigned pathLenConstraint = 0;
+ unsigned *pathLenConstraintPtr = NULL;
+
+ if (opt->ca_path_length_integer > 0 &&
+ opt->ca_path_length_integer < INT_MAX) {
+ pathLenConstraint = opt->ca_path_length_integer;
+ pathLenConstraintPtr = &pathLenConstraint;
+ }
+ ret = hx509_request_set_cA(context, req, pathLenConstraintPtr);
+ if (ret)
+ errx(1, "hx509_request_set_cA: %d\n", ret);
+ } else if (opt->ee_flag) {
+ hx509_request_set_eE(context, req);
+ }
+
if (opt->subject_string) {
hx509_name name = NULL;
hx509_request_add_pkinit
hx509_request_add_registered
hx509_request_add_xmpp_name
+ hx509_request_authorize_cA
hx509_request_authorize_ku
hx509_request_authorize_eku
hx509_request_authorize_san
_hx509_private_key_ref
hx509_request_eku_authorized_p
hx509_request_free
+ hx509_request_get_cA
+ hx509_request_get_cA_pathLenConstraint
hx509_request_get_eku
hx509_request_get_exts
hx509_request_get_ku
hx509_request_add_email
hx509_request_reject_eku
hx509_request_reject_san
+ hx509_request_set_cA
+ hx509_request_set_eE
hx509_request_set_name
hx509_request_set_ku
hx509_request_san_authorized_p
KeyUsage ku;
ExtKeyUsage eku;
GeneralNames san;
+ BasicConstraints bc;
struct abitstring_s authorized_EKUs;
struct abitstring_s authorized_SANs;
- uint32_t nunsupported; /* Count of unsupported features requested */
- uint32_t nauthorized; /* Count of supported features authorized */
+ uint32_t nunsupported_crit; /* Count of unsupported critical features requested */
+ uint32_t nunsupported_opt; /* Count of unsupported optional features requested */
+ uint32_t nauthorized; /* Count of supported features authorized */
+ uint32_t ca_is_authorized:1;
uint32_t ku_are_authorized:1;
+ uint32_t include_BasicConstraints:1;
};
/**
free_SubjectPublicKeyInfo(&req->key);
free_ExtKeyUsage(&req->eku);
free_GeneralNames(&req->san);
+ free_BasicConstraints(&req->bc);
memset(req, 0, sizeof(*req));
free(req);
}
+/**
+ * Make the CSR request a CA certificate
+ *
+ * @param context An hx509 context.
+ * @param req The hx509_request to alter.
+ * @param pathLenConstraint the pathLenConstraint for the BasicConstraints (optional)
+ *
+ * @return An hx509 error code, see hx509_get_error_string().
+ *
+ * @ingroup hx509_request
+ */
+HX509_LIB_FUNCTION int HX509_LIB_CALL
+hx509_request_set_cA(hx509_context context,
+ hx509_request req,
+ unsigned *pathLenConstraint)
+{
+ req->bc.cA = 1;
+ if (pathLenConstraint) {
+ if (req->bc.pathLenConstraint == NULL)
+ req->bc.pathLenConstraint = malloc(sizeof(*pathLenConstraint));
+ if (req->bc.pathLenConstraint == NULL)
+ return ENOMEM;
+ *req->bc.pathLenConstraint = *pathLenConstraint;
+ }
+ return 0;
+}
+
+/**
+ * Make the CSR request an EE (end-entity, i.e., not a CA) certificate
+ *
+ * @param context An hx509 context.
+ * @param req The hx509_request to alter.
+ *
+ * @ingroup hx509_request
+ */
+HX509_LIB_FUNCTION void HX509_LIB_CALL
+hx509_request_set_eE(hx509_context context, hx509_request req)
+{
+ req->bc.cA = 0;
+ free(req->bc.pathLenConstraint);
+ req->include_BasicConstraints = 1;
+ req->ca_is_authorized = 0;
+}
+
/**
* Set the subjectName of the CSR.
*
exts->val = NULL;
exts->len = 0;
+ if (req->bc.cA || req->include_BasicConstraints) {
+ Extension e;
+
+ /*
+ * If `!req->bc.cA' then we don't include BasicConstraints unless
+ * hx509_request_set_eE() was called on this request, and in that case
+ * we make this extension non-critical. We do this to emulate Dell
+ * iDRAC CSR-making software.
+ *
+ * If `req->bc.cA' then we make the BasicConstraints critical,
+ * obviously.
+ */
+ memset(&e, 0, sizeof(e));
+ e.critical = req->bc.cA ? 1 : 0;
+ if (ret == 0)
+ ASN1_MALLOC_ENCODE(BasicConstraints, e.extnValue.data, e.extnValue.length,
+ &req->bc, &size, ret);
+ if (ret == 0)
+ ret = der_copy_oid(&asn1_oid_id_x509_ce_basicConstraints, &e.extnID);
+ if (ret == 0)
+ ret = add_Extensions(exts, &e);
+ free_Extension(&e);
+ }
if (KeyUsage2int(req->ku)) {
Extension e;
* Count all KUs as one requested extension to be authorized,
* though the caller will have to check the KU values individually.
*/
- if (KeyUsage2int((*req)->ku) & ~KeyUsage2int(int2KeyUsage(~0)))
- (*req)->nunsupported++;
+ if (KeyUsage2int((*req)->ku) & ~KeyUsage2int(int2KeyUsage(~0ULL))) {
+ if (e->critical)
+ (*req)->nunsupported_crit++;
+ else
+ (*req)->nunsupported_opt++;
+ }
} else if (der_heim_oid_cmp(&e->extnID,
&asn1_oid_id_x509_ce_extKeyUsage) == 0) {
ret = decode_ExtKeyUsage(e->extnValue.data, e->extnValue.length,
* Count each SAN as a separate requested extension to be
* authorized.
*/
+ } else if (der_heim_oid_cmp(&e->extnID,
+ &asn1_oid_id_x509_ce_basicConstraints) == 0) {
+ (*req)->include_BasicConstraints = 1;
+ ret = decode_BasicConstraints(e->extnValue.data, e->extnValue.length,
+ &(*req)->bc, NULL);
} else {
char *oidstr = NULL;
- (*req)->nunsupported++;
+ if (e->critical)
+ (*req)->nunsupported_crit++;
+ else
+ (*req)->nunsupported_opt++;
/*
* We need an HX509_TRACE facility for this sort of warning.
}
}
+/**
+ * Authorize issuance of a CA certificate as requested.
+ *
+ * @param req The hx509_request object.
+ * @param pathLenConstraint the pathLenConstraint for the BasicConstraints (optional)
+ *
+ * @return an hx509 or system error.
+ *
+ * @ingroup hx509_request
+ */
+HX509_LIB_FUNCTION int HX509_LIB_CALL
+hx509_request_authorize_cA(hx509_request req, unsigned *pathLenConstraint)
+{
+ int ret;
+
+ ret = hx509_request_set_cA(NULL, req, pathLenConstraint);
+ req->ca_is_authorized++;
+ return ret;
+}
+
/**
* Filter the requested KeyUsage and mark it authorized.
*
HX509_LIB_FUNCTION size_t HX509_LIB_CALL
hx509_request_count_unsupported(hx509_request req)
{
- return req->nunsupported;
+ return req->nunsupported_crit;
}
/**
hx509_request_count_unauthorized(hx509_request req)
{
size_t nrequested = req->eku.len + req->san.len +
- (KeyUsage2int(req->ku) ? 1 : 0) + req->nunsupported;
+ (KeyUsage2int(req->ku) ? 1 : 0) + !!req->bc.cA +
+ req->nunsupported_crit;
- return nrequested - (req->nauthorized + req->ku_are_authorized);
+ return nrequested - (req->nauthorized + req->ku_are_authorized + req->ca_is_authorized);
}
static hx509_san_type
return 0;
}
+/**
+ * Indicate if a CSR requested a CA certificate.
+ *
+ * @param context An hx509 context.
+ * @param req The hx509_request object.
+ *
+ * @return 1 if the CSR requested CA certificate, 0 otherwise.
+ *
+ * @ingroup hx509_request
+ */
+HX509_LIB_FUNCTION int HX509_LIB_CALL
+hx509_request_get_cA(hx509_context context,
+ hx509_request req)
+{
+ return req->bc.cA;
+}
+
+/**
+ * Return the CSR's requested BasicConstraints pathLenConstraint.
+ *
+ * @param context An hx509 context.
+ * @param req The hx509_request object.
+ *
+ * @return -1 if no pathLenConstraint was requested (or the BasicConstraints
+ * does not request a CA certificate), or the actual requested
+ * pathLenConstraint.
+ *
+ * @ingroup hx509_request
+ */
+HX509_LIB_FUNCTION int HX509_LIB_CALL
+hx509_request_get_cA_pathLenConstraint(hx509_context context,
+ hx509_request req)
+{
+ if (req->bc.cA && req->bc.pathLenConstraint &&
+ *req->bc.pathLenConstraint < INT_MAX)
+ return *req->bc.pathLenConstraint;
+ return -1;
+}
+
/**
* Display a CSR.
*
*/
fprintf(f, "PKCS#10 CertificationRequest:\n");
+ if (req->include_BasicConstraints) {
+ fprintf(f, " cA: %s\n", req->bc.cA ? "yes" : "no");
+ if (req->bc.pathLenConstraint)
+ fprintf(f, " pathLenConstraint: %u\n", *req->bc.pathLenConstraint);
+ else
+ fprintf(f, " pathLenConstraint: unspecified\n");
+ }
if (req->name) {
char *subject;
ret = hx509_name_to_string(req->name, &subject);
break;
}
}
+ if (req->nunsupported_crit) {
+ fprintf(f, " unsupported_critical_extensions_count: %u\n",
+ (unsigned)req->nunsupported_crit);
+ }
+ if (req->nunsupported_crit) {
+ fprintf(f, " unsupported_optional_extensions_count: %u\n",
+ (unsigned)req->nunsupported_opt);
+ }
free(s); s = NULL;
if (ret == HX509_NO_ITEM)
ret = 0;
EOF
fi
fi
+
+${hxtool} request-create \
+ --ca \
+ --ca-path-length=3 \
+ --subject="cn=ca-cert" \
+ --key=FILE:$srcdir/data/key.der \
+ pkcs10-request.der || exit 1
+${hxtool} request-print PKCS10:pkcs10-request.der > "${objdir}/actual"|| exit 1
+cat > "$objdir/expected" <<EOF
+request print
+PKCS#10 CertificationRequest:
+ cA: yes
+ pathLenConstraint: 3
+ name: CN=ca-cert
+EOF
+diff "$objdir/expected" "${objdir}/actual" || exit 1
+
+${hxtool} request-create \
+ --ca \
+ --subject="cn=ca-cert" \
+ --key=FILE:$srcdir/data/key.der \
+ pkcs10-request.der || exit 1
+${hxtool} request-print PKCS10:pkcs10-request.der > "${objdir}/actual"|| exit 1
+cat > "$objdir/expected" <<EOF
+request print
+PKCS#10 CertificationRequest:
+ cA: yes
+ pathLenConstraint: unspecified
+ name: CN=ca-cert
+EOF
+diff "$objdir/expected" "${objdir}/actual" || exit 1
+
+${hxtool} request-create \
+ --ee \
+ --subject="cn=ca-cert" \
+ --key=FILE:$srcdir/data/key.der \
+ pkcs10-request.der || exit 1
+${hxtool} request-print PKCS10:pkcs10-request.der > "${objdir}/actual" || exit 1
+cat > "$objdir/expected" <<EOF
+request print
+PKCS#10 CertificationRequest:
+ cA: no
+ pathLenConstraint: unspecified
+ name: CN=ca-cert
+EOF
+diff "$objdir/expected" "${objdir}/actual" || exit 1
+
+exit 0
hx509_request_add_pkinit;
hx509_request_add_registered;
hx509_request_add_xmpp_name;
+ hx509_request_authorize_cA;
hx509_request_authorize_ku;
hx509_request_authorize_eku;
hx509_request_authorize_san;
hx509_query_match_option;
hx509_query_statistic_file;
hx509_query_unparse_stats;
+ hx509_request_get_cA;
+ hx509_request_get_cA_pathLenConstraint;
hx509_request_get_eku;
hx509_request_get_exts;
hx509_request_get_ku;
hx509_request_init;
hx509_request_parse;
hx509_request_parse_der;
+ hx509_request_set_cA;
+ hx509_request_set_eE;
hx509_request_set_ku;
hx509_request_set_name;
hx509_request_set_SubjectPublicKeyInfo;
"\xF7",
"\xC0\x01",
"\xC0\x7F",
+ "\xC0\x80",
+ "\xC0\x81",
"\xC0\xFF",
"\xC0\x80\x80",
+ "\xC1\x80",
"\xE0\x01",
"\xE0\x7F",
"\xE0\x80",
"\xE0\xFF",
"\xE0\x80\x20",
"\xE0\x80\xFF",
+ "\xE0\x80\x80",
+ "\xE0\x80\x81",
"\xE0\x80\x80\x80",
+ "\xE0\x81\x80",
"\xF0\x01",
"\xF0\x80",
"\xF0\x80\x01",
"\xF0\x80\x80",
"\xF0\x80\x80\x01",
+ "\xF0\x80\x80\x80",
+ "\xF0\x80\x80\x81",
"\xF0\x80\x80\xFF",
+ "\xF0\x80\x81\x80",
+ "\xF0\x81\x80\x80",
+ "\xF7\xBF\xBF\xBF",
NULL
};
{"\x01", 1, {1}, 0},
{"\x7F", 1, {0x7F}, 0},
{"\x01\x7F", 2, {0x01, 0x7F}, 0},
- {"\xC0\x80", 1, {0}, 0},
- {"\xC0\x81", 1, {1}, 0},
- {"\xC1\x80", 1, {0x40}, 0},
{"\xDF\xBF", 1, {0x7FF}, 0},
- {"\xE0\x80\x80", 1, {0}, 0},
- {"\xE0\x80\x81", 1, {1}, 0},
- {"\xE0\x81\x80", 1, {0x40}, 0},
{"\xE1\x80\x80", 1, {0x1000}, 0},
{"\xEF\xBF\xBF", 1, {0xFFFF}, 0},
- {"\xF0\x80\x80\x80", 1, {0}, 0},
- {"\xF0\x80\x80\x81", 1, {1}, 0},
- {"\xF0\x80\x81\x80", 1, {0x40}, 0},
- {"\xF0\x81\x80\x80", 1, {0x1000}, 0},
{"\xF1\x80\x80\x80", 1, {0x40000}, 0},
- {"\xF7\xBF\xBF\xBF", 1, {0X1FFFFF}, 1},
};
int
utf8toutf32(const unsigned char **pp, uint32_t *out)
{
const unsigned char *p = *pp;
- unsigned c = *p;
+ uint32_t c = *p;
+ uint32_t out_val;
if (c & 0x80) {
if ((c & 0xE0) == 0xC0) {
- const unsigned c2 = *++p;
+ const uint32_t c2 = *++p;
if ((c2 & 0xC0) == 0x80) {
- *out = ((c & 0x1F) << 6)
+ out_val = ((c & 0x1F) << 6)
| (c2 & 0x3F);
+ if (out_val < 0x80) {
+ return WIND_ERR_INVALID_UTF8;
+ }
} else {
return WIND_ERR_INVALID_UTF8;
}
} else if ((c & 0xF0) == 0xE0) {
- const unsigned c2 = *++p;
+ const uint32_t c2 = *++p;
if ((c2 & 0xC0) == 0x80) {
- const unsigned c3 = *++p;
+ const uint32_t c3 = *++p;
if ((c3 & 0xC0) == 0x80) {
- *out = ((c & 0x0F) << 12)
+ out_val = ((c & 0x0F) << 12)
| ((c2 & 0x3F) << 6)
| (c3 & 0x3F);
+ if (out_val < 0x800) {
+ return WIND_ERR_INVALID_UTF8;
+ }
} else {
return WIND_ERR_INVALID_UTF8;
}
return WIND_ERR_INVALID_UTF8;
}
} else if ((c & 0xF8) == 0xF0) {
- const unsigned c2 = *++p;
+ const uint32_t c2 = *++p;
if ((c2 & 0xC0) == 0x80) {
- const unsigned c3 = *++p;
+ const uint32_t c3 = *++p;
if ((c3 & 0xC0) == 0x80) {
- const unsigned c4 = *++p;
+ const uint32_t c4 = *++p;
if ((c4 & 0xC0) == 0x80) {
- *out = ((c & 0x07) << 18)
+ out_val = ((c & 0x07) << 18)
| ((c2 & 0x3F) << 12)
| ((c3 & 0x3F) << 6)
| (c4 & 0x3F);
+ if (out_val < 0x10000) {
+ return WIND_ERR_INVALID_UTF8;
+ }
} else {
return WIND_ERR_INVALID_UTF8;
}
return WIND_ERR_INVALID_UTF8;
}
} else {
- *out = c;
+ out_val = c;
}
+ /* Allow unpaired surrogates (in the range 0xd800–0xdfff). */
+
+ if (out_val > 0x10ffff) {
+ return WIND_ERR_INVALID_UTF8;
+ }
+
+ *out = out_val;
*pp = p;
return 0;
default:
break;
}
+ out += len;
}
- out += len;
}
if (out) {
if (o + 1 >= *out_len)
if (ret)
return ret;
- if (u & 0xffff0000)
- return WIND_ERR_NOT_UTF16;
+ if (u >= 0x10000) {
+ if (out) {
+ uint16_t high_ten_bits;
+ uint16_t low_ten_bits;
- if (out) {
- if (o >= *out_len)
- return WIND_ERR_OVERRUN;
- out[o] = u;
+ if (o + 2 > *out_len)
+ return WIND_ERR_OVERRUN;
+
+ u -= 0x10000;
+ high_ten_bits = (u >> 10) & 0x3ff;
+ low_ten_bits = u & 0x3ff;
+
+ out[o] = 0xd800 | high_ten_bits;
+ out[o+1] = 0xdc00 | low_ten_bits;
+ }
+ o += 2;
+ } else {
+ if (out) {
+ if (o >= *out_len)
+ return WIND_ERR_OVERRUN;
+ out[o] = u;
+ }
+ o++;
}
- o++;
}
*out_len = o;
return 0;
* string.
*
* @param in an UTF-8 string to convert.
- * @param out_len the length of the resulting UCS4 string.
+ * @param out_len the length of the resulting UCS2 string.
*
* @return returns 0 on success, an wind error code otherwise
* @ingroup wind
int
wind_ucs2utf8(const uint16_t *in, size_t in_len, char *out, size_t *out_len)
{
- uint16_t ch;
+ uint32_t ch;
size_t i, len, o;
for (o = 0, i = 0; i < in_len; i++) {
len = 1;
} else if (ch < 0x800) {
len = 2;
- } else
+ } else if (ch < 0xd800 || ch >= 0xe000) {
len = 3;
+ } else if (ch < 0xdc00) {
+ /* A high surrogate. */
+ if (i < in_len - 1) {
+ uint16_t ch2 = in[i + 1];
+
+ if (ch2 >= 0xdc00 && ch2 < 0xe000) {
+ uint16_t high_ten_bits;
+ uint16_t low_ten_bits;
+
+ /* A surrogate pair. */
+ high_ten_bits = ch & 0x3ff;
+ low_ten_bits = ch2 & 0x3ff;
+
+ ch = 0x10000 + ((uint32_t)high_ten_bits << 10 | low_ten_bits);
+ len = 4;
+ ++i;
+ } else {
+ /* An unpaired high surrogate. */
+ len = 3;
+ }
+ } else {
+ /* An unpaired high surrogate. */
+ len = 3;
+ }
+ } else {
+ /* An unpaired low surrogate. */
+ len = 3;
+ }
o += len;
return WIND_ERR_OVERRUN;
switch(len) {
+ case 4:
+ out[3] = (ch | 0x80) & 0xbf;
+ ch = ch >> 6;
+ HEIM_FALLTHROUGH;
case 3:
out[2] = (ch | 0x80) & 0xbf;
ch = ch >> 6;
rm -f trivial.pem server.pem email.pem
-echo "Making a plain CSR"
+echo "Making a plain CSR (with BasicConstraints requesting CA cert)"
csr_revoke
-$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
- --key=FILE:"${objdir}/k.der" "${objdir}/req" ||
+$hxtool request-create --subject='CN=H5LCA' --generate-key=rsa --key-bits=1024 \
+ --ca --key=FILE:"${objdir}/k.der" "${objdir}/req" ||
{ echo "Failed to make a CSR"; exit 2; }
# XXX Add autoconf check for curl?
# Create a barebones bx509 HTTP/1.1 client test program?
+echo "Fail to get a certificate using a CSR requesting a CA cert"
+# Encode the CSR in base64, then URL-encode it
+csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin)
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+if (set -vx; get_cert '' -sf -o "${objdir}/trivial.pem"); then
+ echo 'Issued a certificate for a CSR that requested a CA cert!'
+ exit 1
+else
+ echo 'CSRs requesting CA certs properly rejected'
+fi
+
+echo "Making a plain CSR (with BasicConstraints requesting EE cert)"
+csr_revoke
+$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
+ --ee --key=FILE:"${objdir}/k.der" "${objdir}/req" ||
+ { echo "Failed to make a CSR"; exit 2; }
+
+echo "Fetching a trivial user certificate"
+# Encode the CSR in base64, then URL-encode it
+csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin)
+token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
+if (set -vx; get_cert '' -sf -o "${objdir}/trivial.pem"); then
+ $hxtool print --content "FILE:${objdir}/trivial.pem"
+ if $hxtool acert --end-entity \
+ --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \
+ -P "foo@${R}" "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate with a CSR w/ BasicConstraints requesting EE cert!'
+ else
+ echo 'FAIL: Obtained a trivial client certificate w/o expected PKINIT SAN)'
+ exit 1
+ fi
+ if $hxtool acert --expr="%{certificate.subject} == \"OU=Users,$DCs\"" \
+ --has-private-key "FILE:${objdir}/trivial.pem"; then
+ echo 'Successfully obtained a trivial client certificate!'
+ fi
+else
+ echo 'Failed to get a certificate with a CSR w/ BasicConstraints requesting EE cert!'
+ exit 1
+fi
+
+echo "Making a plain CSR"
+csr_revoke
+$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
+ --key=FILE:"${objdir}/k.der" "${objdir}/req" ||
+ { echo "Failed to make a CSR"; exit 2; }
+
echo "Fetching a trivial user certificate (no authentication, must fail)"
# Encode the CSR in base64, then URL-encode it
csr=$($rkbase64 -- ${objdir}/req | $rkvis -h --stdin)