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>
51 #include <afs/cellconfig.h>
53 #include <afs/afsutil.h>
56 #endif /* defined(UKERNEL) */
59 /* This defines the Andrew string_to_key function. It accepts a password
60 string as input and converts it via a one-way encryption algorithm to a DES
61 encryption key. It is compatible with the original Andrew authentication
62 service password database. */
64 static void Andrew_StringToKey (
66 char *cell, /* cell for password */
67 struct ktc_encryptionKey *key)
68 { char password[8+1]; /* crypt's limit is 8 chars anyway */
72 memset(key, 0, sizeof(struct ktc_encryptionKey));
74 strncpy (password, cell, 8);
75 passlen = strlen (str);
76 if (passlen > 8) passlen = 8;
78 for (i=0; i<passlen; i++)
79 password[i] ^= str[i];
82 if (password[i] == '\0') password[i] = 'X';
84 /* crypt only considers the first 8 characters of password but for some
85 reason returns eleven characters of result (plus the two salt chars). */
87 (char *)crypt(password, "p1") + 2,
88 sizeof(struct ktc_encryptionKey));
90 /* parity is inserted into the LSB so leftshift each byte up one bit. This
91 allows ascii characters with a zero MSB to retain as much significance
93 { char *keybytes = (char *)key;
96 for (i = 0; i < 8; i++) {
97 temp = (unsigned int) keybytes[i];
98 keybytes[i] = (unsigned char) (temp << 1);
101 des_fixup_key_parity (key);
104 static void StringToKey (
106 char *cell, /* cell for password */
107 struct ktc_encryptionKey *key)
108 { des_key_schedule schedule;
111 char password[BUFSIZ];
114 strncpy (password, str, sizeof(password));
115 if ((passlen = strlen (password)) < sizeof(password)-1)
116 strncat (password, cell, sizeof(password)-passlen);
117 if ((passlen = strlen(password)) > sizeof(password))
118 passlen = sizeof(password);
120 memcpy(ivec, "kerberos", 8);
121 memcpy(temp_key, "kerberos", 8);
122 des_fixup_key_parity (temp_key);
123 des_key_sched (temp_key, schedule);
124 des_cbc_cksum (password, ivec, passlen, schedule, ivec);
126 memcpy(temp_key, ivec, 8);
127 des_fixup_key_parity (temp_key);
128 des_key_sched (temp_key, schedule);
129 des_cbc_cksum (password, key, passlen, schedule, ivec);
131 des_fixup_key_parity (key);
134 void ka_StringToKey (
136 char *cell, /* cell for password */
137 struct ktc_encryptionKey *key)
139 char realm[MAXKTCREALMLEN];
143 code = ka_CellToRealm (cell, realm, 0/*local*/);
144 if (code) /* just take his word for it */
145 strncpy (realm, cell, sizeof(realm));
146 else /* for backward compatibility */
147 lcstring (realm, realm, sizeof(realm));
148 if (strlen(str) > 8) StringToKey (str, realm, key);
149 else Andrew_StringToKey (str, realm, key);
153 /* This prints out a prompt and reads a string from the terminal, turning off
154 echoing. If verify is requested it requests that the string be entered
155 again and the two strings are compared. The string is then converted to a
156 DES encryption key. */
159 KAREADPW - some error returned from read_pw_string
162 afs_int32 ka_ReadPassword (
166 struct ktc_encryptionKey *key)
168 char password[BUFSIZ];
172 memset(key, 0, sizeof(struct ktc_encryptionKey));
173 code = read_pw_string (password, sizeof(password), prompt, verify);
178 if (strlen(password) == 0) {
180 return KANULLPASSWORD;
182 ka_StringToKey (password, cell, key);
187 /* This performs the backslash quoting defined by AC_ParseLoginName. */
189 static char map_char (str, ip)
195 if ((c >= '0') && (c <= '7')) {
197 c = (c * 8) + (str[++(*ip)] - '0');
198 c = (c * 8) + (str[++(*ip)] - '0');
203 /* This routine parses a string that might be entered by a user from the
204 terminal. It defines a syntax to allow a user to specify his identity in
205 terms of his name, instance and cell with a single string. These three
206 output strings must be allocated by the caller to their maximum length. The
207 syntax is very simple: the first dot ('.') separates the name from the
208 instance and the first atsign ('@') begins the cell name. A backslash ('\')
209 can be used to quote these special characters. A backslash followed by an
210 octal digit (zero through seven) introduces a three digit octal number which
211 is interpreted as the ascii value of a single character. */
214 KABADARGUMENT - if no output parameters are specified.
215 KABADNAME - if a component of the user name is too long or if a cell was
216 specified but the cell parameter was null.
219 afs_int32 ka_ParseLoginName (
221 char name[MAXKTCNAMELEN],
222 char inst[MAXKTCNAMELEN],
223 char cell[MAXKTCREALMLEN])
225 int login_len = strlen (login);
233 if (!name) return KABADARGUMENT;
235 if (inst) strcpy (inst, "");
236 if (cell) strcpy (cell, "");
240 while (i < login_len) {
242 c = map_char (login, &i);
246 name[j] = 0; /* finish name */
247 reading = READCELL; /* but instance is null */
251 if (inst && (rc == '.')) {
252 name[j] = 0; /* finish name */
257 if (j >= MAXKTCNAMELEN-1) return KABADNAME;
261 if (!inst) return KABADNAME;
263 inst[j] = 0; /* finish name */
268 if (j >= MAXKTCNAMELEN-1) return KABADNAME;
272 if (!cell) return KABADNAME;
273 if (j >= MAXKTCREALMLEN-1) return KABADNAME;
279 if (reading == READNAME) name[j] = 0;
280 else if (reading == READINST) {
281 if (inst) inst[j] = 0;
282 else return KABADNAME;
284 else if (reading == READCELL) {
285 if (cell) cell[j] = 0;
286 else return KABADNAME;
289 /* the cell is really an authDomain and therefore is really a realm */
290 if (cell) ucstring (cell, cell, MAXKTCREALMLEN);
294 /* Client side applications should call this to initialize error tables and
295 connect to the correct CellServDB file. */
297 afs_int32 ka_Init(int flags) /* reserved for future use. */
300 static int inited = 0;
308 initialize_U_error_table();
309 initialize_KA_error_table();
310 initialize_RXK_error_table();
311 initialize_KTC_error_table();
312 initialize_ACFG_error_table();
313 code = ka_CellConfig (AFSDIR_CLIENT_ETC_DIRPATH);
316 if (code) return code;
322 { struct ktc_encryptionKey key;
325 char name[MAXKTCNAMELEN];
326 char instance[MAXKTCNAMELEN];
327 char cell[MAXKTCREALMLEN];
329 printf("Enter login:");
330 fgets (line, 255, stdin);
331 ka_ParseLoginName (line, name, instance, cell);
332 printf ("'%s' '%s' '%s'\n", name, instance, cell);