]> git.sur5r.net Git - openldap/blob - clients/ud/string_to_key.c
Add OpenLDAP RCSid to *.[ch] in clients, libraries, and servers.
[openldap] / clients / ud / string_to_key.c
1 /* $OpenLDAP$ */
2 #include "portable.h"
3
4 #if defined(HAVE_KERBEROS) && !defined(openbsd)
5 /*
6  * $Source: /repo/OpenLDAP/pkg/ldap/clients/ud/string_to_key.c,v $
7  * $Author: hallvard $
8  *
9  * Copyright 1985, 1986, 1987, 1988, 1989 by the Massachusetts Institute
10  * of Technology.
11  *
12  * For copying and distribution information, please see the file
13  * <mit-copyright.h>.
14  *
15  * These routines perform encryption and decryption using the DES
16  * private key algorithm, or else a subset of it-- fewer inner loops.
17  * (AUTH_DES_ITER defaults to 16, may be less.)
18  *
19  * Under U.S. law, this software may not be exported outside the US
20  * without license from the U.S. Commerce department.
21  *
22  * The key schedule is passed as an arg, as well as the cleartext or
23  * ciphertext.  The cleartext and ciphertext should be in host order.
24  *
25  * These routines form the library interface to the DES facilities.
26  *
27  *      spm     8/85    MIT project athena
28  */
29
30 #include <stdio.h>
31 #include <ac/krb.h>
32
33 #if defined( DEBUG ) && defined( HAVE_DES_DEBUG )
34 #define USE_DES_DEBUG
35 extern int des_debug;
36 #endif
37
38 extern void des_fixup_key_parity();
39
40 #ifndef HAVE_AFS_KERBEROS
41 #define WORLDPEACEINOURTIME
42 #endif
43
44 #if defined(WORLDPEACEINOURTIME) /* Use original, not ifs version */
45 #ifndef HAVE_KERBEROS_V
46 /*
47  * convert an arbitrary length string to a DES key
48  */
49 void
50 des_string_to_key( char *str, register des_cblock *key )
51 {
52     register char *in_str;
53     register unsigned temp,i;
54     register int j;
55     register long length;
56     static unsigned char *k_p;
57     static int forward;
58     register char *p_char;
59     static char k_char[64];
60     static des_key_schedule key_sked;
61     extern unsigned long des_cbc_cksum();
62
63     in_str = str;
64     forward = 1;
65     p_char = k_char;
66     length = strlen(str);
67
68     /* init key array for bits */
69     memset(k_char, 0, sizeof(k_char));
70
71 #ifdef USE_DES_DEBUG
72     if (des_debug)
73         fprintf(stdout,
74                 "\n\ninput str length = %d  string = %s\nstring = 0x ",
75                 length,str);
76 #endif
77
78     /* get next 8 bytes, strip parity, xor */
79     for (i = 1; i <= length; i++) {
80         /* get next input key byte */
81         temp = (unsigned int) *str++;
82 #ifdef USE_DES_DEBUG
83         if (des_debug)
84             fprintf(stdout,"%02x ",temp & 0xff);
85 #endif
86         /* loop through bits within byte, ignore parity */
87         for (j = 0; j <= 6; j++) {
88             if (forward)
89                 *p_char++ ^= (int) temp & 01;
90             else
91                 *--p_char ^= (int) temp & 01;
92             temp = temp >> 1;
93         } while (--j > 0);
94
95         /* check and flip direction */
96         if ((i%8) == 0)
97             forward = !forward;
98     }
99
100     /* now stuff into the key des_cblock, and force odd parity */
101     p_char = k_char;
102     k_p = (unsigned char *) key;
103
104     for (i = 0; i <= 7; i++) {
105         temp = 0;
106         for (j = 0; j <= 6; j++)
107             temp |= *p_char++ << (1+j);
108         *k_p++ = (unsigned char) temp;
109     }
110
111     /* fix key parity */
112     des_fixup_key_parity(key);
113
114     /* Now one-way encrypt it with the folded key */
115     (void) des_key_sched(key,key_sked);
116     (void) des_cbc_cksum((des_cblock *)in_str,key,length,key_sked,key);
117     /* erase key_sked */
118     memset((char *)key_sked, 0, sizeof(key_sked));
119
120     /* now fix up key parity again */
121     des_fixup_key_parity(key);
122
123 #ifdef USE_DES_DEBUG
124     if (des_debug)
125         fprintf(stdout,
126                 "\nResulting string_to_key = 0x%lx 0x%lx\n",
127                 *((unsigned long *) key),
128                 *((unsigned long *) key+1));
129 #endif
130 }
131
132 #endif /* HAVE_KERBEROS_V */
133 #else /* Use ifs version */
134
135 #if 0
136 #include <stdio.h>
137     /* These two needed for rxgen output to work */
138 #include <sys/types.h>
139 #include <rx/xdr.h>
140 #include <afs/cellconfig.h>
141 #include <afs/auth.h>
142
143 #include "/usr/andy/kauth/kauth.h"
144 #include "/usr/andy/kauth/kautils.h"
145 #endif
146
147 /* This defines the Andrew string_to_key function.  It accepts a password
148    string as input and converts its via a one-way encryption algorithm to a DES
149    encryption key.  It is compatible with the original Andrew authentication
150    service password database. */
151
152 static void
153 Andrew_StringToKey(
154   char          *str,
155   char          *cell,                  /* cell for password */
156   des_cblock *key
157 )
158 {   char  password[8+1];                /* crypt is limited to 8 chars anyway */
159     int   i;
160     int   passlen;
161
162     memset(key, 0, sizeof(des_cblock));
163     memset(password, 0, sizeof(password));
164
165     strncpy (password, cell, 8);
166     passlen = strlen (str);
167     if (passlen > 8) passlen = 8;
168
169     for (i=0; i<passlen; i++)
170         password[i] = str[i] ^ cell[i];
171
172     for (i=0;i<8;i++)
173         if (password[i] == '\0') password[i] = 'X';
174
175     /* crypt only considers the first 8 characters of password but for some
176        reason returns eleven characters of result (plus the two salt chars). */
177     strncpy(key, crypt(password, "#~") + 2, sizeof(des_cblock));
178
179     /* parity is inserted into the LSB so leftshift each byte up one bit.  This
180        allows ascii characters with a zero MSB to retain as much significance
181        as possible. */
182     {   char *keybytes = (char *)key;
183         unsigned int temp;
184
185         for (i = 0; i < 8; i++) {
186             temp = (unsigned int) keybytes[i];
187             keybytes[i] = (unsigned char) (temp << 1);
188         }
189     }
190     des_fixup_key_parity (key);
191 }
192
193 static void
194 StringToKey(
195   char          *str,
196   char          *cell,                  /* cell for password */
197   des_cblock    *key
198 )
199 {   des_key_schedule schedule;
200     char temp_key[8];
201     char ivec[8];
202     char password[BUFSIZ];
203     int  passlen;
204
205     strncpy (password, str, sizeof(password));
206     if ((passlen = strlen (password)) < sizeof(password)-1)
207         strncat (password, cell, sizeof(password)-passlen);
208     if ((passlen = strlen(password)) > sizeof(password)) passlen = sizeof(password);
209
210     memcpy(ivec, "kerberos", 8);
211     memcpy(temp_key, "kerberos", 8);
212     des_fixup_key_parity (temp_key);
213     des_key_sched (temp_key, schedule);
214     des_cbc_cksum (password, ivec, passlen, schedule, ivec);
215
216     memcpy(temp_key, ivec, 8);
217     des_fixup_key_parity (temp_key);
218     des_key_sched (temp_key, schedule);
219     des_cbc_cksum (password, key, passlen, schedule, ivec);
220
221     des_fixup_key_parity (key);
222 }
223
224 void
225 ka_StringToKey (
226   char          *str,
227   char          *cell,                  /* cell for password */
228   des_cblock    *key
229 )
230 {   char  realm[REALM_SZ];
231
232 #if NOWAYOUTTODAY
233     long  code;
234 #if 0
235     code = ka_CellToRealm (cell, realm, 0/*local*/);
236 #endif
237     if (code) strcpy (realm, "");
238     else lcstring (realm, realm, sizeof(realm)); /* for backward compatibility */
239 #else
240         (void)strcpy(realm, cell);
241 #endif
242
243     if (strlen(str) > 8) StringToKey (str, realm, key);
244     else Andrew_StringToKey (str, realm, key);
245 }
246
247 /*
248  * convert an arbitrary length string to a DES key
249  */
250 int
251 des_string_to_key( char *str, register des_cblock *key )
252 {
253         /* NB: i should probably call routine to get local cell here */
254         ka_StringToKey(str, "umich.edu", key);
255         return 0;
256 }
257
258 #endif /* Use IFS Version */
259
260 #endif /* kerberos */