cmsutil.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,277 行 · 第 1/3 页
C
1,277 行
intmain(int argc, char **argv){ FILE *outFile; NSSCMSMessage *cmsg; PRFileDesc *inFile; PLOptState *optstate; PLOptStatus status; Mode mode = UNKNOWN; PK11PasswordFunc pwcb; void *pwcb_arg; struct decodeOptionsStr decodeOptions = { 0 }; struct signOptionsStr signOptions = { 0 }; struct envelopeOptionsStr envelopeOptions = { 0 }; struct certsonlyOptionsStr certsonlyOptions = { 0 }; struct encryptOptionsStr encryptOptions = { 0 }; struct optionsStr options = { 0 }; int exitstatus; static char *ptrarray[128] = { 0 }; int nrecipients = 0; char *str, *tok; char *envFileName; SECItem input = { 0, 0, 0}; SECItem output = { 0, 0, 0}; SECItem dummy = { 0, 0, 0 }; SECItem envmsg = { 0, 0, 0 }; SECStatus rv; progName = strrchr(argv[0], '/'); progName = progName ? progName+1 : argv[0]; inFile = PR_STDIN; outFile = stdout; envFileName = NULL; mode = UNKNOWN; decodeOptions.contentFile = NULL; decodeOptions.suppressContent = PR_FALSE; decodeOptions.headerLevel = -1; options.certUsage = certUsageEmailSigner; options.password = NULL; signOptions.nickname = NULL; signOptions.detached = PR_FALSE; signOptions.signingTime = PR_FALSE; signOptions.smimeProfile = PR_FALSE; signOptions.encryptionKeyPreferenceNick = NULL; envelopeOptions.recipients = NULL; encryptOptions.recipients = NULL; encryptOptions.envmsg = NULL; encryptOptions.envFile = NULL; encryptOptions.bulkalgtag = SEC_OID_UNKNOWN; encryptOptions.bulkkey = NULL; encryptOptions.keysize = -1; /* * Parse command line arguments */ optstate = PL_CreateOptState(argc, argv, "CDSEOnN:TGPY:h:p:i:c:d:e:o:s:u:r:"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case '?': Usage(progName); break; case 'C': mode = ENCRYPT; break; case 'D': mode = DECODE; break; case 'S': mode = SIGN; break; case 'E': mode = ENVELOPE; break; case 'O': mode = CERTSONLY; break; case 'n': if (mode != DECODE) { fprintf(stderr, "%s: option -n only supported with option -D.\n", progName); Usage(progName); exit(1); } decodeOptions.suppressContent = PR_TRUE; break; case 'N': if (mode != SIGN) { fprintf(stderr, "%s: option -N only supported with option -S.\n", progName); Usage(progName); exit(1); } signOptions.nickname = strdup(optstate->value); break; case 'Y': if (mode != SIGN) { fprintf(stderr, "%s: option -Y only supported with option -S.\n", progName); Usage(progName); exit(1); } signOptions.encryptionKeyPreferenceNick = strdup(optstate->value); break; case 'T': if (mode != SIGN) { fprintf(stderr, "%s: option -T only supported with option -S.\n", progName); Usage(progName); exit(1); } signOptions.detached = PR_TRUE; break; case 'G': if (mode != SIGN) { fprintf(stderr, "%s: option -G only supported with option -S.\n", progName); Usage(progName); exit(1); } signOptions.signingTime = PR_TRUE; break; case 'P': if (mode != SIGN) { fprintf(stderr, "%s: option -P only supported with option -S.\n", progName); Usage(progName); exit(1); } signOptions.smimeProfile = PR_TRUE; break; case 'h': if (mode != DECODE) { fprintf(stderr, "%s: option -h only supported with option -D.\n", progName); Usage(progName); exit(1); } decodeOptions.headerLevel = atoi(optstate->value); if (decodeOptions.headerLevel < 0) { fprintf(stderr, "option -h cannot have a negative value.\n"); exit(1); } break; case 'p': if (!optstate->value) { fprintf(stderr, "%s: option -p must have a value.\n", progName); Usage(progName); exit(1); } options.password = strdup(optstate->value); break; case 'i': inFile = PR_Open(optstate->value, PR_RDONLY, 00660); if (inFile == NULL) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, optstate->value); exit(1); } SECU_FileToItem(&input, inFile); PR_Close(inFile); break; case 'c': if (mode != DECODE) { fprintf(stderr, "%s: option -c only supported with option -D.\n", progName); Usage(progName); exit(1); } if ((decodeOptions.contentFile = PR_Open(optstate->value, PR_RDONLY, 006600)) == NULL) { fprintf(stderr, "%s: unable to open \"%s\" for reading.\n", progName, optstate->value); exit(1); } break; case 'o':#if 0 if (mode == DECODE) { outFile = fopen(optstate->value, "w"); } else { outFile = fopen(optstate->value, "wb"); }#endif outFile = fopen(optstate->value, "wb"); if (outFile == NULL) { fprintf(stderr, "%s: unable to open \"%s\" for writing\n", progName, optstate->value); exit(1); } break; case 'r': if (!optstate->value) { fprintf(stderr, "%s: option -r must have a value.\n", progName); Usage(progName); exit(1); }#if 0 fprintf(stderr, "recipient = %s\n", optstate->value);#endif envelopeOptions.recipients = ptrarray; str = optstate->value; do { tok = strchr(str, ','); if (tok) *tok = '\0'; envelopeOptions.recipients[nrecipients++] = strdup(str); if (tok) str = tok + 1; } while (tok); envelopeOptions.recipients[nrecipients] = NULL; encryptOptions.recipients = envelopeOptions.recipients; certsonlyOptions.recipients = envelopeOptions.recipients; break; case 'd': SECU_ConfigDirectory(optstate->value); break; case 'e': envFileName = strdup(optstate->value); encryptOptions.envFile = PR_Open(envFileName, PR_RDONLY, 00660); break; case 'u': { int usageType; usageType = atoi (strdup(optstate->value)); if (usageType < certUsageSSLClient || usageType > certUsageAnyCA) return -1; options.certUsage = (SECCertUsage)usageType; break; } } } /* Call the libsec initialization routines */ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL)); if (SECSuccess != rv) { SECU_PrintError(progName, "NSS_Init failed"); exit(1); } options.certHandle = CERT_GetDefaultCertDB(); if (!options.certHandle) { SECU_PrintError(progName, "No default cert DB"); exit(1); }#if defined(WIN32) /*if (outFile == stdout && mode != DECODE) {*/ if (outFile == stdout) { /* If we're going to write binary data to stdout, we must put stdout ** into O_BINARY mode or else outgoing \n's will become \r\n's. */ int smrv = _setmode(_fileno(stdout), _O_BINARY); if (smrv == -1) { fprintf(stderr, "%s: Cannot change stdout to binary mode. Use -o option instead.\n", progName); return smrv; } }#endif exitstatus = 0; switch (mode) { case DECODE: decodeOptions.options = &options; if (encryptOptions.envFile) { /* Decoding encrypted-data, so get the bulkkey from an * enveloped-data message. */ SECU_FileToItem(&envmsg, encryptOptions.envFile); decodeOptions.options = &options; encryptOptions.envmsg = decode(NULL, &dummy, &envmsg, decodeOptions); rv = get_enc_params(&encryptOptions); decodeOptions.dkcb = dkcb; decodeOptions.bulkkey = encryptOptions.bulkkey; } cmsg = decode(outFile, &output, &input, decodeOptions); if (!cmsg) { SECU_PrintError(progName, "problem decoding"); exitstatus = 1; } fwrite(output.data, output.len, 1, outFile); break; case SIGN: signOptions.options = &options; cmsg = signed_data(signOptions); if (!cmsg) { SECU_PrintError(progName, "problem signing"); exitstatus = 1; } break; case ENCRYPT: if (!envFileName) { fprintf(stderr, "%s: you must specify an envelope file with -e.\n", progName); exit(1); } encryptOptions.options = &options; encryptOptions.input = &input; encryptOptions.outfile = outFile; if (!encryptOptions.envFile) { encryptOptions.envFile = PR_Open(envFileName, PR_WRONLY|PR_CREATE_FILE, 00660); if (!encryptOptions.envFile) { fprintf(stderr, "%s: failed to create file %s.\n", progName, envFileName); exit(1); } } else { SECU_FileToItem(&envmsg, encryptOptions.envFile); decodeOptions.options = &options; encryptOptions.envmsg = decode(NULL, &dummy, &envmsg, decodeOptions); } /* decode an enveloped-data message to get the bulkkey (create * a new one if neccessary) */ rv = get_enc_params(&encryptOptions); /* create the encrypted-data message */ cmsg = encrypted_data(encryptOptions); if (!cmsg) { SECU_PrintError(progName, "problem encrypting"); exitstatus = 1; } break; case ENVELOPE: envelopeOptions.options = &options;#if 0 if (!envelopeOptions.recipients) parse_message_for_recipients(myIn, &envelopeOptions);#endif cmsg = enveloped_data(envelopeOptions); if (!cmsg) { SECU_PrintError(progName, "problem enveloping"); exitstatus = 1; } break; case CERTSONLY: certsonlyOptions.options = &options; cmsg = signed_data_certsonly(certsonlyOptions); if (!cmsg) { SECU_PrintError(progName, "problem with certs-only"); exitstatus = 1; } break; default: fprintf(stderr, "One of options -D, -S or -E must be set.\n"); Usage(progName); exitstatus = 1; } if (mode == SIGN || mode == ENVELOPE || mode == CERTSONLY) { PLArenaPool *arena = PORT_NewArena(1024); NSSCMSEncoderContext *ecx; SECItem output = { 0, 0, 0 }; if (!arena) { fprintf(stderr, "%s: out of memory.\n", progName); exit(1); } pwcb = (options.password != NULL) ? ownpw : NULL; pwcb_arg = (options.password != NULL) ? (void *)options.password : NULL; ecx = NSS_CMSEncoder_Start(cmsg, NULL, NULL, /* DER output callback */ &output, arena, /* destination storage */ pwcb, pwcb_arg, /* password callback */ NULL, NULL, /* decrypt key callback */ NULL, NULL ); /* detached digests */ if (!ecx) { fprintf(stderr, "%s: cannot create encoder context.\n", progName); exit(1); } if (input.len > 0) { /* skip if certs-only (or other zero content) */ rv = NSS_CMSEncoder_Update(ecx, input.data, input.len); if (rv) { fprintf(stderr, "%s: failed to add data to encoder.\n", progName); exit(1); } } rv = NSS_CMSEncoder_Finish(ecx); if (rv) { fprintf(stderr, "%s: failed to encode data.\n", progName); exit(1); } /*PR_Write(output.data, output.len);*/ fwrite(output.data, output.len, 1, outFile); PORT_FreeArena(arena, PR_FALSE); } if (cmsg) NSS_CMSMessage_Destroy(cmsg); if (outFile != stdout) fclose(outFile); if (decodeOptions.contentFile) PR_Close(decodeOptions.contentFile); exit(exitstatus);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?