in jose/apr_jose_encode.c [481:672]
static apr_status_t apr_jose_encode_json_jws(apr_bucket_brigade *brigade,
apr_brigade_flush flush, void *ctx, apr_jose_t *jose, apr_jose_cb_t *cb,
apr_pool_t *p)
{
apr_json_value_t *json;
char *buf;
const char *buf64;
apr_size_t len;
apr_size_t len64;
apr_bucket_brigade *bb = apr_brigade_create(p,
brigade->bucket_alloc);
apr_jose_jws_t *jws = jose->jose.jws;
apr_status_t status = APR_SUCCESS;
/* create our json */
json = apr_json_object_create(p);
/* calculate BASE64URL(JWS Payload) */
status = apr_jose_encode(bb, flush, ctx, jws->payload, cb, p);
if (APR_SUCCESS != status) {
jose->result = jws->payload->result;
return status;
}
status = apr_brigade_pflatten(bb, &buf, &len, p);
if (APR_SUCCESS != status) {
return status;
}
buf64 = apr_pencode_base64(p, buf, len,
APR_ENCODE_BASE64URL, &len64);
apr_brigade_cleanup(bb);
/* add the payload to our json */
apr_json_object_set(json, "payload", APR_JSON_VALUE_STRING,
apr_json_string_create(p, buf64, len64), p);
/* calculate the flattened signature */
if (jws->signature) {
/* create protected header */
status = apr_jose_encode_base64_json(bb, flush, ctx,
jws->signature->protected_header, p);
if (APR_SUCCESS != status) {
return status;
}
status = apr_brigade_pflatten(bb, &buf, &len, p);
if (APR_SUCCESS != status) {
return status;
}
apr_json_object_set(json, "protected", APR_JSON_VALUE_STRING,
apr_json_string_create(p, buf, len), p);
status = apr_brigade_write(bb, flush, ctx, ".", 1);
if (APR_SUCCESS != status) {
return status;
}
status = apr_brigade_write(bb, flush, ctx, buf64, len64);
if (APR_SUCCESS != status) {
return status;
}
if (cb && cb->sign && jws->signature) {
status = cb->sign(bb, jose, jws->signature, cb->ctx, p);
if (APR_SUCCESS != status) {
return status;
}
}
apr_brigade_cleanup(bb);
/* create header */
apr_json_object_set(json, "header", APR_JSON_VALUE_STRING,
jws->signature->header, p);
apr_brigade_cleanup(bb);
/* create signature */
buf64 = apr_pencode_base64_binary(p,
jws->signature->sig.data, jws->signature->sig.len,
APR_ENCODE_BASE64URL, &len64);
apr_json_object_set(json, "signature", APR_JSON_VALUE_STRING,
apr_json_string_create(p, buf64, len64), p);
}
/* otherwise calculate the general signatures */
else if (jws->signatures) {
apr_json_value_t *sigs;
int i;
/* create signatures element */
sigs = apr_json_array_create(p, jws->signatures->nelts);
apr_json_object_set(json, "signatures", APR_JSON_VALUE_STRING,
sigs, p);
/* populate each signature */
for (i = 0; i < jws->signatures->nelts; i++) {
apr_json_value_t *s = apr_json_object_create(p);
apr_jose_signature_t *sig = APR_ARRAY_IDX(
jws->signatures, i, apr_jose_signature_t *);
apr_json_array_add(sigs, s);
/* create protected header */
status = apr_jose_encode_base64_json(bb, flush, ctx,
sig->protected_header, p);
if (APR_SUCCESS != status) {
return status;
}
status = apr_brigade_pflatten(bb, &buf, &len, p);
if (APR_SUCCESS != status) {
return status;
}
/* add protected header to array */
apr_json_object_set(s, "protected", APR_JSON_VALUE_STRING,
apr_json_string_create(p, buf, len), p);
status = apr_brigade_write(bb, flush, ctx, ".", 1);
if (APR_SUCCESS != status) {
return status;
}
status = apr_brigade_write(bb, flush, ctx, buf64, len64);
if (APR_SUCCESS != status) {
return status;
}
if (cb && cb->sign && sig) {
status = cb->sign(bb, jose, sig, cb->ctx, p);
if (APR_SUCCESS != status) {
return status;
}
}
apr_brigade_cleanup(bb);
/* create header */
apr_json_object_set(s, "header", APR_JSON_VALUE_STRING,
sig->header, p);
apr_brigade_cleanup(bb);
/* create signature */
buf64 = apr_pencode_base64_binary(p, sig->sig.data,
sig->sig.len,
APR_ENCODE_BASE64URL, &len64);
apr_json_object_set(s, "signature", APR_JSON_VALUE_STRING,
apr_json_string_create(p, buf64, len64), p);
}
if (APR_SUCCESS != status) {
return status;
}
}
/* write out our final result */
if (json) {
status = apr_json_encode(brigade, flush, ctx, json,
APR_JSON_FLAGS_WHITESPACE, p);
}
return status;
}