Branch data Line data Source code
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 : : #ifndef macintosh
98 : : # include <malloc.h>
99 : : #endif
100 : :
101 : : #define DETACHED_SIG_TYPE_FILE "application/x-detached-file-signature-file"
102 : :
103 : : /* Read all of a file descriptor to malloc'd buffer, return size.
104 : : * This repeatedly reallocs the buffer (probably internally copying
105 : : * the contents each time). This is a bit inefficient, but will do
106 : : * for quick and dirty now.
107 : : */
108 : :
109 : : /* Called by: get_passwd, main x22, mk_multipart, read_file */
110 : : static int slurp(FILE* fd, char** pb)
111 : 52 : {
112 : 52 : int n = 0;
113 : : int nn;
114 [ - + ]: 52 : if (!fd) /*return -1*/ exit(1);;
115 [ - + ]: 52 : if (!pb) /*return -1*/ exit(1);;
116 [ - + ]: 52 : if ((*pb = (char*)malloc(4097))==NULL) /*return -1;*/ exit(1);
117 : :
118 : : for(;;) {
119 : 98 : nn = fread((*pb)+n, 1, 4096, fd);
120 [ + + ]: 98 : if (nn <= 0) break;
121 : 46 : n+=nn;
122 [ - + ]: 46 : if ((*pb = (char*)realloc(*pb, n+4097))==NULL) /*return -1;*/ exit(1);
123 : 46 : }
124 [ - + ]: 52 : if (nn<0) /*return -1*/ exit(1);;
125 : :
126 : : /* add NULL termination and shrink the buffer */
127 : :
128 : 52 : (*pb)[n] = '\0';
129 [ - + ]: 52 : if ((*pb = (char*)realloc(*pb, n+1))==NULL) /*return -1*/ exit(1);;
130 : 52 : return n; /* returns file length */
131 : : }
132 : :
133 : : /* Called by: main x12, write_file */
134 : : static int barf(FILE* fd, char* b, int len)
135 : 17 : {
136 : 17 : int n = 0;
137 : : int nn;
138 [ - + ]: 17 : if (!fd) return -1;
139 [ - + ]: 17 : if (!b) return -1;
140 : :
141 : : for (;;) {
142 : : /*nn = fwrite(b+n, 1, (len - n) > 4096 ? 4096 : (len-n), fd);*/
143 : 34 : nn = fwrite(b+n, 1, (len - n), fd);
144 [ + + ]: 34 : if (nn <= 0) break;
145 : 17 : n+=nn;
146 : 17 : }
147 [ - + ]: 17 : if (nn<0) return -1;
148 : 17 : return n;
149 : : }
150 : :
151 : : /* Called by: main x10, mk_multipart x3 */
152 : 17 : static int read_file(char* file, char* type, char** data) {
153 : : FILE* fd;
154 : : int n;
155 : :
156 [ - + ]: 17 : if (!(fd = fopen(file, "rb"))) {
157 : 0 : fprintf(stderr, "File `%s' not found? (type=%s)\n", file, type);
158 : 0 : perror(file);
159 : 0 : exit(1);
160 : : }
161 : 17 : n = slurp(fd, data);
162 : 17 : fclose(fd);
163 : 17 : return n; /* returns file length */
164 : : }
165 : :
166 : : /* Called by: main x2 */
167 : 2 : static int write_file(char* file, char* type, char* data, int len) {
168 : : FILE* fd;
169 : : int n;
170 : :
171 [ - + ]: 2 : if (!(fd = fopen(file, "wb"))) {
172 : 0 : fprintf(stderr, "Cant write file `%s' (type=%s)\n", file, type);
173 : 0 : perror(file);
174 : 0 : exit(1);
175 : : }
176 : 2 : n = barf(fd, data, len);
177 : 2 : fclose(fd);
178 : 2 : return n;
179 : : }
180 : :
181 : : /* --------------------- */
182 : :
183 : : /* Get password from file descriptor or environment variable */
184 : :
185 : : /* Called by: main x10 */
186 : : const char* get_passwd(const char* pass)
187 : 14 : {
188 : 14 : FILE* in = NULL;
189 : : char* p;
190 : : int fd;
191 : :
192 [ + - ]: 14 : if (pass[0] != '-') return pass;
193 : 0 : p = (char*)(pass+1);
194 [ # # ]: 0 : if (strlen(p) == strspn(p, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) {
195 : : /* Environment */
196 [ # # ]: 0 : if (!(p = getenv(p))) {
197 : 0 : fprintf(stderr, "No password environment variable `%s'\n", pass);
198 : 0 : exit(1);
199 : : }
200 : 0 : return p;
201 : : }
202 : :
203 [ # # ]: 0 : if (strlen(p) != strspn(p, "0123456789")) return pass;
204 : :
205 : : /* Read it from file descriptor */
206 : :
207 : 0 : fd = atoi(p);
208 [ # # ]: 0 : if (!(in = fdopen(fd, "r"))) {
209 : 0 : fprintf(stderr, "Cant open file descriptor %d for reading password\n", fd);
210 : 0 : perror("fdopen");
211 : 0 : exit(1);
212 : : }
213 : 0 : slurp(in, &p);
214 : 0 : return p;
215 : : }
216 : :
217 : : /* --------------------- */
218 : :
219 : : /* Called by: main */
220 : 1 : static char* mk_multipart (int ac, char* av[]) {
221 : : char* text;
222 : 1 : char* f1 = NULL;
223 : 1 : char* f2 = NULL;
224 : 1 : char* f3 = NULL;
225 : 1 : char* t1 = NULL;
226 : 1 : char* t2 = NULL;
227 : 1 : char* t3 = NULL;
228 : 1 : char* n1 = NULL;
229 : 1 : char* n2 = NULL;
230 : 1 : char* n3 = NULL;
231 : 1 : int l1 = 0, l2 = 0, l3 = 0;
232 : :
233 : : /* Read attachment files, if any */
234 : :
235 : 1 : av++; ac--;
236 [ + - ]: 1 : if (ac>1) {
237 : 1 : t1 = *av;
238 : 1 : av++; ac--;
239 : 1 : l1 = read_file(n1=*av, t1, &f1);
240 : :
241 : 1 : av++; ac--;
242 [ - + ]: 1 : if (ac>1) {
243 : 0 : t2 = *av;
244 : 0 : av++; ac--;
245 : 0 : l2 = read_file(n2=*av, t2, &f2);
246 : :
247 : 0 : av++; ac--;
248 [ # # ]: 0 : if (ac>1) {
249 : 0 : t3 = *av;
250 : 0 : av++; ac--;
251 : 0 : l3 = read_file(n3=*av, t3, &f3);
252 : : }
253 : : }
254 : : }
255 : :
256 : : /* Read text from stdin */
257 : :
258 : 1 : slurp(stdin, &text);
259 : :
260 : 1 : return mime_mk_multipart(text,
261 : : f1, l1, t1, n1,
262 : : f2, l2, t2, n2,
263 : : f3, l3, t3, n3);
264 : : }
265 : :
266 : : #define TOO_FEW_OPTIONS(ac,n,s) if ((ac)<(n)) { \
267 : : fprintf(stderr, "%s needs %d arguments (%d supplied).\n%s", (s), n, ac, \
268 : : usage); exit(1); }
269 : :
270 : : /* ===== M A I N ===== */
271 : :
272 : : /* Called by: */
273 : 35 : int main(int ac, char* av[]) {
274 : 35 : av++; ac--;
275 : :
276 [ - + ]: 35 : if (ac < 1) {
277 : 0 : fprintf(stderr, "Too few options. Need to provide a command switch.\n%s",
278 : : usage);
279 : 0 : exit(1);
280 : : }
281 : :
282 : 35 : smime_init("random.txt", "ssaddsfa", 8 );
283 : :
284 : : /* ./smime -base64 <file >file.base64 */
285 [ + + ]: 35 : if (!strcmp(*av, "-base64")) {
286 : : int n, nn;
287 : : char* b;
288 : : char* b64;
289 : 1 : n = slurp(stdin, &b);
290 : 1 : nn = smime_base64(1, b, n, &b64);
291 : 1 : fprintf(stderr, "%d bytes in, %d bytes out\n", n, nn);
292 : 1 : barf(stdout, b64, nn);
293 : 1 : exit(nn > 0 ? 0 : 1);
294 : : }
295 : :
296 : : /* ./smime -unbase64 <file.base64 >file */
297 [ + + ]: 34 : if (!strcmp(*av, "-unbase64")) {
298 : : int n, nn;
299 : : char* b;
300 : : char* b64;
301 : 1 : n = slurp(stdin, &b);
302 : 1 : nn = smime_base64(0, b, n, &b64);
303 : 1 : fprintf(stderr, "%d bytes in, %d bytes out\n", n, nn);
304 : 1 : barf(stdout, b64, nn);
305 : 1 : exit(nn > 0 ? 0 : 1);
306 : : }
307 : :
308 : : /* ./smime -cat <in >out */
309 [ + + ]: 33 : if (!strcmp(*av, "-cat")) {
310 : : int n;
311 : : char* b;
312 : 1 : n = slurp(stdin, &b);
313 : 1 : fprintf(stderr, "%d bytes\n", n);
314 : 1 : barf(stdout, b, n);
315 : 1 : exit(n > 0 ? 0 : 1);
316 : : }
317 : :
318 : : /* ./smime -mime text/plain <file >mime-entity */
319 [ + + ]: 32 : if (!strcmp(*av, "-mime")) {
320 : : int n, nn;
321 : : char* b;
322 : : char* b64;
323 : :
324 : 7 : ac--; av++;
325 [ - + ]: 7 : TOO_FEW_OPTIONS(ac,1,"-mime");
326 : :
327 : 7 : n = slurp(stdin, &b);
328 : 7 : b64 = mime_raw_entity(b, av[0]);
329 : 7 : fprintf(stderr, "%d bytes in, %d bytes out\n", n, nn=strlen(b64));
330 : 7 : barf(stdout, b64, nn);
331 : 7 : exit(nn > 0 ? 0 : 1);
332 : : }
333 : :
334 : : /* ./smime -split dirprefix <multipart # splits multipart into files */
335 [ - + ]: 25 : if (!strcmp(*av, "-split")) {
336 : : int n, nn;
337 : : char* b;
338 : : char* parts[100];
339 : : int lengths[100];
340 : : char file[4096];
341 : :
342 : 0 : ac--; av++;
343 [ # # ]: 0 : TOO_FEW_OPTIONS(ac,1,"-split");
344 : :
345 : 0 : n = slurp(stdin, &b);
346 [ # # ]: 0 : if ((nn = mime_split_multipart(b, 100, parts, lengths))==-1) {
347 : 0 : fprintf(stderr, "mime error\n%s", smime_get_errors());
348 : 0 : exit(1);
349 : : }
350 : :
351 : : /* Write out the parts */
352 : :
353 [ # # ]: 0 : for (n = 0; n < nn; n++) {
354 : 0 : snprintf(file, sizeof(file), "%s%d", av[0], n);
355 : 0 : fprintf(stderr, "%s\n", file);
356 : 0 : write_file(file, "part", parts[n], lengths[n]);
357 : : }
358 : :
359 : 0 : exit(0);
360 : : }
361 : :
362 : : /* ./smime -mime_base64 image/gif <file.gif >mime-entity */
363 [ + + ]: 25 : if (!strcmp(*av, "-mime_base64")) {
364 : : int n, nn;
365 : : char* b;
366 : : char* b64;
367 : :
368 : 1 : ac--; av++;
369 [ - + ]: 1 : TOO_FEW_OPTIONS(ac,1,"-mime_base64");
370 : :
371 : 1 : n = slurp(stdin, &b);
372 : 1 : b64 = mime_base64_entity(b, n, av[0]);
373 : 1 : fprintf(stderr, "%d bytes in, %d bytes out\n", n, nn=strlen(b64));
374 : 1 : barf(stdout, b64, nn);
375 : 1 : exit(nn > 0 ? 0 : 1);
376 : : }
377 : :
378 : : /* ./smime -m type1 file1 type2 file2 type3 file3 <text # make multipart */
379 [ + + ]: 24 : if (!strcmp(*av, "-m")) {
380 : : char* mime;
381 [ - + ]: 1 : if (!(mime = mk_multipart(ac, av))) exit(1);
382 : 1 : barf(stdout, mime, strlen(mime));
383 : 1 : exit(0);
384 : : }
385 : :
386 : : /* ./smime -cs private password <mime-entity >smime */
387 [ + + ]: 23 : if (!strcmp(*av, "-cs")) {
388 : : char* smime;
389 : : char* mime;
390 : : char* privkey;
391 : :
392 : 4 : ac--; av++;
393 [ - + ]: 4 : TOO_FEW_OPTIONS(ac,2,"-cs");
394 : :
395 : 4 : slurp(stdin, &mime);
396 : 4 : read_file(av[0], "privkey", &privkey);
397 : :
398 [ + - ]: 4 : if (!(smime = smime_clear_sign(privkey, get_passwd(av[1]), mime))) {
399 : 4 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
400 : 4 : exit(1);
401 : : }
402 : 0 : barf(stdout, smime, strlen(smime));
403 : 0 : exit(0);
404 : : }
405 : :
406 : : /* ./smime -s private password <mime-entity >smime */
407 [ + + ]: 19 : if (!strcmp(*av, "-s")) {
408 : : char* smime;
409 : : char* mime;
410 : : char* privkey;
411 : :
412 : 1 : ac--; av++;
413 [ - + ]: 1 : TOO_FEW_OPTIONS(ac,2,"-s");
414 : :
415 : 1 : slurp(stdin, &mime);
416 : 1 : read_file(av[0], "privkey", &privkey);
417 : :
418 [ + - ]: 1 : if (!(smime = smime_sign(privkey, get_passwd(av[1]), mime))) {
419 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
420 : 1 : exit(1);
421 : : }
422 : 0 : barf(stdout, smime, strlen(smime));
423 : 0 : exit(0);
424 : : }
425 : :
426 : : /* ./smime -v cert <smime-entity >signer-dn # verify sig */
427 [ + + ]: 18 : if (!strcmp(*av, "-v")) {
428 : : char* cert;
429 : : char* smime;
430 : : char* signed_data;
431 : 1 : int n = slurp(stdin, &smime);
432 : :
433 : 1 : ac--; av++;
434 [ - + ]: 1 : TOO_FEW_OPTIONS(ac,1,"-v");
435 : :
436 : 1 : fprintf(stderr, "%d bytes in\n", n);
437 : 1 : read_file(av[0], "cert", &cert);
438 : :
439 [ + - ]: 1 : if (!(signed_data = smime_verify_signature(cert, smime, NULL, 0))) {
440 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
441 : 1 : exit(1);
442 : : }
443 : 0 : fputs(signed_data, stdout); /* careful not to output trailing newline */
444 : 0 : exit(0);
445 : : }
446 : :
447 : : /* ./smime -cv cert <smime-entity >signer-dn # verify clear signature */
448 [ - + ]: 17 : if (!strcmp(*av, "-cv")) {
449 : : char* cert;
450 : : char* smime;
451 : : char* parts[2]; /* parts[0] is the clear text, parts[1] is the sig */
452 : : int lengths[2];
453 : : char* signed_data;
454 : 0 : int n = slurp(stdin, &smime);
455 : :
456 : 0 : ac--; av++;
457 [ # # ]: 0 : TOO_FEW_OPTIONS(ac,1,"-cv");
458 : :
459 : 0 : fprintf(stderr, "%d bytes in\n", n);
460 : 0 : read_file(av[0], "cert", &cert);
461 : :
462 : : /* multipart/signed has always exactly two parts */
463 : :
464 [ # # ]: 0 : if (mime_split_multipart(smime, 2, parts, lengths) != 2) {
465 : 0 : fprintf(stderr, "mime error\n%s", smime_get_errors());
466 : 0 : exit(1);
467 : : }
468 : :
469 [ # # ]: 0 : if (!(signed_data =
470 : : smime_verify_signature(cert, parts[1] /*sig*/,
471 : : parts[0] /*plain*/, lengths[0]))) {
472 : 0 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
473 : 0 : exit(1);
474 : : }
475 : 0 : fputs(signed_data, stdout); /* careful not to output trailing newline */
476 : 0 : exit(0);
477 : : }
478 : :
479 : : /* ./smime -vc cacert <cert # verify certificate */
480 [ + + ]: 17 : if (!strcmp(*av, "-vc")) {
481 : : char* cert;
482 : : char* ca_cert;
483 : : int x;
484 : 1 : int n = slurp(stdin, &cert);
485 : :
486 : 1 : ac--; av++;
487 [ - + ]: 1 : TOO_FEW_OPTIONS(ac,1,"-vc");
488 : :
489 : 1 : fprintf(stderr, "%d bytes in\n", n);
490 : 1 : read_file(av[0], "ca_cert", &ca_cert);
491 : :
492 : 1 : x = smime_verify_cert(ca_cert, cert);
493 : :
494 [ - + ]: 1 : if (x == 1) {
495 : 0 : printf("OK\n");
496 : 0 : exit(0);
497 : : }
498 : :
499 [ - + ]: 1 : if (x == 0) {
500 : 0 : printf("NOT OK\n");
501 : 0 : exit(2);
502 : : }
503 : :
504 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
505 : 1 : exit(1);
506 : : }
507 : :
508 : : /* ./smime -ds private passwd <file >smime-sig # make detached signature */
509 : :
510 [ + + ]: 16 : if (!strcmp(*av, "-ds")) {
511 : : char* file;
512 : : char* smime;
513 : : char* mime;
514 : : char* privkey;
515 : : char* parts[2]; /* parts[0] is the clear text, parts[1] is the sig */
516 : : int lengths[2];
517 : : int n;
518 : :
519 : 1 : ac--; av++;
520 [ - + ]: 1 : TOO_FEW_OPTIONS(ac,2,"-ds");
521 : :
522 : 1 : n = slurp(stdin, &file);
523 : 1 : read_file(av[0], "privkey", &privkey);
524 : :
525 [ - + ]: 1 : if (!(mime = mime_base64_entity(file, n, DETACHED_SIG_TYPE_FILE))) {
526 : 0 : fprintf(stderr, "mime error\n%s", smime_get_errors());
527 : 0 : exit(1);
528 : : }
529 : :
530 [ + - ]: 1 : if (!(smime = smime_clear_sign(privkey, get_passwd(av[1]), mime))) {
531 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
532 : 1 : exit(1);
533 : : }
534 : :
535 [ # # ]: 0 : if (mime_split_multipart(smime, 2, parts, lengths) != 2) {
536 : 0 : fprintf(stderr, "mime error\n%s", smime_get_errors());
537 : 0 : exit(1);
538 : : }
539 : :
540 : 0 : barf(stdout, parts[1], lengths[1]);
541 : 0 : exit(0);
542 : : }
543 : :
544 : : /* ./smime -dv file <sig+cert # verify detached signature */
545 : :
546 [ + + ]: 15 : if (!strcmp(*av, "-dv")) {
547 : : char* sig;
548 : : char* file;
549 : : char* cert;
550 : : char* mime;
551 : : char* canon;
552 : : char* p;
553 : : char c;
554 : : int n;
555 : :
556 : 1 : ac--; av++;
557 [ - + ]: 1 : TOO_FEW_OPTIONS(ac,1,"-dv");
558 : :
559 : 1 : n = slurp(stdin, &sig);
560 [ - + ]: 1 : if (!(p = strstr(sig, "-----BEGIN CERTIFICATE-----"))) {
561 : 0 : fprintf(stderr, "No certificate found in stdin.\n");
562 : 0 : exit(1);
563 : : }
564 : :
565 [ - + ]: 1 : if (p == sig) {
566 : : /* Certificate first, then signature */
567 : :
568 [ # # ]: 0 : if (!(p = strstr(sig, "-----END CERTIFICATE-----"))) exit(1);
569 : 0 : p+=strlen("-----END CERTIFICATE-----");
570 [ # # ]: 0 : if (*p == '\015') p++;
571 [ # # ]: 0 : if (*p == '\012') p++;
572 : 0 : c = p[0];
573 : 0 : p[0] = '\0';
574 : 0 : cert = strdup(sig);
575 : 0 : p[0] = c;
576 : 0 : sig = p;
577 : :
578 : : } else {
579 : :
580 : : /* Signature first, then certificate */
581 : :
582 : 1 : p[0] = '\0';
583 : 1 : sig = strdup(sig);
584 : 1 : p[0] = '-';
585 : 1 : cert = p;
586 : : }
587 : :
588 : 1 : n = read_file(av[0], "file", &file);
589 : :
590 : : /* wrap the file in mime entity */
591 : :
592 [ - + ]: 1 : if (!(mime = mime_base64_entity(file, n, DETACHED_SIG_TYPE_FILE))) {
593 : 0 : fprintf(stderr, "mime error\n%s", smime_get_errors());
594 : 0 : exit(1);
595 : : }
596 : :
597 : : /* Must canonize, otherwise the sig will not verify */
598 : :
599 [ - + ]: 1 : if (!(canon = mime_canon(mime))) {
600 : 0 : fprintf(stderr, "canon error\n%s", smime_get_errors());
601 : 0 : exit(1);
602 : : }
603 : :
604 [ + - ]: 1 : if (!smime_verify_signature(cert, sig, canon, strlen(canon))) {
605 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
606 : 1 : exit(1);
607 : : }
608 : 0 : printf("Signature verified OK.\n");
609 : 0 : exit(0);
610 : : }
611 : :
612 : : /* ./smime -e public <mime-entity >smime-ent */
613 [ + + ]: 14 : if (!strcmp(*av, "-e")) {
614 : : char* smime;
615 : : char* mime;
616 : : char* cert;
617 : :
618 : 5 : ac--; av++;
619 [ - + ]: 5 : TOO_FEW_OPTIONS(ac,1,"-e");
620 : :
621 : 5 : slurp(stdin, &mime);
622 : 5 : read_file(av[0], "cert", &cert);
623 : :
624 [ + + ]: 5 : if (!(smime = smime_encrypt(cert, mime))) {
625 : 2 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
626 : 2 : exit(1);
627 : : }
628 : 3 : barf(stdout, smime, strlen(smime));
629 : 3 : exit(0);
630 : : }
631 : :
632 : : /* ./smime -d private password <smime-entity >mime # decrypt */
633 [ + + ]: 9 : if (!strcmp(*av, "-d")) {
634 : : char* smime;
635 : : char* mime;
636 : : char* privkey;
637 : : int n;
638 : :
639 : 1 : ac--; av++;
640 [ - + ]: 1 : TOO_FEW_OPTIONS(ac,2,"-d");
641 : :
642 : 1 : n = slurp(stdin, &smime);
643 : 1 : read_file(av[0], "privkey", &privkey);
644 : :
645 [ + - ]: 1 : if ((n = smime_decrypt(privkey, get_passwd(av[1]), smime, &mime)) < 0) {
646 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
647 : 1 : exit(1);
648 : : }
649 : 0 : barf(stdout, mime, n);
650 : 0 : exit(0);
651 : : }
652 : :
653 : : /* ./smime -kg attr password priv_x509ss.pem req.pem <dn >modulus */
654 : :
655 [ + + ]: 8 : if (!strcmp(*av, "-kg")) {
656 : : char* dn;
657 : : char* priv;
658 : : char* x509ss;
659 : : char* request;
660 : :
661 : 2 : ac--; av++;
662 [ - + ]: 2 : TOO_FEW_OPTIONS(ac,2,"-kg");
663 : :
664 : 2 : slurp(stdin, &dn);
665 : :
666 [ - + ]: 2 : if (smime_keygen(dn, av[0] /*attr*/, get_passwd(av[1]),
667 : : "Test certificate. See http://www.bacus.pt/Net_SSLeay/smime.html",
668 : : &priv, &x509ss, &request)<0) {
669 : 0 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
670 : 0 : exit(1);
671 : : }
672 : :
673 : 2 : puts(priv);
674 : 2 : puts(x509ss);
675 : 2 : write_file(av[2], "pem", request, strlen(request));
676 : 2 : exit(0);
677 : : }
678 : :
679 : : /* ./smime -qr <req.pem # Query all you can about request */
680 : :
681 [ + + ]: 6 : if (!strcmp(*av, "-qr")) {
682 : : char* req;
683 : : char* name;
684 : : char* attr;
685 : : char* mod;
686 : : char* md5;
687 : : char* hash;
688 : : char block1[14];
689 : 1 : int n = slurp(stdin, &req);
690 : 1 : fprintf(stderr, "%d bytes in\n", n);
691 : :
692 [ + - ]: 1 : if (!(name = smime_get_req_name(req))) {
693 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
694 : 1 : exit(1);
695 : : }
696 : 0 : puts(name);
697 : :
698 [ # # ]: 0 : if (!(attr = smime_get_req_attr(req))) {
699 : 0 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
700 : 0 : exit(1);
701 : : }
702 : 0 : puts(attr);
703 : :
704 [ # # ]: 0 : if (!(mod = smime_get_req_modulus(req))) {
705 : 0 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
706 : 0 : exit(1);
707 : : }
708 : 0 : puts(mod);
709 : :
710 [ # # ]: 0 : if (!(md5 = smime_md5(mod))) {
711 : 0 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
712 : 0 : exit(1);
713 : : }
714 : 0 : puts(md5);
715 : :
716 [ # # ]: 0 : if (!(hash = smime_get_req_hash(req))) {
717 : 0 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
718 : 0 : exit(1);
719 : : }
720 : 0 : memcpy(block1, hash, 13);
721 : 0 : block1[13] = '\0';
722 : 0 : printf("\n*%s*\n*%s*\n", block1, hash+13);
723 : 0 : exit(0);
724 : : }
725 : :
726 : : /* ./smime -qc <cert.pem # Query all you can about certificate */
727 : :
728 [ + + ]: 5 : if (!strcmp(*av, "-qc")) {
729 : : char* cert;
730 : : char* name;
731 : : char* issuer;
732 : : char* fingerprint;
733 : : char* mod;
734 : : char* md5;
735 : : long serial;
736 : 1 : int n = slurp(stdin, &cert);
737 : 1 : fprintf(stderr, "%d bytes in\n", n);
738 : :
739 [ + - ]: 1 : if ((serial = smime_get_cert_names(cert, &name, &issuer)) == -1) {
740 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
741 : 1 : exit(1);
742 : : }
743 : 0 : puts(name);
744 : 0 : puts(issuer);
745 : 0 : printf("serial: %ld\n", serial);
746 : :
747 [ # # ]: 0 : if ((serial = smime_get_cert_info(cert, &mod, &fingerprint)) == -1) {
748 : 0 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
749 : 0 : exit(1);
750 : : }
751 : :
752 : 0 : printf("serial: %ld\n", serial);
753 : :
754 : 0 : puts(fingerprint);
755 : 0 : puts(mod);
756 : :
757 [ # # ]: 0 : if (!(md5 = smime_md5(mod))) {
758 : 0 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
759 : 0 : exit(1);
760 : : }
761 : 0 : puts(md5);
762 : 0 : exit(0);
763 : : }
764 : :
765 : : /* ./smime -qs <smime-entity >signing-cert-info
766 : : * find out who signed (query sig) */
767 [ + + ]: 4 : if (!strcmp(*av, "-qs")) {
768 : : char* issuer;
769 : : char* signed_entity;
770 : : long serial;
771 : 1 : int sig_count = 0;
772 : 1 : int n = slurp(stdin, &signed_entity);
773 : 1 : fprintf(stderr, "%d bytes in\n", n);
774 : :
775 [ - + ]: 2 : while ((serial = smime_get_signer_info(signed_entity,
776 : : sig_count, &issuer)) != -1) {
777 : 0 : puts(issuer);
778 : 0 : printf("serial: %ld\n", serial);
779 : 0 : sig_count++;
780 : : }
781 [ + - ]: 1 : if (!sig_count) {
782 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
783 : 1 : exit(1);
784 : : }
785 : 0 : exit(0);
786 : : }
787 : :
788 : : /* ./smime -ca ca_cert passwd serial <req.pem >cert.pem */
789 : :
790 [ + + ]: 3 : if (!strcmp(*av, "-ca")) {
791 : : char* req;
792 : : char* ca_cert;
793 : : char* cert;
794 : 1 : slurp(stdin, &req);
795 : :
796 : 1 : ac--; av++;
797 [ - + ]: 1 : TOO_FEW_OPTIONS(ac,3,"-ca");
798 : :
799 : 1 : read_file(av[0], "ca_cert_pem", &ca_cert);
800 : :
801 [ + - ]: 1 : if (!(cert = smime_ca(ca_cert, get_passwd(av[1]), req,
802 : : "today", "days:365", atoi(av[2]),
803 : : "CA:TRUE,pathlen:3",
804 : : "client,server,email,objsign,sslCA,emailCA,objCA",
805 : : "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign",
806 : : "Test certificate. See http://www.bacus.pt/Net_SSLeay/smime.html"))) {
807 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
808 : 1 : exit(1);
809 : : }
810 : 0 : puts(cert);
811 : 0 : exit(0);
812 : : }
813 : :
814 : : /* ./smime -p12-pem imppw0 exppw1 <x.p12 >x.pem */
815 : :
816 [ + + ]: 2 : if (!strcmp(*av, "-p12-pem")) {
817 : : char* x;
818 : : char* pk;
819 : : char* cert;
820 : 1 : int n = slurp(stdin, &x);
821 : :
822 : 1 : ac--; av++;
823 [ - + ]: 1 : TOO_FEW_OPTIONS(ac,2,"-p12-pem");
824 : :
825 [ + - ]: 1 : if (smime_pkcs12_to_pem(x, n, get_passwd(av[0]), get_passwd(av[1]),
826 : : &pk, &cert) == -1) {
827 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
828 : 1 : exit(1);
829 : : }
830 : :
831 : 0 : puts(pk);
832 : 0 : puts(cert);
833 : 0 : exit(0);
834 : : }
835 : :
836 : : /* ./smime -pem-p12 frindly@name0 pw1 pw2 <x.pem >x.p12 */
837 : :
838 [ + - ]: 1 : if (!strcmp(*av, "-pem-p12")) {
839 : : char* x;
840 : : char* pkcs12;
841 : 1 : int n = slurp(stdin, &x);
842 : :
843 : 1 : ac--; av++;
844 [ - + ]: 1 : TOO_FEW_OPTIONS(ac,3,"-pem-p12");
845 : :
846 [ + - ]: 1 : if ((n = smime_pem_to_pkcs12(av[0], x /*cert*/, x /*privkey*/,
847 : : get_passwd(av[1]), get_passwd(av[2]),
848 : : &pkcs12)) == -1) {
849 : 1 : fprintf(stderr, "crypto error\n%s", smime_get_errors());
850 : 1 : exit(1);
851 : : }
852 : :
853 : 0 : barf(stdout, pkcs12, n);
854 : 0 : exit(0);
855 : : }
856 : :
857 : 0 : fprintf(stderr, "Unknown option.\n%s", usage);
858 : 0 : return 1;
859 : : }
860 : :
861 : : /* EOF - smime.c */
|