| 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 | } |