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 + -
显示快捷键?