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