source: zcrypt.c @ c836519

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