Bug Summary

File:s/cmd/p7sign/p7sign.c
Warning:line 236, column 21
Potential leak of memory pointed to by 'keyName'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name p7sign.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/p7sign -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/p7sign -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -I ../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -I ../../../dist/public/seccmd -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c p7sign.c
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))
28extern int fread(char *, size_t, size_t, FILE *);
29extern int fwrite(char *, size_t, size_t, FILE *);
30extern int fprintf(FILE *, char *, ...);
31#endif
32
33static secuPWData pwdata = { PW_NONE, 0 };
34
35static void
36Usage(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
83static void
84SignOut(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
92static int
93CreateDigest(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
112static int
113SignFile(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
177int
178main(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];
1
Assuming 'progName' is non-null
2
'?' condition is true
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) {
3
Assuming the condition is true
4
Loop condition is true. Entering loop body
7
Execution continues on line 205
8
Assuming the condition is true
9
Loop condition is true. Entering loop body
206 switch (optstate->option) {
5
Control jumps to 'case 107:' at line 229
10
Control jumps to 'case 111:' at line 233
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);
6
Memory is allocated
231 break;
232
233 case 'o':
234 outFile = fopen(optstate->value, "wb");
235 if (!outFile) {
11
Assuming 'outFile' is null
12
Taking true branch
236 fprintf(stderrstderr, "%s: unable to open \"%s\" for writing\n",
13
Potential leak of memory pointed to by 'keyName'
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
314loser:
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}