source: zcrypt.c @ f8074e9

release-1.6release-1.7release-1.8release-1.9
Last change on this file since f8074e9 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
Line 
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>
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
23#include <unistd.h>
24#include <sys/types.h>
25
26#ifdef HAVE_KERBEROS_IV
27#include <kerberosIV/des.h>
28#else
29#include <openssl/des.h>
30#endif
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
49char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance);
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
58static void owl_zcrypt_string_to_schedule(const char *keystring, des_key_schedule *schedule) {
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);
66  des_key_sched(key, *schedule);
67}
68
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 */
73char *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
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
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
127char *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
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
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
208
209#define MAX_BUFF 258
210#define MAX_SEARCH 3
211/* Find the class/instance in the .crypt-table */
212char *GetZephyrVarKeyFile(const char *whoami, const char *class, const char *instance) {
213  char *keyfile = NULL;
214  char *varname[MAX_SEARCH];
215  int length[MAX_SEARCH], i;
216  char buffer[MAX_BUFF];
217  char *filename;
218  char result[MAX_SEARCH][MAX_BUFF];
219  int numsearch = 0;
220  FILE *fsearch;
221
222  memset(varname, 0, sizeof(varname));
223
224  /* 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:");
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 */
240  filename = owl_sprintf("%s/.crypt-table", getenv("HOME"));
241  fsearch = fopen(filename, "r");
242  if (fsearch) {
243    /* Scan file for a match */
244    while (!feof(fsearch)) {
245      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      }
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) {
271      /* printf("Could not find key table entry.\n"); */
272    } 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
Note: See TracBrowser for help on using the repository browser.