source: zcrypt.c @ 732cc15

release-1.6release-1.7release-1.8release-1.9
Last change on this file since 732cc15 was 732cc15, checked in by Anders Kaseorg <andersk@mit.edu>, 12 years ago
owl_zcrypt_decrypt, owl_zcrypt_encrypt: Don’t leak the key filename. Signed-off-by: Anders Kaseorg <andersk@mit.edu> Reviewed-by: Alejandro R. Sedeño <asedeno@mit.edu>
  • Property mode set to 100644
File size: 7.6 KB
RevLine 
[d309eb3]1/* This file is stolen and slightly modified code */
2
3/* zcrypt.c -- Read in a data stream from stdin & dump a decrypted/encrypted *
4 *   datastream.  Reads the string to make the key from from the first       *
5 *   parameter.  Encrypts or decrypts according to -d or -e flag.  (-e is    *
6 *   default.)  Will invoke zwrite if the -c option is provided for          *
7 *   encryption.  If a zephyr class is specified & the keyfile name omitted  *
8 *   the ~/.crypt-table will be checked for "crypt-classname" and then       *
9 *   "crypt-default" for the keyfile name.                                   */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <sys/types.h>
15#include <sys/wait.h>
[ac70242]16#include "owl.h"
[d309eb3]17
[c86a35c]18#ifdef OWL_ENABLE_ZCRYPT
[c269e22]19
[d309eb3]20#define BASE_CODE 70
21#define LAST_CODE (BASE_CODE + 15)
22#define OUTPUT_BLOCK_SIZE 16
23#include <unistd.h>
24#include <sys/types.h>
[806f769]25
26#ifdef HAVE_KERBEROS_IV
27#include <kerberosIV/des.h>
28#else
29#include <openssl/des.h>
30#endif
[d309eb3]31
32#define MAX_KEY 128
33
34#ifndef TRUE
35#define TRUE -1
36#endif
37#ifndef FALSE
38#define FALSE 0
39#endif
40
41#define ZWRITE_OPT_NOAUTH     (1<<0)
42#define ZWRITE_OPT_SIGNATURE  (1<<1)
43#define ZWRITE_OPT_IGNOREVARS (1<<2)
44#define ZWRITE_OPT_VERBOSE    (1<<3)
45#define ZWRITE_OPT_QUIET      (1<<4)
46#define ZCRYPT_OPT_MESSAGE    (1<<5)
47#define ZCRYPT_OPT_IGNOREDOT  (1<<6)
48
49typedef struct
50{
51  int flags;
52  char *signature;
53  char *message;
54} ZWRITEOPTIONS;
55
[e19eb97]56char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance);
[d309eb3]57
58#define M_NONE            0
59#define M_ZEPHYR_ENCRYPT  1
60#define M_DECRYPT         2
61#define M_ENCRYPT         3
62#define M_RANDOMIZE       4
63#define M_SETKEY          5
64
[a52eeb1]65static void owl_zcrypt_string_to_schedule(const char *keystring, des_key_schedule *schedule) {
[3daca13]66#ifdef HAVE_KERBEROS_IV
67  des_cblock key;
68#else
69  des_cblock _key, *key = &_key;
70#endif
71
72  des_string_to_key(keystring, key);
[3f18ad5]73  des_key_sched(key, *schedule);
[3daca13]74}
75
[9ceee9d]76/* The 'owl_zcrypt_decrypt' function was written by kretch for Owl.
77 * Decrypt the message in 'in' on class 'class' and instance
[dacb555]78 * 'instance'.  Return must be freed by caller.
[9ceee9d]79 */
[dacb555]80char *owl_zcrypt_decrypt(const char *in, const char *class, const char *instance)
81{
[65b2173]82  char *fname, keystring[MAX_KEY];
[d309eb3]83  FILE *fkey;
84 
85  fname=GetZephyrVarKeyFile("zcrypt", class, instance);
[dacb555]86  if (!fname) return NULL;
[d309eb3]87  fkey=fopen(fname, "r");
[732cc15]88  owl_free(fname);
[dacb555]89  if (!fkey) return NULL;
[3daca13]90  if (!fgets(keystring, MAX_KEY-1, fkey)) {
91    fclose(fkey);
[dacb555]92    return NULL;
[3daca13]93  }
[d309eb3]94  fclose(fkey);
95
[a52eeb1]96  return owl_zcrypt_decrypt_with_key(in, keystring);
97}
98
99char *owl_zcrypt_decrypt_with_key(const char *in, const char *keystring)
100{
101  const char *inptr, *endptr;
102  char *out;
103  des_key_schedule schedule;
104  unsigned char input[8], output[8];
105  int i, c1, c2;
106
[f61e7ac]107  /* We read in some number of full 16-byte blocks and write out the
108   * same number of 8-byte blocks, plus a null terminator.
109   */
110  out = owl_malloc((strlen(in) / 16) * 8 + 1);
[a52eeb1]111
[d309eb3]112  strcpy(out, "");
113
114  output[0] = '\0';    /* In case no message at all                 */
115
[3f18ad5]116  owl_zcrypt_string_to_schedule(keystring, &schedule);
[d309eb3]117
118  inptr=in;
[1f37eba]119  endptr = in + strlen(in);
120  while (inptr + 16 <= endptr) {
[d309eb3]121    for (i=0; i<8; i++) {
122      c1=(inptr[0])-BASE_CODE;
123      c2=(inptr[1])-BASE_CODE;
124      input[i]=c1 * 0x10 + c2;
125      inptr+=2;
126    }
[3daca13]127    des_ecb_encrypt(&input, &output, schedule, FALSE);
128    strncat(out, (const char *)output, 8);
[d309eb3]129  }
130
[dacb555]131  return out;
[d309eb3]132}
133
[dacb555]134char *owl_zcrypt_encrypt(const char *in, const char *class, const char *instance)
135{
[9ceee9d]136  char *fname, keystring[MAX_KEY];
137  FILE *fkey;
138
139  fname=GetZephyrVarKeyFile("zcrypt", class, instance);
[dacb555]140  if (!fname) return NULL;
[9ceee9d]141  fkey=fopen(fname, "r");
[732cc15]142  owl_free(fname);
[dacb555]143  if (!fkey) return NULL;
[3daca13]144  if (!fgets(keystring, MAX_KEY-1, fkey)) {
145    fclose(fkey);
[dacb555]146    return NULL;
[3daca13]147  }
[9ceee9d]148  fclose(fkey);
149
[a52eeb1]150  return owl_zcrypt_encrypt_with_key(in, keystring);
151}
152
153char *owl_zcrypt_encrypt_with_key(const char *in, const char *keystring)
154{
155  des_key_schedule schedule;
156  char *out;
157  unsigned char input[8], output[8];
158  int size, length, i;
159  const char *inbuff = NULL, *inptr;
160  int num_blocks=0, last_block_size=0;
161
[3f18ad5]162  owl_zcrypt_string_to_schedule(keystring, &schedule);
[9ceee9d]163
[dacb555]164  /* Allocate enough space for the crypted message. For each byte of
165   * the message, the encoded cyphertext will have two bytes. Block
166   * size is 8 bytes of input, or 16 bytes of output, so make sure we
167   * have at least one block worth of space allocated. If the message
168   * is empty, no blocks are sent, but we still allocate one
169   * block. The additional 16 bytes also provide space for the null
170   * terminator, as we will never use all of it for cyphertext.
171   */
172  out = owl_malloc((strlen(in) * 2) + 16);
173
[9ceee9d]174  inbuff=in;
175  length=strlen(inbuff);
176  num_blocks=(length+7)/8;
177  last_block_size=((length+7)%8)+1;
178
179  strcpy(out, "");
180 
181  inptr=inbuff;
182  while (TRUE) {
183    /* Get 8 bytes from buffer */
184    if (num_blocks > 1) {
185      size = 8;
186      memcpy(input, inptr, size);
187      inptr+=8;
188      num_blocks--;
189    } else if (num_blocks == 1) {
190      size=last_block_size;
191      memcpy(input, inptr, size);
192      num_blocks--;
193    } else {
194      size=0;
195    }
196
197    /* Check for EOF and pad the string to 8 chars, if needed */
198    if (size == 0) break;     /* END OF INPUT: BREAK FROM while LOOP! */
199     
200    if (size<8) memset(input + size, 0, 8 - size);
201
202    /* Encrypt and output the block */
[3daca13]203    des_ecb_encrypt(&input, &output, schedule, TRUE);
[9ceee9d]204
205    for (i = 0; i < 8; i++) {
[b9cb41b]206      sprintf(out + strlen(out), "%c", ((output[i] & 0xf0) >> 4) + BASE_CODE);
207      sprintf(out + strlen(out), "%c", (output[i] & 0x0f)        + BASE_CODE);
[9ceee9d]208    }
209
210    if (size < 8) break;
211  }
[dacb555]212  return out;
[d309eb3]213}
214
215
216#define MAX_BUFF 258
217#define MAX_SEARCH 3
218/* Find the class/instance in the .crypt-table */
[e19eb97]219char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance) {
[e3869df]220  char *keyfile = NULL;
[8412869]221  char *varname[MAX_SEARCH];
[d309eb3]222  int length[MAX_SEARCH], i;
223  char buffer[MAX_BUFF];
[8412869]224  char *filename;
[d309eb3]225  char result[MAX_SEARCH][MAX_BUFF];
226  int numsearch = 0;
227  FILE *fsearch;
228
[8412869]229  memset(varname, 0, sizeof(varname));
230
[d309eb3]231  /* Determine names to look for in .crypt-table */
232  if (instance) {
[8412869]233    varname[numsearch++] = owl_sprintf("crypt-%s-%s:", (class?class:"message"), instance);
[d309eb3]234  }
235  if (class) {
[8412869]236    varname[numsearch++] = owl_sprintf("crypt-%s:", class);
[d309eb3]237  }
[8412869]238  varname[numsearch++] = owl_strdup("crypt-default:");
[d309eb3]239
240  /* Setup the result array, and determine string lengths */
241  for (i = 0; i < numsearch; i++) {
242    result[i][0] = '\0';
243    length[i] = strlen(varname[i]);
244  }
245
246  /* Open~/.crypt-table */
[8412869]247  filename = owl_sprintf("%s/.crypt-table", getenv("HOME"));
[d309eb3]248  fsearch = fopen(filename, "r");
249  if (fsearch) {
250    /* Scan file for a match */
251    while (!feof(fsearch)) {
[3daca13]252      if (!fgets(buffer, MAX_BUFF - 3, fsearch)) break;
[d309eb3]253      for (i = 0; i < numsearch; i++) {
254        if (strncasecmp(varname[i], buffer, length[i]) == 0) {
255          int j;
256          for (j = length[i]; buffer[j] == ' '; j++)
257            ;
258          strcpy(result[i], &buffer[j]);
259          if (*result[i]) {
260            if (result[i][strlen(result[i])-1] == '\n') {
261              result[i][strlen(result[i])-1] = '\0';
262            }
263          }
264        }
265      }
266    }
267
268    /* Pick the "best" match found */
269    keyfile = NULL;
270    for (i = 0; i < numsearch; i++) {
271      if (*result[i]) {
272        keyfile = result[i];
273        break;
274      }
275    }
276
277    if (keyfile == NULL) {
[9ceee9d]278      /* printf("Could not find key table entry.\n"); */
[d309eb3]279    } else {
280      /* Prepare result to be returned */
[36486be]281      keyfile = owl_strdup(keyfile);
[d309eb3]282    }
283   
284    fclose(fsearch);
285  } else {
[9ceee9d]286    /* printf("Could not open key table file: %s\n", filename); */
[d309eb3]287  }
288
[8412869]289  for(i = 0; i < MAX_SEARCH; i++) {
290    owl_free(varname[i]);
291  }
292
293  owl_free(filename);
294
[d309eb3]295  return(keyfile);
296}
297
[c269e22]298#endif
Note: See TracBrowser for help on using the repository browser.