Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / kauth / client.c
blob3021c6d2be2803bb83cc6c4b1a2dbab3fe33110e
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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
8 */
10 #include <afsconfig.h>
11 #include <afs/param.h>
13 #include <afs/stds.h>
14 #include <afs/pthread_glock.h>
15 #include <stdio.h>
16 #ifdef AFS_NT40_ENV
17 #include <winsock2.h>
18 #include <crypt.h>
19 #endif
20 #include <string.h>
21 #ifdef HAVE_UNISTD_H
22 #if !defined(__USE_XOPEN)
23 #define __USE_XOPEN
24 #endif
25 #include <unistd.h>
26 #endif
27 #include <afs/cellconfig.h>
28 #include <afs/auth.h>
29 #include <afs/afsutil.h>
30 #include <des.h>
31 #include <des_prototypes.h>
32 #include "kauth.h"
33 #include "kautils.h"
36 /* This defines the Andrew string_to_key function. It accepts a password
37 string as input and converts it via a one-way encryption algorithm to a DES
38 encryption key. It is compatible with the original Andrew authentication
39 service password database. */
41 static void
42 Andrew_StringToKey(char *str, char *cell, /* cell for password */
43 struct ktc_encryptionKey *key)
45 char password[8 + 1]; /* crypt's limit is 8 chars anyway */
46 int i;
47 int passlen;
49 memset(key, 0, sizeof(struct ktc_encryptionKey));
51 strncpy(password, cell, 8);
52 passlen = strlen(str);
53 if (passlen > 8)
54 passlen = 8;
56 for (i = 0; i < passlen; i++)
57 password[i] ^= str[i];
59 for (i = 0; i < 8; i++)
60 if (password[i] == '\0')
61 password[i] = 'X';
63 /* crypt only considers the first 8 characters of password but for some
64 * reason returns eleven characters of result (plus the two salt chars). */
65 strncpy((char *)key, (char *)crypt(password, "p1") + 2,
66 sizeof(struct ktc_encryptionKey));
68 /* parity is inserted into the LSB so leftshift each byte up one bit. This
69 * allows ascii characters with a zero MSB to retain as much significance
70 * as possible. */
72 char *keybytes = (char *)key;
73 unsigned int temp;
75 for (i = 0; i < 8; i++) {
76 temp = (unsigned int)keybytes[i];
77 keybytes[i] = (unsigned char)(temp << 1);
80 des_fixup_key_parity(ktc_to_cblock(key));
83 static void
84 StringToKey(char *str, char *cell, /* cell for password */
85 struct ktc_encryptionKey *key)
87 des_key_schedule schedule;
88 unsigned char temp_key[8];
89 char ivec[8];
90 char password[BUFSIZ];
91 int passlen;
93 strncpy(password, str, sizeof(password));
94 if ((passlen = strlen(password)) < sizeof(password) - 1)
95 strncat(password, cell, sizeof(password) - passlen);
96 if ((passlen = strlen(password)) > sizeof(password))
97 passlen = sizeof(password);
99 memcpy(ivec, "kerberos", 8);
100 memcpy(temp_key, "kerberos", 8);
101 des_fixup_key_parity(temp_key);
102 des_key_sched(temp_key, schedule);
103 des_cbc_cksum(charptr_to_cblockptr(password), charptr_to_cblockptr(ivec), passlen, schedule, charptr_to_cblockptr(ivec));
105 memcpy(temp_key, ivec, 8);
106 des_fixup_key_parity(temp_key);
107 des_key_sched(temp_key, schedule);
108 des_cbc_cksum(charptr_to_cblockptr(password), ktc_to_cblockptr(key), passlen, schedule, charptr_to_cblockptr(ivec));
110 des_fixup_key_parity(ktc_to_cblock(key));
113 void
114 ka_StringToKey(char *str, char *cell, /* cell for password */
115 struct ktc_encryptionKey *key)
117 char realm[MAXKTCREALMLEN];
118 afs_int32 code;
120 LOCK_GLOBAL_MUTEX;
121 code = ka_CellToRealm(cell, realm, 0 /*local */ );
122 if (code) /* just take his word for it */
123 strncpy(realm, cell, sizeof(realm));
124 else /* for backward compatibility */
125 lcstring(realm, realm, sizeof(realm));
126 if (strlen(str) > 8)
127 StringToKey(str, realm, key);
128 else
129 Andrew_StringToKey(str, realm, key);
130 UNLOCK_GLOBAL_MUTEX;
133 /* This prints out a prompt and reads a string from the terminal, turning off
134 echoing. If verify is requested it requests that the string be entered
135 again and the two strings are compared. The string is then converted to a
136 DES encryption key. */
138 /* Errors:
139 KAREADPW - some error returned from read_pw_string
142 afs_int32
143 ka_ReadPassword(char *prompt, int verify, char *cell,
144 struct ktc_encryptionKey *key)
146 char password[BUFSIZ];
147 afs_int32 code;
149 LOCK_GLOBAL_MUTEX;
150 memset(key, 0, sizeof(struct ktc_encryptionKey));
151 code = read_pw_string(password, sizeof(password), prompt, verify);
152 if (code) {
153 UNLOCK_GLOBAL_MUTEX;
154 return KAREADPW;
156 if (strlen(password) == 0) {
157 UNLOCK_GLOBAL_MUTEX;
158 return KANULLPASSWORD;
160 ka_StringToKey(password, cell, key);
161 UNLOCK_GLOBAL_MUTEX;
162 return 0;
165 /* This performs the backslash quoting defined by AC_ParseLoginName. */
167 static char
168 map_char(char *str, int *ip)
170 char c = str[*ip];
171 if (c == '\\') {
172 c = str[++(*ip)];
173 if ((c >= '0') && (c <= '7')) {
174 c = c - '0';
175 c = (c * 8) + (str[++(*ip)] - '0');
176 c = (c * 8) + (str[++(*ip)] - '0');
179 return c;
182 /* This routine parses a string that might be entered by a user from the
183 terminal. It defines a syntax to allow a user to specify his identity in
184 terms of his name, instance and cell with a single string. These three
185 output strings must be allocated by the caller to their maximum length. The
186 syntax is very simple: the first dot ('.') separates the name from the
187 instance and the first atsign ('@') begins the cell name. A backslash ('\')
188 can be used to quote these special characters. A backslash followed by an
189 octal digit (zero through seven) introduces a three digit octal number which
190 is interpreted as the ascii value of a single character. */
192 /* Errors:
193 KABADARGUMENT - if no output parameters are specified.
194 KABADNAME - if a component of the user name is too long or if a cell was
195 specified but the cell parameter was null.
198 afs_int32
199 ka_ParseLoginName(char *login, char name[MAXKTCNAMELEN],
200 char inst[MAXKTCNAMELEN], char cell[MAXKTCREALMLEN])
202 int login_len = strlen(login);
203 char rc, c;
204 int i, j;
205 #define READNAME 1
206 #define READINST 2
207 #define READCELL 3
208 int reading;
210 if (!name)
211 return KABADARGUMENT;
212 strcpy(name, "");
213 if (inst)
214 strcpy(inst, "");
215 if (cell)
216 strcpy(cell, "");
217 reading = READNAME;
218 i = 0;
219 j = 0;
220 while (i < login_len) {
221 rc = login[i];
222 c = map_char(login, &i);
223 switch (reading) {
224 case READNAME:
225 if (rc == '@') {
226 name[j] = 0; /* finish name */
227 reading = READCELL; /* but instance is null */
228 j = 0;
229 break;
231 if (inst && (rc == '.')) {
232 name[j] = 0; /* finish name */
233 reading = READINST;
234 j = 0;
235 break;
237 if (j >= MAXKTCNAMELEN - 1)
238 return KABADNAME;
239 name[j++] = c;
240 break;
241 case READINST:
242 if (!inst)
243 return KABADNAME;
244 if (rc == '@') {
245 inst[j] = 0; /* finish name */
246 reading = READCELL;
247 j = 0;
248 break;
250 if (j >= MAXKTCNAMELEN - 1)
251 return KABADNAME;
252 inst[j++] = c;
253 break;
254 case READCELL:
255 if (!cell)
256 return KABADNAME;
257 if (j >= MAXKTCREALMLEN - 1)
258 return KABADNAME;
259 cell[j++] = c;
260 break;
262 i++;
264 if (reading == READNAME)
265 name[j] = 0;
266 else if (reading == READINST) {
267 if (inst)
268 inst[j] = 0;
269 else
270 return KABADNAME;
271 } else if (reading == READCELL) {
272 if (cell)
273 cell[j] = 0;
274 else
275 return KABADNAME;
278 /* the cell is really an authDomain and therefore is really a realm */
279 if (cell)
280 ucstring(cell, cell, MAXKTCREALMLEN);
281 return 0;
284 /* Client side applications should call this to initialize error tables and
285 connect to the correct CellServDB file. */
287 afs_int32
288 ka_Init(int flags)
289 { /* reserved for future use. */
290 afs_int32 code;
291 static int inited = 0;
293 LOCK_GLOBAL_MUTEX;
294 if (inited) {
295 UNLOCK_GLOBAL_MUTEX;
296 return 0;
298 inited++;
299 initialize_U_error_table();
300 initialize_KA_error_table();
301 initialize_RXK_error_table();
302 initialize_KTC_error_table();
303 initialize_ACFG_error_table();
304 code = ka_CellConfig(AFSDIR_CLIENT_ETC_DIRPATH);
305 UNLOCK_GLOBAL_MUTEX;
306 if (code)
307 return code;
308 return 0;
311 #ifdef MAIN
313 main(void)
315 struct ktc_encryptionKey key;
316 int code;
317 char line[256];
318 char name[MAXKTCNAMELEN];
319 char instance[MAXKTCNAMELEN];
320 char cell[MAXKTCREALMLEN];
322 printf("Enter login:");
323 fgets(line, 255, stdin);
324 ka_ParseLoginName(line, name, instance, cell);
325 printf("'%s' '%s' '%s'\n", name, instance, cell);
328 #endif /* MAIN */