source: zcrypt.c @ 9b3167b

release-1.10release-1.9
Last change on this file since 9b3167b was 97cdbaf5, checked in by David Benjamin <davidben@mit.edu>, 13 years ago
Rewrite call_filter to use g_spawn_async_with_pipes This simplifies the error-handling code. Also fixes a bug where file descriptors get double-closed in call_filter. Also adds a unit test. The separate prog argument is removed to avoid having to deal with G_SPAWN_FILE_AND_ARGV_ZERO, and since we don't really use it anyway.
  • Property mode set to 100644
File size: 20.8 KB
RevLine 
[edae037]1/* zcrypt.c -- Read in a data stream from stdin & dump a decrypted/encrypted *
2 *   datastream.  Reads the string to make the key from from the first       *
3 *   parameter.  Encrypts or decrypts according to -d or -e flag.  (-e is    *
4 *   default.)  Will invoke zwrite if the -c option is provided for          *
5 *   encryption.  If a zephyr class is specified & the keyfile name omitted  *
6 *   the ~/.crypt-table will be checked for "crypt-classname" and then       *
7 *   "crypt-default" for the keyfile name.                                   */
8
9#include <stdio.h>
[6b1c3b6]10
[edae037]11#include <unistd.h>
12#include <sys/types.h>
[6b1c3b6]13#include <glib.h>
[356465e]14#include <string.h>
15#include <stdlib.h>
16#include <sys/wait.h>
[8bd190d]17#include <ctype.h>
[edae037]18
[b094191]19#include "config.h"
20
[49bc81e]21#ifdef HAVE_KERBEROS_IV
22#include <kerberosIV/des.h>
23#else
24#include <openssl/des.h>
25#endif
26
[8bd190d]27#include "filterproc.h"
28
[6829afc]29/* Annotate functions in which the caller owns the return value and is
30 * responsible for ensuring it is freed. */
31#define CALLER_OWN G_GNUC_WARN_UNUSED_RESULT
32
[8bd190d]33#define MAX_KEY      128
34#define MAX_LINE     128
35#define MAX_RESULT   4096
[edae037]36
37#ifndef TRUE
38#define TRUE -1
39#endif
40#ifndef FALSE
41#define FALSE 0
42#endif
43
44#define ZWRITE_OPT_NOAUTH     (1<<0)
45#define ZWRITE_OPT_SIGNATURE  (1<<1)
46#define ZWRITE_OPT_IGNOREVARS (1<<2)
47#define ZWRITE_OPT_VERBOSE    (1<<3)
48#define ZWRITE_OPT_QUIET      (1<<4)
49#define ZCRYPT_OPT_MESSAGE    (1<<5)
50#define ZCRYPT_OPT_IGNOREDOT  (1<<6)
51
52typedef struct
53{
54  int flags;
[1dd285b]55  const char *signature;
[edae037]56  char *message;
57} ZWRITEOPTIONS;
58
[6829afc]59CALLER_OWN char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance);
[e832a52]60int ParseCryptSpec(const char *spec, const char **keyfile);
[6829afc]61CALLER_OWN char *BuildArgString(char **argv, int start, int end);
62CALLER_OWN char *read_keystring(const char *keyfile);
[8bd190d]63
[e832a52]64int do_encrypt(int zephyr, const char *class, const char *instance,
65               ZWRITEOPTIONS *zoptions, const char* keyfile, int cipher);
66int do_encrypt_des(const char *keyfile, const char *in, int len, FILE *out);
67int do_encrypt_aes(const char *keyfile, const char *in, int len, FILE *out);
[8bd190d]68
[e832a52]69int do_decrypt(const char *keyfile, int cipher);
70int do_decrypt_aes(const char *keyfile);
71int do_decrypt_des(const char *keyfile);
[8bd190d]72
[edae037]73
74#define M_NONE            0
75#define M_ZEPHYR_ENCRYPT  1
76#define M_DECRYPT         2
77#define M_ENCRYPT         3
78#define M_RANDOMIZE       4
79#define M_SETKEY          5
80
[6d7f2a8]81enum cipher_algo {
82  CIPHER_DES,
83  CIPHER_AES,
84  NCIPHER
85};
86
87typedef struct {
[e832a52]88  int (*encrypt)(const char *keyfile, const char *in, int len, FILE *out);
89  int (*decrypt)(const char *keyfile);
[6d7f2a8]90} cipher_pair;
91
92cipher_pair ciphers[NCIPHER] = {
[3c2c7fc]93  [CIPHER_DES] = { do_encrypt_des, do_decrypt_des},
94  [CIPHER_AES] = { do_encrypt_aes, do_decrypt_aes},
[6d7f2a8]95};
[9a4077c]96
[c836519]97static void owl_zcrypt_string_to_schedule(char *keystring, des_key_schedule *schedule) {
[356465e]98#ifdef HAVE_KERBEROS_IV
99  des_cblock key;
100#else
101  des_cblock _key, *key = &_key;
102#endif
103
104  des_string_to_key(keystring, key);
[c836519]105  des_key_sched(key, *schedule);
[356465e]106}
107
108int main(int argc, char *argv[])
[edae037]109{
[9a4077c]110  char *cryptspec = NULL;
[e832a52]111  const char *keyfile;
[9a4077c]112  int cipher;
[edae037]113  int error = FALSE;
114  int zephyr = FALSE;
[1dd285b]115  const char *class = NULL, *instance = NULL;
[edae037]116  int mode = M_NONE;
117
118  char c;
119
120  int messageflag = FALSE;
121  ZWRITEOPTIONS zoptions;
122  zoptions.flags = 0;
123
124  while ((c = getopt(argc, argv, "ZDERSF:c:i:advqtluons:f:m")) != (char)EOF)
125  {
126    switch(c)
127    {
128      case 'Z':
129        /* Zephyr encrypt */
130        mode = M_ZEPHYR_ENCRYPT;
[f7f35c0]131        break;
[edae037]132      case 'D':
133        /* Decrypt */
[f7f35c0]134        mode = M_DECRYPT;
135        break;
[edae037]136      case 'E':
[f7f35c0]137        /* Encrypt */
138        mode = M_ENCRYPT;
139        break;
[edae037]140      case 'R':
[f7f35c0]141        /* Randomize the keyfile */
142        mode = M_RANDOMIZE;
143        break;
[edae037]144      case 'S':
[f7f35c0]145        /* Set a new key value from stdin */
146        mode = M_SETKEY;
147        break;
[edae037]148      case 'F':
[f7f35c0]149        /* Specify the keyfile explicitly */
[9a4077c]150        if (cryptspec != NULL) error = TRUE;
151        cryptspec = optarg;
[f7f35c0]152        break;
[edae037]153      case 'c':
[f7f35c0]154        /* Zwrite/zcrypt: class name */
155        if (class != NULL) error = TRUE;
156        class = optarg;
157        break;
[edae037]158      case 'i':
[f7f35c0]159        /* Zwrite/zcrypt: instance name */
160        if (instance != NULL) error = TRUE;
161        instance = optarg;
162        break;
[edae037]163      case 'a':
[f7f35c0]164        /* Zwrite: authenticate (default) */
165        zoptions.flags &= ~ZWRITE_OPT_NOAUTH;
166        break;
[edae037]167      case 'd':
[f7f35c0]168        /* Zwrite: do not authenticate */
169        zoptions.flags |= ZWRITE_OPT_NOAUTH;
170        break;
[edae037]171      case 'v':
[f7f35c0]172        /* Zwrite: verbose */
173        zoptions.flags |= ZWRITE_OPT_VERBOSE;
174        break;
[edae037]175      case 'q':
[f7f35c0]176        /* Zwrite: quiet */
177        zoptions.flags |= ZWRITE_OPT_QUIET;
178        break;
[edae037]179      case 't':
[f7f35c0]180        /* Zwrite: no expand tabs (ignored) */
181        break;
[edae037]182      case 'l':
[f7f35c0]183        /* Zwrite: ignore '.' on a line by itself (ignored) */
184        zoptions.flags |= ZCRYPT_OPT_IGNOREDOT;
185        break;
[edae037]186      case 'u':
[f7f35c0]187        /* Zwrite: urgent message */
188        instance = "URGENT";
189        break;
[edae037]190      case 'o':
[f7f35c0]191        /* Zwrite: ignore zephyr variables zwrite-class, zwrite-inst, */
192        /*         zwrite-opcode */
193        zoptions.flags |= ZWRITE_OPT_IGNOREVARS;
194        break;
[edae037]195      case 'n':
[f7f35c0]196        /* Zwrite: prevent PING message (always used) */
197        break;
[edae037]198      case 's':
[f7f35c0]199        /* Zwrite: signature */
200        zoptions.flags |= ZWRITE_OPT_SIGNATURE;
201        zoptions.signature = optarg;
202        break;
[edae037]203      case 'f':
[f7f35c0]204        /* Zwrite: file system specification (ignored) */
205        break;
[edae037]206      case 'm':
[f7f35c0]207        /* Message on rest of line*/
208        messageflag = TRUE;
209        break;
[edae037]210      case '?':
[f7f35c0]211        error = TRUE;
212        break;
[edae037]213    }
214    if (error || messageflag)
215      break;
216  }
217
218  if (class != NULL || instance != NULL)
219    zephyr = TRUE;
220
221  if (messageflag)
222  {
223    zoptions.flags |= ZCRYPT_OPT_MESSAGE;
224    zoptions.message = BuildArgString(argv, optind, argc);
225    if (!zoptions.message)
226    {
[a08bfc3]227      fprintf(stderr, "Memory allocation error.\n");
[edae037]228      error = TRUE;
229    }
230  }
231  else if (optind < argc)
232  {
233    error = TRUE;
234  }
235
236  if (mode == M_NONE)
237    mode = (zephyr?M_ZEPHYR_ENCRYPT:M_ENCRYPT);
238
239  if (mode == M_ZEPHYR_ENCRYPT && !zephyr)
240    error = TRUE;
241
[9a4077c]242  if (!error && cryptspec == NULL && (class != NULL || instance != NULL)) {
243    cryptspec = GetZephyrVarKeyFile(argv[0], class, instance);
244    if(!cryptspec) {
245      fprintf(stderr, "Unable to find keyfile for ");
246      if(class != NULL) {
247        fprintf(stderr, "-c %s ", class);
248      }
249      if(instance != NULL) {
250        fprintf(stderr, "-i %s ", instance);
251      }
252      fprintf(stderr, "\n");
253      exit(-1);
254    }
255  }
256
[7ba7d66]257  if (error || !cryptspec)
[edae037]258  {
[a08bfc3]259    fprintf(stderr, "Usage: %s [-Z|-D|-E|-R|-S] [-F Keyfile] [-c class] [-i instance]\n", argv[0]);
260    fprintf(stderr, "       [-advqtluon] [-s signature] [-f arg] [-m message]\n");
261    fprintf(stderr, "  One or more of class, instance, and keyfile must be specified.\n");
[4133e34]262    exit(1);
263  }
[9a4077c]264
265  cipher = ParseCryptSpec(cryptspec, &keyfile);
266  if(cipher < 0) {
267    fprintf(stderr, "Invalid cipher specification: %s\n", cryptspec);
[4133e34]268    exit(1);
[edae037]269  }
[9a4077c]270
271
272  if (mode == M_RANDOMIZE)
[edae037]273  {
[9a4077c]274    /* Choose a new, random key */
275    /*
[edae037]276      FILE *fkey = fopen(fname, "w");
277      if (!fkey)
[9a4077c]278      printf("Could not open key file for writing: %s\n", fname);
[edae037]279      else
280      {
[9a4077c]281      char string[100];
282      fputs(fkey, string);
283      fclose(fkey);
[356465e]284      }
[9a4077c]285    */
286    fprintf(stderr, "Feature not yet implemented.\n");
287  }
288  else if (mode == M_SETKEY)
289  {
290    /* Set a new, user-entered key */
291    char newkey[MAX_KEY];
292    FILE *fkey;
[edae037]293
[9a4077c]294    if (isatty(0))
295    {
296      printf("Enter new key: ");
297      /* Really should read without echo!!! */
298    }
299    if(!fgets(newkey, MAX_KEY - 1, stdin)) {
300      fprintf(stderr, "Error reading key.\n");
301      return 1;
[edae037]302    }
[9a4077c]303
304    fkey = fopen(keyfile, "w");
305    if (!fkey)
306      fprintf(stderr, "Could not open key file for writing: %s\n", keyfile);
[edae037]307    else
308    {
[9a4077c]309      if (fputs(newkey, fkey) != strlen(newkey) || putc('\n', fkey) != '\n')
310      {
311        fprintf(stderr, "Error writing to key file.\n");
312        fclose(fkey);
[4133e34]313        exit(1);
314      }
[edae037]315      else
316      {
[f7f35c0]317        fclose(fkey);
[9a4077c]318        fprintf(stderr, "Key update complete.\n");
[edae037]319      }
320    }
321  }
[9a4077c]322  else
323  {
324    if (mode == M_ZEPHYR_ENCRYPT || mode == M_ENCRYPT)
[8bd190d]325      error = !do_encrypt((mode == M_ZEPHYR_ENCRYPT), class, instance,
326                          &zoptions, keyfile, cipher);
[9a4077c]327    else
[8bd190d]328      error = !do_decrypt(keyfile, cipher);
[9a4077c]329  }
[edae037]330
331  /* Always print the **END** message if -D is specified. */
332  if (mode == M_DECRYPT)
333    printf("**END**\n");
[8bd190d]334
335  return error;
[edae037]336}
337
[e832a52]338int ParseCryptSpec(const char *spec, const char **keyfile) {
[8bd190d]339  int cipher = CIPHER_DES;
340  char *cipher_name = strdup(spec);
341  char *colon = strchr(cipher_name, ':');
342
[9a4077c]343  *keyfile = spec;
[8bd190d]344
345  if (colon) {
346    char *rest = strchr(spec, ':') + 1;
347    while(isspace(*rest)) rest++;
348
349    *colon-- = '\0';
350    while (colon >= cipher_name && isspace(*colon)) {
351      *colon = '\0';
352    }
353
354    if(strcmp(cipher_name, "AES") == 0) {
355      cipher = CIPHER_AES;
356      *keyfile = rest;
357    } else if(strcmp(cipher_name, "DES") == 0) {
358      cipher = CIPHER_DES;
359      *keyfile = rest;
360    }
361  }
362
363  free(cipher_name);
364
365  return cipher;
[9a4077c]366}
367
[edae037]368/* Build a space-separated string from argv from elements between start  *
369 * and end - 1.  malloc()'s the returned string. */
[6829afc]370CALLER_OWN char *BuildArgString(char **argv, int start, int end)
[edae037]371{
372  int len = 1;
373  int i;
374  char *result;
375
376  /* Compute the length of the string.  (Plus 1 or 2) */
377  for (i = start; i < end; i++)
378    len += strlen(argv[i]) + 1;
379
380  /* Allocate memory */
381  result = (char *)malloc(len);
382  if (result)
383  {
384    /* Build the string */
385    char *ptr = result;
386    /* Start with an empty string, in case nothing is copied. */
387    *ptr = '\0';
388    /* Copy the arguments */
389    for (i = start; i < end; i++)
390    {
391      char *temp = argv[i];
392      /* Add a space, if not the first argument */
393      if (i != start)
[f7f35c0]394        *ptr++ = ' ';
[edae037]395      /* Copy argv[i], leaving ptr pointing to the '\0' copied from temp */
[356465e]396      while ((*ptr = *temp++))
[f7f35c0]397        ptr++;
[edae037]398    }
399  }
400
401  return result;
402}
403
404#define MAX_BUFF 258
405#define MAX_SEARCH 3
406/* Find the class/instance in the .crypt-table */
[6829afc]407CALLER_OWN char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance)
[edae037]408{
[356465e]409  char *keyfile = NULL;
[6b1c3b6]410  char *varname[MAX_SEARCH];
[edae037]411  int length[MAX_SEARCH], i;
412  char buffer[MAX_BUFF];
[c6332f5]413  const char *home;
[6b1c3b6]414  char *filename;
[edae037]415  char result[MAX_SEARCH][MAX_BUFF];
416  int numsearch = 0;
417  FILE *fsearch;
418
[6b1c3b6]419  memset(varname, 0, sizeof(varname));
420
[edae037]421  /* Determine names to look for in .crypt-table */
422  if (instance)
[6b1c3b6]423    varname[numsearch++] = g_strdup_printf("crypt-%s-%s:", (class?class:"message"), instance);
[edae037]424  if (class)
[6b1c3b6]425    varname[numsearch++] = g_strdup_printf("crypt-%s:", class);
426  varname[numsearch++] = g_strdup("crypt-default:");
[edae037]427
428  /* Setup the result array, and determine string lengths */
429  for (i = 0; i < numsearch; i++)
430  {
431    result[i][0] = '\0';
432    length[i] = strlen(varname[i]);
433  }
434
435  /* Open~/.crypt-table */
[c6332f5]436  home = getenv("HOME");
437  if (home == NULL)
438    home = g_get_home_dir();
[dde1b4d]439  filename = g_build_filename(home, ".crypt-table", NULL);
[edae037]440  fsearch = fopen(filename, "r");
441  if (fsearch)
442  {
443    /* Scan file for a match */
444    while (!feof(fsearch))
445    {
[356465e]446      if (!fgets(buffer, MAX_BUFF - 3, fsearch)) break;
[edae037]447      for (i = 0; i < numsearch; i++)
[f7f35c0]448        if (strncasecmp(varname[i], buffer, length[i]) == 0)
449        {
450          int j;
451          for (j = length[i]; buffer[j] == ' '; j++)
452            ;
453          strcpy(result[i], &buffer[j]);
454          if (*result[i])
455            if (result[i][strlen(result[i])-1] == '\n')
456              result[i][strlen(result[i])-1] = '\0';
457        }
[edae037]458    }
459
460    /* Pick the "best" match found */
461    keyfile = NULL;
462    for (i = 0; i < numsearch; i++)
463      if (*result[i])
464      {
[f7f35c0]465        keyfile = result[i];
466        break;
[edae037]467      }
468
[9a4077c]469    if (keyfile != NULL)
[edae037]470    {
471      /* Prepare result to be returned */
472      char *temp = keyfile;
473      keyfile = (char *)malloc(strlen(temp) + 1);
474      if (keyfile)
[f7f35c0]475        strcpy(keyfile, temp);
[edae037]476      else
[f7f35c0]477        fprintf(stderr, "Memory allocation error.\n");
[edae037]478    }
479    fclose(fsearch);
480  }
481  else
[a08bfc3]482    fprintf(stderr, "Could not open key table file: %s\n", filename);
[edae037]483
[6b1c3b6]484  for(i = 0; i < MAX_SEARCH; i++) {
[3b8a563]485    g_free(varname[i]);
[6b1c3b6]486  }
487
[3b8a563]488  g_free(filename);
[6b1c3b6]489
[edae037]490  return keyfile;
491}
492
493static pid_t zephyrpipe_pid = 0;
494
495/* Open a pipe to zwrite */
[e832a52]496FILE *GetZephyrPipe(const char *class, const char *instance, const ZWRITEOPTIONS *zoptions)
[edae037]497{
498  int fildes[2];
499  pid_t pid;
500  FILE *result;
[e832a52]501  const char *argv[20];
[356465e]502  int argc = 0;
[edae037]503
504  if (pipe(fildes) < 0)
505    return NULL;
506  pid = fork();
507
508  if (pid < 0)
509  {
510    /* Error: clean up */
511    close(fildes[0]);
512    close(fildes[1]);
513    result = NULL;
514  }
515  else if (pid == 0)
516  {
517    /* Setup child process */
518    argv[argc++] = "zwrite";
519    argv[argc++] = "-n";     /* Always send without ping */
520    if (class)
521    {
522      argv[argc++] = "-c";
523      argv[argc++] = class;
524    }
525    if (instance)
526    {
527      argv[argc++] = "-i";
528      argv[argc++] = instance;
529    }
530    if (zoptions->flags & ZWRITE_OPT_NOAUTH)
531      argv[argc++] = "-d";
532    if (zoptions->flags & ZWRITE_OPT_QUIET)
533      argv[argc++] = "-q";
534    if (zoptions->flags & ZWRITE_OPT_VERBOSE)
535      argv[argc++] = "-v";
536    if (zoptions->flags & ZWRITE_OPT_SIGNATURE)
537    {
538      argv[argc++] = "-s";
539      argv[argc++] = zoptions->signature;
540    }
541    argv[argc++] = "-O";
542    argv[argc++] = "crypt";
543    argv[argc] = NULL;
544    close(fildes[1]);
545    if (fildes[0] != STDIN_FILENO)
546    {
547      if (dup2(fildes[0], STDIN_FILENO) != STDIN_FILENO)
[f7f35c0]548        exit(0);
[edae037]549      close(fildes[0]);
550    }
551    close(fildes[0]);
[e832a52]552    execvp(argv[0], (char **)argv);
[a08bfc3]553    fprintf(stderr, "Exec error: could not run zwrite\n");
[edae037]554    exit(0);
555  }
556  else
557  {
558    close(fildes[0]);
559    /* Create a FILE * for the zwrite pipe */
560    result = (FILE *)fdopen(fildes[1], "w");
561    zephyrpipe_pid = pid;
562  }
563
564  return result;
565}
566
567/* Close the pipe to zwrite */
[356465e]568void CloseZephyrPipe(FILE *pipe)
[edae037]569{
570  fclose(pipe);
571  waitpid(zephyrpipe_pid, NULL, 0);
572  zephyrpipe_pid = 0;
573}
574
575#define BASE_CODE 70
576#define LAST_CODE (BASE_CODE + 15)
577#define OUTPUT_BLOCK_SIZE 16
578
[356465e]579void block_to_ascii(unsigned char *output, FILE *outfile)
[edae037]580{
581  int i;
582  for (i = 0; i < 8; i++)
583  {
584    putc(((output[i] & 0xf0) >> 4) + BASE_CODE, outfile);
585    putc( (output[i] & 0x0f)       + BASE_CODE, outfile);
586  }
587}
588
[6829afc]589CALLER_OWN char *slurp_stdin(int ignoredot, int *length) {
[9a4077c]590  char *buf;
591  char *inptr;
[edae037]592
[8bd190d]593  if ((inptr = buf = (char *)malloc(MAX_RESULT)) == NULL)
594  {
595    fprintf(stderr, "Memory allocation error\n");
596    return NULL;
597  }
598  while (inptr - buf < MAX_RESULT - MAX_LINE - 20)
599  {
600    if (fgets(inptr, MAX_LINE, stdin) == NULL)
601      break;
602
603    if (inptr[0])
604    {
605      if (inptr[0] == '.' && inptr[1] == '\n' && !ignoredot)
606      {
607        inptr[0] = '\0';
608        break;
609      }
610      else
611        inptr += strlen(inptr);
612    }
613    else
614      break;
615  }
616  *length = inptr - buf;
617
618  return buf;
619}
620
[6829afc]621CALLER_OWN char *GetInputBuffer(ZWRITEOPTIONS *zoptions, int *length) {
[8bd190d]622  char *buf;
623
[9a4077c]624  if (zoptions->flags & ZCRYPT_OPT_MESSAGE)
[edae037]625  {
[9a4077c]626    /* Use the -m message */
627    buf = strdup(zoptions->message);
628    *length = strlen(buf);
629  }
630  else
631  {
632    if (isatty(0)) {
[edae037]633      /* tty input, so show the "Type your message now..." message */
634      if (zoptions->flags & ZCRYPT_OPT_IGNOREDOT)
[f7f35c0]635        printf("Type your message now.  End with the end-of-file character.\n");
[edae037]636      else
[f7f35c0]637        printf("Type your message now.  End with control-D or a dot on a line by itself.\n");
[9a4077c]638    } else {
639      zoptions->flags |= ZCRYPT_OPT_IGNOREDOT;
640    }
641
[8bd190d]642    buf = slurp_stdin(zoptions->flags & ZCRYPT_OPT_IGNOREDOT, length);
[9a4077c]643  }
644  return buf;
645}
646
[6829afc]647CALLER_OWN char *read_keystring(const char *keyfile) {
[9a4077c]648  char *keystring;
649  FILE *fkey = fopen(keyfile, "r");
650  if(!fkey) {
651    fprintf(stderr, "Unable to open keyfile %s\n", keyfile);
652    return NULL;
653  }
654  keystring = malloc(MAX_KEY);
655  if(!fgets(keystring, MAX_KEY-1, fkey)) {
656    fprintf(stderr, "Unable to read from keyfile: %s\n", keyfile);
657    free(keystring);
658    keystring = NULL;
659  }
660  fclose(fkey);
661  return keystring;
662}
663
664/* Encrypt stdin, with prompt if isatty, and send to stdout, or to zwrite
665   if zephyr is set. */
[e832a52]666int do_encrypt(int zephyr, const char *class, const char *instance,
667               ZWRITEOPTIONS *zoptions, const char *keyfile, int cipher)
[9a4077c]668{
669  FILE *outfile = stdout;
670  char *inbuff = NULL;
671  int buflen;
672  int out = TRUE;
673
674  inbuff = GetInputBuffer(zoptions, &buflen);
675
676  if(!inbuff) {
677    fprintf(stderr, "Error reading zcrypt input!\n");
678    return FALSE;
679  }
[edae037]680
[9a4077c]681  if (zephyr) {
[edae037]682    outfile = GetZephyrPipe(class, instance, zoptions);
683    if (!outfile)
684    {
[a08bfc3]685      fprintf(stderr, "Could not run zwrite\n");
[9a4077c]686      if (inbuff)
[f7f35c0]687        free(inbuff);
[edae037]688      return FALSE;
689    }
690  }
691
[6d7f2a8]692  out = ciphers[cipher].encrypt(keyfile, inbuff, buflen, outfile);
[9a4077c]693
694  if (zephyr)
695    CloseZephyrPipe(outfile);
696
697  free(inbuff);
698  return out;
699}
700
[e832a52]701int do_encrypt_des(const char *keyfile, const char *in, int length, FILE *outfile)
[9a4077c]702{
703  des_key_schedule schedule;
704  unsigned char input[8], output[8];
[e832a52]705  const char *inptr;
[9a4077c]706  int num_blocks, last_block_size;
707  char *keystring;
708  int size;
709
710  keystring = read_keystring(keyfile);
711  if(!keystring) {
712    return FALSE;
713  }
714
[c836519]715  owl_zcrypt_string_to_schedule(keystring, &schedule);
[9a4077c]716  free(keystring);
717
718  inptr = in;
719  num_blocks = (length + 7) / 8;
720  last_block_size = ((length + 7) % 8) + 1;
[edae037]721
722  /* Encrypt the input (inbuff or stdin) and send it to outfile */
723  while (TRUE)
724  {
[9a4077c]725    /* Get 8 bytes from buffer */
726    if (num_blocks > 1)
[edae037]727    {
[9a4077c]728      size = 8;
729      memcpy(input, inptr, size);
730      inptr += 8;
731      num_blocks--;
732    }
733    else if (num_blocks == 1)
734    {
735      size = last_block_size;
736      memcpy(input, inptr, size);
737      num_blocks--;
[edae037]738    }
739    else
[9a4077c]740      size = 0;
[edae037]741
742    /* Check for EOF and pad the string to 8 chars, if needed */
743    if (size == 0)
[9a4077c]744      break;
[edae037]745    if (size < 8)
746      memset(input + size, 0, 8 - size);
747
748    /* Encrypt and output the block */
[356465e]749    des_ecb_encrypt(&input, &output, schedule, TRUE);
[edae037]750    block_to_ascii(output, outfile);
751
752    if (size < 8)
753      break;
754  }
755
[9a4077c]756  putc('\n', outfile);
[edae037]757
[9a4077c]758  return TRUE;
[edae037]759}
760
[e832a52]761int do_encrypt_aes(const char *keyfile, const char *in, int length, FILE *outfile)
[8bd190d]762{
763  char *out;
764  int err, status;
765  const char *argv[] = {
766    "gpg",
767    "--symmetric",
768    "--batch",
769    "--quiet",
770    "--no-use-agent",
771    "--armor",
772    "--cipher-algo", "AES",
773    "--passphrase-file", keyfile,
774    NULL
775  };
[97cdbaf5]776  err = call_filter(argv, in, &out, &status);
[8bd190d]777  if(err || status) {
[3b8a563]778    g_free(out);
[8bd190d]779    return FALSE;
780  }
781  fwrite(out, strlen(out), 1, outfile);
782  g_free(out);
783  return TRUE;
784}
785
[edae037]786/* Read a half-byte from stdin, skipping invalid characters.  Returns -1
787   if at EOF or file error */
[356465e]788int read_ascii_nybble(void)
[edae037]789{
790  char c;
791
792  while (TRUE)
793  {
794    if (fread(&c, 1, 1, stdin) == 0)
795      return -1;
796    else if (c >= BASE_CODE && c <= LAST_CODE)
797      return c - BASE_CODE;
798  }
799}
800
801/* Read both halves of the byte and return the single byte.  Returns -1
802   if at EOF or file error. */
[356465e]803int read_ascii_byte(void)
[edae037]804{
805  int c1, c2;
806  c1 = read_ascii_nybble();
807  if (c1 >= 0)
808  {
809    c2 = read_ascii_nybble();
810    if (c2 >= 0)
811    {
812      return c1 * 0x10 + c2;
813    }
814  }
815  return -1;
816}
817
818/* Read an 8-byte DES block from stdin */
[356465e]819int read_ascii_block(unsigned char *input)
[edae037]820{
821  int c;
822
823  int i;
824  for (i = 0; i < 8; i++)
825  {
826    c = read_ascii_byte();
827    if (c < 0)
828      return FALSE;
829
830    input[i] = c;
831  }
832
833  return TRUE;
834}
835
836/* Decrypt stdin */
[e832a52]837int do_decrypt(const char *keyfile, int cipher)
[edae037]838{
[6d7f2a8]839  return ciphers[cipher].decrypt(keyfile);
[8bd190d]840}
841
[e832a52]842int do_decrypt_aes(const char *keyfile) {
[8bd190d]843  char *in, *out;
844  int length;
845  const char *argv[] = {
846    "gpg",
847    "--decrypt",
848    "--batch",
849    "--no-use-agent",
850    "--quiet",
851    "--passphrase-file", keyfile,
852    NULL
853  };
854  int err, status;
855
856  in = slurp_stdin(TRUE, &length);
857  if(!in) return FALSE;
858
[97cdbaf5]859  err = call_filter(argv, in, &out, &status);
[8bd190d]860  if(err || status) {
[3b8a563]861    g_free(out);
[8bd190d]862    return FALSE;
863  }
864  fwrite(out, strlen(out), 1, stdout);
865  g_free(out);
866
867  return TRUE;
868}
869
[e832a52]870int do_decrypt_des(const char *keyfile) {
[edae037]871  des_key_schedule schedule;
[356465e]872  unsigned char input[8], output[8];
[60fcd71]873  char tmp[9];
[8bd190d]874  char *keystring;
[edae037]875
[60fcd71]876  /*
877    DES decrypts 8 bytes at a time. We copy those over into the 9-byte
878    'tmp', which has the final byte zeroed, to ensure that we always
879    have a NULL-terminated string we can call printf/strlen on.
880
881    We don't pass 'tmp' to des_ecb_encrypt directly, because it's
882    prototyped as taking 'unsigned char[8]', and this avoids a stupid
883    cast.
884
885    We zero 'tmp' entirely, not just the final byte, in case there are
886    no input blocks.
887  */
888  memset(tmp, 0, sizeof tmp);
[edae037]889
[8bd190d]890  keystring = read_keystring(keyfile);
891  if(!keystring) return FALSE;
892
[c836519]893  owl_zcrypt_string_to_schedule(keystring, &schedule);
[edae037]894
[8bd190d]895  free(keystring);
896
[edae037]897  while (read_ascii_block(input))
898  {
[356465e]899    des_ecb_encrypt(&input, &output, schedule, FALSE);
[60fcd71]900    memcpy(tmp, output, 8);
901    printf("%s", tmp);
[edae037]902  }
903
[60fcd71]904  if (!tmp[0] || tmp[strlen(tmp) - 1] != '\n')
[edae037]905      printf("\n");
[9a4077c]906  return TRUE;
[edae037]907}
Note: See TracBrowser for help on using the repository browser.