X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fcms.c;h=5f77f8fbb03f14066cae8cd819b67dba51a2fc0f;hp=b757908070851d197fe90735525c9b8f7bb45f06;hb=4badfebefc22c196ebc23863f910678a799599ec;hpb=4f1aa191b33f0bbda29c3289d50fee2991b77df0 diff --git a/apps/cms.c b/apps/cms.c index b757908070..5f77f8fbb0 100644 --- a/apps/cms.c +++ b/apps/cms.c @@ -69,7 +69,11 @@ #undef PROG #define PROG cms_main static int save_certs(char *signerfile, STACK_OF(X509) *signers); -static int smime_cb(int ok, X509_STORE_CTX *ctx); +static int cms_cb(int ok, X509_STORE_CTX *ctx); +static void receipt_request_print(BIO *out, CMS_ContentInfo *cms); +static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, + int rr_allorfirst, + STACK_OF(OPENSSL_STRING) *rr_from); #define SMIME_OP 0x10 #define SMIME_IP 0x20 @@ -88,6 +92,10 @@ static int smime_cb(int ok, X509_STORE_CTX *ctx); #define SMIME_COMPRESS (12 | SMIME_OP) #define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP) #define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP) +#define SMIME_SIGN_RECEIPT (15 | SMIME_IP | SMIME_OP) +#define SMIME_VERIFY_RECEIPT (16 | SMIME_IP) + +int verify_err = 0; int MAIN(int, char **); @@ -98,33 +106,40 @@ int MAIN(int argc, char **argv) int ret = 0; char **args; const char *inmode = "r", *outmode = "w"; - char *infile = NULL, *outfile = NULL; + char *infile = NULL, *outfile = NULL, *rctfile = NULL; char *signerfile = NULL, *recipfile = NULL; - STACK *sksigners = NULL, *skkeys = NULL; + STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; char *certfile = NULL, *keyfile = NULL, *contfile=NULL; + char *certsoutfile = NULL; const EVP_CIPHER *cipher = NULL; - CMS_ContentInfo *cms = NULL; + CMS_ContentInfo *cms = NULL, *rcms = NULL; X509_STORE *store = NULL; X509 *cert = NULL, *recip = NULL, *signer = NULL; EVP_PKEY *key = NULL; STACK_OF(X509) *encerts = NULL, *other = NULL; - BIO *in = NULL, *out = NULL, *indata = NULL; + BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL; int badarg = 0; - int flags = CMS_DETACHED; + int flags = CMS_DETACHED, noout = 0, print = 0; + int verify_retcode = 0; + int rr_print = 0, rr_allorfirst = -1; + STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL; + CMS_ReceiptRequest *rr = NULL; char *to = NULL, *from = NULL, *subject = NULL; char *CAfile = NULL, *CApath = NULL; char *passargin = NULL, *passin = NULL; char *inrand = NULL; int need_rand = 0; - int indef = 0; const EVP_MD *sign_md = NULL; int informat = FORMAT_SMIME, outformat = FORMAT_SMIME; - int keyform = FORMAT_PEM; + int rctformat = FORMAT_SMIME, keyform = FORMAT_PEM; #ifndef OPENSSL_NO_ENGINE char *engine=NULL; #endif - unsigned char *secret_key = NULL; - size_t secret_keylen; + unsigned char *secret_key = NULL, *secret_keyid = NULL; + unsigned char *pwri_pass = NULL, *pwri_tmp = NULL; + size_t secret_keylen = 0, secret_keyidlen = 0; + + ASN1_OBJECT *econtent_type = NULL; X509_VERIFY_PARAM *vpm = NULL; @@ -150,10 +165,22 @@ int MAIN(int argc, char **argv) operation = SMIME_DECRYPT; else if (!strcmp (*args, "-sign")) operation = SMIME_SIGN; + else if (!strcmp (*args, "-sign_receipt")) + operation = SMIME_SIGN_RECEIPT; else if (!strcmp (*args, "-resign")) operation = SMIME_RESIGN; else if (!strcmp (*args, "-verify")) operation = SMIME_VERIFY; + else if (!strcmp (*args, "-verify_retcode")) + verify_retcode = 1; + else if (!strcmp(*args,"-verify_receipt")) + { + operation = SMIME_VERIFY_RECEIPT; + if (!args[1]) + goto argerr; + args++; + rctfile = *args; + } else if (!strcmp (*args, "-cmsout")) operation = SMIME_CMSOUT; else if (!strcmp (*args, "-data_out")) @@ -206,6 +233,8 @@ int MAIN(int argc, char **argv) else if (!strcmp(*args,"-camellia256")) cipher = EVP_camellia_256_cbc(); #endif + else if (!strcmp (*args, "-debug_decrypt")) + flags |= CMS_DEBUG_DECRYPT; else if (!strcmp (*args, "-text")) flags |= CMS_TEXT; else if (!strcmp (*args, "-nointern")) @@ -232,15 +261,46 @@ int MAIN(int argc, char **argv) else if (!strcmp (*args, "-no_attr_verify")) flags |= CMS_NO_ATTR_VERIFY; else if (!strcmp (*args, "-stream")) - indef = 1; + flags |= CMS_STREAM; else if (!strcmp (*args, "-indef")) - indef = 1; + flags |= CMS_STREAM; else if (!strcmp (*args, "-noindef")) - indef = 0; + flags &= ~CMS_STREAM; else if (!strcmp (*args, "-nooldmime")) flags |= CMS_NOOLDMIMETYPE; else if (!strcmp (*args, "-crlfeol")) flags |= CMS_CRLFEOL; + else if (!strcmp (*args, "-noout")) + noout = 1; + else if (!strcmp (*args, "-receipt_request_print")) + rr_print = 1; + else if (!strcmp (*args, "-receipt_request_all")) + rr_allorfirst = 0; + else if (!strcmp (*args, "-receipt_request_first")) + rr_allorfirst = 1; + else if (!strcmp(*args,"-receipt_request_from")) + { + if (!args[1]) + goto argerr; + args++; + if (!rr_from) + rr_from = sk_OPENSSL_STRING_new_null(); + sk_OPENSSL_STRING_push(rr_from, *args); + } + else if (!strcmp(*args,"-receipt_request_to")) + { + if (!args[1]) + goto argerr; + args++; + if (!rr_to) + rr_to = sk_OPENSSL_STRING_new_null(); + sk_OPENSSL_STRING_push(rr_to, *args); + } + else if (!strcmp (*args, "-print")) + { + noout = 1; + print = 1; + } else if (!strcmp(*args,"-secretkey")) { long ltmp; @@ -255,6 +315,39 @@ int MAIN(int argc, char **argv) } secret_keylen = (size_t)ltmp; } + else if (!strcmp(*args,"-secretkeyid")) + { + long ltmp; + if (!args[1]) + goto argerr; + args++; + secret_keyid = string_to_hex(*args, <mp); + if (!secret_keyid) + { + BIO_printf(bio_err, "Invalid id %s\n", *args); + goto argerr; + } + secret_keyidlen = (size_t)ltmp; + } + else if (!strcmp(*args,"-pwri_password")) + { + if (!args[1]) + goto argerr; + args++; + pwri_pass = (unsigned char *)*args; + } + else if (!strcmp(*args,"-econtent_type")) + { + if (!args[1]) + goto argerr; + args++; + econtent_type = OBJ_txt2obj(*args, 0); + if (!econtent_type) + { + BIO_printf(bio_err, "Invalid OID %s\n", *args); + goto argerr; + } + } else if (!strcmp(*args,"-rand")) { if (!args[1]) @@ -304,13 +397,13 @@ int MAIN(int argc, char **argv) if (signerfile) { if (!sksigners) - sksigners = sk_new_null(); - sk_push(sksigners, signerfile); + sksigners = sk_OPENSSL_STRING_new_null(); + sk_OPENSSL_STRING_push(sksigners, signerfile); if (!keyfile) keyfile = signerfile; if (!skkeys) - skkeys = sk_new_null(); - sk_push(skkeys, keyfile); + skkeys = sk_OPENSSL_STRING_new_null(); + sk_OPENSSL_STRING_push(skkeys, keyfile); keyfile = NULL; } signerfile = *++args; @@ -321,6 +414,12 @@ int MAIN(int argc, char **argv) goto argerr; recipfile = *++args; } + else if (!strcmp (*args, "-certsout")) + { + if (!args[1]) + goto argerr; + certsoutfile = *++args; + } else if (!strcmp (*args, "-md")) { if (!args[1]) @@ -346,12 +445,12 @@ int MAIN(int argc, char **argv) goto argerr; } if (!sksigners) - sksigners = sk_new_null(); - sk_push(sksigners, signerfile); + sksigners = sk_OPENSSL_STRING_new_null(); + sk_OPENSSL_STRING_push(sksigners, signerfile); signerfile = NULL; if (!skkeys) - skkeys = sk_new_null(); - sk_push(skkeys, keyfile); + skkeys = sk_OPENSSL_STRING_new_null(); + sk_OPENSSL_STRING_push(skkeys, keyfile); } keyfile = *++args; } @@ -361,6 +460,12 @@ int MAIN(int argc, char **argv) goto argerr; keyform = str2fmt(*++args); } + else if (!strcmp (*args, "-rctform")) + { + if (!args[1]) + goto argerr; + rctformat = str2fmt(*++args); + } else if (!strcmp (*args, "-certfile")) { if (!args[1]) @@ -416,6 +521,17 @@ int MAIN(int argc, char **argv) args++; } + if (((rr_allorfirst != -1) || rr_from) && !rr_to) + { + BIO_puts(bio_err, "No Signed Receipts Recipients\n"); + goto argerr; + } + + if (!(operation & SMIME_SIGNERS) && (rr_to || rr_from)) + { + BIO_puts(bio_err, "Signed receipts only allowed with -sign\n"); + goto argerr; + } if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) { BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); @@ -424,22 +540,22 @@ int MAIN(int argc, char **argv) if (operation & SMIME_SIGNERS) { - /* Check to see if any final signer needs to be appended */ if (keyfile && !signerfile) { BIO_puts(bio_err, "Illegal -inkey without -signer\n"); goto argerr; } + /* Check to see if any final signer needs to be appended */ if (signerfile) { if (!sksigners) - sksigners = sk_new_null(); - sk_push(sksigners, signerfile); + sksigners = sk_OPENSSL_STRING_new_null(); + sk_OPENSSL_STRING_push(sksigners, signerfile); if (!skkeys) - skkeys = sk_new_null(); + skkeys = sk_OPENSSL_STRING_new_null(); if (!keyfile) keyfile = signerfile; - sk_push(skkeys, keyfile); + sk_OPENSSL_STRING_push(skkeys, keyfile); } if (!sksigners) { @@ -450,9 +566,10 @@ int MAIN(int argc, char **argv) keyfile = NULL; need_rand = 1; } + else if (operation == SMIME_DECRYPT) { - if (!recipfile && !keyfile) + if (!recipfile && !keyfile && !secret_key && !pwri_pass) { BIO_printf(bio_err, "No recipient certificate or key specified\n"); badarg = 1; @@ -460,7 +577,7 @@ int MAIN(int argc, char **argv) } else if (operation == SMIME_ENCRYPT) { - if (!*args) + if (!*args && !secret_key && !pwri_pass) { BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); badarg = 1; @@ -473,7 +590,7 @@ int MAIN(int argc, char **argv) if (badarg) { argerr: - BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n"); + BIO_printf (bio_err, "Usage cms [options] cert.pem ...\n"); BIO_printf (bio_err, "where options are\n"); BIO_printf (bio_err, "-encrypt encrypt message\n"); BIO_printf (bio_err, "-decrypt decrypt encrypted message\n"); @@ -508,9 +625,10 @@ int MAIN(int argc, char **argv) BIO_printf (bio_err, "-noattr don't include any signed attributes\n"); BIO_printf (bio_err, "-binary don't translate message to text\n"); BIO_printf (bio_err, "-certfile file other certificates file\n"); + BIO_printf (bio_err, "-certsout file certificate output file\n"); BIO_printf (bio_err, "-signer file signer certificate file\n"); BIO_printf (bio_err, "-recip file recipient certificate file for decryption\n"); - BIO_printf (bio_err, "-skeyid use subject key identifier\n"); + BIO_printf (bio_err, "-keyid use subject key identifier\n"); BIO_printf (bio_err, "-in file input file\n"); BIO_printf (bio_err, "-inform arg input format SMIME (default), PEM or DER\n"); BIO_printf (bio_err, "-inkey file input private key (if not signer or recipient)\n"); @@ -586,24 +704,27 @@ int MAIN(int argc, char **argv) { if (!cipher) { -#ifndef OPENSSL_NO_RC2 - cipher = EVP_rc2_40_cbc(); +#ifndef OPENSSL_NO_DES + cipher = EVP_des_ede3_cbc(); #else BIO_printf(bio_err, "No cipher selected\n"); goto end; #endif } - encerts = sk_X509_new_null(); + + if (secret_key && !secret_keyid) + { + BIO_printf(bio_err, "No secret key id\n"); + goto end; + } + + if (*args) + encerts = sk_X509_new_null(); while (*args) { if (!(cert = load_cert(bio_err,*args,FORMAT_PEM, NULL, e, "recipient certificate file"))) - { -#if 0 /* An appropriate message is already printed */ - BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args); -#endif goto end; - } sk_X509_push(encerts, cert); cert = NULL; args++; @@ -630,12 +751,22 @@ int MAIN(int argc, char **argv) } } + if (operation == SMIME_SIGN_RECEIPT) + { + if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM,NULL, + e, "receipt signer certificate file"))) + { + ERR_print_errors(bio_err); + goto end; + } + } + if (operation == SMIME_DECRYPT) { if (!keyfile) keyfile = recipfile; } - else if (operation == SMIME_SIGN) + else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) { if (!keyfile) keyfile = signerfile; @@ -690,6 +821,49 @@ int MAIN(int argc, char **argv) goto end; } } + if (certsoutfile) + { + STACK_OF(X509) *allcerts; + allcerts = CMS_get1_certs(cms); + if (!save_certs(certsoutfile, allcerts)) + { + BIO_printf(bio_err, + "Error writing certs to %s\n", + certsoutfile); + ret = 5; + goto end; + } + sk_X509_pop_free(allcerts, X509_free); + } + } + + if (rctfile) + { + char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r"; + if (!(rctin = BIO_new_file(rctfile, rctmode))) + { + BIO_printf (bio_err, + "Can't open receipt file %s\n", rctfile); + goto end; + } + + if (rctformat == FORMAT_SMIME) + rcms = SMIME_read_CMS(rctin, NULL); + else if (rctformat == FORMAT_PEM) + rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL); + else if (rctformat == FORMAT_ASN1) + rcms = d2i_CMS_bio(rctin, NULL); + else + { + BIO_printf(bio_err, "Bad input format for receipt\n"); + goto end; + } + + if (!rcms) + { + BIO_printf(bio_err, "Error reading receipt\n"); + goto end; + } } if (outfile) @@ -712,11 +886,11 @@ int MAIN(int argc, char **argv) #endif } - if (operation == SMIME_VERIFY) + if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) { if (!(store = setup_verify(bio_err, CAfile, CApath))) goto end; - X509_STORE_set_verify_cb_func(store, smime_cb); + X509_STORE_set_verify_cb(store, cms_cb); if (vpm) X509_STORE_set1_param(store, vpm); } @@ -726,62 +900,112 @@ int MAIN(int argc, char **argv) if (operation == SMIME_DATA_CREATE) { - if (indef) - flags |= CMS_STREAM; cms = CMS_data_create(in, flags); } else if (operation == SMIME_DIGEST_CREATE) { - if (indef) - flags |= CMS_STREAM; cms = CMS_digest_create(in, sign_md, flags); } else if (operation == SMIME_COMPRESS) { - if (indef) - flags |= CMS_STREAM; cms = CMS_compress(in, -1, flags); } else if (operation == SMIME_ENCRYPT) { - if (indef) - flags |= CMS_STREAM; + flags |= CMS_PARTIAL; cms = CMS_encrypt(encerts, in, cipher, flags); + if (!cms) + goto end; + if (secret_key) + { + if (!CMS_add0_recipient_key(cms, NID_undef, + secret_key, secret_keylen, + secret_keyid, secret_keyidlen, + NULL, NULL, NULL)) + goto end; + /* NULL these because call absorbs them */ + secret_key = NULL; + secret_keyid = NULL; + } + if (pwri_pass) + { + pwri_tmp = (unsigned char *)BUF_strdup((char *)pwri_pass); + if (!pwri_tmp) + goto end; + if (!CMS_add0_recipient_password(cms, + -1, NID_undef, NID_undef, + pwri_tmp, -1, NULL)) + goto end; + pwri_tmp = NULL; + } + if (!(flags & CMS_STREAM)) + { + if (!CMS_final(cms, in, NULL, flags)) + goto end; + } } else if (operation == SMIME_ENCRYPTED_ENCRYPT) { - if (indef) - flags |= CMS_STREAM; cms = CMS_EncryptedData_encrypt(in, cipher, secret_key, secret_keylen, flags); + + } + else if (operation == SMIME_SIGN_RECEIPT) + { + CMS_ContentInfo *srcms = NULL; + STACK_OF(CMS_SignerInfo) *sis; + CMS_SignerInfo *si; + sis = CMS_get0_SignerInfos(cms); + if (!sis) + goto end; + si = sk_CMS_SignerInfo_value(sis, 0); + srcms = CMS_sign_receipt(si, signer, key, other, flags); + if (!srcms) + goto end; + CMS_ContentInfo_free(cms); + cms = srcms; } else if (operation & SMIME_SIGNERS) { int i; - /* If detached data content we only enable streaming if + /* If detached data content we enable streaming if * S/MIME output format. */ if (operation == SMIME_SIGN) { + if (flags & CMS_DETACHED) { if (outformat == FORMAT_SMIME) flags |= CMS_STREAM; } - else if (indef) - flags |= CMS_STREAM; flags |= CMS_PARTIAL; cms = CMS_sign(NULL, NULL, other, in, flags); if (!cms) goto end; + if (econtent_type) + CMS_set1_eContentType(cms, econtent_type); + + if (rr_to) + { + rr = make_receipt_request(rr_to, rr_allorfirst, + rr_from); + if (!rr) + { + BIO_puts(bio_err, + "Signed Receipt Request Creation Error\n"); + goto end; + } + } } else flags |= CMS_REUSE_DIGEST; - for (i = 0; i < sk_num(sksigners); i++) + for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { - signerfile = sk_value(sksigners, i); - keyfile = sk_value(skkeys, i); + CMS_SignerInfo *si; + signerfile = sk_OPENSSL_STRING_value(sksigners, i); + keyfile = sk_OPENSSL_STRING_value(skkeys, i); signer = load_cert(bio_err, signerfile,FORMAT_PEM, NULL, e, "signer certificate"); if (!signer) @@ -790,7 +1014,10 @@ int MAIN(int argc, char **argv) "signing key file"); if (!key) goto end; - if (!CMS_add1_signer(cms, signer, key, sign_md, flags)) + si = CMS_add1_signer(cms, signer, key, sign_md, flags); + if (!si) + goto end; + if (rr && !CMS_add1_ReceiptRequest(si, rr)) goto end; X509_free(signer); signer = NULL; @@ -800,7 +1027,7 @@ int MAIN(int argc, char **argv) /* If not streaming or resigning finalize structure */ if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) { - if (!CMS_final(cms, in, flags)) + if (!CMS_final(cms, in, NULL, flags)) goto end; } } @@ -814,7 +1041,42 @@ int MAIN(int argc, char **argv) ret = 4; if (operation == SMIME_DECRYPT) { - if (!CMS_decrypt(cms, key, recip, indata, out, flags)) + if (flags & CMS_DEBUG_DECRYPT) + CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags); + + if (secret_key) + { + if (!CMS_decrypt_set1_key(cms, + secret_key, secret_keylen, + secret_keyid, secret_keyidlen)) + { + BIO_puts(bio_err, + "Error decrypting CMS using secret key\n"); + goto end; + } + } + + if (key) + { + if (!CMS_decrypt_set1_pkey(cms, key, recip)) + { + BIO_puts(bio_err, + "Error decrypting CMS using private key\n"); + goto end; + } + } + + if (pwri_pass) + { + if (!CMS_decrypt_set1_password(cms, pwri_pass, -1)) + { + BIO_puts(bio_err, + "Error decrypting CMS using password\n"); + goto end; + } + } + + if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags)) { BIO_printf(bio_err, "Error decrypting CMS structure\n"); goto end; @@ -853,6 +1115,8 @@ int MAIN(int argc, char **argv) else { BIO_printf(bio_err, "Verification failure\n"); + if (verify_retcode) + ret = verify_err + 32; goto end; } if (signerfile) @@ -869,10 +1133,28 @@ int MAIN(int argc, char **argv) } sk_X509_free(signers); } + if (rr_print) + receipt_request_print(bio_err, cms); + + } + else if (operation == SMIME_VERIFY_RECEIPT) + { + if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0) + BIO_printf(bio_err, "Verification successful\n"); + else + { + BIO_printf(bio_err, "Verification failure\n"); + goto end; + } } else { - if (outformat == FORMAT_SMIME) + if (noout) + { + if (print) + CMS_ContentInfo_print_ctx(out, cms, 0, NULL); + } + else if (outformat == FORMAT_SMIME) { if (to) BIO_printf(out, "To: %s\n", to); @@ -911,17 +1193,31 @@ end: if (vpm) X509_VERIFY_PARAM_free(vpm); if (sksigners) - sk_free(sksigners); + sk_OPENSSL_STRING_free(sksigners); if (skkeys) - sk_free(skkeys); + sk_OPENSSL_STRING_free(skkeys); if (secret_key) OPENSSL_free(secret_key); + if (secret_keyid) + OPENSSL_free(secret_keyid); + if (pwri_tmp) + OPENSSL_free(pwri_tmp); + if (econtent_type) + ASN1_OBJECT_free(econtent_type); + if (rr) + CMS_ReceiptRequest_free(rr); + if (rr_to) + sk_OPENSSL_STRING_free(rr_to); + if (rr_from) + sk_OPENSSL_STRING_free(rr_from); X509_STORE_free(store); X509_free(cert); X509_free(recip); X509_free(signer); EVP_PKEY_free(key); CMS_ContentInfo_free(cms); + CMS_ContentInfo_free(rcms); + BIO_free(rctin); BIO_free(in); BIO_free(indata); BIO_free_all(out); @@ -946,12 +1242,14 @@ static int save_certs(char *signerfile, STACK_OF(X509) *signers) /* Minimal callback just to output policy info (if any) */ -static int smime_cb(int ok, X509_STORE_CTX *ctx) +static int cms_cb(int ok, X509_STORE_CTX *ctx) { int error; error = X509_STORE_CTX_get_error(ctx); + verify_err = error; + if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) && ((error != X509_V_OK) || (ok != 2))) return ok; @@ -962,4 +1260,138 @@ static int smime_cb(int ok, X509_STORE_CTX *ctx) } +static void gnames_stack_print(BIO *out, STACK_OF(GENERAL_NAMES) *gns) + { + STACK_OF(GENERAL_NAME) *gens; + GENERAL_NAME *gen; + int i, j; + for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++) + { + gens = sk_GENERAL_NAMES_value(gns, i); + for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) + { + gen = sk_GENERAL_NAME_value(gens, j); + BIO_puts(out, " "); + GENERAL_NAME_print(out, gen); + BIO_puts(out, "\n"); + } + } + return; + } + +static void receipt_request_print(BIO *out, CMS_ContentInfo *cms) + { + STACK_OF(CMS_SignerInfo) *sis; + CMS_SignerInfo *si; + CMS_ReceiptRequest *rr; + int allorfirst; + STACK_OF(GENERAL_NAMES) *rto, *rlist; + ASN1_STRING *scid; + int i, rv; + sis = CMS_get0_SignerInfos(cms); + for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) + { + si = sk_CMS_SignerInfo_value(sis, i); + rv = CMS_get1_ReceiptRequest(si, &rr); + BIO_printf(bio_err, "Signer %d:\n", i + 1); + if (rv == 0) + BIO_puts(bio_err, " No Receipt Request\n"); + else if (rv < 0) + { + BIO_puts(bio_err, " Receipt Request Parse Error\n"); + ERR_print_errors(bio_err); + } + else + { + char *id; + int idlen; + CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst, + &rlist, &rto); + BIO_puts(out, " Signed Content ID:\n"); + idlen = ASN1_STRING_length(scid); + id = (char *)ASN1_STRING_data(scid); + BIO_dump_indent(out, id, idlen, 4); + BIO_puts(out, " Receipts From"); + if (rlist) + { + BIO_puts(out, " List:\n"); + gnames_stack_print(out, rlist); + } + else if (allorfirst == 1) + BIO_puts(out, ": First Tier\n"); + else if (allorfirst == 0) + BIO_puts(out, ": All\n"); + else + BIO_printf(out, " Unknown (%d)\n", allorfirst); + BIO_puts(out, " Receipts To:\n"); + gnames_stack_print(out, rto); + } + if (rr) + CMS_ReceiptRequest_free(rr); + } + } + +static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns) + { + int i; + STACK_OF(GENERAL_NAMES) *ret; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + ret = sk_GENERAL_NAMES_new_null(); + if (!ret) + goto err; + for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++) + { + char *str = sk_OPENSSL_STRING_value(ns, i); + gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0); + if (!gen) + goto err; + gens = GENERAL_NAMES_new(); + if (!gens) + goto err; + if (!sk_GENERAL_NAME_push(gens, gen)) + goto err; + gen = NULL; + if (!sk_GENERAL_NAMES_push(ret, gens)) + goto err; + gens = NULL; + } + + return ret; + + err: + if (ret) + sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free); + if (gens) + GENERAL_NAMES_free(gens); + if (gen) + GENERAL_NAME_free(gen); + return NULL; + } + + +static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, + int rr_allorfirst, + STACK_OF(OPENSSL_STRING) *rr_from) + { + STACK_OF(GENERAL_NAMES) *rct_to, *rct_from; + CMS_ReceiptRequest *rr; + rct_to = make_names_stack(rr_to); + if (!rct_to) + goto err; + if (rr_from) + { + rct_from = make_names_stack(rr_from); + if (!rct_from) + goto err; + } + else + rct_from = NULL; + rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from, + rct_to); + return rr; + err: + return NULL; + } + #endif