source: zcrypt.c @ 2ee9e8d

release-1.6release-1.7release-1.8release-1.9
Last change on this file since 2ee9e8d was f8074e9, checked in by Anders Kaseorg <andersk@mit.edu>, 12 years ago
Use bool from <stdbool.h> instead of an ad-hoc definition in libfaim/aim.h. Signed-off-by: Anders Kaseorg <andersk@mit.edu> Reviewed-by: Nelson Elhage <nelhage@mit.edu>
  • Property mode set to 100644
File size: 7.5 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#define ZWRITE_OPT_NOAUTH     (1<<0)
35#define ZWRITE_OPT_SIGNATURE  (1<<1)
36#define ZWRITE_OPT_IGNOREVARS (1<<2)
37#define ZWRITE_OPT_VERBOSE    (1<<3)
38#define ZWRITE_OPT_QUIET      (1<<4)
39#define ZCRYPT_OPT_MESSAGE    (1<<5)
40#define ZCRYPT_OPT_IGNOREDOT  (1<<6)
41
42typedef struct
43{
44  int flags;
45  char *signature;
46  char *message;
47} ZWRITEOPTIONS;
48
[e19eb97]49char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance);
[d309eb3]50
51#define M_NONE            0
52#define M_ZEPHYR_ENCRYPT  1
53#define M_DECRYPT         2
54#define M_ENCRYPT         3
55#define M_RANDOMIZE       4
56#define M_SETKEY          5
57
[a52eeb1]58static void owl_zcrypt_string_to_schedule(const char *keystring, des_key_schedule *schedule) {
[3daca13]59#ifdef HAVE_KERBEROS_IV
60  des_cblock key;
61#else
62  des_cblock _key, *key = &_key;
63#endif
64
65  des_string_to_key(keystring, key);
[3f18ad5]66  des_key_sched(key, *schedule);
[3daca13]67}
68
[9ceee9d]69/* The 'owl_zcrypt_decrypt' function was written by kretch for Owl.
70 * Decrypt the message in 'in' on class 'class' and instance
[dacb555]71 * 'instance'.  Return must be freed by caller.
[9ceee9d]72 */
[dacb555]73char *owl_zcrypt_decrypt(const char *in, const char *class, const char *instance)
74{
[65b2173]75  char *fname, keystring[MAX_KEY];
[d309eb3]76  FILE *fkey;
77 
78  fname=GetZephyrVarKeyFile("zcrypt", class, instance);
[dacb555]79  if (!fname) return NULL;
[d309eb3]80  fkey=fopen(fname, "r");
[732cc15]81  owl_free(fname);
[dacb555]82  if (!fkey) return NULL;
[3daca13]83  if (!fgets(keystring, MAX_KEY-1, fkey)) {
84    fclose(fkey);
[dacb555]85    return NULL;
[3daca13]86  }
[d309eb3]87  fclose(fkey);
88
[a52eeb1]89  return owl_zcrypt_decrypt_with_key(in, keystring);
90}
91
92char *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
[f61e7ac]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);
[a52eeb1]104
[d309eb3]105  strcpy(out, "");
106
107  output[0] = '\0';    /* In case no message at all                 */
108
[3f18ad5]109  owl_zcrypt_string_to_schedule(keystring, &schedule);
[d309eb3]110
111  inptr=in;
[1f37eba]112  endptr = in + strlen(in);
113  while (inptr + 16 <= endptr) {
[d309eb3]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    }
[3daca13]120    des_ecb_encrypt(&input, &output, schedule, FALSE);
121    strncat(out, (const char *)output, 8);
[d309eb3]122  }
123
[dacb555]124  return out;
[d309eb3]125}
126
[dacb555]127char *owl_zcrypt_encrypt(const char *in, const char *class, const char *instance)
128{
[9ceee9d]129  char *fname, keystring[MAX_KEY];
130  FILE *fkey;
131
132  fname=GetZephyrVarKeyFile("zcrypt", class, instance);
[dacb555]133  if (!fname) return NULL;
[9ceee9d]134  fkey=fopen(fname, "r");
[732cc15]135  owl_free(fname);
[dacb555]136  if (!fkey) return NULL;
[3daca13]137  if (!fgets(keystring, MAX_KEY-1, fkey)) {
138    fclose(fkey);
[dacb555]139    return NULL;
[3daca13]140  }
[9ceee9d]141  fclose(fkey);
142
[a52eeb1]143  return owl_zcrypt_encrypt_with_key(in, keystring);
144}
145
146char *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
[3f18ad5]155  owl_zcrypt_string_to_schedule(keystring, &schedule);
[9ceee9d]156
[dacb555]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
[9ceee9d]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 */
[3daca13]196    des_ecb_encrypt(&input, &output, schedule, TRUE);
[9ceee9d]197
198    for (i = 0; i < 8; i++) {
[b9cb41b]199      sprintf(out + strlen(out), "%c", ((output[i] & 0xf0) >> 4) + BASE_CODE);
200      sprintf(out + strlen(out), "%c", (output[i] & 0x0f)        + BASE_CODE);
[9ceee9d]201    }
202
203    if (size < 8) break;
204  }
[dacb555]205  return out;
[d309eb3]206}
207
208
209#define MAX_BUFF 258
210#define MAX_SEARCH 3
211/* Find the class/instance in the .crypt-table */
[e19eb97]212char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance) {
[e3869df]213  char *keyfile = NULL;
[8412869]214  char *varname[MAX_SEARCH];
[d309eb3]215  int length[MAX_SEARCH], i;
216  char buffer[MAX_BUFF];
[8412869]217  char *filename;
[d309eb3]218  char result[MAX_SEARCH][MAX_BUFF];
219  int numsearch = 0;
220  FILE *fsearch;
221
[8412869]222  memset(varname, 0, sizeof(varname));
223
[d309eb3]224  /* Determine names to look for in .crypt-table */
225  if (instance) {
[8412869]226    varname[numsearch++] = owl_sprintf("crypt-%s-%s:", (class?class:"message"), instance);
[d309eb3]227  }
228  if (class) {
[8412869]229    varname[numsearch++] = owl_sprintf("crypt-%s:", class);
[d309eb3]230  }
[8412869]231  varname[numsearch++] = owl_strdup("crypt-default:");
[d309eb3]232
233  /* Setup the result array, and determine string lengths */
234  for (i = 0; i < numsearch; i++) {
235    result[i][0] = '\0';
236    length[i] = strlen(varname[i]);
237  }
238
239  /* Open~/.crypt-table */
[8412869]240  filename = owl_sprintf("%s/.crypt-table", getenv("HOME"));
[d309eb3]241  fsearch = fopen(filename, "r");
242  if (fsearch) {
243    /* Scan file for a match */
244    while (!feof(fsearch)) {
[3daca13]245      if (!fgets(buffer, MAX_BUFF - 3, fsearch)) break;
[d309eb3]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      }
259    }
260
261    /* Pick the "best" match found */
262    keyfile = NULL;
263    for (i = 0; i < numsearch; i++) {
264      if (*result[i]) {
265        keyfile = result[i];
266        break;
267      }
268    }
269
270    if (keyfile == NULL) {
[9ceee9d]271      /* printf("Could not find key table entry.\n"); */
[d309eb3]272    } else {
273      /* Prepare result to be returned */
[36486be]274      keyfile = owl_strdup(keyfile);
[d309eb3]275    }
276   
277    fclose(fsearch);
278  } else {
[9ceee9d]279    /* printf("Could not open key table file: %s\n", filename); */
[d309eb3]280  }
281
[8412869]282  for(i = 0; i < MAX_SEARCH; i++) {
283    owl_free(varname[i]);
284  }
285
286  owl_free(filename);
287
[d309eb3]288  return(keyfile);
289}
290
[c269e22]291#endif
Note: See TracBrowser for help on using the repository browser.