Remove redundant casts
[opensuse:sign.git] / sign.c
1 /*
2  * Copyright (c) 2006, 2007, 2008 Michael Schroeder, Novell Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program (see the file COPYING); if not, write to the
15  * Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  ***************************************************************/
19
20 #define MYPORT 5167
21
22 static char *host;
23 static char *user;
24 static char *algouser;
25 static int port = MYPORT;
26
27 #define HEADER_SIGNATURES 62
28 #define RPMSIGTAG_DSA   267             /* header only sig */
29 #define RPMSIGTAG_RSA   268             /* header only sig */
30 #define RPMSIGTAG_SHA1  269             /* header only hash */
31 #define RPMSIGTAG_SIZE 1000
32 #define RPMSIGTAG_PGP  1002
33 #define RPMSIGTAG_MD5  1004
34 #define RPMSIGTAG_GPG  1005
35
36 #include <endian.h>
37 #if __BYTE_ORDER == __LITTLE_ENDIAN
38 #       undef BIG_ENDIAN_HOST
39 #else
40 #       define BIG_ENDIAN_HOST 1
41 #endif
42
43
44 /* sha1.c - SHA1 hash function
45  * sha256.c - SHA256 hash function
46  *      Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
47  *
48  * Please see below for more legal information!
49  *
50  * This file is part of GnuPG.
51  *
52  * GnuPG is free software; you can redistribute it and/or modify
53  * it under the terms of the GNU General Public License as published by
54  * the Free Software Foundation; either version 2 of the License, or
55  * (at your option) any later version.
56  *
57  * GnuPG is distributed in the hope that it will be useful,
58  * but WITHOUT ANY WARRANTY; without even the implied warranty of
59  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
60  * GNU General Public License for more details.
61  *
62  * You should have received a copy of the GNU General Public License
63  * along with this program; if not, write to the Free Software
64  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
65  */
66
67
68 /*  Test vectors:
69  *
70  *  "abc"
71  *  A999 3E36 4706 816A BA3E  2571 7850 C26C 9CD0 D89D
72  *
73  *  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
74  *  8498 3E44 1C3B D26E BAAE  4AA1 F951 29E5 E546 70F1
75  */
76
77
78 #include <stdio.h>
79 #include <stdlib.h>
80 #include <string.h>
81 #include <unistd.h>
82 #include <assert.h>
83 #include <fcntl.h>
84 #include <sys/socket.h>
85 #include <netinet/in.h>
86 #include <arpa/inet.h>
87 #include <netdb.h>
88 #include <time.h>
89 #include <errno.h>
90 #include <sys/stat.h>
91 #include <sys/types.h>
92 #include <pwd.h>
93
94
95 typedef unsigned int u32;
96 typedef unsigned char byte;
97
98 #if defined(__GNUC__) && defined(__i386__)
99 static inline u32
100 rol( u32 x, int n)
101 {
102         __asm__("roll %%cl,%0"
103                 :"=r" (x)
104                 :"0" (x),"c" (n));
105         return x;
106 }
107 #else
108 #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
109 #endif
110
111 typedef struct {
112     u32  h0,h1,h2,h3,h4;
113     u32  nblocks;
114     byte buf[64];
115     int  count;
116 } SHA1_CONTEXT;
117
118 static void
119 burn_stack (int bytes)
120 {
121     char buf[128];
122     
123     memset (buf, 0, sizeof buf);
124     bytes -= sizeof buf;
125     if (bytes > 0)
126         burn_stack (bytes);
127 }
128
129
130 static void
131 sha1_init( SHA1_CONTEXT *hd )
132 {
133     hd->h0 = 0x67452301;
134     hd->h1 = 0xefcdab89;
135     hd->h2 = 0x98badcfe;
136     hd->h3 = 0x10325476;
137     hd->h4 = 0xc3d2e1f0;
138     hd->nblocks = 0;
139     hd->count = 0;
140 }
141
142
143 /****************
144  * Transform the message X which consists of 16 32-bit-words
145  */
146 static void
147 sha1_transform( SHA1_CONTEXT *hd, byte *data )
148 {
149     u32 a,b,c,d,e,tm;
150     u32 x[16];
151
152     /* get values from the chaining vars */
153     a = hd->h0;
154     b = hd->h1;
155     c = hd->h2;
156     d = hd->h3;
157     e = hd->h4;
158
159 #ifdef BIG_ENDIAN_HOST
160     memcpy( x, data, 64 );
161 #else
162     { int i;
163       byte *p2;
164       for(i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) {
165         p2[3] = *data++;
166         p2[2] = *data++;
167         p2[1] = *data++;
168         p2[0] = *data++;
169       }
170     }
171 #endif
172
173
174 #define K1  0x5A827999L
175 #define K2  0x6ED9EBA1L
176 #define K3  0x8F1BBCDCL
177 #define K4  0xCA62C1D6L
178 #define F1(x,y,z)   ( z ^ ( x & ( y ^ z ) ) )
179 #define F2(x,y,z)   ( x ^ y ^ z )
180 #define F3(x,y,z)   ( ( x & y ) | ( z & ( x | y ) ) )
181 #define F4(x,y,z)   ( x ^ y ^ z )
182
183
184 #define M(i) ( tm =   x[i&0x0f] ^ x[(i-14)&0x0f] \
185                     ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \
186                , (x[i&0x0f] = rol(tm,1)) )
187
188 #define R(a,b,c,d,e,f,k,m)  do { e += rol( a, 5 )     \
189                                       + f( b, c, d )  \
190                                       + k             \
191                                       + m;            \
192                                  b = rol( b, 30 );    \
193                                } while(0)
194     R( a, b, c, d, e, F1, K1, x[ 0] );
195     R( e, a, b, c, d, F1, K1, x[ 1] );
196     R( d, e, a, b, c, F1, K1, x[ 2] );
197     R( c, d, e, a, b, F1, K1, x[ 3] );
198     R( b, c, d, e, a, F1, K1, x[ 4] );
199     R( a, b, c, d, e, F1, K1, x[ 5] );
200     R( e, a, b, c, d, F1, K1, x[ 6] );
201     R( d, e, a, b, c, F1, K1, x[ 7] );
202     R( c, d, e, a, b, F1, K1, x[ 8] );
203     R( b, c, d, e, a, F1, K1, x[ 9] );
204     R( a, b, c, d, e, F1, K1, x[10] );
205     R( e, a, b, c, d, F1, K1, x[11] );
206     R( d, e, a, b, c, F1, K1, x[12] );
207     R( c, d, e, a, b, F1, K1, x[13] );
208     R( b, c, d, e, a, F1, K1, x[14] );
209     R( a, b, c, d, e, F1, K1, x[15] );
210     R( e, a, b, c, d, F1, K1, M(16) );
211     R( d, e, a, b, c, F1, K1, M(17) );
212     R( c, d, e, a, b, F1, K1, M(18) );
213     R( b, c, d, e, a, F1, K1, M(19) );
214     R( a, b, c, d, e, F2, K2, M(20) );
215     R( e, a, b, c, d, F2, K2, M(21) );
216     R( d, e, a, b, c, F2, K2, M(22) );
217     R( c, d, e, a, b, F2, K2, M(23) );
218     R( b, c, d, e, a, F2, K2, M(24) );
219     R( a, b, c, d, e, F2, K2, M(25) );
220     R( e, a, b, c, d, F2, K2, M(26) );
221     R( d, e, a, b, c, F2, K2, M(27) );
222     R( c, d, e, a, b, F2, K2, M(28) );
223     R( b, c, d, e, a, F2, K2, M(29) );
224     R( a, b, c, d, e, F2, K2, M(30) );
225     R( e, a, b, c, d, F2, K2, M(31) );
226     R( d, e, a, b, c, F2, K2, M(32) );
227     R( c, d, e, a, b, F2, K2, M(33) );
228     R( b, c, d, e, a, F2, K2, M(34) );
229     R( a, b, c, d, e, F2, K2, M(35) );
230     R( e, a, b, c, d, F2, K2, M(36) );
231     R( d, e, a, b, c, F2, K2, M(37) );
232     R( c, d, e, a, b, F2, K2, M(38) );
233     R( b, c, d, e, a, F2, K2, M(39) );
234     R( a, b, c, d, e, F3, K3, M(40) );
235     R( e, a, b, c, d, F3, K3, M(41) );
236     R( d, e, a, b, c, F3, K3, M(42) );
237     R( c, d, e, a, b, F3, K3, M(43) );
238     R( b, c, d, e, a, F3, K3, M(44) );
239     R( a, b, c, d, e, F3, K3, M(45) );
240     R( e, a, b, c, d, F3, K3, M(46) );
241     R( d, e, a, b, c, F3, K3, M(47) );
242     R( c, d, e, a, b, F3, K3, M(48) );
243     R( b, c, d, e, a, F3, K3, M(49) );
244     R( a, b, c, d, e, F3, K3, M(50) );
245     R( e, a, b, c, d, F3, K3, M(51) );
246     R( d, e, a, b, c, F3, K3, M(52) );
247     R( c, d, e, a, b, F3, K3, M(53) );
248     R( b, c, d, e, a, F3, K3, M(54) );
249     R( a, b, c, d, e, F3, K3, M(55) );
250     R( e, a, b, c, d, F3, K3, M(56) );
251     R( d, e, a, b, c, F3, K3, M(57) );
252     R( c, d, e, a, b, F3, K3, M(58) );
253     R( b, c, d, e, a, F3, K3, M(59) );
254     R( a, b, c, d, e, F4, K4, M(60) );
255     R( e, a, b, c, d, F4, K4, M(61) );
256     R( d, e, a, b, c, F4, K4, M(62) );
257     R( c, d, e, a, b, F4, K4, M(63) );
258     R( b, c, d, e, a, F4, K4, M(64) );
259     R( a, b, c, d, e, F4, K4, M(65) );
260     R( e, a, b, c, d, F4, K4, M(66) );
261     R( d, e, a, b, c, F4, K4, M(67) );
262     R( c, d, e, a, b, F4, K4, M(68) );
263     R( b, c, d, e, a, F4, K4, M(69) );
264     R( a, b, c, d, e, F4, K4, M(70) );
265     R( e, a, b, c, d, F4, K4, M(71) );
266     R( d, e, a, b, c, F4, K4, M(72) );
267     R( c, d, e, a, b, F4, K4, M(73) );
268     R( b, c, d, e, a, F4, K4, M(74) );
269     R( a, b, c, d, e, F4, K4, M(75) );
270     R( e, a, b, c, d, F4, K4, M(76) );
271     R( d, e, a, b, c, F4, K4, M(77) );
272     R( c, d, e, a, b, F4, K4, M(78) );
273     R( b, c, d, e, a, F4, K4, M(79) );
274
275     /* update chainig vars */
276     hd->h0 += a;
277     hd->h1 += b;
278     hd->h2 += c;
279     hd->h3 += d;
280     hd->h4 += e;
281 }
282
283
284 /* Update the message digest with the contents
285  * of INBUF with length INLEN.
286  */
287 static void
288 sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen)
289 {
290     if( hd->count == 64 ) { /* flush the buffer */
291         sha1_transform( hd, hd->buf );
292         burn_stack (88+4*sizeof(void*));
293         hd->count = 0;
294         hd->nblocks++;
295     }
296     if( !inbuf )
297         return;
298     if( hd->count ) {
299         for( ; inlen && hd->count < 64; inlen-- )
300             hd->buf[hd->count++] = *inbuf++;
301         sha1_write( hd, NULL, 0 );
302         if( !inlen )
303             return;
304     }
305
306     while( inlen >= 64 ) {
307         sha1_transform( hd, inbuf );
308         hd->count = 0;
309         hd->nblocks++;
310         inlen -= 64;
311         inbuf += 64;
312     }
313     burn_stack (88+4*sizeof(void*));
314     for( ; inlen && hd->count < 64; inlen-- )
315         hd->buf[hd->count++] = *inbuf++;
316 }
317
318
319 /* The routine final terminates the computation and
320  * returns the digest.
321  * The handle is prepared for a new cycle, but adding bytes to the
322  * handle will the destroy the returned buffer.
323  * Returns: 20 bytes representing the digest.
324  */
325
326 static void
327 sha1_final(SHA1_CONTEXT *hd)
328 {
329     u32 t, msb, lsb;
330     byte *p;
331
332     sha1_write(hd, NULL, 0); /* flush */;
333
334     t = hd->nblocks;
335     /* multiply by 64 to make a byte count */
336     lsb = t << 6;
337     msb = t >> 26;
338     /* add the count */
339     t = lsb;
340     if( (lsb += hd->count) < t )
341         msb++;
342     /* multiply by 8 to make a bit count */
343     t = lsb;
344     lsb <<= 3;
345     msb <<= 3;
346     msb |= t >> 29;
347
348     if( hd->count < 56 ) { /* enough room */
349         hd->buf[hd->count++] = 0x80; /* pad */
350         while( hd->count < 56 )
351             hd->buf[hd->count++] = 0;  /* pad */
352     }
353     else { /* need one extra block */
354         hd->buf[hd->count++] = 0x80; /* pad character */
355         while( hd->count < 64 )
356             hd->buf[hd->count++] = 0;
357         sha1_write(hd, NULL, 0);  /* flush */;
358         memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
359     }
360     /* append the 64 bit count */
361     hd->buf[56] = msb >> 24;
362     hd->buf[57] = msb >> 16;
363     hd->buf[58] = msb >>  8;
364     hd->buf[59] = msb      ;
365     hd->buf[60] = lsb >> 24;
366     hd->buf[61] = lsb >> 16;
367     hd->buf[62] = lsb >>  8;
368     hd->buf[63] = lsb      ;
369     sha1_transform( hd, hd->buf );
370     burn_stack (88+4*sizeof(void*));
371
372     p = hd->buf;
373   #ifdef BIG_ENDIAN_HOST
374     #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
375   #else /* little endian */
376     #define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16;      \
377                       *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0)
378   #endif
379     X(0);
380     X(1);
381     X(2);
382     X(3);
383     X(4);
384   #undef X
385
386 }
387
388 static byte *
389 sha1_read( SHA1_CONTEXT *hd )
390 {
391     return hd->buf;
392 }
393
394 /*****************************************************************/
395
396 typedef struct {
397     u32  h0,h1,h2,h3,h4,h5,h6,h7;
398     u32  nblocks;
399     byte buf[64];
400     int  count;
401 } SHA256_CONTEXT;
402
403 static void
404 sha256_init( SHA256_CONTEXT *hd )
405 {
406     hd->h0 = 0x6a09e667;
407     hd->h1 = 0xbb67ae85;
408     hd->h2 = 0x3c6ef372;
409     hd->h3 = 0xa54ff53a;
410     hd->h4 = 0x510e527f;
411     hd->h5 = 0x9b05688c;
412     hd->h6 = 0x1f83d9ab;
413     hd->h7 = 0x5be0cd19;
414
415     hd->nblocks = 0;
416     hd->count = 0;
417 }
418
419 /****************
420  * Transform the message w which consists of 16 32-bit words
421  */
422 static void
423 sha256_transform( SHA256_CONTEXT *hd, byte *data )
424 {
425   u32 a,b,c,d,e,f,g,h;
426   u32 w[64];
427   int t;
428   static const u32 k[]=
429     {
430       0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
431       0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
432       0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
433       0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
434       0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
435       0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
436       0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
437       0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
438       0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
439       0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
440       0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
441     };
442
443   /* get values from the chaining vars */
444   a = hd->h0;
445   b = hd->h1;
446   c = hd->h2;
447   d = hd->h3;
448   e = hd->h4;
449   f = hd->h5;
450   g = hd->h6;
451   h = hd->h7;
452
453 #ifdef BIG_ENDIAN_HOST
454   memcpy( w, data, 64 );
455 #else
456   {
457     int i;
458     byte *p2;
459
460     for(i=0, p2=(byte*)w; i < 16; i++, p2 += 4 )
461       {
462         p2[3] = *data++;
463         p2[2] = *data++;
464         p2[1] = *data++;
465         p2[0] = *data++;
466       }
467   }
468 #endif
469
470 #define ROTR(x,n) (((x)>>(n)) | ((x)<<(32-(n))))
471 #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
472 #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
473 #define Sum0(x) (ROTR((x),2) ^ ROTR((x),13) ^ ROTR((x),22))
474 #define Sum1(x) (ROTR((x),6) ^ ROTR((x),11) ^ ROTR((x),25))
475 #define S0(x) (ROTR((x),7) ^ ROTR((x),18) ^ ((x)>>3))
476 #define S1(x) (ROTR((x),17) ^ ROTR((x),19) ^ ((x)>>10))
477
478   for(t=16;t<64;t++)
479     w[t] = S1(w[t-2]) + w[t-7] + S0(w[t-15]) + w[t-16];
480
481   for(t=0;t<64;t++)
482     {
483       u32 t1,t2;
484
485       t1=h+Sum1(e)+Ch(e,f,g)+k[t]+w[t];
486       t2=Sum0(a)+Maj(a,b,c);
487       h=g;
488       g=f;
489       f=e;
490       e=d+t1;
491       d=c;
492       c=b;
493       b=a;
494       a=t1+t2;
495       /* printf("t=%d a=%08lX b=%08lX c=%08lX d=%08lX e=%08lX f=%08lX g=%08lX h=
496 %08lX\n",t,a,b,c,d,e,f,g,h); */
497     }
498
499   /* update chaining vars */
500   hd->h0 += a;
501   hd->h1 += b;
502   hd->h2 += c;
503   hd->h3 += d;
504   hd->h4 += e;
505   hd->h5 += f;
506   hd->h6 += g;
507   hd->h7 += h;
508 }
509
510 /* Update the message digest with the contents
511  * of INBUF with length INLEN.
512  */
513 static void
514 sha256_write( SHA256_CONTEXT *hd, byte *inbuf, size_t inlen)
515 {
516     if( hd->count == 64 ) { /* flush the buffer */
517         sha256_transform( hd, hd->buf );
518         burn_stack (328);
519         hd->count = 0;
520         hd->nblocks++;
521     }
522     if( !inbuf )
523         return;
524     if( hd->count ) {
525         for( ; inlen && hd->count < 64; inlen-- )
526             hd->buf[hd->count++] = *inbuf++;
527         sha256_write( hd, NULL, 0 );
528         if( !inlen )
529             return;
530     }
531
532     while( inlen >= 64 ) {
533         sha256_transform( hd, inbuf );
534         hd->count = 0;
535         hd->nblocks++;
536         inlen -= 64;
537         inbuf += 64;
538     }
539     burn_stack (328);
540     for( ; inlen && hd->count < 64; inlen-- )
541         hd->buf[hd->count++] = *inbuf++;
542 }
543 /* The routine final terminates the computation and
544  * returns the digest.
545  * The handle is prepared for a new cycle, but adding bytes to the
546  * handle will the destroy the returned buffer.
547  * Returns: 32 bytes representing the digest.
548  */
549
550 static void
551 sha256_final(SHA256_CONTEXT *hd)
552 {
553     u32 t, msb, lsb;
554     byte *p;
555
556     sha256_write(hd, NULL, 0); /* flush */;
557
558     t = hd->nblocks;
559     /* multiply by 64 to make a byte count */
560     lsb = t << 6;
561     msb = t >> 26;
562     /* add the count */
563     t = lsb;
564     if( (lsb += hd->count) < t )
565         msb++;
566     /* multiply by 8 to make a bit count */
567     t = lsb;
568     lsb <<= 3;
569     msb <<= 3;
570     msb |= t >> 29;
571
572     if( hd->count < 56 ) { /* enough room */
573         hd->buf[hd->count++] = 0x80; /* pad */
574         while( hd->count < 56 )
575             hd->buf[hd->count++] = 0;  /* pad */
576     }
577     else { /* need one extra block */
578         hd->buf[hd->count++] = 0x80; /* pad character */
579         while( hd->count < 64 )
580             hd->buf[hd->count++] = 0;
581         sha256_write(hd, NULL, 0);  /* flush */;
582         memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
583     }
584     /* append the 64 bit count */
585     hd->buf[56] = msb >> 24;
586     hd->buf[57] = msb >> 16;
587     hd->buf[58] = msb >>  8;
588     hd->buf[59] = msb      ;
589     hd->buf[60] = lsb >> 24;
590     hd->buf[61] = lsb >> 16;
591     hd->buf[62] = lsb >>  8;
592     hd->buf[63] = lsb      ;
593     sha256_transform( hd, hd->buf );
594     burn_stack (328);
595
596     p = hd->buf;
597 #ifdef BIG_ENDIAN_HOST
598 #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
599 #else /* little endian */
600 #define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16;  \
601                       *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0)
602 #endif
603     X(0);
604     X(1);
605     X(2);
606     X(3);
607     X(4);
608     X(5);
609     X(6);
610     X(7);
611 #undef X
612 }
613
614 static byte *
615 sha256_read( SHA256_CONTEXT *hd )
616 {
617     return hd->buf;
618 }
619
620
621 /*****************************************************************/
622
623 struct MD5Context {
624         u32 buf[4];
625         u32 bits[2];
626         byte in[64];
627 };
628
629 typedef struct MD5Context MD5_CTX;
630 static void rpmMD5Transform(u32 buf[4], u32 const in[16]);
631
632 #ifdef BIG_ENDIAN_HOST
633 static void byteReverse(unsigned char *buf, unsigned longs)
634 {
635     u32 t;
636     do {
637         t = ((unsigned) buf[3] << 8 | buf[2]) << 16 |
638             ((unsigned) buf[1] << 8 | buf[0]);
639         *(u32 *) buf = t;
640         buf += 4;
641     } while (--longs);
642 }
643 #endif
644
645 /*
646  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
647  * initialization constants.
648  */
649 static void md5_init(struct MD5Context *ctx)
650 {
651     ctx->buf[0] = 0x67452301;
652     ctx->buf[1] = 0xefcdab89;
653     ctx->buf[2] = 0x98badcfe;
654     ctx->buf[3] = 0x10325476;
655     ctx->bits[0] = 0;
656     ctx->bits[1] = 0;
657 }
658
659 static void md5_write(struct MD5Context *ctx, byte const *buf, u32 len)
660 {
661     u32 t;
662
663     t = ctx->bits[0];
664     if ((ctx->bits[0] = t + (len << 3)) < t)
665         ctx->bits[1]++;         /* Carry from low to high */
666     ctx->bits[1] += len >> 29;
667
668     t = (t >> 3) & 0x3f;        /* Bytes already in shsInfo->data */
669     if (t) {
670         unsigned char *p = (unsigned char *) ctx->in + t;
671
672         t = 64 - t;
673         if (len < t) {
674             memcpy(p, buf, len);
675             return;
676         }
677         memcpy(p, buf, t);
678 #ifdef BIG_ENDIAN_HOST
679         byteReverse(ctx->in, 16);
680 #endif
681         rpmMD5Transform(ctx->buf, (u32 *) ctx->in);
682         buf += t;
683         len -= t;
684     }
685     while (len >= 64) {
686         memcpy(ctx->in, buf, 64);
687 #ifdef BIG_ENDIAN_HOST
688         byteReverse(ctx->in, 16);
689 #endif
690         rpmMD5Transform(ctx->buf, (u32 *) ctx->in);
691         buf += 64;
692         len -= 64;
693     }
694     memcpy(ctx->in, buf, len);
695 }
696
697 static void md5_final(byte *digest, struct MD5Context *ctx)
698 {
699     unsigned count;
700     unsigned char *p;
701
702     /* Compute number of bytes mod 64 */
703     count = (ctx->bits[0] >> 3) & 0x3F;
704
705     /* Set the first char of padding to 0x80.  This is safe since there is
706        always at least one byte free */
707     p = ctx->in + count;
708     *p++ = 0x80;
709
710     /* Bytes of padding needed to make 64 bytes */
711     count = 64 - 1 - count;
712
713     /* Pad out to 56 mod 64 */
714     if (count < 8) {
715         /* Two lots of padding:  Pad the first block to 64 bytes */
716         memset(p, 0, count);
717 #ifdef BIG_ENDIAN_HOST
718         byteReverse(ctx->in, 16);
719 #endif
720         rpmMD5Transform(ctx->buf, (u32 *) ctx->in);
721
722         /* Now fill the next block with 56 bytes */
723         memset(ctx->in, 0, 56);
724     } else {
725         /* Pad block to 56 bytes */
726         memset(p, 0, count - 8);
727     }
728 #ifdef BIG_ENDIAN_HOST
729     byteReverse(ctx->in, 14);
730 #endif
731
732     /* Append length in bits and transform */
733     ((u32 *) ctx->in)[14] = ctx->bits[0];
734     ((u32 *) ctx->in)[15] = ctx->bits[1];
735
736     rpmMD5Transform(ctx->buf, (u32 *) ctx->in);
737 #ifdef BIG_ENDIAN_HOST
738     byteReverse((unsigned char *) ctx->buf, 4);
739 #endif
740     memcpy(digest, ctx->buf, 16);
741     memset(ctx, 0, sizeof(ctx));        /* In case it's sensitive */
742 }
743
744 /* The four core functions - F1 is optimized somewhat */
745 #undef F1
746 #undef F2
747 #undef F3
748 #undef F4
749
750 /* #define F1(x, y, z) (x & y | ~x & z) */
751 #define F1(x, y, z) (z ^ (x & (y ^ z)))
752 #define F2(x, y, z) F1(z, x, y)
753 #define F3(x, y, z) (x ^ y ^ z)
754 #define F4(x, y, z) (y ^ (x | ~z))
755
756 /* This is the central step in the MD5 algorithm. */
757 #define MD5STEP(f, w, x, y, z, data, s) \
758         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
759
760 /*
761  * The core of the MD5 algorithm, this alters an existing MD5 hash to
762  * reflect the addition of 16 longwords of new data.  md5_write blocks
763  * the data and converts bytes into longwords for this routine.
764  */
765 static void rpmMD5Transform(u32 buf[4], u32 const in[16])
766 {
767     register u32 a, b, c, d;
768
769     a = buf[0];
770     b = buf[1];
771     c = buf[2];
772     d = buf[3];
773
774     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
775     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
776     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
777     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
778     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
779     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
780     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
781     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
782     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
783     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
784     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
785     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
786     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
787     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
788     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
789     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
790
791     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
792     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
793     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
794     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
795     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
796     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
797     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
798     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
799     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
800     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
801     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
802     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
803     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
804     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
805     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
806     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
807
808     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
809     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
810     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
811     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
812     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
813     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
814     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
815     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
816     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
817     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
818     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
819     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
820     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
821     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
822     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
823     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
824
825     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
826     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
827     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
828     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
829     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
830     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
831     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
832     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
833     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
834     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
835     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
836     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
837     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
838     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
839     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
840     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
841
842     buf[0] += a;
843     buf[1] += b;
844     buf[2] += c;
845     buf[3] += d;
846 }
847
848
849
850 /*****************************************************************/
851
852
853
854 #define CRCINIT 0xb704ce
855 #define CRCPOLY 0x864cfb
856
857
858 static u32
859 crc24(byte *octets, int len)
860 {
861   u32 crc = CRCINIT;
862   int i;
863
864   while (len-- > 0) {
865     crc ^= (*octets++) << 16;
866     for (i = 0; i < 8; i++) {
867       crc <<= 1;
868       if (crc & 0x1000000)
869         crc ^= CRCPOLY;
870     }
871   }
872   return crc & 0xffffff;
873 }
874
875 static void
876 printr64(FILE *f, byte *str, int len)
877 {
878   int a, b, c, i;
879   static byte bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
880
881   i = 0;
882   while (len > 0)
883     {
884       if (++i == 16)
885         {
886           i = 0;
887           putc('\n', f);
888         }
889       a = *str++;
890       b = --len > 0 ? *str++ : 0;
891       c = --len > 0 ? *str++ : 0;
892       --len;
893       putc(bintoasc[a >> 2], f);
894       putc(bintoasc[(a & 3) << 4 | b >> 4], f);
895       putc(len > -2 ? bintoasc[(b & 15) << 2 | c >> 6] : '=', f);
896       putc(len > -1 ? bintoasc[c & 63] : '=', f);
897     }
898     putc('\n', f);
899 }
900
901 static ssize_t xread(int fd, void *buf, size_t count)
902 {
903   ssize_t r, r2;
904   r2 = 0;
905   while(count)
906     {
907       r = read(fd, buf, count);
908       if (r <= 0)
909         return r2 ? r2 : r;
910       count -= r;
911       buf += r;
912       r2 += r;
913     }
914   return r2;
915 }
916
917 static ssize_t xwrite(int fd, void *buf, size_t count)
918 {
919   ssize_t r, r2;
920   r2 = 0;
921   while(count)
922     {
923       r = write(fd, buf, count);
924       if (r < 0)
925         {
926           perror("write");
927           exit(1);
928         }
929       count -= r;
930       buf += r;
931       r2 += r;
932     }
933   return r2;
934 }
935
936 static uid_t uid;
937
938 static int opensocket(void)
939 {
940   static int hostknown;
941   static struct sockaddr_in svt;
942   int sock;
943
944   if (!hostknown)
945     {
946       svt.sin_addr.s_addr = inet_addr(host);
947       svt.sin_family = AF_INET;
948       if (svt.sin_addr.s_addr == -1)
949         {
950           struct hostent *hp;
951           if (!(hp = gethostbyname(host)))
952             {
953               printf("%s: unknown host\n", host);
954               exit(1);
955             }
956           memmove(&svt.sin_addr, hp->h_addr, hp->h_length);
957           svt.sin_family = hp->h_addrtype;
958         }
959       svt.sin_port = htons(port);
960       hostknown = 1;
961     }
962   if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
963     {
964       perror("socket");
965       exit(1);
966     }
967   if (uid)
968     seteuid(0);
969   for (;;)
970     {
971       if (!bindresvport(sock, NULL))
972         break;
973       if (errno != EADDRINUSE)
974         {
975           perror("bindresvport");
976           exit(1);
977         }
978       sleep(1);
979     }
980   if (uid)
981     {
982       if (seteuid(uid))
983         {
984           perror("seteuid");
985           exit(1);
986         }
987     }
988   if (connect(sock, (struct sockaddr *)&svt, sizeof(svt)))
989     {
990       perror(host);
991       exit(1);
992     }
993   return sock;
994 }
995
996 static int verbose;
997
998 #define HASH_SHA1       0
999 #define HASH_SHA256     1
1000
1001 static char *hashname[] = {"SHA1", "SHA256"};
1002 static int  hashlen[] = {20, 32};
1003 static int  hashtag[] = { RPMSIGTAG_GPG, RPMSIGTAG_PGP };
1004 static int  hashtagh[] = { RPMSIGTAG_DSA, RPMSIGTAG_RSA };
1005 static int hashalgo = HASH_SHA1;
1006 static char *timearg;
1007 static char *privkey;
1008 static int noheaderonly;
1009
1010 typedef union {
1011   SHA1_CONTEXT sha1;
1012   SHA256_CONTEXT sha256;
1013 } HASH_CONTEXT;
1014
1015 static void hash_init(HASH_CONTEXT *c)
1016 {
1017   if (hashalgo == HASH_SHA1)
1018     sha1_init(&c->sha1);
1019   else if (hashalgo == HASH_SHA256)
1020     sha256_init(&c->sha256);
1021 }
1022
1023 static void hash_write(HASH_CONTEXT *c, unsigned char *b, size_t l)
1024 {
1025   if (hashalgo == HASH_SHA1)
1026     sha1_write(&c->sha1, b, l);
1027   else if (hashalgo == HASH_SHA256)
1028     sha256_write(&c->sha256, b, l);
1029 }
1030
1031 static void hash_final(HASH_CONTEXT *c)
1032 {
1033   if (hashalgo == HASH_SHA1)
1034     sha1_final(&c->sha1);
1035   else if (hashalgo == HASH_SHA256)
1036     sha256_final(&c->sha256);
1037 }
1038
1039 static unsigned char *hash_read(HASH_CONTEXT *c)
1040 {
1041   if (hashalgo == HASH_SHA1)
1042     return sha1_read(&c->sha1);
1043   else if (hashalgo == HASH_SHA256)
1044     return sha256_read(&c->sha256);
1045   return 0;
1046 }
1047
1048 #define MODE_UNSET        0
1049 #define MODE_RPMSIGN      1
1050 #define MODE_CLEARSIGN    2
1051 #define MODE_DETACHEDSIGN 3
1052 #define MODE_KEYID        4
1053 #define MODE_PUBKEY       5
1054 #define MODE_KEYGEN       6
1055
1056 static char *modes[] = {"?", "rpm sign", "clear sign", "detached sign"};
1057
1058 static void
1059 readprivkey(void)
1060 {
1061   FILE *fp;
1062   int l, ll;
1063   if ((fp = fopen(privkey, "r")) == 0)
1064     {
1065       perror(privkey);
1066       exit(1);
1067     }
1068   privkey = malloc(8192);
1069   *privkey = 0;
1070   l = 0;
1071   while (l < 8192 && (ll = fread(privkey + l, 1, 8192 - l, fp)) > 0)
1072     l += ll;
1073   fclose(fp);
1074   if (l == 0)
1075     {
1076       fprintf(stderr, "empty private\n");
1077       exit(1);
1078     }
1079   if (l == 8192)
1080     {
1081       fprintf(stderr, "private key too large\n");
1082       exit(1);
1083     }
1084   if (privkey[l - 1] == '\n')
1085     l--;
1086   privkey[l] = 0;
1087 }
1088
1089 static int
1090 doreq(int sock, int argc, char **argv, byte *buf, int bufl, int nret)
1091 {
1092   byte *bp;
1093   int i, l, v, outl, errl;
1094
1095   bp = buf + 2;
1096   *bp++ = 0;
1097   *bp++ = 0;
1098   *bp++ = argc >> 8;
1099   *bp++ = argc & 255;
1100   for (i = 0; i < argc; i++)
1101     {
1102       v = strlen(argv[i]);
1103       *bp++ = v >> 8;
1104       *bp++ = v & 255;
1105     }
1106   for (i = 0; i < argc; i++)
1107     {
1108       v = strlen(argv[i]);
1109       if (bp + v > buf + bufl)
1110         {
1111           fprintf(stderr, "request buffer overflow\n");
1112           return -1;
1113         }
1114       memcpy(bp, argv[i], v);
1115       bp += v;
1116     }
1117   v = bp - (buf + 4);
1118   buf[0] = v >> 8;
1119   buf[1] = v & 255;
1120
1121   i = bp - buf;
1122   if (write(sock, buf, i) != i)
1123     {
1124       perror("write");
1125       return -1;
1126     }
1127   l = 0;
1128   for (;;)
1129     {
1130       int ll;
1131       if (l == bufl)
1132         {
1133           fprintf(stderr, "packet too big\n");
1134           return -1;
1135         }
1136       ll = read(sock, buf + l, bufl - l);
1137       if (ll == -1)
1138         {
1139           perror("read");
1140           return -1;
1141         }
1142       if (ll == 0)
1143         break;
1144       l += ll;
1145     }
1146   close(sock);
1147   if (l < 6)
1148     {
1149       fprintf(stderr, "packet too small\n");
1150       return -1;
1151     }
1152   outl = buf[2] << 8 | buf[3];
1153   errl = buf[4] << 8 | buf[5];
1154   if (l != outl + errl + 6)
1155     {
1156       fprintf(stderr, "packet size mismatch %d %d %d\n", l, outl, errl);
1157       return -1;
1158     }
1159   if (errl)
1160     fwrite(buf + 6 + outl, 1, errl, stderr);
1161
1162   if (buf[0] << 8 | buf[1])
1163     return -(buf[0] << 8 | buf[1]);
1164   memmove(buf, buf + 6, outl);
1165   if (nret)
1166     {
1167       if (outl < 2 + 2 * nret)
1168         {
1169           fprintf(stderr, "answer too small\n");
1170           return -1;
1171         }
1172       if (buf[0] != 0 || buf[1] != nret)
1173         {
1174           fprintf(stderr, "bad answer\n");
1175           return -1;
1176         }
1177       l = 2;
1178       for (i = 0; i < nret; i++)
1179         l += 2 + (buf[2 + i * 2] << 8 | buf[2 + i * 2 + 1]);
1180       if (l != outl)
1181         {
1182           fprintf(stderr, "answer size mismatch\n");
1183           return -1;
1184         }
1185     }
1186   return outl;
1187 }
1188
1189 static inline int
1190 getu8(byte *p)
1191 {
1192   return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1193 }
1194
1195 static inline int
1196 getu8c(byte *p)
1197 {
1198   if (p[0])
1199     {
1200       fprintf(stderr, "header data overflow\n");
1201       exit(1);
1202     }
1203   return p[1] << 16 | p[2] << 8 | p[3];
1204 }
1205
1206 static byte *
1207 findmax(byte *rpmsig, int rpmsigcnt, int targetoff)
1208 {
1209   int i;
1210   byte *rsp;
1211   int maxoff;
1212   byte *maxrsp;
1213
1214   maxoff = -1;
1215   maxrsp = 0;
1216   for (i = 0, rsp = rpmsig; i < rpmsigcnt; i++, rsp += 16)
1217     {
1218       int off = getu8c(rsp + 8);
1219       if (off >= targetoff || off < maxoff)
1220         continue;
1221       maxoff = off;
1222       maxrsp = rsp;
1223     }
1224   return maxrsp;
1225 }
1226
1227 static int
1228 datalen(byte *rpmsig, int rpmsigcnt, byte *rsp)
1229 {
1230   int type, cnt;
1231
1232   type = getu8c(rsp + 4);
1233   cnt = getu8c(rsp + 12);
1234   if (type == 6 || type == 8 || type == 9)
1235     {
1236       int i = 0;
1237       int off = getu8c(rsp + 8);
1238       if (type == 6)
1239         cnt = 1;
1240       while (cnt-- > 0)
1241         {
1242           while (rpmsig[rpmsigcnt * 16 + off + i])
1243             i++;
1244           i++;  /* count termination 0 */
1245         }
1246       return i;
1247     }
1248   if (type == 3)
1249     return 2 * cnt;
1250   else if (type == 4)
1251     return 4 * cnt;
1252   else if (type == 5)
1253     return 8 * cnt;
1254   return cnt;
1255 }
1256
1257 static int
1258 rpminsertsig(byte *rpmsig, int *rpmsigsizep, int *rpmsigcntp, int *rpmsigdlenp, int sigtag, byte *newsig, int newsiglen)
1259 {
1260   int rpmsigsize, rpmsigcnt, rpmsigdlen;
1261   int i, myi, tag, off, type;
1262   byte *rsp;
1263   u32 before;
1264   int pad;
1265   byte *region = 0;
1266
1267   rpmsigsize = *rpmsigsizep;
1268   rpmsigcnt = *rpmsigcntp;
1269   rpmsigdlen = *rpmsigdlenp;
1270
1271   if (newsiglen > 1024)
1272     {
1273       fprintf(stderr, "signature too big: %d\n", newsiglen);
1274       return -1;
1275     }
1276
1277   // first some sanity checking
1278   for (i = 0, rsp = rpmsig; i < rpmsigcnt; i++, rsp += 16)
1279     {
1280       off = getu8c(rsp + 8);
1281       if (off < 0 || off > rpmsigdlen)
1282         {
1283           fprintf(stderr, "data offset out of range\n");
1284           exit(1);
1285         }
1286     }
1287
1288   // now find the correct place to insert the signature
1289   for (i = 0, rsp = rpmsig; i < rpmsigcnt; i++, rsp += 16)
1290     {
1291       tag = getu8(rsp);
1292       // fprintf(stderr, "tag %d\n", tag);
1293       if (i == 0 && tag >= 61 && tag < 64)
1294         region = rsp;
1295       if (tag >= sigtag)
1296         break;
1297     }
1298   // fprintf(stderr, "inserting at position %d of %d\n", i, rpmsigcnt);
1299   if (i < rpmsigcnt && tag == sigtag)
1300     abort();
1301
1302   // insert it
1303   memmove(rsp + 16, rsp, rpmsigsize - i * 16);
1304   memset(rsp, 0, 16);
1305   rsp[2] = sigtag >> 8;
1306   rsp[3] = sigtag & 0xff;
1307   rsp[7] = 7;
1308   rsp[14] = newsiglen >> 8;
1309   rsp[15] = newsiglen & 0xff;
1310
1311   if (i < rpmsigcnt)
1312     before = getu8c(rsp + 16 + 8);
1313   else if (region)
1314     before = getu8c(region + 8);
1315   else
1316     before = rpmsigdlen;
1317   if (before > rpmsigdlen)
1318     {
1319       fprintf(stderr, "sig data range error\n");
1320       return -1;
1321     }
1322
1323   // fprintf(stderr, "before=%d sigdlen=%d\n", before, rpmsigdlen);
1324   rpmsigcnt++;
1325   if (before < rpmsigdlen)
1326     memmove(rpmsig + rpmsigcnt * 16 + before + newsiglen, rpmsig + rpmsigcnt * 16 + before, rpmsigdlen - before);
1327   memmove(rpmsig + rpmsigcnt * 16 + before, newsig, newsiglen);
1328   rsp[8] = before >> 24;
1329   rsp[9] = before >> 16;
1330   rsp[10] = before >> 8;
1331   rsp[11] = before;
1332   rpmsigdlen += newsiglen;
1333
1334   // now fix up all entries behind us
1335   myi = i;
1336   rsp = rpmsig;
1337   for (i = 0; i < rpmsigcnt; i++, rsp += 16)
1338     {
1339       if (i == myi)
1340         continue;
1341       off = getu8c(rsp + 8);
1342       if (off < before)
1343         continue;
1344       off += newsiglen;
1345       rsp[8] = off >> 24;
1346       rsp[9] = off >> 16;
1347       rsp[10] = off >> 8;
1348       rsp[11] = off;
1349     }
1350
1351   // correct the padding of all entries
1352   for (i = 0, rsp = rpmsig; i < rpmsigcnt; i++, rsp += 16)
1353     {
1354       int align, off2, type, lastoff;
1355       byte *lastrsp;
1356
1357       type = getu8c(rsp + 4);
1358       if (type == 3)
1359         align = 2;
1360       else if (type == 4)
1361         align = 4;
1362       else if (type == 5)
1363         align = 8;
1364       else
1365         continue;
1366       off = getu8c(rsp + 8);
1367       if (off % align == 0)
1368         continue;
1369       /* have to re-align, find end of last data */
1370       lastrsp = findmax(rpmsig, rpmsigcnt, off);
1371       lastoff = getu8c(lastrsp + 8);
1372       lastoff += datalen(rpmsig, rpmsigcnt, lastrsp);
1373       if (lastoff > off)
1374         {
1375           fprintf(stderr, "lastoff error %d %d\n", lastoff, off);
1376           return -1;
1377         }
1378       if (lastoff % align)
1379         lastoff += align - (lastoff % align);
1380       /* now move over from off to lastoff */
1381       memmove(rpmsig + rpmsigcnt * 16 + lastoff, rpmsig + rpmsigcnt * 16 + off, rpmsigdlen - off);
1382       rpmsigdlen += lastoff - off;
1383       if (lastoff > off)
1384         memset(rpmsig + rpmsigcnt * 16 + off, 0, lastoff - off);
1385       /* fix up all offsets */
1386       for (i = 0, rsp = rpmsig; i < rpmsigcnt; i++, rsp += 16)
1387         {
1388           off2 = getu8c(rsp + 8);
1389           if (off2 < off)
1390             continue;
1391           off2 += lastoff - off;
1392           rsp[8] = off2 >> 24;
1393           rsp[9] = off2 >> 16;
1394           rsp[10] = off2 >> 8;
1395           rsp[11] = off2;
1396         }
1397       /* start over */
1398       i = -1;
1399       rsp = rpmsig - 16;
1400     }
1401
1402   // correct region count
1403   if (region)
1404     {
1405       if (getu8(region + 12) != 16)
1406         {
1407           fprintf(stderr, "bad region in signature\n");
1408           return -1;
1409         }
1410       off = getu8c(region + 8);
1411       rsp = rpmsig + rpmsigcnt * 16 + off;
1412       tag = getu8(rsp + 8);
1413       if (-tag != (rpmsigcnt - 1) * 16)
1414         {
1415           fprintf(stderr, "bad region data in signature (%d)\n", -tag);
1416           return -1;
1417         }
1418       tag -= 16;
1419       rsp[8] = tag >> 24;
1420       rsp[9] = tag >> 16;
1421       rsp[10] = tag >> 8;
1422       rsp[11] = tag;
1423     }
1424
1425   // align to multiple of 8
1426   pad = 7 - ((rpmsigdlen + 7) & 7);
1427   if (pad)
1428     memset(rpmsig + rpmsigcnt * 16 + rpmsigdlen, 0, pad);
1429   rpmsigsize = rpmsigcnt * 16 + rpmsigdlen + pad;
1430
1431   *rpmsigsizep = rpmsigsize;
1432   *rpmsigcntp = rpmsigcnt;
1433   *rpmsigdlenp = rpmsigdlen;
1434   return 0;
1435 }
1436
1437 static int
1438 sign(char *filename, int isfilter, int mode)
1439 {
1440   u32 signtime;
1441   u32 crc;
1442   byte buf[8192], *bp;
1443   byte *cbuf;
1444   int cbufl;
1445   int l, fd;
1446   int i;
1447   byte hash[5], *p, *ph = 0;
1448   HASH_CONTEXT ctx;
1449   MD5_CTX md5ctx;
1450   HASH_CONTEXT hctx;
1451   int force = 1;
1452   int outl, outlh, errl;
1453   int sock;
1454   int ulen;
1455   byte rpmlead[96];
1456   byte rpmsighead[16], *rsp;
1457   byte *rpmsig = 0;
1458   int rpmsigcnt = 0, rpmsigdlen = 0;
1459   int rpmsigsize = 0, tag;
1460   u32 lensig, lenhdr;
1461   byte rpmmd5sum[16];
1462   byte rpmmd5sum2[16];
1463   byte *hdrin_md5 = 0;
1464   u32 hdrin_size = 0;
1465   u32 rpmdataoff = 0;
1466   char *outfilename = 0;
1467   FILE *fout = 0;
1468   int foutfd;
1469   int getbuildtime = 0;
1470   int buildtimeoff = 0;
1471   byte btbuf[4];
1472   int gotsha1 = 0;
1473
1474   if (mode == MODE_UNSET)
1475     {
1476       force = 0;
1477       if (isfilter)
1478         {
1479           fprintf(stderr, "please specify a mode for filter usage.\n");
1480           exit(1);
1481         }
1482       l = strlen(filename);
1483       if (l > 4 && (!strcmp(filename + l - 4, ".rpm") || !strcmp(filename + l - 4, ".spm")))
1484         mode = MODE_RPMSIGN;
1485       else
1486         mode = MODE_CLEARSIGN;
1487     }
1488   if (isfilter)
1489     fd = 0;
1490   else if ((fd = open(filename, O_RDONLY)) == -1)
1491     {
1492       perror(filename);
1493       exit(1);
1494     }
1495   else
1496     {
1497       outfilename = malloc(strlen(filename) + 16);
1498       if (!outfilename)
1499         {
1500           fprintf(stderr, "out of memory for filename\n");
1501           exit(1);
1502         }
1503       if (mode == MODE_DETACHEDSIGN)
1504         sprintf(outfilename, "%s.asc", filename);
1505       else
1506         sprintf(outfilename, "%s.sIgN%d", filename, getpid());
1507     }
1508   if (!timearg || mode == MODE_KEYID || mode == MODE_PUBKEY)
1509     signtime = time(NULL);
1510   else if (*timearg >= '0' && *timearg <= '9')
1511     signtime = strtoul(timearg, NULL, 0);
1512   else if (mode == MODE_RPMSIGN && !strcmp(timearg, "buildtime"))
1513     {
1514       getbuildtime = 1;
1515       signtime = 0;             /* rpmsign && buildtime */
1516     }
1517   else
1518     {
1519       struct stat stb;
1520       if (fstat(fd, &stb))
1521         {
1522           perror("fstat");
1523           exit(1);
1524         }
1525       if (S_ISFIFO(stb.st_mode))
1526         {
1527           fprintf(stderr, "cannot use mtime on pipes\n");
1528           exit(1);
1529         }
1530       signtime = stb.st_mtime;
1531     }
1532
1533   if (mode == MODE_RPMSIGN)
1534     {
1535       if (read(fd, rpmlead, 96) != 96 || rpmlead[0] != 0xed || rpmlead[1] != 0xab || rpmlead[2] != 0xee || rpmlead[3] != 0xdb)
1536         {
1537           fprintf(stderr, "%s: not a rpm\n", filename);
1538           exit(1);
1539         }
1540       if (rpmlead[4] != 0x03 || rpmlead[0x4e] != 0 || rpmlead[0x4f] != 5)
1541         {
1542           fprintf(stderr, "%s: not a v3 rpm or not new header styles\n", filename);
1543           exit(1);
1544         }
1545       if (read(fd, rpmsighead, 16) != 16 || rpmsighead[0] != 0x8e || rpmsighead[1] != 0xad || rpmsighead[2] != 0xe8 || rpmsighead[3] != 0x01)
1546         {
1547           fprintf(stderr, "%s: bad signature header\n", filename);
1548           exit(1);
1549         }
1550       rpmsigcnt = rpmsighead[8] << 24 | rpmsighead[9] << 16 | rpmsighead[10] << 8 | rpmsighead[11];
1551       rpmsigdlen = rpmsighead[12] << 24 | rpmsighead[13] << 16 | rpmsighead[14] << 8 | rpmsighead[15];
1552       rpmsigsize = rpmsigcnt * 16 + ((rpmsigdlen + 7) & ~7);
1553       rpmsig = malloc(rpmsigsize + 2 * (1024 + 16 + 4));
1554       if (!rpmsig)
1555         {
1556           fprintf(stderr, "%s: no memory for signature area\n", filename);
1557           exit(1);
1558         }
1559       if (xread(fd, rpmsig, rpmsigsize) != rpmsigsize)
1560         {
1561           fprintf(stderr, "%s: read error in signature area\n", filename);
1562           exit(1);
1563         }
1564       rpmdataoff = 96 + 16 + rpmsigsize;
1565       rsp = rpmsig;
1566       for (i = 0; i < rpmsigcnt; i++)
1567         {
1568           tag = rsp[0] << 24 | rsp[1] << 16 | rsp[2] << 8 | rsp[3];
1569           if (tag == hashtag[hashalgo] || tag == hashtagh[hashalgo])
1570             {
1571               fprintf(isfilter ? stderr : stdout, "%s: already signed\n", filename);
1572               close(fd);
1573               free(rpmsig);
1574               if (outfilename)
1575                 free(outfilename);
1576               if (isfilter)
1577                 exit(1);
1578               return 1;
1579             }
1580           if (tag == RPMSIGTAG_SHA1)
1581             gotsha1 = 1;
1582           if (tag == RPMSIGTAG_MD5)
1583             {
1584               if (rsp[4] || rsp[5] || rsp[6] || rsp[7] != 7 || rsp[12] || rsp[13] || rsp[14] || rsp[15] != 16)
1585                 {
1586                   fprintf(stderr, "%s: bad MD5 tag\n", filename);
1587                   exit(1);
1588                 }
1589               hdrin_md5 = rpmsig + rpmsigcnt * 16 + (rsp[8] << 24 | rsp[9] << 16 | rsp[10] << 8 | rsp[11]);
1590             }
1591           if (tag == RPMSIGTAG_SIZE)
1592             {
1593               if (rsp[4] || rsp[5] || rsp[6] || rsp[7] != 4 || rsp[12] || rsp[13] || rsp[14] || rsp[15] != 1)
1594                 {
1595                   fprintf(stderr, "%s: bad SIZE tag\n", filename);
1596                   exit(1);
1597                 }
1598               p = rpmsig + rpmsigcnt * 16 + (rsp[8] << 24 | rsp[9] << 16 | rsp[10] << 8 | rsp[11]);
1599               hdrin_size = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1600             }
1601           rsp += 16;
1602         }
1603     }
1604
1605
1606   hash_init(&ctx);
1607   if (mode == MODE_CLEARSIGN)
1608     {
1609       int have = 0;
1610       int i, j;
1611       int nl = 0;
1612       int first = 1;
1613
1614       if ((cbuf = malloc(8192)) == NULL)
1615         {
1616           fprintf(stderr, "no mem for clearsign buffer\n");
1617           exit(1);
1618         }
1619       cbufl = 8192;
1620       l = read(fd, cbuf, cbufl);
1621       if (l < 0)
1622         {
1623           perror("read");
1624           exit(1);
1625         }
1626       if (l >= 34 && !strncmp((char *)cbuf, "-----BEGIN PGP SIGNED MESSAGE-----", 34))
1627         {
1628           fprintf(isfilter ? stderr : stdout, "%s: already signed\n", filename);
1629           close(fd);
1630           if (outfilename)
1631             free(outfilename);
1632           if (isfilter)
1633             exit(1);
1634           return(1);
1635         }
1636       for (i = 0; i < l; i++)
1637         {
1638           if (cbuf[i] >= 32 || cbuf[i] == '\t' || cbuf[i] == '\r' || cbuf[i] == '\n')
1639             continue;
1640           first++;
1641         }
1642       if (first > 4 && !force)
1643         {
1644           fprintf(stderr, "%s: won't clearsign binaries\n", filename);
1645           exit(1);
1646         }
1647       sock = opensocket();
1648       if (isfilter)
1649         fout = stdout;
1650       else if ((fout = fopen(outfilename, "w")) == 0)
1651         {
1652           perror(outfilename);
1653           exit(1);
1654         }
1655       foutfd = fileno(fout);
1656       fprintf(fout, "-----BEGIN PGP SIGNED MESSAGE-----\nHash: %s\n\n", hashname[hashalgo]);
1657       while (first || (l = read(fd, cbuf + have, cbufl - have)) > 0 || (l == 0 && have))
1658         {
1659           first = 0;
1660           if (nl)
1661             hash_write(&ctx, (unsigned char *)"\r\n",  2);
1662           nl = 0;
1663           l += have;
1664           for (i = 0; i < l; i++)
1665             if (cbuf[i] == '\n')
1666               break;
1667           if (i == l && i == cbufl && l != have)
1668             {
1669               cbufl *= 2;
1670               cbuf = realloc(cbuf, cbufl);
1671               if (!cbuf)
1672                 {
1673                   fprintf(stderr, "no mem for clearsign buffer\n");
1674                   exit(1);
1675                 }
1676               have = l;
1677               continue;
1678             }
1679           if ((l > 0 && cbuf[0] == '-') || (l > 4 && !strncmp((char *)cbuf, "From ", 5)))
1680             fprintf(fout, "- ");
1681           if (i == l)
1682             {
1683               /* EOF reached, line is unterminated */
1684               cbuf[l] = '\n';
1685               l++;
1686             }
1687           if (i > 20000)
1688             {
1689               fprintf(stderr, "line too long for clearsign\n");
1690               exit(1);
1691             }
1692           fwrite(cbuf, 1, i + 1, fout);
1693           for (j = i - 1; j >= 0; j--)
1694             if (cbuf[j] != '\r' && cbuf[j] != ' ' && cbuf[j] != '\t')
1695               break;
1696           if (j >= 0)
1697             hash_write(&ctx, cbuf, j + 1);
1698           nl = 1;
1699           i++;
1700           if (i < l)
1701             memmove(cbuf, cbuf + i, l - i);
1702           have = l - i;
1703         }
1704       if (l < 0)
1705         {
1706           perror("read");
1707           if (!isfilter)
1708             unlink(outfilename);
1709           exit(1);
1710         }
1711       free(cbuf);
1712       cbuf = 0;
1713       cbufl = 0;
1714     }
1715   else if (mode == MODE_KEYID || mode == MODE_PUBKEY)
1716     {
1717       /* sign empty string */
1718       sock = opensocket();
1719     }
1720   else
1721     {
1722       sock = opensocket();
1723       if (mode == MODE_RPMSIGN)
1724         {
1725           md5_init(&md5ctx);
1726           hash_init(&hctx);
1727         }
1728       lensig = 0;
1729       lenhdr = 0;
1730       while ((l = read(fd, buf, sizeof(buf))) > 0)
1731         {
1732           if (!lensig && mode == MODE_RPMSIGN)
1733             {
1734               if (l < 16)
1735                 {
1736                   fprintf(stderr, "cannot calculate header size: short read\n");
1737                   exit(1);
1738                 }
1739               lenhdr = 16;
1740               lenhdr += 16 * (buf[8] << 24 |  buf[9] << 16 | buf[10] << 8 | buf[11]);
1741               lenhdr += buf[12] << 24 |  buf[13] << 16 | buf[14] << 8 | buf[15];
1742             }
1743           if (getbuildtime && !lensig)
1744             {
1745               int n;
1746               n = buf[8] << 24 |  buf[9] << 16 | buf[10] << 8 | buf[11];
1747               if ((l - 16) / 16 < n)
1748                 n = (l - 16) / 16;
1749               for (i = 0; i < n; i++)
1750                 if (!memcmp(buf + 16 + 16 * i, "\0\0\003\356\0\0\0\4", 8))
1751                   break;
1752               if (i == n)
1753                 {
1754                   fprintf(stderr, "cannot calculate buildtime: tag not found\n");
1755                   exit(1);
1756                 }
1757               buildtimeoff = 16 + (buf[8] << 24 |  buf[9] << 16 | buf[10] << 8 | buf[11]) * 16;
1758               i = 16 + 16 * i + 8;
1759               buildtimeoff += buf[i] << 24 |  buf[i + 1] << 16 | buf[i + 2] << 8 | buf[i + 3];
1760             }
1761           if (getbuildtime && lensig < buildtimeoff + 4 && lensig + l > buildtimeoff)
1762             {
1763               for (i = 0; i < l; i++)
1764                 if (lensig + i >= buildtimeoff && lensig + i < buildtimeoff + 4)
1765                   btbuf[lensig + i - buildtimeoff] = buf[i];
1766             }
1767           hash_write(&ctx, buf,  l);
1768           if (mode == MODE_RPMSIGN)
1769             {
1770               md5_write(&md5ctx, buf, l);
1771               if (lenhdr)
1772                 {
1773                   if (l >= lenhdr)
1774                     {
1775                       hash_write(&hctx, buf,  lenhdr);
1776                       lenhdr = 0;
1777                     }
1778                   else
1779                     {
1780                       hash_write(&hctx, buf,  l);
1781                       lenhdr -= l;
1782                     }
1783                 }
1784             }
1785           lensig += l;
1786         }
1787       if (mode == MODE_RPMSIGN)
1788         {
1789           md5_final(rpmmd5sum, &md5ctx);
1790           if (lenhdr)
1791             {
1792               fprintf(stderr, "%s: bad header size (%u)\n", filename, lenhdr);
1793               exit(1);
1794             }
1795         }
1796       if (hdrin_size && lensig != hdrin_size)
1797         {
1798           fprintf(stderr, "%s: SIZE checksum error %d %d\n", filename, hdrin_size, lensig);
1799           exit(1);
1800         }
1801       if (hdrin_md5 && memcmp(hdrin_md5, rpmmd5sum, 16))
1802         {
1803           fprintf(stderr, "%s: MD5 checksum error\n", filename);
1804           exit(1);
1805         }
1806       if (getbuildtime && lensig < buildtimeoff + 4)
1807         {
1808           fprintf(stderr, "cannot calculate buildtime: bad data pointer\n");
1809           exit(1);
1810         }
1811       if (getbuildtime)
1812         signtime = btbuf[0] << 24 | btbuf[1] << 16 | btbuf[2] << 8 | btbuf[3];
1813     }
1814
1815   if (verbose && mode != MODE_KEYID && mode != MODE_PUBKEY)
1816     {
1817       if (*user)
1818         fprintf(isfilter ? stderr : stdout, "%s %s user %s\n", modes[mode],  filename, user);
1819       else
1820         fprintf(isfilter ? stderr : stdout, "%s %s\n", modes[mode],  filename);
1821     }
1822
1823   hash[0] = mode == MODE_CLEARSIGN ? 0x01 : 0x00; /* class */
1824   hash[1] = signtime >> 24;
1825   hash[2] = signtime >> 16;
1826   hash[3] = signtime >> 8;
1827   hash[4] = signtime;
1828   hash_write(&ctx, hash, 5);
1829   hash_final(&ctx);
1830   p = hash_read(&ctx);
1831   ph = 0;
1832   outlh = 0;
1833   if (mode == MODE_RPMSIGN)
1834     {
1835       hash_write(&hctx, hash, 5);
1836       hash_final(&hctx);
1837       /* header only seems to work only if there's a header only hash */
1838       if (!noheaderonly && gotsha1)
1839         ph = hash_read(&hctx);
1840     }
1841
1842   ulen = strlen(user);
1843   if (!privkey && !ph)
1844     {
1845       if (ulen + hashlen[hashalgo] * 2 + 1 + 5 * 2 + 4 + 1 + (hashalgo == HASH_SHA1 ? 0 : strlen(hashname[hashalgo]) + 1) > sizeof(buf))
1846         {
1847           fprintf(stderr, "packet too big\n");
1848           if (mode == MODE_CLEARSIGN && !isfilter)
1849             unlink(outfilename);
1850           exit(1);
1851         }
1852       buf[0] = ulen >> 8;
1853       buf[1] = ulen;
1854       buf[2] = 0;
1855       buf[3] = 0;
1856       memmove(buf + 4, user, ulen);
1857       bp = buf + 4 + ulen;
1858       if (hashalgo != HASH_SHA1)
1859         {
1860           strcpy((char *)bp, hashname[hashalgo]);
1861           bp += strlen((const char *)bp);
1862           *bp++ = ':';
1863         }
1864       if (mode == MODE_PUBKEY)
1865         {
1866           strcpy((char *)bp, "PUBKEY");
1867           bp += 6;
1868         }
1869       else
1870         {
1871           for (i = 0; i < hashlen[hashalgo]; i++, bp += 2)
1872             sprintf((char *)bp, "%02x", p[i]);
1873           *bp++ = '@';
1874           for (i = 0; i < 5; i++, bp += 2)
1875             sprintf((char *)bp, "%02x", hash[i]);
1876         }
1877       buf[3] = bp - (buf + 4 + ulen);
1878       i = bp - buf;
1879       if (write(sock, buf, i) != i)
1880         {
1881           perror("write");
1882           if (mode == MODE_CLEARSIGN && !isfilter)
1883             unlink(outfilename);
1884           exit(1);
1885         }
1886       l = 0;
1887       for (;;)
1888         {
1889           int ll;
1890           if (l == sizeof(buf))
1891             {
1892               fprintf(stderr, "packet too big\n");
1893               exit(1);
1894             }
1895           ll = read(sock, buf + l, sizeof(buf) - l);
1896           if (ll == -1)
1897             {
1898               perror("read");
1899               if (mode == MODE_CLEARSIGN && !isfilter)
1900                 unlink(outfilename);
1901               exit(1);
1902             }
1903           if (ll == 0)
1904             break;
1905           l += ll;
1906         }
1907       close(sock);
1908       if (l < 6)
1909         {
1910           fprintf(stderr, "packet too small\n");
1911           exit(1);
1912         }
1913       outl = buf[2] << 8 | buf[3];
1914       errl = buf[4] << 8 | buf[5];
1915       if (l != outl + errl + 6)
1916         {
1917           fprintf(stderr, "packet size mismatch %d %d %d\n", l, outl, errl);
1918           if (mode == MODE_CLEARSIGN && !isfilter)
1919             unlink(outfilename);
1920           exit(1);
1921         }
1922       if (errl)
1923         fwrite(buf + 6 + outl, 1, errl, stderr);
1924
1925       if (buf[0] << 8 | buf[1])
1926         {
1927           if (mode == MODE_CLEARSIGN && !isfilter)
1928             unlink(outfilename);
1929           exit(buf[0] << 8 | buf[1]);
1930         }
1931     }
1932   else
1933     {
1934       char *args[5], *bp;
1935       char hashhex[1024];
1936       char hashhexh[1024];
1937       int argc;
1938
1939       if (mode == MODE_PUBKEY)
1940         {
1941           fprintf(stderr, "pubkey mode does not work with a private key\n");
1942           exit(1);
1943         }
1944       if (privkey)
1945         readprivkey();
1946       bp = hashhex;
1947       for (i = 0; i < hashlen[hashalgo]; i++, bp += 2)
1948         sprintf(bp, "%02x", p[i]);
1949       *bp++ = '@';
1950       for (i = 0; i < 5; i++, bp += 2)
1951         sprintf(bp, "%02x", hash[i]);
1952       *bp = 0;
1953       if (ph)
1954         {
1955           bp = hashhexh;
1956           for (i = 0; i < hashlen[hashalgo]; i++, bp += 2)
1957             sprintf(bp, "%02x", ph[i]);
1958           *bp++ = '@';
1959           for (i = 0; i < 5; i++, bp += 2)
1960             sprintf(bp, "%02x", hash[i]);
1961           *bp = 0;
1962         }
1963       args[0] = privkey ? "privsign" : "sign";
1964       args[1] = algouser;
1965       argc = 2;
1966       if (privkey)
1967         args[argc++] = privkey;
1968       args[argc++] = hashhex;
1969       if (ph)
1970         args[argc++] = hashhexh;
1971       l = doreq(sock, argc, args, buf, sizeof(buf), ph ? 2 : 1);
1972       close(sock);
1973       if (l < 0)
1974         {
1975           if (mode == MODE_CLEARSIGN && !isfilter)
1976             unlink(outfilename);
1977           exit(-l);
1978         }
1979       if (buf[0] != 0 || buf[1] != (ph ? 2 : 1))
1980         {
1981           if (mode == MODE_CLEARSIGN && !isfilter)
1982             unlink(outfilename);
1983           fprintf(stderr, "bad return count\n");
1984           exit(1);
1985         }
1986       outl = buf[2] << 8 | buf[3];
1987       outlh = ph ? (buf[4] << 8 | buf[5]) : 0;
1988       if (outl == 0 || (ph && outlh == 0))
1989         {
1990           if (mode == MODE_CLEARSIGN && !isfilter)
1991             unlink(outfilename);
1992           fprintf(stderr, "server returned empty signature\n");
1993           exit(1);
1994         }
1995       if (l != outl + outlh + (ph ? 6 : 4))
1996         {
1997           if (mode == MODE_CLEARSIGN && !isfilter)
1998             unlink(outfilename);
1999           fprintf(stderr, "bad return length\n");
2000           exit(1);
2001         }
2002       if (!ph)
2003         memmove(buf + 6, buf + 4, outl);
2004     }
2005   if (mode == MODE_KEYID)
2006     {
2007       int o;
2008       if (outl < 2)
2009         {
2010           fprintf(stderr, "answer package too short\n");
2011           exit(1);
2012         }
2013       if (buf[6] == 0x88)
2014         o = 8;
2015       else if (buf[6] == 0x89)
2016         o = 9;
2017       else if (buf[6] == 0x90)
2018         o = 11;
2019       else
2020         {
2021           fprintf(stderr, "bad answer package: %02x\n", buf[6]);
2022           exit(1);
2023         }
2024       if (buf[o] == 3)
2025         {
2026           printf("%02X%02X%02X%02X\n", buf[o + 11], buf[o + 12], buf[o + 13], buf[o + 14]);
2027           exit(0);
2028         }
2029       else if (buf[o] == 4)
2030         {
2031           /* assumes sign id is first in unhashed data */
2032           o += (buf[o + 4] << 8) + buf[o + 5];  /* skip over hashed data */
2033           if (buf[o + 9] != 16)
2034             {
2035               fprintf(stderr, "issuer not first in unhashed data\n");
2036               exit(1);
2037             }
2038           printf("%02X%02X%02X%02X\n", buf[o + 14], buf[o + 15], buf[o + 16], buf[o + 17]);
2039           exit(0);
2040         }
2041       else
2042         {
2043           fprintf(stderr, "unknown signature version: %d\n", buf[o]);
2044           exit(1);
2045         }
2046     }
2047   if (isfilter)
2048     {
2049       fout = stdout;
2050       foutfd = 1;
2051     }
2052   else if (mode != MODE_CLEARSIGN)
2053     {
2054       if ((fout = fopen(outfilename, "w")) == 0)
2055         {
2056           perror(outfilename);
2057           exit(1);
2058         }
2059       foutfd = fileno(fout);
2060     }
2061
2062   if (mode == MODE_CLEARSIGN || mode == MODE_DETACHEDSIGN)
2063     {
2064       fprintf(fout, "-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v1.0.7 (GNU/Linux)\n\n");
2065       printr64(fout, buf + 6, outl);
2066       crc = crc24(buf + 6, outl);
2067       hash[0] = crc >> 16;
2068       hash[1] = crc >> 8;
2069       hash[2] = crc;
2070       putc('=', fout);
2071       printr64(fout, hash, 3);
2072       fprintf(fout, "-----END PGP SIGNATURE-----\n");
2073     }
2074   else if (mode == MODE_RPMSIGN)
2075     {
2076       if (rpminsertsig(rpmsig, &rpmsigsize, &rpmsigcnt, &rpmsigdlen, hashtag[hashalgo], buf + 6, outl))
2077         {
2078           if (!isfilter)
2079             unlink(outfilename);
2080           exit(1);
2081         }
2082       if (outlh)
2083         {
2084           if (rpminsertsig(rpmsig, &rpmsigsize, &rpmsigcnt, &rpmsigdlen, hashtagh[hashalgo], buf + 6 + outl, outlh))
2085             {
2086               if (!isfilter)
2087                 unlink(outfilename);
2088               exit(1);
2089             }
2090         }
2091       rpmsighead[8]  = rpmsigcnt >> 24;
2092       rpmsighead[9]  = rpmsigcnt >> 16;
2093       rpmsighead[10] = rpmsigcnt >> 8 ;
2094       rpmsighead[11] = rpmsigcnt;
2095
2096       rpmsighead[12] = rpmsigdlen >> 24;
2097       rpmsighead[13] = rpmsigdlen >> 16;
2098       rpmsighead[14] = rpmsigdlen >> 8 ;
2099       rpmsighead[15] = rpmsigdlen;
2100
2101       if (lseek(fd, rpmdataoff, SEEK_SET) == (off_t)-1)
2102         {
2103           perror("lseek");
2104           if (!isfilter)
2105             unlink(outfilename);
2106           exit(1);
2107         }
2108
2109       xwrite(foutfd, rpmlead, 96);
2110       xwrite(foutfd, rpmsighead, 16);
2111       xwrite(foutfd, rpmsig, rpmsigsize);
2112       md5_init(&md5ctx);
2113       lensig = 0;
2114       while ((l = read(fd, buf, sizeof(buf))) > 0)
2115         {
2116           md5_write(&md5ctx, buf, l);
2117           xwrite(foutfd, buf, l);
2118           lensig += l;
2119         }
2120       md5_final(rpmmd5sum2, &md5ctx);
2121       if (memcmp(rpmmd5sum2, rpmmd5sum, 16))
2122         {
2123           fprintf(stderr, "rpm has changed, bailing out!\n");
2124           if (!isfilter)
2125             unlink(outfilename);
2126           exit(1);
2127         }
2128       free(rpmsig);
2129     }
2130   else
2131     fwrite(buf + 6, 1, outl, fout);
2132   if (!isfilter)
2133     {
2134       close(fd);
2135       if (fclose(fout))
2136         {
2137           perror("fclose");
2138           unlink(outfilename);
2139           exit(1);
2140         }
2141       if (mode != MODE_DETACHEDSIGN && rename(outfilename, filename))
2142         {
2143           perror("rename");
2144           unlink(outfilename);
2145           exit(1);
2146         }
2147     }
2148   if (outfilename)
2149     free(outfilename);
2150   return 0;
2151 }
2152
2153 static void
2154 keygen(char *type, char *expire, char *name, char *email)
2155 {
2156   char *args[6];
2157   byte buf[8192];
2158   int l, publ, privl;
2159   int sock = opensocket();
2160
2161   args[0] = "keygen";
2162   args[1] = algouser;
2163   args[2] = type;
2164   args[3] = expire;
2165   args[4] = name;
2166   args[5] = email;
2167   l = doreq(sock, 6, args, buf, sizeof(buf), 2);
2168   close(sock);
2169   if (l < 0)
2170     exit(-l);
2171   publ = buf[2] << 8 | buf[3];
2172   privl = buf[4] << 8 | buf[5];
2173   if (privkey && strcmp(privkey, "-"))
2174     {
2175       int fout;
2176       char *outfilename = malloc(strlen(privkey) + 16);
2177
2178       sprintf(outfilename, "%s.sIgN%d", privkey, getpid());
2179       if ((fout = open(outfilename, O_WRONLY|O_CREAT|O_TRUNC, 0600)) == -1)
2180         {
2181           perror(outfilename);
2182           exit(1);
2183         }
2184       if (write(fout, buf + 6 + publ, privl) != privl)
2185         {
2186           perror("privkey write error");
2187           exit(1);
2188         }
2189       if (write(fout, "\n", 1) != 1)
2190         {
2191           perror("privkey write error");
2192           exit(1);
2193         }
2194       if (close(fout))
2195         {
2196           perror("privkey write error");
2197           exit(1);
2198         }
2199       if (rename(outfilename, privkey))
2200         {
2201           perror(privkey);
2202           exit(1);
2203         }
2204     }
2205   else
2206     {
2207       if (fwrite(buf + 6 + publ, privl, 1, stdout) != 1)
2208         {
2209           fprintf(stderr, "privkey write error\n");
2210           exit(1);
2211         }
2212       printf("\n");
2213     }
2214   if (fwrite(buf + 6, publ, 1, stdout) != 1)
2215     {
2216       fprintf(stderr, "pubkey write error\n");
2217       exit(1);
2218     }
2219   if (fflush(stdout))
2220     {
2221       fprintf(stderr, "pubkey write error\n");
2222       exit(1);
2223     }
2224   exit(0);
2225 }
2226
2227 int
2228 main(int argc, char **argv)
2229 {
2230   FILE *cfp;
2231   char buf[256], *bp;
2232   int c, l;
2233   int allowuser = 0;
2234   struct passwd *pwd = 0;
2235   int mode = MODE_UNSET;
2236
2237   uid = getuid();
2238   if (uid)
2239     pwd = getpwuid(uid);
2240   user = strdup("");
2241   host = strdup("127.0.0.1");
2242   if ((cfp = fopen("/etc/sign.conf", "r")) == 0)
2243     {
2244       perror("/etc/sign.conf");
2245       exit(1);
2246     }
2247   while (fgets(buf, sizeof(buf), cfp))
2248     {
2249       l = strlen(buf);
2250       if (!l)
2251         continue;
2252       if (buf[l - 1] != '\n')
2253         {
2254           while ((c = getc(cfp)) != EOF)
2255             if (c == '\n')
2256               break;
2257           continue;
2258         }
2259       if (*buf == '#')
2260         continue;
2261       buf[--l] = ' ';
2262       while (l && (buf[l] == ' ' || buf[l] == '\t'))
2263         buf[l--] = 0;
2264       for (bp = buf; *bp && *bp != ':'; bp++)
2265         ;
2266       if (!*bp)
2267         continue;
2268       *bp++ = 0;
2269       while (*bp == ' ' || *bp == '\t')
2270         bp++;
2271       if (!strcmp(buf, "user"))
2272         {
2273           user = strdup(bp);
2274           continue;
2275         }
2276       if (!strcmp(buf, "server"))
2277         {
2278           host = strdup(bp);
2279           continue;
2280         }
2281       if (!strcmp(buf, "port"))
2282         {
2283           port = atoi(bp);
2284           continue;
2285         }
2286       if (!strcmp(buf, "hash"))
2287         {
2288           if (!strcasecmp(bp, "sha1"))
2289             hashalgo = HASH_SHA1;
2290           else if (!strcasecmp(bp, "sha256"))
2291             hashalgo = HASH_SHA256;
2292           else
2293             {
2294               fprintf(stderr, "sign: hash: unknown argument\n");
2295               exit(1);
2296             }
2297         }
2298       if (uid && !allowuser && !strcmp(buf, "allowuser"))
2299         {
2300           if (pwd && !strcmp(pwd->pw_name, bp))
2301             allowuser = 1;
2302           else
2303             {
2304               long int li;
2305               char *ep = 0;
2306               li = strtol(bp, &ep, 10);
2307               if (*ep == 0 && li == (long int)uid)
2308                 allowuser = 1;
2309             }
2310         }
2311     }
2312   fclose(cfp);
2313   if (uid)
2314     {
2315       if (!allowuser)
2316         {
2317           fprintf(stderr, "sign: permission denied\n");
2318           exit(1);
2319         }
2320       if (seteuid(uid))
2321         {
2322           perror("seteuid");
2323           exit(1);
2324         }
2325     }
2326   if (argc == 2 && !strcmp(argv[1], "-t"))
2327     {
2328       char buf[6];
2329       int r;
2330       int sock = opensocket();
2331       if (sock == -1)
2332         exit(1);
2333       if (write(sock, "\0\0\0\0", 4) != 4)
2334         {
2335           perror("write");
2336           exit(1);
2337         }
2338       r = read(sock, buf, 6);
2339       if (r == -1)
2340         {
2341           perror("read");
2342           exit(1);
2343         }
2344       close(sock);
2345       if (r != 6)
2346         exit(1);
2347       exit(buf[0] << 8 | buf[1]);
2348     }
2349   while (argc > 1)
2350     {
2351       if (argc > 2 && !strcmp(argv[1], "-u"))
2352         {
2353           user = argv[2];
2354           argc -= 2;
2355           argv += 2;
2356         }
2357       else if (argc > 2 && !strcmp(argv[1], "-h"))
2358         {
2359           if (!strcasecmp(argv[2], "sha1"))
2360             hashalgo = HASH_SHA1;
2361           else if (!strcasecmp(argv[2], "sha256"))
2362             hashalgo = HASH_SHA256;
2363           else
2364             {
2365               fprintf(stderr, "sign: unknown hash algorithm '%s'\n", argv[2]);
2366               exit(1);
2367             }
2368           argc -= 2;
2369           argv += 2;
2370         }
2371       else if (argc > 1 && !strcmp(argv[1], "-c"))
2372         {
2373           mode = MODE_CLEARSIGN;
2374           argc--;
2375           argv++;
2376         }
2377       else if (argc > 1 && !strcmp(argv[1], "-d"))
2378         {
2379           mode = MODE_DETACHEDSIGN;
2380           argc--;
2381           argv++;
2382         }
2383       else if (argc > 1 && !strcmp(argv[1], "-r"))
2384         {
2385           mode = MODE_RPMSIGN;
2386           argc--;
2387           argv++;
2388         }
2389       else if (argc > 1 && !strcmp(argv[1], "-v"))
2390         {
2391           verbose++;
2392           argc--;
2393           argv++;
2394         }
2395       else if (argc > 1 && !strcmp(argv[1], "--noheaderonly"))
2396         {
2397           noheaderonly = 1;
2398           argc--;
2399           argv++;
2400         }
2401       else if (argc > 1 && !strcmp(argv[1], "-k"))
2402         {
2403           mode = MODE_KEYID;
2404           argc--;
2405           argv++;
2406         }
2407       else if (argc > 1 && !strcmp(argv[1], "-p"))
2408         {
2409           mode = MODE_PUBKEY;
2410           argc--;
2411           argv++;
2412         }
2413       else if (argc > 1 && !strcmp(argv[1], "-g"))
2414         {
2415           mode = MODE_KEYGEN;
2416           argc--;
2417           argv++;
2418         }
2419       else if (argc > 2 && !strcmp(argv[1], "-T"))
2420         {
2421           timearg = argv[2];
2422           argc -= 2;
2423           argv += 2;
2424           if (!*timearg || ((*timearg < '0' || *timearg > '9') && strcmp(timearg, "mtime") && strcmp(timearg, "buildtime")))
2425             {
2426               fprintf(stderr, "illegal time argument: %s\n", timearg);
2427               exit(1);
2428             }
2429         }
2430       else if (argc > 2 && !strcmp(argv[1], "-P"))
2431         {
2432           privkey = argv[2];
2433           argc -= 2;
2434           argv += 2;
2435         }
2436       else if (argc > 1 && !strcmp(argv[1], "--"))
2437         {
2438           argc--;
2439           argv++;
2440           break;
2441         }
2442       else if (argc > 1 && argv[1][0] == '-')
2443         {
2444           fprintf(stderr, "usage: sign [-c|-d|-r] [-u user] <file>\n");
2445           exit(1);
2446         }
2447       else
2448         break;
2449     }
2450   if (hashalgo == HASH_SHA1)
2451     algouser = user;
2452   else
2453     {
2454       algouser = malloc(strlen(user) + strlen(hashname[hashalgo]) + 2);
2455       sprintf(algouser, "%s:%s", hashname[hashalgo], user);
2456     }
2457   if ((mode == MODE_KEYID || mode == MODE_PUBKEY) && argc > 1)
2458     {
2459       fprintf(stderr, "usage: sign [-c|-d|-r] [-u user] <file>\n");
2460       exit(1);
2461     }
2462   if (mode == MODE_KEYGEN)
2463     {
2464       if (argc != 5)
2465         {
2466           fprintf(stderr, "usage: sign -g <type> <expire> <name> <email>\n");
2467           exit(1);
2468         }
2469       keygen(argv[1], argv[2], argv[3], argv[4]);
2470       exit(0);
2471     }
2472   if (privkey && access(privkey, R_OK))
2473     {
2474       perror(privkey);
2475       exit(1);
2476     }
2477   if (argc == 1)
2478     sign("<stdin>", 1, mode);
2479   else while (argc > 1)
2480     {
2481       sign(argv[1], 0, mode);
2482       argv++;
2483       argc--;
2484     }
2485   exit(0);
2486 }
2487