Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / pkg_install / sign / sha1.c
1 /* $OpenBSD: sha1.c,v 1.1 1999/10/04 21:46:29 espie Exp $ */
2 /*-
3  * Copyright (c) 1999 Marc Espie.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Marc Espie for the OpenBSD
16  * Project.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS 
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
21  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OPENBSD
22  * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * $FreeBSD: src/usr.sbin/pkg_install/sign/sha1.c,v 1.1.2.3 2002/08/20 06:35:08 obrien Exp $
31  * $DragonFly: src/usr.sbin/pkg_install/sign/Attic/sha1.c,v 1.2 2003/06/17 04:29:59 dillon Exp $
32  */
33
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <assert.h>
39 #include <openssl/sha.h>
40 #include "stand.h"
41 #include "gzip.h"
42 #include "extern.h"
43
44 /* private context for sha1 signature checker */
45 struct sha1_checker {
46         SHA_CTX context;
47         const char *id;
48         const char *filename;
49 };
50
51
52 #define SHA1_TEMPLATE "SHA1 (%s) = "
53 #define BUFSIZE (MAXID+sizeof(SHA1_TEMPLATE)+2*SHA_DIGEST_LENGTH+1)
54
55 /*
56  * Finalize SHA1 checksum for our sha1_context into result 
57  * (size at least BUFSIZE).  Returns the length of the checksum
58  * marker, e.g.,   SHA1 (id) = xxxxxxxxx
59  *                             ^here 
60  * Return 0 for errors.
61  */
62 size_t 
63 sha1_build_checksum(result, n)
64         char *result;
65         struct sha1_checker *n;
66 {
67         size_t length;
68
69         sprintf(result, "SHA1 (%s) = ", n->id);
70         length = strlen(result);
71         SHA1_Final(result + length, &n->context);
72         strcat(result, "\n");
73         free(n);        
74         return length;
75 }
76
77 void *
78 new_sha1_checker(h, sign, userid, envp, filename)
79         struct mygzip_header *h;
80         struct signature *sign;
81         const char *userid;     
82         char *envp[];
83         /*@observer@*/const char *filename;
84 {
85         struct sha1_checker *n;
86
87         assert(sign->type == TAG_SHA1);
88         /* make sure data conforms to what we can handle */
89         if (sign->length > MAXID || sign->data[sign->length-1] != '\0') {
90                 warnx("Corrupted SHA1 header in %s", filename);
91                 return 0;
92         }
93
94         n = malloc(sizeof *n);
95         if (n == NULL) {
96                 warnx("Can't allocate sha1_checker");
97                 return NULL;
98         }
99         SHA1_Init(&n->context);
100         n->id = sign->data;
101         n->filename = filename;
102
103         /* copy header, as this is a checksum, we don't strip our own marker */
104         if (gzip_copy_header(h, sign, sha1_add, n) == 0) {
105                 warnx("Unexpected header in %s", filename);
106                 free(n);
107                 return 0;
108         }
109         return n;
110 }
111         
112 void 
113 sha1_add(arg, buffer, length)
114         void *arg;
115         const char *buffer;
116         size_t length;
117 {
118         struct sha1_checker *n = arg;
119         SHA1_Update(&n->context, buffer, length);
120 }
121
122 int
123 sha1_sign_ok(arg)
124         void *arg;
125 {
126         struct sha1_checker *n = arg;
127         char buffer[BUFSIZE];
128         char scan[BUFSIZE];
129         size_t length;
130         FILE *f;
131         int tag_found;
132
133         length = sha1_build_checksum(buffer, n);
134         f= fopen(SHA1_DB_NAME, "r");
135         tag_found = 0;
136
137         if (f == NULL) {
138                 warn("Can't access checksum file %s", SHA1_DB_NAME);
139                 return PKG_BADSIG;
140         }
141         while (fgets(scan, sizeof(scan), f) != NULL) {
142                 if (strcmp(scan, buffer) == 0) {
143                         fprintf(stderr, "Checksum ok\n");
144                         return PKG_GOODSIG;
145                 }
146                 if (strncmp(scan, buffer, length) == 0)
147                         tag_found = 1;
148         }
149
150         if (tag_found) {
151                 warnx("Checksum incorrect for %s (%s)", n->filename, n->id);
152                 return PKG_BADSIG;
153         } else {
154                 warnx("No checksum found for %s (%s)", n->filename, n->id);
155                 return PKG_SIGUNKNOWN;
156         }
157 }
158
159 int 
160 retrieve_sha1_marker(filename, sign, userid)
161         const char *filename;
162         struct signature **sign;
163         const char *userid;
164 {
165         struct signature *n;
166         struct mygzip_header h;
167         FILE *f;
168         char buffer[1024];
169         char result[BUFSIZE];
170         ssize_t length;
171         struct sha1_checker *checker;
172         struct signature *old;
173
174         *sign = NULL;
175         if (userid == NULL)
176                 return 0;
177
178         /*
179          * Create a blank signature and fill it with the userid.
180          */
181         n = malloc(sizeof *n);
182         if (n == NULL) 
183                 return 0;
184         n->data = (char *)userid;
185         n->length = strlen(n->data)+1;
186         n->type = TAG_SHA1;
187         memcpy(n->tag, sha1tag, sizeof sha1tag);
188         sign_fill_tag(n);
189
190         /*
191          * Read the gzip header and add our "userid" signature to it.
192          */
193         f = fopen(filename, "r");
194         if (f == NULL) {
195                 free(n);
196                 return 0;
197         }
198         if (gzip_read_header(f, &h, sign) == GZIP_NOT_GZIP) {
199                 warnx("File %s is not a gzip file\n", filename);
200                 fclose(f);
201                 free(n);
202                 return 0;
203         }
204         n->next = *sign;
205         *sign = n;
206
207         /*
208          * Calculate the SHA1 of the remaining data and write it to stderr.
209          */
210         checker = new_sha1_checker(&h, *sign, NULL, NULL, filename);
211         while ((length = fread(buffer, 1, sizeof buffer, f)) > 0)
212                 sha1_add(checker, buffer, length);
213         if (fclose(f) != 0 || length == -1) {
214                 warn("Problem checksumming %s", filename);
215                 *sign = n->next;
216                 free(n);
217                 return 0;
218         }
219
220         (void)sha1_build_checksum(result, checker);
221         fputs(result, stderr);
222         return 1;
223 }
224