Changes in / [8a5b5a1:e2cbbbe]


Ignore:
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • .gitignore

    r1703f72 r7d03c8d  
    1515autom4te.cache
    1616barnowl.bin
     17zcrypt
    1718blib
    1819config.cache
  • Makefile.am

    r10557e6 r7d03c8d  
    55
    66bin_PROGRAMS = barnowl.bin
     7if ENABLE_ZCRYPT
     8bin_PROGRAMS += zcrypt
     9endif
     10
     11zcrypt_SOURCES = zcrypt.c filterproc.c
     12
    713check_PROGRAMS = tester perl_tester
    814
    915barnowl_bin_SOURCES = $(BASE_SRCS) \
    1016     owl.h owl_perl.h config.h \
    11      owl.c \
     17     owl.c filterproc.c \
    1218     $(GEN_C) $(GEN_H)
    1319
     
    3844     perlconfig.c keys.c functions.c zwrite.c viewwin.c help.c filter.c \
    3945     regex.c history.c view.c dict.c variable.c filterelement.c pair.c \
    40      keypress.c keymap.c keybinding.c cmd.c context.c zcrypt.c \
     46     keypress.c keymap.c keybinding.c cmd.c context.c \
    4147     aim.c buddy.c buddylist.c style.c errqueue.c \
    4248     zbuddylist.c popexec.c obarray.c select.c wcwidth.c \
  • barnowl

    rd5ef539 r9a7b4f2  
    1313
    1414export BARNOWL_DATA_DIR="$SRCDIR/perl/"
     15export BARNOWL_BIN_DIR="$SRCDIR/"
    1516exec "$EXE" "$@"
  • commands.c

    r8a5b5a1 r8a5b5a1  
    20222022char *owl_command_zcrypt(int argc, const char *const *argv, const char *buff)
    20232023{
    2024 #ifdef OWL_ENABLE_ZCRYPT
    20252024  owl_zwrite z;
    20262025
     
    20442043  }
    20452044  return(NULL);
    2046 #else
    2047   owl_function_makemsg("This Owl does not support zcrypt");
    2048   return NULL;
    2049 #endif
    20502045}
    20512046
  • configure.ac

    r2d3ed95 r9a7b4f2  
    6565
    6666AC_CHECK_FUNCS([use_default_colors resizeterm])
    67 AC_CHECK_FUNCS([des_string_to_key des_key_sched des_ecb_encrypt])
    68 AC_CHECK_FUNCS([DES_string_to_key DES_ecb_encrypt DES_key_sched])
     67AC_CHECK_FUNCS([des_string_to_key DES_string_to_key], [HAVE_DES_STRING_TO_KEY=1])
     68AC_CHECK_FUNCS([des_ecb_encrypt DES_ecb_encrypt], [HAVE_DES_ECB_ENCRYPT=1])
     69AC_CHECK_FUNCS([des_key_sched DES_key_sched], [HAVE_DES_KEY_SCHED=1])
    6970
    7071dnl Checks for header files.
     
    118119AC_DEFINE_UNQUOTED([DATADIR],["${prefix}/share/${PACKAGE}"],
    119120                   [Package data directory])
     121AC_DEFINE_UNQUOTED([BINDIR],["${prefix}/bin"],
     122                   [Binary directory])
    120123
    121124dnl Checks for typedefs, structures, and compiler characteristics.
     
    126129AX_C_CHECK_FLAG([-Wno-pointer-sign],[],[],
    127130  [LIBFAIM_CFLAGS="$LIBFAIM_CFLAGS -Wno-pointer-sign"])
     131
     132AM_CONDITIONAL([ENABLE_ZCRYPT], [test "$HAVE_DES_STRING_TO_KEY" && dnl
     133                                 test "$HAVE_DES_KEY_SCHED" && dnl
     134                                 test "$HAVE_DES_ECB_ENCRYPT"])
    128135
    129136AC_SUBST([LIBFAIM_CFLAGS])
  • functions.c

    r8a5b5a1 r9a7b4f2  
    1212#include <signal.h>
    1313#include "owl.h"
     14#include "filterproc.h"
    1415
    1516char *owl_function_command(const char *cmdbuff)
     
    399400  char *cryptmsg;
    400401  owl_message *m;
     402  const char *argv[7];
     403  char *zcrypt;
     404  int rv, status;
    401405
    402406  /* create the zwrite and send the message */
     
    408412
    409413  mymsg=owl_zwrite_get_message(&z);
    410 #ifdef OWL_ENABLE_ZCRYPT
    411   cryptmsg = owl_zcrypt_encrypt(mymsg, owl_zwrite_get_class(&z), owl_zwrite_get_instance(&z));
    412   if (!cryptmsg) {
     414
     415  zcrypt = owl_sprintf("%s/zcrypt", owl_get_bindir());
     416  argv[0] = "zcrypt";
     417  argv[1] = "-E";
     418  argv[2] = "-c"; argv[3] = owl_zwrite_get_class(&z);
     419  argv[4] = "-i"; argv[5] = owl_zwrite_get_instance(&z);
     420  argv[6] = NULL;
     421
     422  rv = call_filter(zcrypt, argv, mymsg, &cryptmsg, &status);
     423
     424  owl_free(zcrypt);
     425
     426  if (rv || status) {
     427    if(cryptmsg) owl_free(cryptmsg);
    413428    owl_function_error("Error in zcrypt, possibly no key found.  Message not sent.");
    414429    owl_function_beep();
     
    416431    return;
    417432  }
    418 #else
    419   cryptmsg=owl_strdup(mymsg);
    420 #endif
    421433
    422434  owl_zwrite_set_message(&z, cryptmsg);
  • message.c

    r66a8cd6 r9a7b4f2  
    1010#include <time.h>
    1111#include "owl.h"
     12#include "filterproc.h"
    1213
    1314static owl_fmtext_cache fmtext_cache[OWL_FMTEXT_CACHE_SIZE];
     
    838839  owl_free(tmp);
    839840
    840 #ifdef OWL_ENABLE_ZCRYPT
    841841  /* if zcrypt is enabled try to decrypt the message */
    842842  if (owl_global_is_zcrypt(&g) && !strcasecmp(n->z_opcode, "crypt")) {
    843     char *out = owl_zcrypt_decrypt(owl_message_get_body(m), owl_message_get_class(m), owl_message_get_instance(m));
    844     if (out) {
     843    const char *argv[] = {
     844      "zcrypt",
     845      "-D",
     846      "-c", owl_message_get_class(m),
     847      "-i", owl_message_get_instance(m),
     848      NULL
     849    };
     850    char *out;
     851    int rv;
     852    int status;
     853    char *zcrypt;
     854
     855    zcrypt = owl_sprintf("%s/zcrypt", owl_get_bindir());
     856
     857    rv = call_filter(zcrypt, argv, owl_message_get_body(m), &out, &status);
     858    owl_free(zcrypt);
     859
     860    if(!rv && !status) {
     861      int len = strlen(out);
     862      if(len >= 8 && !strcmp(out + len - 8, "**END**\n")) {
     863        out[len - 8] = 0;
     864      }
    845865      owl_message_set_body(m, out);
    846866      owl_free(out);
     867    } else if(out) {
     868      owl_free(out);
    847869    }
    848870  }
    849 #endif 
    850871}
    851872#else
  • tester.c

    r30bb10a rd564c3d  
    1313int owl_obarray_regtest(void);
    1414int owl_editwin_regtest(void);
    15 #ifdef OWL_ENABLE_ZCRYPT
    16 int owl_zcrypt_regtest(void);
    17 #endif
    1815
    1916int main(int argc, char **argv, char **env)
     
    3633  numfailures += owl_obarray_regtest();
    3734  numfailures += owl_editwin_regtest();
    38 #ifdef OWL_ENABLE_ZCRYPT
    39   numfailures += owl_zcrypt_regtest();
    40 #endif
    4135  if (numfailures) {
    4236      fprintf(stderr, "# *** WARNING: %d failures total\n", numfailures);
     
    367361  return numfailed;
    368362}
    369 
    370 #ifdef OWL_ENABLE_ZCRYPT
    371 int owl_zcrypt_regtest(void)
    372 {
    373   int numfailed = 0;
    374   char *encrypted, *decrypted;
    375 
    376   printf("# BEGIN testing owl_zcrypt\n");
    377 
    378   encrypted = owl_zcrypt_encrypt_with_key("Hello, world!", "seekritkey");
    379   FAIL_UNLESS("zcrypt encrypt", strcmp(encrypted, "TLJMKQSIGKSJRIJRSIIPIJFFULKRJSPK") == 0);
    380   decrypted = owl_zcrypt_decrypt_with_key(encrypted, "seekritkey");
    381   FAIL_UNLESS("zcrypt decrypt", strcmp(decrypted, "Hello, world!") == 0);
    382   owl_free(decrypted);
    383   owl_free(encrypted);
    384 
    385   printf("# END testing owl_zcrypt (%d failures)\n", numfailed);
    386 
    387   return numfailed;
    388 }
    389 #endif
  • util.c

    rf449096 r9a7b4f2  
    609609}
    610610
     611const char * owl_get_bindir(void)
     612{
     613  const char * bindir = getenv("BARNOWL_BIN_DIR");
     614  if(bindir != NULL)
     615    return bindir;
     616  return BINDIR;
     617}
     618
    611619/* Strips format characters from a valid utf-8 string. Returns the
    612620   empty string if 'in' does not validate. */
  • zcrypt.c

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