source: zcrypt.c @ 478dc8e

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