16f9291ceSJung-uk Kim /* 2*a7148ab3SEnji Cooper * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. 3f579bf8eSKris Kennaway * 4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 8f579bf8eSKris Kennaway */ 9f579bf8eSKris Kennaway 10f579bf8eSKris Kennaway /* S/MIME utility function */ 11f579bf8eSKris Kennaway 12f579bf8eSKris Kennaway #include <stdio.h> 13f579bf8eSKris Kennaway #include <string.h> 14f579bf8eSKris Kennaway #include "apps.h" 15e71b7053SJung-uk Kim #include "progs.h" 16f579bf8eSKris Kennaway #include <openssl/crypto.h> 17f579bf8eSKris Kennaway #include <openssl/pem.h> 18f579bf8eSKris Kennaway #include <openssl/err.h> 193b4e3dcbSSimon L. B. Nielsen #include <openssl/x509_vfy.h> 203b4e3dcbSSimon L. B. Nielsen #include <openssl/x509v3.h> 21f579bf8eSKris Kennaway 22f579bf8eSKris Kennaway static int save_certs(char *signerfile, STACK_OF(X509) *signers); 233b4e3dcbSSimon L. B. Nielsen static int smime_cb(int ok, X509_STORE_CTX *ctx); 24f579bf8eSKris Kennaway 25f579bf8eSKris Kennaway #define SMIME_OP 0x10 261f13597dSJung-uk Kim #define SMIME_IP 0x20 271f13597dSJung-uk Kim #define SMIME_SIGNERS 0x40 28f579bf8eSKris Kennaway #define SMIME_ENCRYPT (1 | SMIME_OP) 291f13597dSJung-uk Kim #define SMIME_DECRYPT (2 | SMIME_IP) 301f13597dSJung-uk Kim #define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) 311f13597dSJung-uk Kim #define SMIME_VERIFY (4 | SMIME_IP) 321f13597dSJung-uk Kim #define SMIME_PK7OUT (5 | SMIME_IP | SMIME_OP) 331f13597dSJung-uk Kim #define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) 34f579bf8eSKris Kennaway 35e71b7053SJung-uk Kim typedef enum OPTION_choice { 36b077aed3SPierre Pronchery OPT_COMMON, 37e71b7053SJung-uk Kim OPT_ENCRYPT, OPT_DECRYPT, OPT_SIGN, OPT_RESIGN, OPT_VERIFY, 38e71b7053SJung-uk Kim OPT_PK7OUT, OPT_TEXT, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCHAIN, 39e71b7053SJung-uk Kim OPT_NOCERTS, OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, 40e71b7053SJung-uk Kim OPT_BINARY, OPT_NOSIGS, OPT_STREAM, OPT_INDEF, OPT_NOINDEF, 41e71b7053SJung-uk Kim OPT_CRLFEOL, OPT_ENGINE, OPT_PASSIN, 42e71b7053SJung-uk Kim OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD, 43e71b7053SJung-uk Kim OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE, 44b077aed3SPierre Pronchery OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE, OPT_NOCAPATH, OPT_NOCASTORE, 45b077aed3SPierre Pronchery OPT_R_ENUM, OPT_PROV_ENUM, OPT_CONFIG, 46e71b7053SJung-uk Kim OPT_V_ENUM, 47b077aed3SPierre Pronchery OPT_IN, OPT_INFORM, OPT_OUT, 48e71b7053SJung-uk Kim OPT_OUTFORM, OPT_CONTENT 49e71b7053SJung-uk Kim } OPTION_CHOICE; 50f579bf8eSKris Kennaway 51e71b7053SJung-uk Kim const OPTIONS smime_options[] = { 52b077aed3SPierre Pronchery {OPT_HELP_STR, 1, '-', "Usage: %s [options] [cert...]\n"}, 53b077aed3SPierre Pronchery 54b077aed3SPierre Pronchery OPT_SECTION("General"), 55e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"}, 56e71b7053SJung-uk Kim {"in", OPT_IN, '<', "Input file"}, 57e71b7053SJung-uk Kim {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"}, 58e71b7053SJung-uk Kim {"out", OPT_OUT, '>', "Output file"}, 59e71b7053SJung-uk Kim {"outform", OPT_OUTFORM, 'c', 60e71b7053SJung-uk Kim "Output format SMIME (default), PEM or DER"}, 61b077aed3SPierre Pronchery {"inkey", OPT_INKEY, 's', 62b077aed3SPierre Pronchery "Input private key (if not signer or recipient)"}, 63b077aed3SPierre Pronchery {"keyform", OPT_KEYFORM, 'f', "Input private key format (ENGINE, other values ignored)"}, 64b077aed3SPierre Pronchery #ifndef OPENSSL_NO_ENGINE 65b077aed3SPierre Pronchery {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 66b077aed3SPierre Pronchery #endif 67b077aed3SPierre Pronchery {"stream", OPT_STREAM, '-', "Enable CMS streaming" }, 68b077aed3SPierre Pronchery {"indef", OPT_INDEF, '-', "Same as -stream" }, 69b077aed3SPierre Pronchery {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"}, 70b077aed3SPierre Pronchery OPT_CONFIG_OPTION, 71b077aed3SPierre Pronchery 72b077aed3SPierre Pronchery OPT_SECTION("Action"), 73b077aed3SPierre Pronchery {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"}, 74b077aed3SPierre Pronchery {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"}, 75b077aed3SPierre Pronchery {"sign", OPT_SIGN, '-', "Sign message"}, 76b077aed3SPierre Pronchery {"resign", OPT_RESIGN, '-', "Resign a signed message"}, 77b077aed3SPierre Pronchery {"verify", OPT_VERIFY, '-', "Verify signed message"}, 78b077aed3SPierre Pronchery 79b077aed3SPierre Pronchery OPT_SECTION("Signing/Encryption"), 80b077aed3SPierre Pronchery {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, 81b077aed3SPierre Pronchery {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, 82b077aed3SPierre Pronchery {"", OPT_CIPHER, '-', "Any supported cipher"}, 83b077aed3SPierre Pronchery {"pk7out", OPT_PK7OUT, '-', "Output PKCS#7 structure"}, 84b077aed3SPierre Pronchery {"nointern", OPT_NOINTERN, '-', 85b077aed3SPierre Pronchery "Don't search certificates in message for signer"}, 86b077aed3SPierre Pronchery {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, 87b077aed3SPierre Pronchery {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, 88b077aed3SPierre Pronchery {"binary", OPT_BINARY, '-', "Don't translate message to text"}, 89b077aed3SPierre Pronchery {"signer", OPT_SIGNER, 's', "Signer certificate file"}, 90e71b7053SJung-uk Kim {"content", OPT_CONTENT, '<', 91e71b7053SJung-uk Kim "Supply or override content for detached signature"}, 92b077aed3SPierre Pronchery {"nocerts", OPT_NOCERTS, '-', 93b077aed3SPierre Pronchery "Don't include signers certificate when signing"}, 94b077aed3SPierre Pronchery 95b077aed3SPierre Pronchery OPT_SECTION("Verification/Decryption"), 96b077aed3SPierre Pronchery {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, 97b077aed3SPierre Pronchery {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, 98b077aed3SPierre Pronchery 99b077aed3SPierre Pronchery {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, 100b077aed3SPierre Pronchery {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"}, 101b077aed3SPierre Pronchery 102b077aed3SPierre Pronchery OPT_SECTION("Email"), 103e71b7053SJung-uk Kim {"to", OPT_TO, 's', "To address"}, 104e71b7053SJung-uk Kim {"from", OPT_FROM, 's', "From address"}, 105e71b7053SJung-uk Kim {"subject", OPT_SUBJECT, 's', "Subject"}, 106e71b7053SJung-uk Kim {"text", OPT_TEXT, '-', "Include or delete text MIME headers"}, 107b077aed3SPierre Pronchery {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, 108b077aed3SPierre Pronchery 109b077aed3SPierre Pronchery OPT_SECTION("Certificate chain"), 110e71b7053SJung-uk Kim {"CApath", OPT_CAPATH, '/', "Trusted certificates directory"}, 111e71b7053SJung-uk Kim {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"}, 112b077aed3SPierre Pronchery {"CAstore", OPT_CASTORE, ':', "Trusted certificates store URI"}, 113e71b7053SJung-uk Kim {"no-CAfile", OPT_NOCAFILE, '-', 114e71b7053SJung-uk Kim "Do not load the default certificates file"}, 115e71b7053SJung-uk Kim {"no-CApath", OPT_NOCAPATH, '-', 116e71b7053SJung-uk Kim "Do not load certificates from the default certificates directory"}, 117b077aed3SPierre Pronchery {"no-CAstore", OPT_NOCASTORE, '-', 118b077aed3SPierre Pronchery "Do not load certificates from the default certificates store"}, 119e71b7053SJung-uk Kim {"nochain", OPT_NOCHAIN, '-', 120e71b7053SJung-uk Kim "set PKCS7_NOCHAIN so certificates contained in the message are not used as untrusted CAs" }, 121*a7148ab3SEnji Cooper {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of LF only"}, 122b077aed3SPierre Pronchery 123e71b7053SJung-uk Kim OPT_R_OPTIONS, 124e71b7053SJung-uk Kim OPT_V_OPTIONS, 125b077aed3SPierre Pronchery OPT_PROV_OPTIONS, 126b077aed3SPierre Pronchery 127b077aed3SPierre Pronchery OPT_PARAMETERS(), 128b077aed3SPierre Pronchery {"cert", 0, 0, "Recipient certs, used when encrypting"}, 129e71b7053SJung-uk Kim {NULL} 130e71b7053SJung-uk Kim }; 1311f13597dSJung-uk Kim 132e71b7053SJung-uk Kim int smime_main(int argc, char **argv) 133e71b7053SJung-uk Kim { 134b077aed3SPierre Pronchery CONF *conf = NULL; 135e71b7053SJung-uk Kim BIO *in = NULL, *out = NULL, *indata = NULL; 136e71b7053SJung-uk Kim EVP_PKEY *key = NULL; 137e71b7053SJung-uk Kim PKCS7 *p7 = NULL; 138e71b7053SJung-uk Kim STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL; 139e71b7053SJung-uk Kim STACK_OF(X509) *encerts = NULL, *other = NULL; 140e71b7053SJung-uk Kim X509 *cert = NULL, *recip = NULL, *signer = NULL; 141e71b7053SJung-uk Kim X509_STORE *store = NULL; 142e71b7053SJung-uk Kim X509_VERIFY_PARAM *vpm = NULL; 143b077aed3SPierre Pronchery EVP_CIPHER *cipher = NULL; 144b077aed3SPierre Pronchery EVP_MD *sign_md = NULL; 145b077aed3SPierre Pronchery const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL, *prog = NULL; 146e71b7053SJung-uk Kim char *certfile = NULL, *keyfile = NULL, *contfile = NULL; 147e71b7053SJung-uk Kim char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile = NULL; 148b077aed3SPierre Pronchery char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL; 149b077aed3SPierre Pronchery char *subject = NULL, *digestname = NULL, *ciphername = NULL; 150e71b7053SJung-uk Kim OPTION_CHOICE o; 151b077aed3SPierre Pronchery int noCApath = 0, noCAfile = 0, noCAstore = 0; 152e71b7053SJung-uk Kim int flags = PKCS7_DETACHED, operation = 0, ret = 0, indef = 0; 153e71b7053SJung-uk Kim int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform = 154b077aed3SPierre Pronchery FORMAT_UNDEF; 155e71b7053SJung-uk Kim int vpmtouched = 0, rv = 0; 156e71b7053SJung-uk Kim ENGINE *e = NULL; 157e71b7053SJung-uk Kim const char *mime_eol = "\n"; 158b077aed3SPierre Pronchery OSSL_LIB_CTX *libctx = app_get0_libctx(); 159e71b7053SJung-uk Kim 160e71b7053SJung-uk Kim if ((vpm = X509_VERIFY_PARAM_new()) == NULL) 161e71b7053SJung-uk Kim return 1; 162e71b7053SJung-uk Kim 163e71b7053SJung-uk Kim prog = opt_init(argc, argv, smime_options); 164e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) { 165e71b7053SJung-uk Kim switch (o) { 166e71b7053SJung-uk Kim case OPT_EOF: 167e71b7053SJung-uk Kim case OPT_ERR: 168e71b7053SJung-uk Kim opthelp: 169e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 170e71b7053SJung-uk Kim goto end; 171e71b7053SJung-uk Kim case OPT_HELP: 172e71b7053SJung-uk Kim opt_help(smime_options); 173e71b7053SJung-uk Kim ret = 0; 174e71b7053SJung-uk Kim goto end; 175e71b7053SJung-uk Kim case OPT_INFORM: 176e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat)) 177e71b7053SJung-uk Kim goto opthelp; 178e71b7053SJung-uk Kim break; 179e71b7053SJung-uk Kim case OPT_IN: 180e71b7053SJung-uk Kim infile = opt_arg(); 181e71b7053SJung-uk Kim break; 182e71b7053SJung-uk Kim case OPT_OUTFORM: 183e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat)) 184e71b7053SJung-uk Kim goto opthelp; 185e71b7053SJung-uk Kim break; 186e71b7053SJung-uk Kim case OPT_OUT: 187e71b7053SJung-uk Kim outfile = opt_arg(); 188e71b7053SJung-uk Kim break; 189e71b7053SJung-uk Kim case OPT_ENCRYPT: 190e71b7053SJung-uk Kim operation = SMIME_ENCRYPT; 191e71b7053SJung-uk Kim break; 192e71b7053SJung-uk Kim case OPT_DECRYPT: 193e71b7053SJung-uk Kim operation = SMIME_DECRYPT; 194e71b7053SJung-uk Kim break; 195e71b7053SJung-uk Kim case OPT_SIGN: 196e71b7053SJung-uk Kim operation = SMIME_SIGN; 197e71b7053SJung-uk Kim break; 198e71b7053SJung-uk Kim case OPT_RESIGN: 199e71b7053SJung-uk Kim operation = SMIME_RESIGN; 200e71b7053SJung-uk Kim break; 201e71b7053SJung-uk Kim case OPT_VERIFY: 202e71b7053SJung-uk Kim operation = SMIME_VERIFY; 203e71b7053SJung-uk Kim break; 204e71b7053SJung-uk Kim case OPT_PK7OUT: 205e71b7053SJung-uk Kim operation = SMIME_PK7OUT; 206e71b7053SJung-uk Kim break; 207e71b7053SJung-uk Kim case OPT_TEXT: 208e71b7053SJung-uk Kim flags |= PKCS7_TEXT; 209e71b7053SJung-uk Kim break; 210e71b7053SJung-uk Kim case OPT_NOINTERN: 211e71b7053SJung-uk Kim flags |= PKCS7_NOINTERN; 212e71b7053SJung-uk Kim break; 213e71b7053SJung-uk Kim case OPT_NOVERIFY: 214e71b7053SJung-uk Kim flags |= PKCS7_NOVERIFY; 215e71b7053SJung-uk Kim break; 216e71b7053SJung-uk Kim case OPT_NOCHAIN: 217e71b7053SJung-uk Kim flags |= PKCS7_NOCHAIN; 218e71b7053SJung-uk Kim break; 219e71b7053SJung-uk Kim case OPT_NOCERTS: 220e71b7053SJung-uk Kim flags |= PKCS7_NOCERTS; 221e71b7053SJung-uk Kim break; 222e71b7053SJung-uk Kim case OPT_NOATTR: 223e71b7053SJung-uk Kim flags |= PKCS7_NOATTR; 224e71b7053SJung-uk Kim break; 225e71b7053SJung-uk Kim case OPT_NODETACH: 226e71b7053SJung-uk Kim flags &= ~PKCS7_DETACHED; 227e71b7053SJung-uk Kim break; 228e71b7053SJung-uk Kim case OPT_NOSMIMECAP: 229e71b7053SJung-uk Kim flags |= PKCS7_NOSMIMECAP; 230e71b7053SJung-uk Kim break; 231e71b7053SJung-uk Kim case OPT_BINARY: 232e71b7053SJung-uk Kim flags |= PKCS7_BINARY; 233e71b7053SJung-uk Kim break; 234e71b7053SJung-uk Kim case OPT_NOSIGS: 235e71b7053SJung-uk Kim flags |= PKCS7_NOSIGS; 236e71b7053SJung-uk Kim break; 237e71b7053SJung-uk Kim case OPT_STREAM: 238e71b7053SJung-uk Kim case OPT_INDEF: 239e71b7053SJung-uk Kim indef = 1; 240e71b7053SJung-uk Kim break; 241e71b7053SJung-uk Kim case OPT_NOINDEF: 242e71b7053SJung-uk Kim indef = 0; 243e71b7053SJung-uk Kim break; 244e71b7053SJung-uk Kim case OPT_CRLFEOL: 245e71b7053SJung-uk Kim flags |= PKCS7_CRLFEOL; 246e71b7053SJung-uk Kim mime_eol = "\r\n"; 247e71b7053SJung-uk Kim break; 248e71b7053SJung-uk Kim case OPT_R_CASES: 249e71b7053SJung-uk Kim if (!opt_rand(o)) 250e71b7053SJung-uk Kim goto end; 251e71b7053SJung-uk Kim break; 252b077aed3SPierre Pronchery case OPT_PROV_CASES: 253b077aed3SPierre Pronchery if (!opt_provider(o)) 254b077aed3SPierre Pronchery goto end; 255b077aed3SPierre Pronchery break; 256b077aed3SPierre Pronchery case OPT_CONFIG: 257b077aed3SPierre Pronchery conf = app_load_config_modules(opt_arg()); 258b077aed3SPierre Pronchery if (conf == NULL) 259b077aed3SPierre Pronchery goto end; 260b077aed3SPierre Pronchery break; 261e71b7053SJung-uk Kim case OPT_ENGINE: 262e71b7053SJung-uk Kim e = setup_engine(opt_arg(), 0); 263e71b7053SJung-uk Kim break; 264e71b7053SJung-uk Kim case OPT_PASSIN: 265e71b7053SJung-uk Kim passinarg = opt_arg(); 266e71b7053SJung-uk Kim break; 267e71b7053SJung-uk Kim case OPT_TO: 268e71b7053SJung-uk Kim to = opt_arg(); 269e71b7053SJung-uk Kim break; 270e71b7053SJung-uk Kim case OPT_FROM: 271e71b7053SJung-uk Kim from = opt_arg(); 272e71b7053SJung-uk Kim break; 273e71b7053SJung-uk Kim case OPT_SUBJECT: 274e71b7053SJung-uk Kim subject = opt_arg(); 275e71b7053SJung-uk Kim break; 276e71b7053SJung-uk Kim case OPT_SIGNER: 277e71b7053SJung-uk Kim /* If previous -signer argument add signer to list */ 278e71b7053SJung-uk Kim if (signerfile != NULL) { 279e71b7053SJung-uk Kim if (sksigners == NULL 280e71b7053SJung-uk Kim && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) 281e71b7053SJung-uk Kim goto end; 2821f13597dSJung-uk Kim sk_OPENSSL_STRING_push(sksigners, signerfile); 283e71b7053SJung-uk Kim if (keyfile == NULL) 2841f13597dSJung-uk Kim keyfile = signerfile; 285e71b7053SJung-uk Kim if (skkeys == NULL 286e71b7053SJung-uk Kim && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) 287e71b7053SJung-uk Kim goto end; 2881f13597dSJung-uk Kim sk_OPENSSL_STRING_push(skkeys, keyfile); 2891f13597dSJung-uk Kim keyfile = NULL; 2903b4e3dcbSSimon L. B. Nielsen } 291e71b7053SJung-uk Kim signerfile = opt_arg(); 292e71b7053SJung-uk Kim break; 293e71b7053SJung-uk Kim case OPT_RECIP: 294e71b7053SJung-uk Kim recipfile = opt_arg(); 295e71b7053SJung-uk Kim break; 296e71b7053SJung-uk Kim case OPT_MD: 297b077aed3SPierre Pronchery digestname = opt_arg(); 298e71b7053SJung-uk Kim break; 299e71b7053SJung-uk Kim case OPT_CIPHER: 300b077aed3SPierre Pronchery ciphername = opt_unknown(); 301e71b7053SJung-uk Kim break; 302e71b7053SJung-uk Kim case OPT_INKEY: 303e71b7053SJung-uk Kim /* If previous -inkey argument add signer to list */ 304e71b7053SJung-uk Kim if (keyfile != NULL) { 305e71b7053SJung-uk Kim if (signerfile == NULL) { 306e71b7053SJung-uk Kim BIO_printf(bio_err, 307e71b7053SJung-uk Kim "%s: Must have -signer before -inkey\n", prog); 308e71b7053SJung-uk Kim goto opthelp; 3091f13597dSJung-uk Kim } 310e71b7053SJung-uk Kim if (sksigners == NULL 311e71b7053SJung-uk Kim && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) 312e71b7053SJung-uk Kim goto end; 3131f13597dSJung-uk Kim sk_OPENSSL_STRING_push(sksigners, signerfile); 3141f13597dSJung-uk Kim signerfile = NULL; 315e71b7053SJung-uk Kim if (skkeys == NULL 316e71b7053SJung-uk Kim && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) 317e71b7053SJung-uk Kim goto end; 3181f13597dSJung-uk Kim sk_OPENSSL_STRING_push(skkeys, keyfile); 3191f13597dSJung-uk Kim } 320e71b7053SJung-uk Kim keyfile = opt_arg(); 321e71b7053SJung-uk Kim break; 322e71b7053SJung-uk Kim case OPT_KEYFORM: 323e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) 324e71b7053SJung-uk Kim goto opthelp; 325e71b7053SJung-uk Kim break; 326e71b7053SJung-uk Kim case OPT_CERTFILE: 327e71b7053SJung-uk Kim certfile = opt_arg(); 328e71b7053SJung-uk Kim break; 329e71b7053SJung-uk Kim case OPT_CAFILE: 330e71b7053SJung-uk Kim CAfile = opt_arg(); 331e71b7053SJung-uk Kim break; 332e71b7053SJung-uk Kim case OPT_CAPATH: 333e71b7053SJung-uk Kim CApath = opt_arg(); 334e71b7053SJung-uk Kim break; 335b077aed3SPierre Pronchery case OPT_CASTORE: 336b077aed3SPierre Pronchery CAstore = opt_arg(); 337b077aed3SPierre Pronchery break; 338e71b7053SJung-uk Kim case OPT_NOCAFILE: 339e71b7053SJung-uk Kim noCAfile = 1; 340e71b7053SJung-uk Kim break; 341e71b7053SJung-uk Kim case OPT_NOCAPATH: 342e71b7053SJung-uk Kim noCApath = 1; 343e71b7053SJung-uk Kim break; 344b077aed3SPierre Pronchery case OPT_NOCASTORE: 345b077aed3SPierre Pronchery noCAstore = 1; 346b077aed3SPierre Pronchery break; 347e71b7053SJung-uk Kim case OPT_CONTENT: 348e71b7053SJung-uk Kim contfile = opt_arg(); 349e71b7053SJung-uk Kim break; 350e71b7053SJung-uk Kim case OPT_V_CASES: 351e71b7053SJung-uk Kim if (!opt_verify(o, vpm)) 352e71b7053SJung-uk Kim goto opthelp; 353e71b7053SJung-uk Kim vpmtouched++; 354e71b7053SJung-uk Kim break; 355f579bf8eSKris Kennaway } 356e71b7053SJung-uk Kim } 357b077aed3SPierre Pronchery 358b077aed3SPierre Pronchery /* Extra arguments are files with recipient keys. */ 359e71b7053SJung-uk Kim argc = opt_num_rest(); 360e71b7053SJung-uk Kim argv = opt_rest(); 361f579bf8eSKris Kennaway 362b077aed3SPierre Pronchery if (!app_RAND_load()) 363b077aed3SPierre Pronchery goto end; 364b077aed3SPierre Pronchery 365b077aed3SPierre Pronchery if (digestname != NULL) { 366b077aed3SPierre Pronchery if (!opt_md(digestname, &sign_md)) 367b077aed3SPierre Pronchery goto opthelp; 368b077aed3SPierre Pronchery } 369b077aed3SPierre Pronchery if (ciphername != NULL) { 370b077aed3SPierre Pronchery if (!opt_cipher_any(ciphername, &cipher)) 371b077aed3SPierre Pronchery goto opthelp; 372b077aed3SPierre Pronchery } 373e71b7053SJung-uk Kim if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) { 3741f13597dSJung-uk Kim BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); 375e71b7053SJung-uk Kim goto opthelp; 3761f13597dSJung-uk Kim } 377b077aed3SPierre Pronchery if (!operation) { 378b077aed3SPierre Pronchery BIO_puts(bio_err, 379b077aed3SPierre Pronchery "No operation (-encrypt|-sign|...) specified\n"); 380b077aed3SPierre Pronchery goto opthelp; 381b077aed3SPierre Pronchery } 3821f13597dSJung-uk Kim 3836f9291ceSJung-uk Kim if (operation & SMIME_SIGNERS) { 3841f13597dSJung-uk Kim /* Check to see if any final signer needs to be appended */ 3856f9291ceSJung-uk Kim if (keyfile && !signerfile) { 3861f13597dSJung-uk Kim BIO_puts(bio_err, "Illegal -inkey without -signer\n"); 387e71b7053SJung-uk Kim goto opthelp; 3881f13597dSJung-uk Kim } 389e71b7053SJung-uk Kim if (signerfile != NULL) { 390e71b7053SJung-uk Kim if (sksigners == NULL 391e71b7053SJung-uk Kim && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL) 392e71b7053SJung-uk Kim goto end; 3931f13597dSJung-uk Kim sk_OPENSSL_STRING_push(sksigners, signerfile); 394e71b7053SJung-uk Kim if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL) 395e71b7053SJung-uk Kim goto end; 3961f13597dSJung-uk Kim if (!keyfile) 3971f13597dSJung-uk Kim keyfile = signerfile; 3981f13597dSJung-uk Kim sk_OPENSSL_STRING_push(skkeys, keyfile); 3991f13597dSJung-uk Kim } 400e71b7053SJung-uk Kim if (sksigners == NULL) { 401f579bf8eSKris Kennaway BIO_printf(bio_err, "No signer certificate specified\n"); 402e71b7053SJung-uk Kim goto opthelp; 403f579bf8eSKris Kennaway } 4041f13597dSJung-uk Kim signerfile = NULL; 4051f13597dSJung-uk Kim keyfile = NULL; 4066f9291ceSJung-uk Kim } else if (operation == SMIME_DECRYPT) { 407e71b7053SJung-uk Kim if (recipfile == NULL && keyfile == NULL) { 4086f9291ceSJung-uk Kim BIO_printf(bio_err, 4096f9291ceSJung-uk Kim "No recipient certificate or key specified\n"); 410e71b7053SJung-uk Kim goto opthelp; 411f579bf8eSKris Kennaway } 4126f9291ceSJung-uk Kim } else if (operation == SMIME_ENCRYPT) { 413e71b7053SJung-uk Kim if (argc == 0) { 414f579bf8eSKris Kennaway BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); 415e71b7053SJung-uk Kim goto opthelp; 416f579bf8eSKris Kennaway } 417f579bf8eSKris Kennaway } 4185c87c606SMark Murray 419e71b7053SJung-uk Kim if (!app_passwd(passinarg, NULL, &passin, NULL)) { 420f579bf8eSKris Kennaway BIO_printf(bio_err, "Error getting password\n"); 421f579bf8eSKris Kennaway goto end; 422f579bf8eSKris Kennaway } 423f579bf8eSKris Kennaway 424f579bf8eSKris Kennaway ret = 2; 425f579bf8eSKris Kennaway 4261f13597dSJung-uk Kim if (!(operation & SMIME_SIGNERS)) 4273b4e3dcbSSimon L. B. Nielsen flags &= ~PKCS7_DETACHED; 428f579bf8eSKris Kennaway 429e71b7053SJung-uk Kim if (!(operation & SMIME_OP)) { 4303b4e3dcbSSimon L. B. Nielsen if (flags & PKCS7_BINARY) 431e71b7053SJung-uk Kim outformat = FORMAT_BINARY; 4321f13597dSJung-uk Kim } 4331f13597dSJung-uk Kim 434e71b7053SJung-uk Kim if (!(operation & SMIME_IP)) { 4351f13597dSJung-uk Kim if (flags & PKCS7_BINARY) 436e71b7053SJung-uk Kim informat = FORMAT_BINARY; 4371f13597dSJung-uk Kim } 438f579bf8eSKris Kennaway 4396f9291ceSJung-uk Kim if (operation == SMIME_ENCRYPT) { 440e71b7053SJung-uk Kim if (cipher == NULL) { 44194ad176cSJung-uk Kim #ifndef OPENSSL_NO_DES 442b077aed3SPierre Pronchery cipher = (EVP_CIPHER *)EVP_des_ede3_cbc(); 443f579bf8eSKris Kennaway #else 444f579bf8eSKris Kennaway BIO_printf(bio_err, "No cipher selected\n"); 445f579bf8eSKris Kennaway goto end; 446f579bf8eSKris Kennaway #endif 447f579bf8eSKris Kennaway } 448f579bf8eSKris Kennaway encerts = sk_X509_new_null(); 449e71b7053SJung-uk Kim if (encerts == NULL) 450f579bf8eSKris Kennaway goto end; 451e71b7053SJung-uk Kim while (*argv != NULL) { 452b077aed3SPierre Pronchery cert = load_cert(*argv, FORMAT_UNDEF, 453e71b7053SJung-uk Kim "recipient certificate file"); 454e71b7053SJung-uk Kim if (cert == NULL) 455e71b7053SJung-uk Kim goto end; 456e0c4386eSCy Schubert if (!sk_X509_push(encerts, cert)) 457e0c4386eSCy Schubert goto end; 458f579bf8eSKris Kennaway cert = NULL; 459e71b7053SJung-uk Kim argv++; 460f579bf8eSKris Kennaway } 461f579bf8eSKris Kennaway } 462f579bf8eSKris Kennaway 463e71b7053SJung-uk Kim if (certfile != NULL) { 464b077aed3SPierre Pronchery if (!load_certs(certfile, 0, &other, NULL, "certificates")) { 465f579bf8eSKris Kennaway ERR_print_errors(bio_err); 466f579bf8eSKris Kennaway goto end; 467f579bf8eSKris Kennaway } 468f579bf8eSKris Kennaway } 469f579bf8eSKris Kennaway 470e71b7053SJung-uk Kim if (recipfile != NULL && (operation == SMIME_DECRYPT)) { 471b077aed3SPierre Pronchery if ((recip = load_cert(recipfile, FORMAT_UNDEF, 472e71b7053SJung-uk Kim "recipient certificate file")) == NULL) { 473f579bf8eSKris Kennaway ERR_print_errors(bio_err); 474f579bf8eSKris Kennaway goto end; 475f579bf8eSKris Kennaway } 476f579bf8eSKris Kennaway } 477f579bf8eSKris Kennaway 4786f9291ceSJung-uk Kim if (operation == SMIME_DECRYPT) { 479e71b7053SJung-uk Kim if (keyfile == NULL) 4803b4e3dcbSSimon L. B. Nielsen keyfile = recipfile; 4816f9291ceSJung-uk Kim } else if (operation == SMIME_SIGN) { 482e71b7053SJung-uk Kim if (keyfile == NULL) 4833b4e3dcbSSimon L. B. Nielsen keyfile = signerfile; 484e71b7053SJung-uk Kim } else { 4856f9291ceSJung-uk Kim keyfile = NULL; 486e71b7053SJung-uk Kim } 487f579bf8eSKris Kennaway 488e71b7053SJung-uk Kim if (keyfile != NULL) { 489b077aed3SPierre Pronchery key = load_key(keyfile, keyform, 0, passin, e, "signing key"); 490e71b7053SJung-uk Kim if (key == NULL) 491f579bf8eSKris Kennaway goto end; 492f579bf8eSKris Kennaway } 493f579bf8eSKris Kennaway 494e71b7053SJung-uk Kim in = bio_open_default(infile, 'r', informat); 495e71b7053SJung-uk Kim if (in == NULL) 496f579bf8eSKris Kennaway goto end; 497f579bf8eSKris Kennaway 4986f9291ceSJung-uk Kim if (operation & SMIME_IP) { 499b077aed3SPierre Pronchery PKCS7 *p7_in = NULL; 500b077aed3SPierre Pronchery 501b077aed3SPierre Pronchery p7 = PKCS7_new_ex(libctx, app_get0_propq()); 502b077aed3SPierre Pronchery if (p7 == NULL) { 503b077aed3SPierre Pronchery BIO_printf(bio_err, "Error allocating PKCS7 object\n"); 504b077aed3SPierre Pronchery goto end; 505b077aed3SPierre Pronchery } 506e71b7053SJung-uk Kim if (informat == FORMAT_SMIME) { 507b077aed3SPierre Pronchery p7_in = SMIME_read_PKCS7_ex(in, &indata, &p7); 508e71b7053SJung-uk Kim } else if (informat == FORMAT_PEM) { 509b077aed3SPierre Pronchery p7_in = PEM_read_bio_PKCS7(in, &p7, NULL, NULL); 510e71b7053SJung-uk Kim } else if (informat == FORMAT_ASN1) { 511b077aed3SPierre Pronchery p7_in = d2i_PKCS7_bio(in, &p7); 512e71b7053SJung-uk Kim } else { 513ddd58736SKris Kennaway BIO_printf(bio_err, "Bad input format for PKCS#7 file\n"); 514ddd58736SKris Kennaway goto end; 515ddd58736SKris Kennaway } 516ddd58736SKris Kennaway 517b077aed3SPierre Pronchery if (p7_in == NULL) { 518f579bf8eSKris Kennaway BIO_printf(bio_err, "Error reading S/MIME message\n"); 519f579bf8eSKris Kennaway goto end; 520f579bf8eSKris Kennaway } 521e71b7053SJung-uk Kim if (contfile != NULL) { 522ddd58736SKris Kennaway BIO_free(indata); 523e71b7053SJung-uk Kim if ((indata = BIO_new_file(contfile, "rb")) == NULL) { 524ddd58736SKris Kennaway BIO_printf(bio_err, "Can't read content file %s\n", contfile); 525ddd58736SKris Kennaway goto end; 526ddd58736SKris Kennaway } 527ddd58736SKris Kennaway } 528f579bf8eSKris Kennaway } 529f579bf8eSKris Kennaway 530e71b7053SJung-uk Kim out = bio_open_default(outfile, 'w', outformat); 531e71b7053SJung-uk Kim if (out == NULL) 5321f13597dSJung-uk Kim goto end; 5331f13597dSJung-uk Kim 5346f9291ceSJung-uk Kim if (operation == SMIME_VERIFY) { 535b077aed3SPierre Pronchery if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath, 536b077aed3SPierre Pronchery CAstore, noCAstore)) == NULL) 5371f13597dSJung-uk Kim goto end; 5381f13597dSJung-uk Kim X509_STORE_set_verify_cb(store, smime_cb); 539e71b7053SJung-uk Kim if (vpmtouched) 5401f13597dSJung-uk Kim X509_STORE_set1_param(store, vpm); 5411f13597dSJung-uk Kim } 5421f13597dSJung-uk Kim 5431f13597dSJung-uk Kim ret = 3; 5441f13597dSJung-uk Kim 5456f9291ceSJung-uk Kim if (operation == SMIME_ENCRYPT) { 5461f13597dSJung-uk Kim if (indef) 5471f13597dSJung-uk Kim flags |= PKCS7_STREAM; 548b077aed3SPierre Pronchery p7 = PKCS7_encrypt_ex(encerts, in, cipher, flags, libctx, app_get0_propq()); 5496f9291ceSJung-uk Kim } else if (operation & SMIME_SIGNERS) { 5501f13597dSJung-uk Kim int i; 5516f9291ceSJung-uk Kim /* 5526f9291ceSJung-uk Kim * If detached data content we only enable streaming if S/MIME output 5536f9291ceSJung-uk Kim * format. 5541f13597dSJung-uk Kim */ 5556f9291ceSJung-uk Kim if (operation == SMIME_SIGN) { 5566f9291ceSJung-uk Kim if (flags & PKCS7_DETACHED) { 5571f13597dSJung-uk Kim if (outformat == FORMAT_SMIME) 5581f13597dSJung-uk Kim flags |= PKCS7_STREAM; 559e71b7053SJung-uk Kim } else if (indef) { 5601f13597dSJung-uk Kim flags |= PKCS7_STREAM; 561e71b7053SJung-uk Kim } 5621f13597dSJung-uk Kim flags |= PKCS7_PARTIAL; 563b077aed3SPierre Pronchery p7 = PKCS7_sign_ex(NULL, NULL, other, in, flags, libctx, app_get0_propq()); 564e71b7053SJung-uk Kim if (p7 == NULL) 5651f13597dSJung-uk Kim goto end; 5667bded2dbSJung-uk Kim if (flags & PKCS7_NOCERTS) { 5677bded2dbSJung-uk Kim for (i = 0; i < sk_X509_num(other); i++) { 5687bded2dbSJung-uk Kim X509 *x = sk_X509_value(other, i); 5697bded2dbSJung-uk Kim PKCS7_add_certificate(p7, x); 5707bded2dbSJung-uk Kim } 5717bded2dbSJung-uk Kim } 572e71b7053SJung-uk Kim } else { 5731f13597dSJung-uk Kim flags |= PKCS7_REUSE_DIGEST; 574e71b7053SJung-uk Kim } 5756f9291ceSJung-uk Kim for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) { 5761f13597dSJung-uk Kim signerfile = sk_OPENSSL_STRING_value(sksigners, i); 5771f13597dSJung-uk Kim keyfile = sk_OPENSSL_STRING_value(skkeys, i); 578b077aed3SPierre Pronchery signer = load_cert(signerfile, FORMAT_UNDEF, "signer certificate"); 579e71b7053SJung-uk Kim if (signer == NULL) 5801f13597dSJung-uk Kim goto end; 581b077aed3SPierre Pronchery key = load_key(keyfile, keyform, 0, passin, e, "signing key"); 582e71b7053SJung-uk Kim if (key == NULL) 5831f13597dSJung-uk Kim goto end; 584b077aed3SPierre Pronchery 5856f9291ceSJung-uk Kim if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags)) 5861f13597dSJung-uk Kim goto end; 5871f13597dSJung-uk Kim X509_free(signer); 5881f13597dSJung-uk Kim signer = NULL; 5891f13597dSJung-uk Kim EVP_PKEY_free(key); 5901f13597dSJung-uk Kim key = NULL; 5911f13597dSJung-uk Kim } 5921f13597dSJung-uk Kim /* If not streaming or resigning finalize structure */ 5936f9291ceSJung-uk Kim if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) { 5941f13597dSJung-uk Kim if (!PKCS7_final(p7, in, flags)) 5951f13597dSJung-uk Kim goto end; 5961f13597dSJung-uk Kim } 5971f13597dSJung-uk Kim } 5981f13597dSJung-uk Kim 599e71b7053SJung-uk Kim if (p7 == NULL) { 600f579bf8eSKris Kennaway BIO_printf(bio_err, "Error creating PKCS#7 structure\n"); 601f579bf8eSKris Kennaway goto end; 602f579bf8eSKris Kennaway } 603f579bf8eSKris Kennaway 604f579bf8eSKris Kennaway ret = 4; 6056f9291ceSJung-uk Kim if (operation == SMIME_DECRYPT) { 6066f9291ceSJung-uk Kim if (!PKCS7_decrypt(p7, key, recip, out, flags)) { 607f579bf8eSKris Kennaway BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n"); 608f579bf8eSKris Kennaway goto end; 609f579bf8eSKris Kennaway } 6106f9291ceSJung-uk Kim } else if (operation == SMIME_VERIFY) { 611f579bf8eSKris Kennaway STACK_OF(X509) *signers; 6123b4e3dcbSSimon L. B. Nielsen if (PKCS7_verify(p7, other, store, indata, out, flags)) 613c1803d78SJacques Vidrine BIO_printf(bio_err, "Verification successful\n"); 6146f9291ceSJung-uk Kim else { 615c1803d78SJacques Vidrine BIO_printf(bio_err, "Verification failure\n"); 616f579bf8eSKris Kennaway goto end; 617f579bf8eSKris Kennaway } 618f579bf8eSKris Kennaway signers = PKCS7_get0_signers(p7, other, flags); 6196f9291ceSJung-uk Kim if (!save_certs(signerfile, signers)) { 6206f9291ceSJung-uk Kim BIO_printf(bio_err, "Error writing signers to %s\n", signerfile); 621f579bf8eSKris Kennaway ret = 5; 622f579bf8eSKris Kennaway goto end; 623f579bf8eSKris Kennaway } 624f579bf8eSKris Kennaway sk_X509_free(signers); 625e71b7053SJung-uk Kim } else if (operation == SMIME_PK7OUT) { 626f579bf8eSKris Kennaway PEM_write_bio_PKCS7(out, p7); 627e71b7053SJung-uk Kim } else { 6283b4e3dcbSSimon L. B. Nielsen if (to) 629e71b7053SJung-uk Kim BIO_printf(out, "To: %s%s", to, mime_eol); 6303b4e3dcbSSimon L. B. Nielsen if (from) 631e71b7053SJung-uk Kim BIO_printf(out, "From: %s%s", from, mime_eol); 6323b4e3dcbSSimon L. B. Nielsen if (subject) 633e71b7053SJung-uk Kim BIO_printf(out, "Subject: %s%s", subject, mime_eol); 6346f9291ceSJung-uk Kim if (outformat == FORMAT_SMIME) { 6351f13597dSJung-uk Kim if (operation == SMIME_RESIGN) 636e71b7053SJung-uk Kim rv = SMIME_write_PKCS7(out, p7, indata, flags); 6371f13597dSJung-uk Kim else 638e71b7053SJung-uk Kim rv = SMIME_write_PKCS7(out, p7, in, flags); 639e71b7053SJung-uk Kim } else if (outformat == FORMAT_PEM) { 640e71b7053SJung-uk Kim rv = PEM_write_bio_PKCS7_stream(out, p7, in, flags); 641e71b7053SJung-uk Kim } else if (outformat == FORMAT_ASN1) { 642e71b7053SJung-uk Kim rv = i2d_PKCS7_bio_stream(out, p7, in, flags); 643e71b7053SJung-uk Kim } else { 644ddd58736SKris Kennaway BIO_printf(bio_err, "Bad output format for PKCS#7 file\n"); 645ddd58736SKris Kennaway goto end; 646ddd58736SKris Kennaway } 647e71b7053SJung-uk Kim if (rv == 0) { 648e71b7053SJung-uk Kim BIO_printf(bio_err, "Error writing output\n"); 649e71b7053SJung-uk Kim ret = 3; 650e71b7053SJung-uk Kim goto end; 651e71b7053SJung-uk Kim } 652f579bf8eSKris Kennaway } 653f579bf8eSKris Kennaway ret = 0; 654f579bf8eSKris Kennaway end: 6556f9291ceSJung-uk Kim if (ret) 6566f9291ceSJung-uk Kim ERR_print_errors(bio_err); 657f579bf8eSKris Kennaway sk_X509_pop_free(encerts, X509_free); 658f579bf8eSKris Kennaway sk_X509_pop_free(other, X509_free); 6593b4e3dcbSSimon L. B. Nielsen X509_VERIFY_PARAM_free(vpm); 6601f13597dSJung-uk Kim sk_OPENSSL_STRING_free(sksigners); 6611f13597dSJung-uk Kim sk_OPENSSL_STRING_free(skkeys); 662f579bf8eSKris Kennaway X509_STORE_free(store); 663f579bf8eSKris Kennaway X509_free(cert); 664f579bf8eSKris Kennaway X509_free(recip); 665f579bf8eSKris Kennaway X509_free(signer); 666f579bf8eSKris Kennaway EVP_PKEY_free(key); 667b077aed3SPierre Pronchery EVP_MD_free(sign_md); 668b077aed3SPierre Pronchery EVP_CIPHER_free(cipher); 669f579bf8eSKris Kennaway PKCS7_free(p7); 6706cf8931aSJung-uk Kim release_engine(e); 671f579bf8eSKris Kennaway BIO_free(in); 672f579bf8eSKris Kennaway BIO_free(indata); 673ddd58736SKris Kennaway BIO_free_all(out); 6746f9291ceSJung-uk Kim OPENSSL_free(passin); 675b077aed3SPierre Pronchery NCONF_free(conf); 676e71b7053SJung-uk Kim return ret; 677f579bf8eSKris Kennaway } 678f579bf8eSKris Kennaway 679f579bf8eSKris Kennaway static int save_certs(char *signerfile, STACK_OF(X509) *signers) 680f579bf8eSKris Kennaway { 681f579bf8eSKris Kennaway int i; 682f579bf8eSKris Kennaway BIO *tmp; 683e71b7053SJung-uk Kim 684e71b7053SJung-uk Kim if (signerfile == NULL) 6853b4e3dcbSSimon L. B. Nielsen return 1; 686f579bf8eSKris Kennaway tmp = BIO_new_file(signerfile, "w"); 687e71b7053SJung-uk Kim if (tmp == NULL) 6886f9291ceSJung-uk Kim return 0; 689f579bf8eSKris Kennaway for (i = 0; i < sk_X509_num(signers); i++) 690f579bf8eSKris Kennaway PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); 691f579bf8eSKris Kennaway BIO_free(tmp); 692f579bf8eSKris Kennaway return 1; 693f579bf8eSKris Kennaway } 694f579bf8eSKris Kennaway 6953b4e3dcbSSimon L. B. Nielsen /* Minimal callback just to output policy info (if any) */ 6963b4e3dcbSSimon L. B. Nielsen 6973b4e3dcbSSimon L. B. Nielsen static int smime_cb(int ok, X509_STORE_CTX *ctx) 6983b4e3dcbSSimon L. B. Nielsen { 6993b4e3dcbSSimon L. B. Nielsen int error; 7003b4e3dcbSSimon L. B. Nielsen 7013b4e3dcbSSimon L. B. Nielsen error = X509_STORE_CTX_get_error(ctx); 7023b4e3dcbSSimon L. B. Nielsen 7033b4e3dcbSSimon L. B. Nielsen if ((error != X509_V_ERR_NO_EXPLICIT_POLICY) 7043b4e3dcbSSimon L. B. Nielsen && ((error != X509_V_OK) || (ok != 2))) 7053b4e3dcbSSimon L. B. Nielsen return ok; 7063b4e3dcbSSimon L. B. Nielsen 707e71b7053SJung-uk Kim policies_print(ctx); 7083b4e3dcbSSimon L. B. Nielsen 7093b4e3dcbSSimon L. B. Nielsen return ok; 7103b4e3dcbSSimon L. B. Nielsen } 711