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>
11 #include <afs/param.h>
16 #include <afs/pthread_glock.h>
24 #if !defined(__USE_XOPEN)
29 #include <afs/cellconfig.h>
31 #include <afs/afsutil.h>
33 #include <des_prototypes.h>
38 /* This defines the Andrew string_to_key function. It accepts a password
39 string as input and converts it via a one-way encryption algorithm to a DES
40 encryption key. It is compatible with the original Andrew authentication
41 service password database. */
44 Andrew_StringToKey(char *str, char *cell, /* cell for password */
45 struct ktc_encryptionKey *key)
47 char password[8 + 1]; /* crypt's limit is 8 chars anyway */
51 memset(key, 0, sizeof(struct ktc_encryptionKey));
53 strncpy(password, cell, 8);
54 passlen = strlen(str);
58 for (i = 0; i < passlen; i++)
59 password[i] ^= str[i];
61 for (i = 0; i < 8; i++)
62 if (password[i] == '\0')
65 /* crypt only considers the first 8 characters of password but for some
66 * reason returns eleven characters of result (plus the two salt chars). */
67 strncpy((char *)key, (char *)crypt(password, "p1") + 2,
68 sizeof(struct ktc_encryptionKey));
70 /* parity is inserted into the LSB so leftshift each byte up one bit. This
71 * allows ascii characters with a zero MSB to retain as much significance
74 char *keybytes = (char *)key;
77 for (i = 0; i < 8; i++) {
78 temp = (unsigned int)keybytes[i];
79 keybytes[i] = (unsigned char)(temp << 1);
82 des_fixup_key_parity(ktc_to_cblock(key));
86 StringToKey(char *str, char *cell, /* cell for password */
87 struct ktc_encryptionKey *key)
89 des_key_schedule schedule;
90 unsigned char temp_key[8];
92 char password[BUFSIZ];
95 strncpy(password, str, sizeof(password));
96 if ((passlen = strlen(password)) < sizeof(password) - 1)
97 strncat(password, cell, sizeof(password) - passlen);
98 if ((passlen = strlen(password)) > sizeof(password))
99 passlen = sizeof(password);
101 memcpy(ivec, "kerberos", 8);
102 memcpy(temp_key, "kerberos", 8);
103 des_fixup_key_parity(temp_key);
104 des_key_sched(temp_key, schedule);
105 des_cbc_cksum(charptr_to_cblockptr(password), charptr_to_cblockptr(ivec), passlen, schedule, charptr_to_cblockptr(ivec));
107 memcpy(temp_key, ivec, 8);
108 des_fixup_key_parity(temp_key);
109 des_key_sched(temp_key, schedule);
110 des_cbc_cksum(charptr_to_cblockptr(password), ktc_to_cblockptr(key), passlen, schedule, charptr_to_cblockptr(ivec));
112 des_fixup_key_parity(ktc_to_cblock(key));
116 ka_StringToKey(char *str, char *cell, /* cell for password */
117 struct ktc_encryptionKey *key)
119 char realm[MAXKTCREALMLEN];
123 code = ka_CellToRealm(cell, realm, 0 /*local */ );
124 if (code) /* just take his word for it */
125 strncpy(realm, cell, sizeof(realm));
126 else /* for backward compatibility */
127 lcstring(realm, realm, sizeof(realm));
129 StringToKey(str, realm, key);
131 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
145 ka_ReadPassword(char *prompt, int verify, char *cell,
146 struct ktc_encryptionKey *key)
148 char password[BUFSIZ];
152 memset(key, 0, sizeof(struct ktc_encryptionKey));
153 code = read_pw_string(password, sizeof(password), prompt, verify);
158 if (strlen(password) == 0) {
160 return KANULLPASSWORD;
162 ka_StringToKey(password, cell, key);
167 /* This performs the backslash quoting defined by AC_ParseLoginName. */
170 map_char(char *str, int *ip)
175 if ((c >= '0') && (c <= '7')) {
177 c = (c * 8) + (str[++(*ip)] - '0');
178 c = (c * 8) + (str[++(*ip)] - '0');
184 /* This routine parses a string that might be entered by a user from the
185 terminal. It defines a syntax to allow a user to specify his identity in
186 terms of his name, instance and cell with a single string. These three
187 output strings must be allocated by the caller to their maximum length. The
188 syntax is very simple: the first dot ('.') separates the name from the
189 instance and the first atsign ('@') begins the cell name. A backslash ('\')
190 can be used to quote these special characters. A backslash followed by an
191 octal digit (zero through seven) introduces a three digit octal number which
192 is interpreted as the ascii value of a single character. */
195 KABADARGUMENT - if no output parameters are specified.
196 KABADNAME - if a component of the user name is too long or if a cell was
197 specified but the cell parameter was null.
201 ka_ParseLoginName(char *login, char name[MAXKTCNAMELEN],
202 char inst[MAXKTCNAMELEN], char cell[MAXKTCREALMLEN])
204 int login_len = strlen(login);
213 return KABADARGUMENT;
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)
247 inst[j] = 0; /* finish name */
252 if (j >= MAXKTCNAMELEN - 1)
259 if (j >= MAXKTCREALMLEN - 1)
266 if (reading == READNAME)
268 else if (reading == READINST) {
273 } else if (reading == READCELL) {
280 /* the cell is really an authDomain and therefore is really a realm */
282 ucstring(cell, cell, MAXKTCREALMLEN);
286 /* Client side applications should call this to initialize error tables and
287 connect to the correct CellServDB file. */
291 { /* reserved for future use. */
293 static int inited = 0;
301 initialize_U_error_table();
302 initialize_KA_error_table();
303 initialize_RXK_error_table();
304 initialize_KTC_error_table();
305 initialize_ACFG_error_table();
306 code = ka_CellConfig(AFSDIR_CLIENT_ETC_DIRPATH);
317 struct ktc_encryptionKey key;
320 char name[MAXKTCNAMELEN];
321 char instance[MAXKTCNAMELEN];
322 char cell[MAXKTCREALMLEN];
324 printf("Enter login:");
325 fgets(line, 255, stdin);
326 ka_ParseLoginName(line, name, instance, cell);
327 printf("'%s' '%s' '%s'\n", name, instance, cell);