%macro handling
[platform/upstream/rpm.git] / checksig.c
1 /* checksig.c: verify the signature of an RPM */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <string.h>
8
9 #include "checksig.h"
10 #include "rpmlib.h"
11 #include "rpmlead.h"
12 #include "signature.h"
13 #include "messages.h"
14
15 int doReSign(int add, char *passPhrase, char **argv)
16 {
17     int fd, ofd, count;
18     struct rpmlead lead;
19     unsigned short sigtype;
20     char *rpm, sigtarget[1024];
21     char tmprpm[1024];
22     unsigned char buffer[8192];
23     Header sig;
24     
25     while (*argv) {
26         rpm = *argv++;
27         printf("%s:\n", rpm);
28         if ((fd = open(rpm, O_RDONLY, 0644)) < 0) {
29             fprintf(stderr, "%s: Open failed\n", rpm);
30             exit(1);
31         }
32         if (readLead(fd, &lead)) {
33             fprintf(stderr, "%s: readLead failed\n", rpm);
34             exit(1);
35         }
36         if (lead.major == 1) {
37             fprintf(stderr, "%s: Can't sign v1.0 RPM\n", rpm);
38             exit(1);
39         }
40         if (lead.major == 2) {
41             fprintf(stderr, "%s: Can't re-sign v2.0 RPM\n", rpm);
42             exit(1);
43         }
44         if (rpmReadSignature(fd, &sig, lead.signature_type)) {
45             fprintf(stderr, "%s: rpmReadSignature failed\n", rpm);
46             exit(1);
47         }
48         if (add != ADD_SIGNATURE) {
49             rpmFreeSignature(sig);
50         }
51
52         /* Write the rest to a temp file */
53         strcpy(sigtarget, tempnam(rpmGetVar(RPMVAR_TMPPATH), "rpmsigtarget"));
54         ofd = open(sigtarget, O_WRONLY|O_CREAT|O_TRUNC, 0644);
55         while ((count = read(fd, buffer, sizeof(buffer))) > 0) {
56             if (count == -1) {
57                 perror("Couldn't read the header/archive");
58                 close(ofd);
59                 unlink(sigtarget);
60                 exit(1);
61             }
62             if (write(ofd, buffer, count) < 0) {
63                 perror("Couldn't write header/archive to temp file");
64                 close(ofd);
65                 unlink(sigtarget);
66                 exit(1);
67             }
68         }
69         close(fd);
70         close(ofd);
71
72         /* Start writing the new RPM */
73         sprintf(tmprpm, "%s.tmp", rpm);
74         ofd = open(tmprpm, O_WRONLY|O_CREAT|O_TRUNC, 0644);
75         lead.signature_type = RPMSIG_HEADERSIG;
76         if (writeLead(ofd, &lead)) {
77             perror("writeLead()");
78             close(ofd);
79             unlink(sigtarget);
80             unlink(tmprpm);
81             exit(1);
82         }
83
84         /* Generate the signature */
85         sigtype = rpmLookupSignatureType();
86         rpmMessage(RPMMESS_VERBOSE, "Generating signature: %d\n", sigtype);
87         if (add != ADD_SIGNATURE) {
88             sig = rpmNewSignature();
89             rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, passPhrase);
90             rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, passPhrase);
91         }
92         if (sigtype>0) {
93             rpmAddSignature(sig, sigtarget, sigtype, passPhrase);
94         }
95         if (rpmWriteSignature(ofd, sig)) {
96             close(ofd);
97             unlink(sigtarget);
98             unlink(tmprpm);
99             rpmFreeSignature(sig);
100             exit(1);
101         }
102         rpmFreeSignature(sig);
103
104         /* Append the header and archive */
105         fd = open(sigtarget, O_RDONLY);
106         while ((count = read(fd, buffer, sizeof(buffer))) > 0) {
107             if (count == -1) {
108                 perror("Couldn't read sigtarget");
109                 close(ofd);
110                 close(fd);
111                 unlink(sigtarget);
112                 unlink(tmprpm);
113                 exit(1);
114             }
115             if (write(ofd, buffer, count) < 0) {
116                 perror("Couldn't write package");
117                 close(ofd);
118                 close(fd);
119                 unlink(sigtarget);
120                 unlink(tmprpm);
121                 exit(1);
122             }
123         }
124         close(fd);
125         close(ofd);
126         unlink(sigtarget);
127
128         /* Move it in to place */
129         unlink(rpm);
130         rename(tmprpm, rpm);
131     }
132
133     return 0;
134 }
135
136 int doCheckSig(int flags, char **argv)
137 {
138     int fd, ofd, res, res2, res3, missingKeys;
139     struct rpmlead lead;
140     char *rpm;
141     char result[1024], sigtarget[1024];
142     unsigned char buffer[8192];
143     Header sig;
144     HeaderIterator sigIter;
145     int_32 tag, type, count;
146     void *ptr;
147
148     res = 0;
149     while (*argv) {
150         rpm = *argv++;
151         if ((fd = open(rpm, O_RDONLY, 0644)) < 0) {
152             fprintf(stderr, "%s: Open failed\n", rpm);
153             res++;
154             continue;
155         }
156         if (readLead(fd, &lead)) {
157             fprintf(stderr, "%s: readLead failed\n", rpm);
158             res++;
159             continue;
160         }
161         if (lead.major == 1) {
162             fprintf(stderr, "%s: No signature available (v1.0 RPM)\n", rpm);
163             res++;
164             continue;
165         }
166         if (rpmReadSignature(fd, &sig, lead.signature_type)) {
167             fprintf(stderr, "%s: rpmReadSignature failed\n", rpm);
168             res++;
169             continue;
170         }
171         if (! sig) {
172             fprintf(stderr, "%s: No signature available\n", rpm);
173             res++;
174             continue;
175         }
176         /* Write the rest to a temp file */
177         strcpy(sigtarget, tempnam(rpmGetVar(RPMVAR_TMPPATH), "rpmsigtarget"));
178         ofd = open(sigtarget, O_WRONLY|O_CREAT|O_TRUNC, 0644);
179         while ((count = read(fd, buffer, sizeof(buffer))) > 0) {
180             if (count == -1) {
181                 perror("Couldn't read the header/archive");
182                 close(ofd);
183                 unlink(sigtarget);
184                 exit(1);
185             }
186             if (write(ofd, buffer, count) < 0) {
187                 fprintf(stderr, "Unable to write %s", sigtarget);
188                 perror("");
189                 close(ofd);
190                 unlink(sigtarget);
191                 exit(1);
192             }
193         }
194         close(fd);
195         close(ofd);
196
197         sigIter = headerInitIterator(sig);
198         res2 = 0;
199         missingKeys = 0;
200         if (rpmIsVerbose()) {
201             sprintf(buffer, "%s:\n", rpm);
202         } else {
203             sprintf(buffer, "%s: ", rpm);
204         }
205         while (headerNextIterator(sigIter, &tag, &type, &ptr, &count)) {
206             if ((tag == RPMSIGTAG_PGP) && !(flags & CHECKSIG_PGP)) 
207                 continue;
208             else if ((tag == RPMSIGTAG_MD5 || 
209                       tag == RPMSIGTAG_LEMD5_2 ||
210                       tag == RPMSIGTAG_LEMD5_1) 
211                       && !(flags & CHECKSIG_MD5)) 
212                 continue;
213
214             if ((res3 = rpmVerifySignature(sigtarget, tag, ptr, count, 
215                                            result))) {
216                 if (rpmIsVerbose()) {
217                     strcat(buffer, result);
218                     res2 = 1;
219                 } else {
220                     switch (tag) {
221                       case RPMSIGTAG_SIZE:
222                         strcat(buffer, "SIZE ");
223                         res2 = 1;
224                         break;
225                       case RPMSIGTAG_MD5:
226                       case RPMSIGTAG_LEMD5_1:
227                       case RPMSIGTAG_LEMD5_2:
228                         strcat(buffer, "MD5 ");
229                         res2 = 1;
230                         break;
231                       case RPMSIGTAG_PGP:
232                         if (res3 == RPMSIG_NOKEY) {
233                             /* Do not consedier this a failure */
234                             strcat(buffer, "(PGP) ");
235                             missingKeys = 1;
236                         } else {
237                             strcat(buffer, "PGP ");
238                             res2 = 1;
239                         }
240                         break;
241                       default:
242                         strcat(buffer, "!!! ");
243                         res2 = 1;
244                     }
245                 }
246             } else {
247                 if (rpmIsVerbose()) {
248                     strcat(buffer, result);
249                 } else {
250                     switch (tag) {
251                       case RPMSIGTAG_SIZE:
252                         strcat(buffer, "size ");
253                         break;
254                       case RPMSIGTAG_MD5:
255                       case RPMSIGTAG_LEMD5_1:
256                       case RPMSIGTAG_LEMD5_2:
257                         strcat(buffer, "md5 ");
258                         break;
259                       case RPMSIGTAG_PGP:
260                         strcat(buffer, "pgp ");
261                         break;
262                       default:
263                         strcat(buffer, "??? ");
264                     }
265                 }
266             }
267         }
268         headerFreeIterator(sigIter);
269         res += res2;
270         unlink(sigtarget);
271
272         if (res2) {
273             if (rpmIsVerbose()) {
274                 fprintf(stderr, "%s", buffer);
275             } else {
276                 fprintf(stderr, "%sNOT OK%s\n", buffer,
277                         missingKeys ? " (MISSING KEYS)" : "");
278             }
279         } else {
280             if (rpmIsVerbose()) {
281                 printf("%s", buffer);
282             } else {
283                 printf("%sOK%s\n", buffer,
284                        missingKeys ? " (MISSING KEYS)" : "");
285             }
286         }
287     }
288
289     return res;
290 }