| File: | s/cmd/p7sign/p7sign.c | 
| Warning: | line 205, column 13 Although the value stored to 'status' is used in the enclosing expression, the value is never actually read from 'status'  | 
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* This Source Code Form is subject to the terms of the Mozilla Public | 
| 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this | 
| 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 
| 4 | |
| 5 | /* | 
| 6 | * p7sign -- A command to create a *detached* pkcs7 signature (over a given | 
| 7 | * input file). | 
| 8 | */ | 
| 9 | |
| 10 | #include "nspr.h" | 
| 11 | #include "plgetopt.h" | 
| 12 | #include "secutil.h" | 
| 13 | #include "secpkcs7.h" | 
| 14 | #include "cert.h" | 
| 15 | #include "certdb.h" | 
| 16 | #include "sechash.h" /* for HASH_GetHashObject() */ | 
| 17 | #include "nss.h" | 
| 18 | #include "pk11func.h" | 
| 19 | |
| 20 | #if defined(XP_UNIX1) | 
| 21 | #include <unistd.h> | 
| 22 | #endif | 
| 23 | |
| 24 | #include <stdio.h> | 
| 25 | #include <string.h> | 
| 26 | |
| 27 | #if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4)) | 
| 28 | extern int fread(char *, size_t, size_t, FILE *); | 
| 29 | extern int fwrite(char *, size_t, size_t, FILE *); | 
| 30 | extern int fprintf(FILE *, char *, ...); | 
| 31 | #endif | 
| 32 | |
| 33 | static secuPWData pwdata = { PW_NONE, 0 }; | 
| 34 | |
| 35 | static void | 
| 36 | Usage(char *progName) | 
| 37 | { | 
| 38 | HASH_HashType hashAlg; | 
| 39 | |
| 40 | fprintf(stderrstderr, | 
| 41 | "Usage: %s -k keyname [-d keydir] [-i input] [-o output] [-e]\n", | 
| 42 | progName); | 
| 43 | fprintf(stderrstderr, | 
| 44 | " %*s [-p password|-f password file] [-a hash] [-u certusage]\n", | 
| 45 | (int)strlen(progName), ""); | 
| 46 | fprintf(stderrstderr, "%-20s Nickname of key to use for signature\n", | 
| 47 | "-k keyname"); | 
| 48 | fprintf(stderrstderr, "%-20s Key database directory (default is ~/.netscape)\n", | 
| 49 | "-d keydir"); | 
| 50 | fprintf(stderrstderr, "%-20s Define an input file to use (default is stdin)\n", | 
| 51 | "-i input"); | 
| 52 | fprintf(stderrstderr, "%-20s Define an output file to use (default is stdout)\n", | 
| 53 | "-o output"); | 
| 54 | fprintf(stderrstderr, "%-20s Encapsulate content in signature message\n", | 
| 55 | "-e"); | 
| 56 | fprintf(stderrstderr, "%-20s Password to the key databse\n", "-p password"); | 
| 57 | fprintf(stderrstderr, "%-20s File to read password from\n", "-f password file"); | 
| 58 | fprintf(stderrstderr, "%-20s Use case-insensitive hash algorithm (default: SHA-1)\n", | 
| 59 | "-a hash"); | 
| 60 | fprintf(stderrstderr, "%-25s ", ""); | 
| 61 | for (hashAlg = HASH_AlgNULL + 1; hashAlg != HASH_AlgTOTAL; ++hashAlg) | 
| 62 | fprintf(stderrstderr, "%s%s", hashAlg == HASH_AlgNULL + 1 ? "" : ", ", | 
| 63 | SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(HASH_GetHashOidTagByHashTypeHASH_GetHashOidTagByHashType_Util(hashAlg))->desc); | 
| 64 | fputc('\n', stderrstderr); | 
| 65 | fprintf(stderrstderr, "%-20s Sign for usage (default: certUsageEmailSigner)\n", | 
| 66 | "-u certusage"); | 
| 67 | fprintf(stderrstderr, "%-25s 0 - certUsageSSLClient\n", ""); | 
| 68 | fprintf(stderrstderr, "%-25s 1 - certUsageSSLServer\n", ""); | 
| 69 | fprintf(stderrstderr, "%-25s 2 - certUsageSSLServerWithStepUp\n", ""); | 
| 70 | fprintf(stderrstderr, "%-25s 3 - certUsageSSLCA\n", ""); | 
| 71 | fprintf(stderrstderr, "%-25s 4 - certUsageEmailSigner\n", ""); | 
| 72 | fprintf(stderrstderr, "%-25s 5 - certUsageEmailRecipient\n", ""); | 
| 73 | fprintf(stderrstderr, "%-25s 6 - certUsageObjectSigner\n", ""); | 
| 74 | fprintf(stderrstderr, "%-25s 7 - certUsageUserCertImport\n", ""); | 
| 75 | fprintf(stderrstderr, "%-25s 8 - certUsageVerifyCA\n", ""); | 
| 76 | fprintf(stderrstderr, "%-25s 9 - certUsageProtectedObjectSigner\n", ""); | 
| 77 | fprintf(stderrstderr, "%-25s 10 - certUsageStatusResponder\n", ""); | 
| 78 | fprintf(stderrstderr, "%-25s 11 - certUsageAnyCA\n", ""); | 
| 79 | fprintf(stderrstderr, "%-25s 12 - certUsageIPsec\n", ""); | 
| 80 | exit(-1); | 
| 81 | } | 
| 82 | |
| 83 | static void | 
| 84 | SignOut(void *arg, const char *buf, unsigned long len) | 
| 85 | { | 
| 86 | FILE *out; | 
| 87 | |
| 88 | out = (FILE *)arg; | 
| 89 | fwrite(buf, len, 1, out); | 
| 90 | } | 
| 91 | |
| 92 | static int | 
| 93 | CreateDigest(SECItem *data, char *digestdata, unsigned int *len, | 
| 94 | unsigned int maxlen, HASH_HashType hashAlg) | 
| 95 | { | 
| 96 | const SECHashObject *hashObj; | 
| 97 | void *hashcx; | 
| 98 | |
| 99 | hashObj = HASH_GetHashObject(hashAlg); | 
| 100 | |
| 101 | hashcx = (*hashObj->create)(); | 
| 102 | if (hashcx == NULL((void*)0)) | 
| 103 | return -1; | 
| 104 | |
| 105 | (*hashObj->begin)(hashcx); | 
| 106 | (*hashObj->update)(hashcx, data->data, data->len); | 
| 107 | (*hashObj->end)(hashcx, (unsigned char *)digestdata, len, maxlen); | 
| 108 | (*hashObj->destroy)(hashcx, PR_TRUE1); | 
| 109 | return 0; | 
| 110 | } | 
| 111 | |
| 112 | static int | 
| 113 | SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert, | 
| 114 | PRBool encapsulated, HASH_HashType hashAlg, SECOidTag hashAlgOid, | 
| 115 | SECCertUsage usage) | 
| 116 | { | 
| 117 | char digestdata[HASH_LENGTH_MAX64]; | 
| 118 | unsigned int len; | 
| 119 | SECItem digest, data2sign; | 
| 120 | SEC_PKCS7ContentInfo *cinfo; | 
| 121 | SECStatus rv; | 
| 122 | |
| 123 | if (outFile == NULL((void*)0) || inFile == NULL((void*)0) || cert == NULL((void*)0)) | 
| 124 | return -1; | 
| 125 | |
| 126 | /* suck the file in */ | 
| 127 | if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE0, | 
| 128 | PR_FALSE0) != SECSuccess) | 
| 129 | return -1; | 
| 130 | |
| 131 | if (!encapsulated) { | 
| 132 | /* unfortunately, we must create the digest ourselves */ | 
| 133 | /* SEC_PKCS7CreateSignedData should have a flag to not include */ | 
| 134 | /* the content for non-encapsulated content at encode time, but */ | 
| 135 | /* should always compute the hash itself */ | 
| 136 | if (CreateDigest(&data2sign, digestdata, &len, | 
| 137 | sizeof(digestdata), hashAlg) < 0) { | 
| 138 | SECITEM_FreeItemSECITEM_FreeItem_Util(&data2sign, PR_FALSE0); | 
| 139 | return -1; | 
| 140 | } | 
| 141 | digest.data = (unsigned char *)digestdata; | 
| 142 | digest.len = len; | 
| 143 | } | 
| 144 | |
| 145 | cinfo = SEC_PKCS7CreateSignedData(cert, usage, NULL((void*)0), | 
| 146 | hashAlgOid, | 
| 147 | encapsulated ? NULL((void*)0) : &digest, | 
| 148 | NULL((void*)0), NULL((void*)0)); | 
| 149 | if (cinfo == NULL((void*)0)) { | 
| 150 | SECITEM_FreeItemSECITEM_FreeItem_Util(&data2sign, PR_FALSE0); | 
| 151 | return -1; | 
| 152 | } | 
| 153 | |
| 154 | if (encapsulated) { | 
| 155 | SEC_PKCS7SetContent(cinfo, (char *)data2sign.data, data2sign.len); | 
| 156 | } | 
| 157 | |
| 158 | rv = SEC_PKCS7IncludeCertChain(cinfo, NULL((void*)0)); | 
| 159 | if (rv != SECSuccess) { | 
| 160 | SEC_PKCS7DestroyContentInfo(cinfo); | 
| 161 | SECITEM_FreeItemSECITEM_FreeItem_Util(&data2sign, PR_FALSE0); | 
| 162 | return -1; | 
| 163 | } | 
| 164 | |
| 165 | rv = SEC_PKCS7Encode(cinfo, SignOut, outFile, NULL((void*)0), | 
| 166 | NULL((void*)0), &pwdata); | 
| 167 | |
| 168 | SECITEM_FreeItemSECITEM_FreeItem_Util(&data2sign, PR_FALSE0); | 
| 169 | SEC_PKCS7DestroyContentInfo(cinfo); | 
| 170 | |
| 171 | if (rv != SECSuccess) | 
| 172 | return -1; | 
| 173 | |
| 174 | return 0; | 
| 175 | } | 
| 176 | |
| 177 | int | 
| 178 | main(int argc, char **argv) | 
| 179 | { | 
| 180 | char *progName; | 
| 181 | FILE *outFile; | 
| 182 | PRFileDesc *inFile; | 
| 183 | char *keyName = NULL((void*)0); | 
| 184 | CERTCertDBHandle *certHandle; | 
| 185 | CERTCertificate *cert = NULL((void*)0); | 
| 186 | PRBool encapsulated = PR_FALSE0; | 
| 187 | HASH_HashType hashAlg = HASH_AlgSHA1; | 
| 188 | SECOidTag hashAlgOid = SEC_OID_SHA1; | 
| 189 | SECCertUsage usage = certUsageEmailSigner; | 
| 190 | PLOptState *optstate; | 
| 191 | PLOptStatus status; | 
| 192 | SECStatus rv; | 
| 193 | |
| 194 | progName = strrchr(argv[0], '/'); | 
| 195 | progName = progName ? progName + 1 : argv[0]; | 
| 196 | |
| 197 | inFile = NULL((void*)0); | 
| 198 | outFile = NULL((void*)0); | 
| 199 | keyName = NULL((void*)0); | 
| 200 | |
| 201 | /* | 
| 202 | * Parse command line arguments | 
| 203 | */ | 
| 204 | optstate = PL_CreateOptState(argc, argv, "ed:k:i:o:p:f:a:u:"); | 
| 205 | while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { | 
Although the value stored to 'status' is used in the enclosing expression, the value is never actually read from 'status'  | |
| 206 | switch (optstate->option) { | 
| 207 | case '?': | 
| 208 | Usage(progName); | 
| 209 | break; | 
| 210 | |
| 211 | case 'e': | 
| 212 | /* create a message with the signed content encapsulated */ | 
| 213 | encapsulated = PR_TRUE1; | 
| 214 | break; | 
| 215 | |
| 216 | case 'd': | 
| 217 | SECU_ConfigDirectory(optstate->value); | 
| 218 | break; | 
| 219 | |
| 220 | case 'i': | 
| 221 | inFile = PR_Open(optstate->value, PR_RDONLY0x01, 0); | 
| 222 | if (!inFile) { | 
| 223 | fprintf(stderrstderr, "%s: unable to open \"%s\" for reading\n", | 
| 224 | progName, optstate->value); | 
| 225 | return -1; | 
| 226 | } | 
| 227 | break; | 
| 228 | |
| 229 | case 'k': | 
| 230 | keyName = strdup(optstate->value); | 
| 231 | break; | 
| 232 | |
| 233 | case 'o': | 
| 234 | outFile = fopen(optstate->value, "wb"); | 
| 235 | if (!outFile) { | 
| 236 | fprintf(stderrstderr, "%s: unable to open \"%s\" for writing\n", | 
| 237 | progName, optstate->value); | 
| 238 | return -1; | 
| 239 | } | 
| 240 | break; | 
| 241 | case 'p': | 
| 242 | pwdata.source = PW_PLAINTEXT; | 
| 243 | pwdata.data = strdup(optstate->value); | 
| 244 | break; | 
| 245 | |
| 246 | case 'f': | 
| 247 | pwdata.source = PW_FROMFILE; | 
| 248 | pwdata.data = PORT_StrdupPORT_Strdup_Util(optstate->value); | 
| 249 | break; | 
| 250 | |
| 251 | case 'a': | 
| 252 | for (hashAlg = HASH_AlgNULL + 1; hashAlg != HASH_AlgTOTAL; | 
| 253 | ++hashAlg) { | 
| 254 | hashAlgOid = HASH_GetHashOidTagByHashTypeHASH_GetHashOidTagByHashType_Util(hashAlg); | 
| 255 | if (!PORT_StrcasecmpPL_strcasecmp(optstate->value, | 
| 256 | SECOID_FindOIDByTagSECOID_FindOIDByTag_Util(hashAlgOid)->desc)) | 
| 257 | break; | 
| 258 | } | 
| 259 | if (hashAlg == HASH_AlgTOTAL) | 
| 260 | Usage(progName); | 
| 261 | break; | 
| 262 | |
| 263 | case 'u': | 
| 264 | usage = atoi(optstate->value); | 
| 265 | if (usage < certUsageSSLClient || usage > certUsageIPsec) | 
| 266 | Usage(progName); | 
| 267 | break; | 
| 268 | } | 
| 269 | } | 
| 270 | PL_DestroyOptState(optstate); | 
| 271 | |
| 272 | if (!keyName) | 
| 273 | Usage(progName); | 
| 274 | |
| 275 | if (!inFile) | 
| 276 | inFile = PR_STDINPR_GetSpecialFD(PR_StandardInput); | 
| 277 | if (!outFile) | 
| 278 | outFile = stdoutstdout; | 
| 279 | |
| 280 | /* Call the initialization routines */ | 
| 281 | PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); | 
| 282 | rv = NSS_Init(SECU_ConfigDirectory(NULL((void*)0))); | 
| 283 | if (rv != SECSuccess) { | 
| 284 | SECU_PrintPRandOSError(progName); | 
| 285 | goto loser; | 
| 286 | } | 
| 287 | |
| 288 | PK11_SetPasswordFunc(SECU_GetModulePassword); | 
| 289 | |
| 290 | /* open cert database */ | 
| 291 | certHandle = CERT_GetDefaultCertDB(); | 
| 292 | if (certHandle == NULL((void*)0)) { | 
| 293 | rv = SECFailure; | 
| 294 | goto loser; | 
| 295 | } | 
| 296 | |
| 297 | /* find cert */ | 
| 298 | cert = SECU_FindCertByNicknameOrFilename(certHandle, keyName, PR_FALSE0, NULL((void*)0)); | 
| 299 | if (cert == NULL((void*)0)) { | 
| 300 | SECU_PrintError(progName, | 
| 301 | "the corresponding cert for key \"%s\" does not exist", | 
| 302 | keyName); | 
| 303 | rv = SECFailure; | 
| 304 | goto loser; | 
| 305 | } | 
| 306 | |
| 307 | if (SignFile(outFile, inFile, cert, encapsulated, | 
| 308 | hashAlg, hashAlgOid, usage)) { | 
| 309 | SECU_PrintError(progName, "problem signing data"); | 
| 310 | rv = SECFailure; | 
| 311 | goto loser; | 
| 312 | } | 
| 313 | |
| 314 | loser: | 
| 315 | if (pwdata.data) { | 
| 316 | PORT_FreePORT_Free_Util(pwdata.data); | 
| 317 | } | 
| 318 | if (keyName) { | 
| 319 | PORT_FreePORT_Free_Util(keyName); | 
| 320 | } | 
| 321 | if (cert) { | 
| 322 | CERT_DestroyCertificate(cert); | 
| 323 | } | 
| 324 | if (inFile && inFile != PR_STDINPR_GetSpecialFD(PR_StandardInput)) { | 
| 325 | PR_Close(inFile); | 
| 326 | } | 
| 327 | if (outFile && outFile != stdoutstdout) { | 
| 328 | fclose(outFile); | 
| 329 | } | 
| 330 | if (NSS_Shutdown() != SECSuccess) { | 
| 331 | SECU_PrintError(progName, "NSS shutdown:"); | 
| 332 | exit(1); | 
| 333 | } | 
| 334 | |
| 335 | return (rv != SECSuccess); | 
| 336 | } |