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
11 #include "../afs/param.h"
12 #include "../afs/sysincludes.h"
13 #include "../afs/afsincludes.h"
14 #include "../afs/stds.h"
15 #include "../afs/pthread_glock.h"
16 #include "../afs/cellconfig.h"
17 #include "../afs/afsutil.h"
18 #include "../afs/auth.h"
19 #include "../afsint/kauth.h"
20 #include "../afs/kautils.h"
21 #include "../afs/pthread_glock.h"
22 #include "../des/des.h"
24 #else /* defined(UKERNEL) */
25 #include <afs/param.h>
27 #include <afs/pthread_glock.h>
33 #include <afs/cellconfig.h>
35 #include <afs/afsutil.h>
38 #endif /* defined(UKERNEL) */
41 /* This defines the Andrew string_to_key function. It accepts a password
42 string as input and converts it via a one-way encryption algorithm to a DES
43 encryption key. It is compatible with the original Andrew authentication
44 service password database. */
46 static void Andrew_StringToKey (
48 char *cell, /* cell for password */
49 struct ktc_encryptionKey *key)
50 { char password[8+1]; /* crypt's limit is 8 chars anyway */
54 bzero (key, sizeof(struct ktc_encryptionKey));
56 strncpy (password, cell, 8);
57 passlen = strlen (str);
58 if (passlen > 8) passlen = 8;
60 for (i=0; i<passlen; i++)
61 password[i] ^= str[i];
64 if (password[i] == '\0') password[i] = 'X';
66 /* crypt only considers the first 8 characters of password but for some
67 reason returns eleven characters of result (plus the two salt chars). */
69 (char *)crypt(password, "p1") + 2,
70 sizeof(struct ktc_encryptionKey));
72 /* parity is inserted into the LSB so leftshift each byte up one bit. This
73 allows ascii characters with a zero MSB to retain as much significance
75 { char *keybytes = (char *)key;
78 for (i = 0; i < 8; i++) {
79 temp = (unsigned int) keybytes[i];
80 keybytes[i] = (unsigned char) (temp << 1);
83 des_fixup_key_parity (key);
86 static void StringToKey (
88 char *cell, /* cell for password */
89 struct ktc_encryptionKey *key)
90 { des_key_schedule schedule;
93 char password[BUFSIZ];
96 strncpy (password, str, sizeof(password));
97 if ((passlen = strlen (password)) < sizeof(password)-1)
98 strncat (password, cell, sizeof(password)-passlen);
99 if ((passlen = strlen(password)) > sizeof(password))
100 passlen = sizeof(password);
102 bcopy ("kerberos", ivec, 8);
103 bcopy ("kerberos", temp_key, 8);
104 des_fixup_key_parity (temp_key);
105 des_key_sched (temp_key, schedule);
106 des_cbc_cksum (password, ivec, passlen, schedule, ivec);
108 bcopy (ivec, temp_key, 8);
109 des_fixup_key_parity (temp_key);
110 des_key_sched (temp_key, schedule);
111 des_cbc_cksum (password, key, passlen, schedule, ivec);
113 des_fixup_key_parity (key);
116 void ka_StringToKey (
118 char *cell, /* cell for password */
119 struct ktc_encryptionKey *key)
121 char realm[MAXKTCREALMLEN];
125 code = ka_CellToRealm (cell, realm, 0/*local*/);
126 if (code) /* just take his word for it */
127 strncpy (realm, cell, sizeof(realm));
128 else /* for backward compatibility */
129 lcstring (realm, realm, sizeof(realm));
130 if (strlen(str) > 8) StringToKey (str, realm, key);
131 else Andrew_StringToKey (str, realm, key);
135 /* This prints out a prompt and reads a string from the terminal, turning off
136 echoing. If verify is requested it requests that the string be entered
137 again and the two strings are compared. The string is then converted to a
138 DES encryption key. */
141 KAREADPW - some error returned from read_pw_string
144 afs_int32 ka_ReadPassword (
148 struct ktc_encryptionKey *key)
150 char password[BUFSIZ];
154 bzero (key, sizeof(struct ktc_encryptionKey));
155 code = read_pw_string (password, sizeof(password), prompt, verify);
160 if (strlen(password) == 0) {
162 return KANULLPASSWORD;
164 ka_StringToKey (password, cell, key);
169 /* This performs the backslash quoting defined by AC_ParseLoginName. */
171 static char map_char (str, ip)
177 if ((c >= '0') && (c <= '7')) {
179 c = (c * 8) + (str[++(*ip)] - '0');
180 c = (c * 8) + (str[++(*ip)] - '0');
185 /* This routine parses a string that might be entered by a user from the
186 terminal. It defines a syntax to allow a user to specify his identity in
187 terms of his name, instance and cell with a single string. These three
188 output strings must be allocated by the caller to their maximum length. The
189 syntax is very simple: the first dot ('.') separates the name from the
190 instance and the first atsign ('@') begins the cell name. A backslash ('\')
191 can be used to quote these special characters. A backslash followed by an
192 octal digit (zero through seven) introduces a three digit octal number which
193 is interpreted as the ascii value of a single character. */
196 KABADARGUMENT - if no output parameters are specified.
197 KABADNAME - if a component of the user name is too long or if a cell was
198 specified but the cell parameter was null.
201 afs_int32 ka_ParseLoginName (
203 char name[MAXKTCNAMELEN],
204 char inst[MAXKTCNAMELEN],
205 char cell[MAXKTCREALMLEN])
207 int login_len = strlen (login);
215 if (!name) return KABADARGUMENT;
217 if (inst) strcpy (inst, "");
218 if (cell) strcpy (cell, "");
222 while (i < login_len) {
224 c = map_char (login, &i);
228 name[j] = 0; /* finish name */
229 reading = READCELL; /* but instance is null */
233 if (inst && (rc == '.')) {
234 name[j] = 0; /* finish name */
239 if (j >= MAXKTCNAMELEN-1) return KABADNAME;
243 if (!inst) return KABADNAME;
245 inst[j] = 0; /* finish name */
250 if (j >= MAXKTCNAMELEN-1) return KABADNAME;
254 if (!cell) return KABADNAME;
255 if (j >= MAXKTCREALMLEN-1) return KABADNAME;
261 if (reading == READNAME) name[j] = 0;
262 else if (reading == READINST) {
263 if (inst) inst[j] = 0;
264 else return KABADNAME;
266 else if (reading == READCELL) {
267 if (cell) cell[j] = 0;
268 else return KABADNAME;
271 /* the cell is really an authDomain and therefore is really a realm */
272 if (cell) ucstring (cell, cell, MAXKTCREALMLEN);
276 /* Client side applications should call this to initialize error tables and
277 connect to the correct CellServDB file. */
279 afs_int32 ka_Init(int flags) /* reserved for future use. */
282 static int inited = 0;
290 initialize_u_error_table();
291 initialize_ka_error_table();
292 initialize_rxk_error_table();
293 initialize_ktc_error_table();
294 initialize_acfg_error_table();
295 code = ka_CellConfig (AFSDIR_CLIENT_ETC_DIRPATH);
298 if (code) return code;
304 { struct ktc_encryptionKey key;
307 char name[MAXKTCNAMELEN];
308 char instance[MAXKTCNAMELEN];
309 char cell[MAXKTCREALMLEN];
311 printf("Enter login:");
312 fgets (line, 255, stdin);
313 ka_ParseLoginName (line, name, instance, cell);
314 printf ("'%s' '%s' '%s'\n", name, instance, cell);