1 /*
2 KRB4_std.c
3
4 Kerberos v4 jonks, from KTH krb4.
5
6 $OpenBSD: str2key.c,v 1.6 1998/06/22 15:22:27 beck Exp $
7 $KTH: str2key.c,v 1.10 1997/03/23 03:53:19 joda Exp $
8 */
9
10 /* This defines the Andrew string_to_key function. It accepts a password
11 * string as input and converts its via a one-way encryption algorithm to a DES
12 * encryption key. It is compatible with the original Andrew authentication
13 * service password database.
14 */
15
16 #if AC_BUILT
17 #include "autoconfig.h"
18 #endif
19
20 #ifdef KRB4_USE_SYSTEM_CRYPT
21 #define _XOPEN_SOURCE 4 /* for crypt(3) */
22 #define _XOPEN_SOURCE_EXTENDED
23 #define _XOPEN_VERSION 4
24 #define _XPG4_2
25 #if (!AC_BUILT || HAVE_UNISTD_H) && !_MSC_VER
26 #include <unistd.h>
27 #endif
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <openssl/des.h>
34
35 #include "KRB4_std.h"
36
37 #ifndef des_fixup_key_parity
38 #define des_fixup_key_parity DES_set_odd_parity
39 #endif
40
41 static void
mklower(char * s)42 mklower(char *s)
43 {
44 for (; s[0] != '\0'; s++)
45 if ('A' <= *s && *s <= 'Z')
46 *s = *s - 'A' + 'a';
47 }
48
49 /*
50 * Short passwords, i.e 8 characters or less.
51 */
52 static void
afs_cmu_StringToKey(char * str,char * cell,DES_cblock * key)53 afs_cmu_StringToKey (char *str, char *cell, DES_cblock *key)
54 {
55 char password[8+1]; /* crypt is limited to 8 chars anyway */
56 int i;
57 int passlen;
58
59 strncpy (password, cell, 8);
60 password[8] = '\0';
61 passlen = strlen (str);
62 if (passlen > 8) passlen = 8;
63
64 for (i=0; i<passlen; i++)
65 password[i] = str[i] ^ cell[i]; /* make sure cell is zero padded */
66
67 for (i=0; i<8; i++)
68 if (password[i] == '\0') password[i] = 'X';
69
70 /* crypt only considers the first 8 characters of password but for some
71 reason returns eleven characters of result (plus the two salt chars). */
72 #ifdef KRB4_USE_SYSTEM_CRYPT
73 strncpy((char *)key, crypt(password, "p1") + 2, sizeof(DES_cblock));
74 #else
75 /* Use OpenSSL's DES_crypt() */
76 strncpy((char *)key, DES_crypt(password, "p1") + 2, sizeof(DES_cblock));
77 #endif
78
79 /* parity is inserted into the LSB so leftshift each byte up one bit. This
80 allows ascii characters with a zero MSB to retain as much significance
81 as possible. */
82 { char *keybytes = (char *)key;
83 unsigned int temp;
84
85 for (i = 0; i < 8; i++) {
86 temp = (unsigned int) keybytes[i];
87 keybytes[i] = (unsigned char) (temp << 1);
88 }
89 }
90 des_fixup_key_parity (key);
91 }
92
93 /*
94 * Long passwords, i.e 9 characters or more.
95 */
96 static void
afs_transarc_StringToKey(char * str,char * cell,DES_cblock * key)97 afs_transarc_StringToKey (char *str, char *cell, DES_cblock *key)
98 {
99 DES_key_schedule schedule;
100 DES_cblock temp_key;
101 DES_cblock ivec;
102 char password[512];
103 int passlen;
104
105 strncpy (password, str, sizeof(password));
106 password[sizeof(password)-1] = '\0';
107 if ((passlen = strlen (password)) < sizeof(password)-1)
108 strncat (password, cell, sizeof(password)-passlen);
109 if ((passlen = strlen(password)) > sizeof(password)) passlen = sizeof(password);
110
111 memcpy(&ivec, "kerberos", 8);
112 memcpy(&temp_key, "kerberos", 8);
113 des_fixup_key_parity (&temp_key);
114 DES_key_sched (&temp_key, &schedule);
115 DES_cbc_cksum ((unsigned char *)password, &ivec, passlen, &schedule, &ivec);
116
117 memcpy(&temp_key, &ivec, 8);
118 des_fixup_key_parity (&temp_key);
119 DES_key_sched (&temp_key, &schedule);
120 DES_cbc_cksum ((unsigned char *)password, key, passlen, &schedule, &ivec);
121
122 des_fixup_key_parity (key);
123 }
124
125 void
afs_string_to_key(char * str,char * cell,DES_cblock * key)126 afs_string_to_key(char *str, char *cell, DES_cblock *key)
127 {
128 char realm[REALM_SZ+1];
129 strncpy(realm, cell, REALM_SZ);
130 realm[REALM_SZ] = 0;
131 mklower(realm);
132
133 if (strlen(str) > 8)
134 afs_transarc_StringToKey (str, realm, key);
135 else
136 afs_cmu_StringToKey (str, realm, key);
137 }
138