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 #include "signtool.h"
6 #include "pk11func.h"
7 #include "certdb.h"
8
9 static int num_trav_certs = 0;
10 static SECStatus cert_trav_callback(CERTCertificate *cert, SECItem *k,
11 void *data);
12
13 /*********************************************************************
14 *
15 * L i s t C e r t s
16 */
17 int
ListCerts(char * key,int list_certs)18 ListCerts(char *key, int list_certs)
19 {
20 int failed = 0;
21 SECStatus rv;
22 CERTCertDBHandle *db;
23
24 CERTCertificate *cert;
25 CERTVerifyLog errlog;
26
27 errlog.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
28 if (errlog.arena == NULL) {
29 out_of_memory();
30 }
31 errlog.head = NULL;
32 errlog.tail = NULL;
33 errlog.count = 0;
34
35 db = CERT_GetDefaultCertDB();
36
37 if (list_certs == 2) {
38 PR_fprintf(outputFD, "\nS Certificates\n");
39 PR_fprintf(outputFD, "- ------------\n");
40 } else {
41 PR_fprintf(outputFD, "\nObject signing certificates\n");
42 PR_fprintf(outputFD, "---------------------------------------\n");
43 }
44
45 num_trav_certs = 0;
46
47 /* Traverse ALL tokens in all slots, authenticating to them all */
48 rv = PK11_TraverseSlotCerts(cert_trav_callback, (void *)&list_certs,
49 &pwdata);
50
51 if (rv) {
52 PR_fprintf(outputFD, "**Traverse of ALL slots & tokens failed**\n");
53 return -1;
54 }
55
56 if (num_trav_certs == 0) {
57 PR_fprintf(outputFD,
58 "You don't appear to have any object signing certificates.\n");
59 }
60
61 if (list_certs == 2) {
62 PR_fprintf(outputFD, "- ------------\n");
63 } else {
64 PR_fprintf(outputFD, "---------------------------------------\n");
65 }
66
67 if (list_certs == 1) {
68 PR_fprintf(outputFD,
69 "For a list including CA's, use \"%s -L\"\n", PROGRAM_NAME);
70 }
71
72 if (list_certs == 2) {
73 PR_fprintf(outputFD,
74 "Certificates that can be used to sign objects have *'s to "
75 "their left.\n");
76 }
77
78 if (key) {
79 /* Do an analysis of the given cert */
80
81 cert = PK11_FindCertFromNickname(key, &pwdata);
82
83 if (cert) {
84 PR_fprintf(outputFD,
85 "\nThe certificate with nickname \"%s\" was found:\n",
86 cert->nickname);
87 PR_fprintf(outputFD, "\tsubject name: %s\n", cert->subjectName);
88 PR_fprintf(outputFD, "\tissuer name: %s\n", cert->issuerName);
89
90 PR_fprintf(outputFD, "\n");
91
92 rv = CERT_CertTimesValid(cert);
93 if (rv != SECSuccess) {
94 PR_fprintf(outputFD, "**This certificate is expired**\n");
95 } else {
96 PR_fprintf(outputFD, "This certificate is not expired.\n");
97 }
98
99 rv = CERT_VerifyCert(db, cert, PR_TRUE,
100 certUsageObjectSigner, PR_Now(), &pwdata, &errlog);
101
102 if (rv != SECSuccess) {
103 failed = 1;
104 if (errlog.count > 0) {
105 PR_fprintf(outputFD,
106 "**Certificate validation failed for the "
107 "following reason(s):**\n");
108 } else {
109 PR_fprintf(outputFD, "**Certificate validation failed**");
110 }
111 } else {
112 PR_fprintf(outputFD, "This certificate is valid.\n");
113 }
114 displayVerifyLog(&errlog);
115
116 } else {
117 failed = 1;
118 PR_fprintf(outputFD,
119 "The certificate with nickname \"%s\" was NOT FOUND\n", key);
120 }
121 }
122
123 if (errlog.arena != NULL) {
124 PORT_FreeArena(errlog.arena, PR_FALSE);
125 }
126
127 if (failed) {
128 return -1;
129 }
130 return 0;
131 }
132
133 /********************************************************************
134 *
135 * c e r t _ t r a v _ c a l l b a c k
136 */
137 static SECStatus
cert_trav_callback(CERTCertificate * cert,SECItem * k,void * data)138 cert_trav_callback(CERTCertificate *cert, SECItem *k, void *data)
139 {
140 int list_certs = 1;
141 char *name;
142
143 if (data) {
144 list_certs = *((int *)data);
145 }
146
147 #define LISTING_USER_SIGNING_CERTS (list_certs == 1)
148 #define LISTING_ALL_CERTS (list_certs == 2)
149
150 name = cert->nickname;
151 if (name) {
152 int isSigningCert;
153
154 isSigningCert = cert->nsCertType & NS_CERT_TYPE_OBJECT_SIGNING;
155 if (!isSigningCert && LISTING_USER_SIGNING_CERTS)
156 return (SECSuccess);
157
158 /* Display this name or email address */
159 num_trav_certs++;
160
161 if (LISTING_ALL_CERTS) {
162 PR_fprintf(outputFD, "%s ", isSigningCert ? "*" : " ");
163 }
164 PR_fprintf(outputFD, "%s\n", name);
165
166 if (LISTING_USER_SIGNING_CERTS) {
167 int rv = SECFailure;
168 if (rv) {
169 CERTCertificate *issuerCert;
170 issuerCert = CERT_FindCertIssuer(cert, PR_Now(),
171 certUsageObjectSigner);
172 if (issuerCert) {
173 if (issuerCert->nickname && issuerCert->nickname[0]) {
174 PR_fprintf(outputFD, " Issued by: %s\n",
175 issuerCert->nickname);
176 rv = SECSuccess;
177 }
178 CERT_DestroyCertificate(issuerCert);
179 }
180 }
181 if (rv && cert->issuerName && cert->issuerName[0]) {
182 PR_fprintf(outputFD, " Issued by: %s \n", cert->issuerName);
183 }
184 {
185 char *expires;
186 expires = DER_TimeChoiceDayToAscii(&cert->validity.notAfter);
187 if (expires) {
188 PR_fprintf(outputFD, " Expires: %s\n", expires);
189 PORT_Free(expires);
190 }
191 }
192
193 rv = CERT_VerifyCertNow(cert->dbhandle, cert,
194 PR_TRUE, certUsageObjectSigner, &pwdata);
195
196 if (rv != SECSuccess) {
197 rv = PORT_GetError();
198 PR_fprintf(outputFD,
199 " ++ Error ++ THIS CERTIFICATE IS NOT VALID (%s)\n",
200 secErrorString(rv));
201 }
202 }
203 }
204
205 return (SECSuccess);
206 }
207