2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
12 #include "../afs/param.h"
14 #include <afs/param.h>
20 #include "../afs/sysincludes.h"
21 #include "../afs/afsincludes.h"
22 #include "../afs/stds.h"
23 #include "../afs/pthread_glock.h"
24 #include "../afs/cellconfig.h"
25 #include "../afs/afsutil.h"
26 #include "../afs/auth.h"
27 #include "../afsint/kauth.h"
28 #include "../afs/kautils.h"
29 #include "../afs/pthread_glock.h"
30 #include "../des/des.h"
32 #else /* defined(UKERNEL) */
34 #include <afs/pthread_glock.h>
40 #include <afs/cellconfig.h>
42 #include <afs/afsutil.h>
45 #endif /* defined(UKERNEL) */
48 /* This defines the Andrew string_to_key function. It accepts a password
49 string as input and converts it via a one-way encryption algorithm to a DES
50 encryption key. It is compatible with the original Andrew authentication
51 service password database. */
53 static void Andrew_StringToKey (
55 char *cell, /* cell for password */
56 struct ktc_encryptionKey *key)
57 { char password[8+1]; /* crypt's limit is 8 chars anyway */
61 memset(key, 0, sizeof(struct ktc_encryptionKey));
63 strncpy (password, cell, 8);
64 passlen = strlen (str);
65 if (passlen > 8) passlen = 8;
67 for (i=0; i<passlen; i++)
68 password[i] ^= str[i];
71 if (password[i] == '\0') password[i] = 'X';
73 /* crypt only considers the first 8 characters of password but for some
74 reason returns eleven characters of result (plus the two salt chars). */
76 (char *)crypt(password, "p1") + 2,
77 sizeof(struct ktc_encryptionKey));
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
82 { char *keybytes = (char *)key;
85 for (i = 0; i < 8; i++) {
86 temp = (unsigned int) keybytes[i];
87 keybytes[i] = (unsigned char) (temp << 1);
90 des_fixup_key_parity (key);
93 static void StringToKey (
95 char *cell, /* cell for password */
96 struct ktc_encryptionKey *key)
97 { des_key_schedule schedule;
100 char password[BUFSIZ];
103 strncpy (password, str, sizeof(password));
104 if ((passlen = strlen (password)) < sizeof(password)-1)
105 strncat (password, cell, sizeof(password)-passlen);
106 if ((passlen = strlen(password)) > sizeof(password))
107 passlen = sizeof(password);
109 memcpy(ivec, "kerberos", 8);
110 memcpy(temp_key, "kerberos", 8);
111 des_fixup_key_parity (temp_key);
112 des_key_sched (temp_key, schedule);
113 des_cbc_cksum (password, ivec, passlen, schedule, ivec);
115 memcpy(temp_key, ivec, 8);
116 des_fixup_key_parity (temp_key);
117 des_key_sched (temp_key, schedule);
118 des_cbc_cksum (password, key, passlen, schedule, ivec);
120 des_fixup_key_parity (key);
123 void ka_StringToKey (
125 char *cell, /* cell for password */
126 struct ktc_encryptionKey *key)
128 char realm[MAXKTCREALMLEN];
132 code = ka_CellToRealm (cell, realm, 0/*local*/);
133 if (code) /* just take his word for it */
134 strncpy (realm, cell, sizeof(realm));
135 else /* for backward compatibility */
136 lcstring (realm, realm, sizeof(realm));
137 if (strlen(str) > 8) StringToKey (str, realm, key);
138 else Andrew_StringToKey (str, realm, key);
142 /* This prints out a prompt and reads a string from the terminal, turning off
143 echoing. If verify is requested it requests that the string be entered
144 again and the two strings are compared. The string is then converted to a
145 DES encryption key. */
148 KAREADPW - some error returned from read_pw_string
151 afs_int32 ka_ReadPassword (
155 struct ktc_encryptionKey *key)
157 char password[BUFSIZ];
161 memset(key, 0, sizeof(struct ktc_encryptionKey));
162 code = read_pw_string (password, sizeof(password), prompt, verify);
167 if (strlen(password) == 0) {
169 return KANULLPASSWORD;
171 ka_StringToKey (password, cell, key);
176 /* This performs the backslash quoting defined by AC_ParseLoginName. */
178 static char map_char (str, ip)
184 if ((c >= '0') && (c <= '7')) {
186 c = (c * 8) + (str[++(*ip)] - '0');
187 c = (c * 8) + (str[++(*ip)] - '0');
192 /* This routine parses a string that might be entered by a user from the
193 terminal. It defines a syntax to allow a user to specify his identity in
194 terms of his name, instance and cell with a single string. These three
195 output strings must be allocated by the caller to their maximum length. The
196 syntax is very simple: the first dot ('.') separates the name from the
197 instance and the first atsign ('@') begins the cell name. A backslash ('\')
198 can be used to quote these special characters. A backslash followed by an
199 octal digit (zero through seven) introduces a three digit octal number which
200 is interpreted as the ascii value of a single character. */
203 KABADARGUMENT - if no output parameters are specified.
204 KABADNAME - if a component of the user name is too long or if a cell was
205 specified but the cell parameter was null.
208 afs_int32 ka_ParseLoginName (
210 char name[MAXKTCNAMELEN],
211 char inst[MAXKTCNAMELEN],
212 char cell[MAXKTCREALMLEN])
214 int login_len = strlen (login);
222 if (!name) return KABADARGUMENT;
224 if (inst) strcpy (inst, "");
225 if (cell) strcpy (cell, "");
229 while (i < login_len) {
231 c = map_char (login, &i);
235 name[j] = 0; /* finish name */
236 reading = READCELL; /* but instance is null */
240 if (inst && (rc == '.')) {
241 name[j] = 0; /* finish name */
246 if (j >= MAXKTCNAMELEN-1) return KABADNAME;
250 if (!inst) return KABADNAME;
252 inst[j] = 0; /* finish name */
257 if (j >= MAXKTCNAMELEN-1) return KABADNAME;
261 if (!cell) return KABADNAME;
262 if (j >= MAXKTCREALMLEN-1) return KABADNAME;
268 if (reading == READNAME) name[j] = 0;
269 else if (reading == READINST) {
270 if (inst) inst[j] = 0;
271 else return KABADNAME;
273 else if (reading == READCELL) {
274 if (cell) cell[j] = 0;
275 else return KABADNAME;
278 /* the cell is really an authDomain and therefore is really a realm */
279 if (cell) ucstring (cell, cell, MAXKTCREALMLEN);
283 /* Client side applications should call this to initialize error tables and
284 connect to the correct CellServDB file. */
286 afs_int32 ka_Init(int flags) /* reserved for future use. */
289 static int inited = 0;
297 initialize_U_error_table();
298 initialize_KA_error_table();
299 initialize_RXK_error_table();
300 initialize_KTC_error_table();
301 initialize_ACFG_error_table();
302 code = ka_CellConfig (AFSDIR_CLIENT_ETC_DIRPATH);
305 if (code) return code;
311 { struct ktc_encryptionKey key;
314 char name[MAXKTCNAMELEN];
315 char instance[MAXKTCNAMELEN];
316 char cell[MAXKTCREALMLEN];
318 printf("Enter login:");
319 fgets (line, 255, stdin);
320 ka_ParseLoginName (line, name, instance, cell);
321 printf ("'%s' '%s' '%s'\n", name, instance, cell);