1 /* smime.c - Command line tool for testing smimeutil.c
2 *
3 * Copyright (c) 1999 Sampo Kellomaki <sampo@iki.fi>, All Rights Reserved.
4 * License: This software may be distributed under the same license
5 * terms as openssl (i.e. free, but mandatory attribution).
6 *
7 * Official web site: http://zxid.org/Net_SSLeay/smime.html
8 *
9 * 11.9.1999, Created. --Sampo
10 * 13.9.1999, added decryption and sig verification --Sampo
11 * 25.10.1999, added query sig to know who signed --Sampo
12 * 17.11.1999, added detached verification functions --Sampo
13 *
14 * Memory management: most routines malloc the results. Freeing them is
15 * application's responsibility. I use libc malloc, but if in doubt
16 * it might be safer to just leak the memory (i.e. don't ever free it).
17 * This library works entirely in memory, so maximum memory consumption
18 * might be more than twice the total size of all files to be encrypted.
19 *
20 * This tool is not generic in any sense (for that see openssl tool). It has
21 * many choices hard wired in a way that is convenient for me. They are
22 * just one way that works. There are many others equally good, but not
23 * implemented here.
24 *
25 gcc -c -g smimeutil.c -I/usr/local/ssl/include -o smimeutil.o
26 gcc -c -g smime.c -I/usr/local/ssl/include -o smime.o
27 gcc -g smime.o smimeutil.o -L/usr/local/ssl/lib -lcrypto -o smime
28 *
29 * ### For importing to browsers (S/MIME)
30 * openssl pkcs12 -name "End-CA" -nokey -inkey ca-priv.pem -in ca-cert.pem -export >end-ca.p12
31 *
32 * ### Note: to arrange for delivery of the certificate, arrange
33 * ### for web server to send it using mimetype (or extension)
34 * AddType application/x-x509-ca-cert .crt
35 * AddType application/x-pkcs7-crl .crl
36 *
37 * ### then just copy the pem file under extension .crt
38 */
39
40 #include "smimeutil.h"
41
42 char usage[] =
43 SMIME_VERSION "\n"
44 "Copyright (c) 1999 Sampo Kellomaki <sampo@iki.fi>. All Rights Reserved.\n"
45 "See file LICENSE in distribution directory for full copyright and license\n"
46 "information. This file also explains OpenSSL and SSLeay licenses.\n"
47 "Copyright (c) 1999 The OpenSSL Project. All rights reserved.\n"
48 "This product includes software developed by the OpenSSL Project\n"
49 "for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
50 "Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com), All rights reserved.\n"
51 "This product includes cryptographic software written by Eric Young\n"
52 "(eay@cryptsoft.com). This product includes software written by Tim\n"
53 "Hudson (tjh@cryptsoft.com).\n\n"
54
55 "Official web site: http://zxid.org/Net_SSLeay/smime.html\n\n"
56
57 "./smime -cs private password <mime-entity >smime # clear sign\n"
58 "./smime -cv cert <smime-entity >data # verify clear signature\n"
59 "./smime -ds private passwd <file >smime-sig # make detached signature\n"
60 "./smime -dv file <cert+sig-entity # verify detached sig\n"
61 "./smime -s private password <mime-entity >smime # sign\n"
62 "./smime -qs <smime-entity >signing-cert-info # find out who signed\n"
63 "./smime -v cert <smime-entity >signer-dn # verify signature\n\n"
64 "./smime -vc cacert <cert # verify certificate\n\n"
65 "./smime -e public <mime-entity >smime-ent # encrypt\n"
66 "./smime -d private password <smime-entity >mime # decrypt\n\n"
67 "./smime -qr <req.pem # Query all you can about request\n"
68 "./smime -qc <cert.pem # Query all you can about certificate\n"
69 "./smime -ca ca_cert passwd serial <req.pem >cert.pem # sign a req into cert\n\n"
70 "./smime -p12-pem p12pw pempw <x.p12 >x.pem # convert PKCS12 to pem\n"
71 "./smime -pem-p12 frindly@name.com pempw p12pw <x.pem >x.p12 # pem to PKCS12\n\n"
72 "./smime -m type1 file1 type2 file2 type3 file3 <text # make multipart\n"
73 "./smime -m image/gif foo.gif <message | ./smime -s private pass >smime\n\n"
74 "./smime -kg attr passwd req.pem <dn >priv_ss.pem # keygen\n\n"
75 "./smime -base64 <file >file.base64\n"
76 "./smime -unbase64 <file.base64 >file\n"
77 "./smime -mime text/plain <file >mime-entity\n"
78 "./smime -mime_base64 image/gif <file.gif >mime-entity\n"
79 "./smime -split dirprefix <multipart # splits multipart into files\n"
80 "./smime -base64 <in | ./smime -unbase64 >out\n"
81 "./smime -cat <in >out # copy input to output using slurp and barf\n\n"
82 "./smime -kg 'description=Test' secret req.pem <me.dn >ss.pem\n\n"
83 "echo 'countryName=PT|organizationName=Universidade|organizationalUnitName=IST|commonName=t11|emailAddress=t11@test.com' | ./smime -kg 'description=t11' secret r11.pem | tee t11.pem | ./smime -pem-p12 t11@test.com secret secret >t11.p12\n\n"
84 "./smime -p12-pem secret secret <t.p12 | ./smime -qc\n"
85 "./smime -m image/gif a.gif <text | ./smime -cs both.pem 1234 | ./smime -e both.pem | ./send.pl\n\n"
86 "WARNING: passing passwords on command line or environment is not secure. \n"
87 " You can pass\n"
88 " -\\d+ (`-' and a number) to cause the password to be read from fd, or\n"
89 " -[A-Z]+ to cause the password to be taken from an environment variable.\n"
90 " Like this: ./smime -s priv.pem -3 <me >sme\n"
91 " The file descriptor method is the safest. Be careful.\n"
92 ;
93
94 #include <stdio.h>
95 #include <string.h>
96 #include <stdlib.h>
97
98 #define DETACHED_SIG_TYPE_FILE "application/x-detached-file-signature-file"
99
100 /* Read all of a file descriptor to malloc'd buffer, return size.
101 * This repeatedly reallocs the buffer (probably internally copying
102 * the contents each time). This is a bit inefficient, but will do
103 * for quick and dirty now.
104 */
105
106 /* Called by: get_passwd, main x22, mk_multipart, read_file */
slurp(FILE * fd,char ** pb)107 static int slurp(FILE* fd, char** pb)
108 {
109 int n = 0;
110 int nn;
111 if (!fd) /*return -1*/ exit(1);;
112 if (!pb) /*return -1*/ exit(1);;
113 if ((*pb = (char*)malloc(4097))==NULL) /*return -1;*/ exit(1);
114
115 for(;;) {
116 nn = fread((*pb)+n, 1, 4096, fd);
117 if (nn <= 0) break;
118 n+=nn;
119 if ((*pb = (char*)realloc(*pb, n+4097))==NULL) /*return -1;*/ exit(1);
120 }
121 if (nn<0) /*return -1*/ exit(1);;
122
123 /* add NULL termination and shrink the buffer */
124
125 (*pb)[n] = '\0';
126 if ((*pb = (char*)realloc(*pb, n+1))==NULL) /*return -1*/ exit(1);;
127 return n; /* returns file length */
128 }
129
130 /* Called by: main x12, write_file */
barf(FILE * fd,char * b,int len)131 static int barf(FILE* fd, char* b, int len)
132 {
133 int n = 0;
134 int nn;
135 if (!fd) return -1;
136 if (!b) return -1;
137
138 for (;;) {
139 /*nn = fwrite(b+n, 1, (len - n) > 4096 ? 4096 : (len-n), fd);*/
140 nn = fwrite(b+n, 1, (len - n), fd);
141 if (nn <= 0) break;
142 n+=nn;
143 }
144 if (nn<0) return -1;
145 return n;
146 }
147
148 /* Called by: main x10, mk_multipart x3 */
read_file(char * file,char * type,char ** data)149 static int read_file(char* file, char* type, char** data) {
150 FILE* fd;
151 int n;
152
153 if (!(fd = fopen(file, "rb"))) {
154 fprintf(stderr, "File `%s' not found? (type=%s)\n", file, type);
155 perror(file);
156 exit(1);
157 }
158 n = slurp(fd, data);
159 fclose(fd);
160 return n; /* returns file length */
161 }
162
163 /* Called by: main x2 */
write_file(char * file,char * type,char * data,int len)164 static int write_file(char* file, char* type, char* data, int len) {
165 FILE* fd;
166 int n;
167
168 if (!(fd = fopen(file, "wb"))) {
169 fprintf(stderr, "Cant write file `%s' (type=%s)\n", file, type);
170 perror(file);
171 exit(1);
172 }
173 n = barf(fd, data, len);
174 fclose(fd);
175 return n;
176 }
177
178 /* --------------------- */
179
180 /* Get password from file descriptor or environment variable */
181
182 /* Called by: main x10 */
get_passwd(const char * pass)183 const char* get_passwd(const char* pass)
184 {
185 FILE* in = NULL;
186 char* p;
187 int fd;
188
189 if (pass[0] != '-') return pass;
190 p = (char*)(pass+1);
191 if (strlen(p) == strspn(p, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) {
192 /* Environment */
193 if (!(p = getenv(p))) {
194 fprintf(stderr, "No password environment variable `%s'\n", pass);
195 exit(1);
196 }
197 return p;
198 }
199
200 if (strlen(p) != strspn(p, "0123456789")) return pass;
201
202 /* Read it from file descriptor */
203
204 fd = atoi(p);
205 if (!(in = fdopen(fd, "r"))) {
206 fprintf(stderr, "Cant open file descriptor %d for reading password\n", fd);
207 perror("fdopen");
208 exit(1);
209 }
210 slurp(in, &p);
211 return p;
212 }
213
214 /* --------------------- */
215
216 /* Called by: main */
mk_multipart(int ac,char * av[])217 static char* mk_multipart (int ac, char* av[]) {
218 char* text;
219 char* f1 = NULL;
220 char* f2 = NULL;
221 char* f3 = NULL;
222 char* t1 = NULL;
223 char* t2 = NULL;
224 char* t3 = NULL;
225 char* n1 = NULL;
226 char* n2 = NULL;
227 char* n3 = NULL;
228 int l1 = 0, l2 = 0, l3 = 0;
229
230 /* Read attachment files, if any */
231
232 av++; ac--;
233 if (ac>1) {
234 t1 = *av;
235 av++; ac--;
236 l1 = read_file(n1=*av, t1, &f1);
237
238 av++; ac--;
239 if (ac>1) {
240 t2 = *av;
241 av++; ac--;
242 l2 = read_file(n2=*av, t2, &f2);
243
244 av++; ac--;
245 if (ac>1) {
246 t3 = *av;
247 av++; ac--;
248 l3 = read_file(n3=*av, t3, &f3);
249 }
250 }
251 }
252
253 /* Read text from stdin */
254
255 slurp(stdin, &text);
256
257 return mime_mk_multipart(text,
258 f1, l1, t1, n1,
259 f2, l2, t2, n2,
260 f3, l3, t3, n3);
261 }
262
263 #define TOO_FEW_OPTIONS(ac,n,s) if ((ac)<(n)) { \
264 fprintf(stderr, "%s needs %d arguments (%d supplied).\n%s", (s), n, ac, \
265 usage); exit(1); }
266
267 /* ===== M A I N ===== */
268
269 /* Called by: */
main(int ac,char * av[])270 int main(int ac, char* av[]) {
271 av++; ac--;
272
273 if (ac < 1) {
274 fprintf(stderr, "Too few options. Need to provide a command switch.\n%s",
275 usage);
276 exit(1);
277 }
278
279 smime_init("random.txt", "ssaddsfa", 8 );
280
281 /* ./smime -base64 <file >file.base64 */
282 if (!strcmp(*av, "-base64")) {
283 int n, nn;
284 char* b;
285 char* b64;
286 n = slurp(stdin, &b);
287 nn = smime_base64(1, b, n, &b64);
288 fprintf(stderr, "%d bytes in, %d bytes out\n", n, nn);
289 barf(stdout, b64, nn);
290 exit(nn > 0 ? 0 : 1);
291 }
292
293 /* ./smime -unbase64 <file.base64 >file */
294 if (!strcmp(*av, "-unbase64")) {
295 int n, nn;
296 char* b;
297 char* b64;
298 n = slurp(stdin, &b);
299 nn = smime_base64(0, b, n, &b64);
300 fprintf(stderr, "%d bytes in, %d bytes out\n", n, nn);
301 barf(stdout, b64, nn);
302 exit(nn > 0 ? 0 : 1);
303 }
304
305 /* ./smime -cat <in >out */
306 if (!strcmp(*av, "-cat")) {
307 int n;
308 char* b;
309 n = slurp(stdin, &b);
310 fprintf(stderr, "%d bytes\n", n);
311 barf(stdout, b, n);
312 exit(n > 0 ? 0 : 1);
313 }
314
315 /* ./smime -mime text/plain <file >mime-entity */
316 if (!strcmp(*av, "-mime")) {
317 int n, nn;
318 char* b;
319 char* b64;
320
321 ac--; av++;
322 TOO_FEW_OPTIONS(ac,1,"-mime");
323
324 n = slurp(stdin, &b);
325 b64 = mime_raw_entity(b, av[0]);
326 fprintf(stderr, "%d bytes in, %d bytes out\n", n, nn=strlen(b64));
327 barf(stdout, b64, nn);
328 exit(nn > 0 ? 0 : 1);
329 }
330
331 /* ./smime -split dirprefix <multipart # splits multipart into files */
332 if (!strcmp(*av, "-split")) {
333 int n, nn;
334 char* b;
335 char* parts[100];
336 int lengths[100];
337 char file[4096];
338
339 ac--; av++;
340 TOO_FEW_OPTIONS(ac,1,"-split");
341
342 n = slurp(stdin, &b);
343 if ((nn = mime_split_multipart(b, 100, parts, lengths))==-1) {
344 fprintf(stderr, "mime error\n%s", smime_get_errors());
345 exit(1);
346 }
347
348 /* Write out the parts */
349
350 for (n = 0; n < nn; n++) {
351 snprintf(file, sizeof(file), "%s%d", av[0], n);
352 fprintf(stderr, "%s\n", file);
353 write_file(file, "part", parts[n], lengths[n]);
354 }
355
356 exit(0);
357 }
358
359 /* ./smime -mime_base64 image/gif <file.gif >mime-entity */
360 if (!strcmp(*av, "-mime_base64")) {
361 int n, nn;
362 char* b;
363 char* b64;
364
365 ac--; av++;
366 TOO_FEW_OPTIONS(ac,1,"-mime_base64");
367
368 n = slurp(stdin, &b);
369 b64 = mime_base64_entity(b, n, av[0]);
370 fprintf(stderr, "%d bytes in, %d bytes out\n", n, nn=strlen(b64));
371 barf(stdout, b64, nn);
372 exit(nn > 0 ? 0 : 1);
373 }
374
375 /* ./smime -m type1 file1 type2 file2 type3 file3 <text # make multipart */
376 if (!strcmp(*av, "-m")) {
377 char* mime;
378 if (!(mime = mk_multipart(ac, av))) exit(1);
379 barf(stdout, mime, strlen(mime));
380 exit(0);
381 }
382
383 /* ./smime -cs private password <mime-entity >smime */
384 if (!strcmp(*av, "-cs")) {
385 char* smime;
386 char* mime;
387 char* privkey;
388
389 ac--; av++;
390 TOO_FEW_OPTIONS(ac,2,"-cs");
391
392 slurp(stdin, &mime);
393 read_file(av[0], "privkey", &privkey);
394
395 if (!(smime = smime_clear_sign(privkey, get_passwd(av[1]), mime))) {
396 fprintf(stderr, "crypto error\n%s", smime_get_errors());
397 exit(1);
398 }
399 barf(stdout, smime, strlen(smime));
400 exit(0);
401 }
402
403 /* ./smime -s private password <mime-entity >smime */
404 if (!strcmp(*av, "-s")) {
405 char* smime;
406 char* mime;
407 char* privkey;
408
409 ac--; av++;
410 TOO_FEW_OPTIONS(ac,2,"-s");
411
412 slurp(stdin, &mime);
413 read_file(av[0], "privkey", &privkey);
414
415 if (!(smime = smime_sign(privkey, get_passwd(av[1]), mime))) {
416 fprintf(stderr, "crypto error\n%s", smime_get_errors());
417 exit(1);
418 }
419 barf(stdout, smime, strlen(smime));
420 exit(0);
421 }
422
423 /* ./smime -v cert <smime-entity >signer-dn # verify sig */
424 if (!strcmp(*av, "-v")) {
425 char* cert;
426 char* smime;
427 char* signed_data;
428 int n = slurp(stdin, &smime);
429
430 ac--; av++;
431 TOO_FEW_OPTIONS(ac,1,"-v");
432
433 fprintf(stderr, "%d bytes in\n", n);
434 read_file(av[0], "cert", &cert);
435
436 if (!(signed_data = smime_verify_signature(cert, smime, NULL, 0))) {
437 fprintf(stderr, "crypto error\n%s", smime_get_errors());
438 exit(1);
439 }
440 fputs(signed_data, stdout); /* careful not to output trailing newline */
441 exit(0);
442 }
443
444 /* ./smime -cv cert <smime-entity >signer-dn # verify clear signature */
445 if (!strcmp(*av, "-cv")) {
446 char* cert;
447 char* smime;
448 char* parts[2]; /* parts[0] is the clear text, parts[1] is the sig */
449 int lengths[2];
450 char* signed_data;
451 int n = slurp(stdin, &smime);
452
453 ac--; av++;
454 TOO_FEW_OPTIONS(ac,1,"-cv");
455
456 fprintf(stderr, "%d bytes in\n", n);
457 read_file(av[0], "cert", &cert);
458
459 /* multipart/signed has always exactly two parts */
460
461 if (mime_split_multipart(smime, 2, parts, lengths) != 2) {
462 fprintf(stderr, "mime error\n%s", smime_get_errors());
463 exit(1);
464 }
465
466 if (!(signed_data =
467 smime_verify_signature(cert, parts[1] /*sig*/,
468 parts[0] /*plain*/, lengths[0]))) {
469 fprintf(stderr, "crypto error\n%s", smime_get_errors());
470 exit(1);
471 }
472 fputs(signed_data, stdout); /* careful not to output trailing newline */
473 exit(0);
474 }
475
476 /* ./smime -vc cacert <cert # verify certificate */
477 if (!strcmp(*av, "-vc")) {
478 char* cert;
479 char* ca_cert;
480 int x;
481 int n = slurp(stdin, &cert);
482
483 ac--; av++;
484 TOO_FEW_OPTIONS(ac,1,"-vc");
485
486 fprintf(stderr, "%d bytes in\n", n);
487 read_file(av[0], "ca_cert", &ca_cert);
488
489 x = smime_verify_cert(ca_cert, cert);
490
491 if (x == 1) {
492 printf("OK\n");
493 exit(0);
494 }
495
496 if (x == 0) {
497 printf("NOT OK\n");
498 exit(2);
499 }
500
501 fprintf(stderr, "crypto error\n%s", smime_get_errors());
502 exit(1);
503 }
504
505 /* ./smime -ds private passwd <file >smime-sig # make detached signature */
506
507 if (!strcmp(*av, "-ds")) {
508 char* file;
509 char* smime;
510 char* mime;
511 char* privkey;
512 char* parts[2]; /* parts[0] is the clear text, parts[1] is the sig */
513 int lengths[2];
514 int n;
515
516 ac--; av++;
517 TOO_FEW_OPTIONS(ac,2,"-ds");
518
519 n = slurp(stdin, &file);
520 read_file(av[0], "privkey", &privkey);
521
522 if (!(mime = mime_base64_entity(file, n, DETACHED_SIG_TYPE_FILE))) {
523 fprintf(stderr, "mime error\n%s", smime_get_errors());
524 exit(1);
525 }
526
527 if (!(smime = smime_clear_sign(privkey, get_passwd(av[1]), mime))) {
528 fprintf(stderr, "crypto error\n%s", smime_get_errors());
529 exit(1);
530 }
531
532 if (mime_split_multipart(smime, 2, parts, lengths) != 2) {
533 fprintf(stderr, "mime error\n%s", smime_get_errors());
534 exit(1);
535 }
536
537 barf(stdout, parts[1], lengths[1]);
538 exit(0);
539 }
540
541 /* ./smime -dv file <sig+cert # verify detached signature */
542
543 if (!strcmp(*av, "-dv")) {
544 char* sig;
545 char* file;
546 char* cert;
547 char* mime;
548 char* canon;
549 char* p;
550 char c;
551 int n;
552
553 ac--; av++;
554 TOO_FEW_OPTIONS(ac,1,"-dv");
555
556 n = slurp(stdin, &sig);
557 if (!(p = strstr(sig, "-----BEGIN CERTIFICATE-----"))) {
558 fprintf(stderr, "No certificate found in stdin.\n");
559 exit(1);
560 }
561
562 if (p == sig) {
563 /* Certificate first, then signature */
564
565 if (!(p = strstr(sig, "-----END CERTIFICATE-----"))) exit(1);
566 p+=strlen("-----END CERTIFICATE-----");
567 if (*p == '\015') p++;
568 if (*p == '\012') p++;
569 c = p[0];
570 p[0] = '\0';
571 cert = strdup(sig);
572 p[0] = c;
573 sig = p;
574
575 } else {
576
577 /* Signature first, then certificate */
578
579 p[0] = '\0';
580 sig = strdup(sig);
581 p[0] = '-';
582 cert = p;
583 }
584
585 n = read_file(av[0], "file", &file);
586
587 /* wrap the file in mime entity */
588
589 if (!(mime = mime_base64_entity(file, n, DETACHED_SIG_TYPE_FILE))) {
590 fprintf(stderr, "mime error\n%s", smime_get_errors());
591 exit(1);
592 }
593
594 /* Must canonize, otherwise the sig will not verify */
595
596 if (!(canon = mime_canon(mime))) {
597 fprintf(stderr, "canon error\n%s", smime_get_errors());
598 exit(1);
599 }
600
601 if (!smime_verify_signature(cert, sig, canon, strlen(canon))) {
602 fprintf(stderr, "crypto error\n%s", smime_get_errors());
603 exit(1);
604 }
605 printf("Signature verified OK.\n");
606 exit(0);
607 }
608
609 /* ./smime -e public <mime-entity >smime-ent */
610 if (!strcmp(*av, "-e")) {
611 char* smime;
612 char* mime;
613 char* cert;
614
615 ac--; av++;
616 TOO_FEW_OPTIONS(ac,1,"-e");
617
618 slurp(stdin, &mime);
619 read_file(av[0], "cert", &cert);
620
621 if (!(smime = smime_encrypt(cert, mime))) {
622 fprintf(stderr, "crypto error\n%s", smime_get_errors());
623 exit(1);
624 }
625 barf(stdout, smime, strlen(smime));
626 exit(0);
627 }
628
629 /* ./smime -d private password <smime-entity >mime # decrypt */
630 if (!strcmp(*av, "-d")) {
631 char* smime;
632 char* mime;
633 char* privkey;
634 int n;
635
636 ac--; av++;
637 TOO_FEW_OPTIONS(ac,2,"-d");
638
639 n = slurp(stdin, &smime);
640 read_file(av[0], "privkey", &privkey);
641
642 if ((n = smime_decrypt(privkey, get_passwd(av[1]), smime, &mime)) < 0) {
643 fprintf(stderr, "crypto error\n%s", smime_get_errors());
644 exit(1);
645 }
646 barf(stdout, mime, n);
647 exit(0);
648 }
649
650 /* ./smime -kg attr password priv_x509ss.pem req.pem <dn >modulus */
651
652 if (!strcmp(*av, "-kg")) {
653 char* dn;
654 char* priv;
655 char* x509ss;
656 char* request;
657
658 ac--; av++;
659 TOO_FEW_OPTIONS(ac,2,"-kg");
660
661 slurp(stdin, &dn);
662
663 if (smime_keygen(dn, av[0] /*attr*/, get_passwd(av[1]),
664 "Test certificate. See http://www.bacus.pt/Net_SSLeay/smime.html",
665 &priv, &x509ss, &request)<0) {
666 fprintf(stderr, "crypto error\n%s", smime_get_errors());
667 exit(1);
668 }
669
670 puts(priv);
671 puts(x509ss);
672 write_file(av[2], "pem", request, strlen(request));
673 exit(0);
674 }
675
676 /* ./smime -qr <req.pem # Query all you can about request */
677
678 if (!strcmp(*av, "-qr")) {
679 char* req;
680 char* name;
681 char* attr;
682 char* mod;
683 char* md5;
684 char* hash;
685 char block1[14];
686 int n = slurp(stdin, &req);
687 fprintf(stderr, "%d bytes in\n", n);
688
689 if (!(name = smime_get_req_name(req))) {
690 fprintf(stderr, "crypto error\n%s", smime_get_errors());
691 exit(1);
692 }
693 puts(name);
694
695 if (!(attr = smime_get_req_attr(req))) {
696 fprintf(stderr, "crypto error\n%s", smime_get_errors());
697 exit(1);
698 }
699 puts(attr);
700
701 if (!(mod = smime_get_req_modulus(req))) {
702 fprintf(stderr, "crypto error\n%s", smime_get_errors());
703 exit(1);
704 }
705 puts(mod);
706
707 if (!(md5 = smime_md5(mod))) {
708 fprintf(stderr, "crypto error\n%s", smime_get_errors());
709 exit(1);
710 }
711 puts(md5);
712
713 if (!(hash = smime_get_req_hash(req))) {
714 fprintf(stderr, "crypto error\n%s", smime_get_errors());
715 exit(1);
716 }
717 memcpy(block1, hash, 13);
718 block1[13] = '\0';
719 printf("\n*%s*\n*%s*\n", block1, hash+13);
720 exit(0);
721 }
722
723 /* ./smime -qc <cert.pem # Query all you can about certificate */
724
725 if (!strcmp(*av, "-qc")) {
726 char* cert;
727 char* name;
728 char* issuer;
729 char* fingerprint;
730 char* mod;
731 char* md5;
732 long serial;
733 int n = slurp(stdin, &cert);
734 fprintf(stderr, "%d bytes in\n", n);
735
736 if ((serial = smime_get_cert_names(cert, &name, &issuer)) == -1) {
737 fprintf(stderr, "crypto error\n%s", smime_get_errors());
738 exit(1);
739 }
740 puts(name);
741 puts(issuer);
742 printf("serial: %ld\n", serial);
743
744 if ((serial = smime_get_cert_info(cert, &mod, &fingerprint)) == -1) {
745 fprintf(stderr, "crypto error\n%s", smime_get_errors());
746 exit(1);
747 }
748
749 printf("serial: %ld\n", serial);
750
751 puts(fingerprint);
752 puts(mod);
753
754 if (!(md5 = smime_md5(mod))) {
755 fprintf(stderr, "crypto error\n%s", smime_get_errors());
756 exit(1);
757 }
758 puts(md5);
759 exit(0);
760 }
761
762 /* ./smime -qs <smime-entity >signing-cert-info
763 * find out who signed (query sig) */
764 if (!strcmp(*av, "-qs")) {
765 char* issuer;
766 char* signed_entity;
767 long serial;
768 int sig_count = 0;
769 int n = slurp(stdin, &signed_entity);
770 fprintf(stderr, "%d bytes in\n", n);
771
772 while ((serial = smime_get_signer_info(signed_entity,
773 sig_count, &issuer)) != -1) {
774 puts(issuer);
775 printf("serial: %ld\n", serial);
776 sig_count++;
777 }
778 if (!sig_count) {
779 fprintf(stderr, "crypto error\n%s", smime_get_errors());
780 exit(1);
781 }
782 exit(0);
783 }
784
785 /* ./smime -ca ca_cert passwd serial <req.pem >cert.pem */
786
787 if (!strcmp(*av, "-ca")) {
788 char* req;
789 char* ca_cert;
790 char* cert;
791 slurp(stdin, &req);
792
793 ac--; av++;
794 TOO_FEW_OPTIONS(ac,3,"-ca");
795
796 read_file(av[0], "ca_cert_pem", &ca_cert);
797
798 if (!(cert = smime_ca(ca_cert, get_passwd(av[1]), req,
799 "today", "days:365", atoi(av[2]),
800 "CA:TRUE,pathlen:3",
801 "client,server,email,objsign,sslCA,emailCA,objCA",
802 "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign",
803 "Test certificate. See http://www.bacus.pt/Net_SSLeay/smime.html"))) {
804 fprintf(stderr, "crypto error\n%s", smime_get_errors());
805 exit(1);
806 }
807 puts(cert);
808 exit(0);
809 }
810
811 /* ./smime -p12-pem imppw0 exppw1 <x.p12 >x.pem */
812
813 if (!strcmp(*av, "-p12-pem")) {
814 char* x;
815 char* pk;
816 char* cert;
817 int n = slurp(stdin, &x);
818
819 ac--; av++;
820 TOO_FEW_OPTIONS(ac,2,"-p12-pem");
821
822 if (smime_pkcs12_to_pem(x, n, get_passwd(av[0]), get_passwd(av[1]),
823 &pk, &cert) == -1) {
824 fprintf(stderr, "crypto error\n%s", smime_get_errors());
825 exit(1);
826 }
827
828 puts(pk);
829 puts(cert);
830 exit(0);
831 }
832
833 /* ./smime -pem-p12 frindly@name0 pw1 pw2 <x.pem >x.p12 */
834
835 if (!strcmp(*av, "-pem-p12")) {
836 char* x;
837 char* pkcs12;
838 int n = slurp(stdin, &x);
839
840 ac--; av++;
841 TOO_FEW_OPTIONS(ac,3,"-pem-p12");
842
843 if ((n = smime_pem_to_pkcs12(av[0], x /*cert*/, x /*privkey*/,
844 get_passwd(av[1]), get_passwd(av[2]),
845 &pkcs12)) == -1) {
846 fprintf(stderr, "crypto error\n%s", smime_get_errors());
847 exit(1);
848 }
849
850 barf(stdout, pkcs12, n);
851 exit(0);
852 }
853
854 fprintf(stderr, "Unknown option.\n%s", usage);
855 return 1;
856 }
857
858 /* EOF - smime.c */
859