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