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>
17 #include <hcrypto/des.h>
18 #include <hcrypto/ui.h>
20 #include <rx/rxkad_convert.h>
22 #include <afs/pthread_glock.h>
23 #include <afs/cellconfig.h>
25 #include <afs/afsutil.h>
30 /* This defines the Andrew string_to_key function. It accepts a password
31 string as input and converts it via a one-way encryption algorithm to a DES
32 encryption key. It is compatible with the original Andrew authentication
33 service password database. */
36 Andrew_StringToKey(char *str
, char *cell
, /* cell for password */
37 struct ktc_encryptionKey
*key
)
39 char password
[8 + 1]; /* crypt's limit is 8 chars anyway */
43 memset(key
, 0, sizeof(struct ktc_encryptionKey
));
45 strncpy(password
, cell
, 8);
46 passlen
= strlen(str
);
50 for (i
= 0; i
< passlen
; i
++)
51 password
[i
] ^= str
[i
];
53 for (i
= 0; i
< 8; i
++)
54 if (password
[i
] == '\0')
57 /* crypt only considers the first 8 characters of password but for some
58 * reason returns eleven characters of result (plus the two salt chars). */
59 strncpy((char *)key
, (char *)crypt(password
, "p1") + 2,
60 sizeof(struct ktc_encryptionKey
));
62 /* parity is inserted into the LSB so leftshift each byte up one bit. This
63 * allows ascii characters with a zero MSB to retain as much significance
66 char *keybytes
= (char *)key
;
69 for (i
= 0; i
< 8; i
++) {
70 temp
= (unsigned int)keybytes
[i
];
71 keybytes
[i
] = (unsigned char)(temp
<< 1);
74 DES_set_odd_parity(ktc_to_cblock(key
));
78 StringToKey(char *str
, char *cell
, /* cell for password */
79 struct ktc_encryptionKey
*key
)
81 DES_key_schedule schedule
;
84 char password
[BUFSIZ
];
87 strncpy(password
, str
, sizeof(password
));
88 if ((passlen
= strlen(password
)) < sizeof(password
) - 1)
89 strncat(password
, cell
, sizeof(password
) - passlen
);
90 if ((passlen
= strlen(password
)) > sizeof(password
))
91 passlen
= sizeof(password
);
93 memcpy(&ivec
, "kerberos", 8);
94 memcpy(&temp_key
, "kerberos", 8);
95 DES_set_odd_parity(&temp_key
);
96 DES_key_sched(&temp_key
, &schedule
);
97 DES_cbc_cksum((DES_cblock
*) password
, &ivec
, passlen
, &schedule
, &ivec
);
99 memcpy(&temp_key
, &ivec
, 8);
100 DES_set_odd_parity(&temp_key
);
101 DES_key_sched(&temp_key
, &schedule
);
102 DES_cbc_cksum((DES_cblock
*)password
, ktc_to_cblock(key
), passlen
,
105 DES_set_odd_parity(ktc_to_cblock(key
));
109 ka_StringToKey(char *str
, char *cell
, /* cell for password */
110 struct ktc_encryptionKey
*key
)
112 char realm
[MAXKTCREALMLEN
];
116 code
= ka_CellToRealm(cell
, realm
, 0 /*local */ );
117 if (code
) /* just take his word for it */
118 strncpy(realm
, cell
, sizeof(realm
));
119 else /* for backward compatibility */
120 lcstring(realm
, realm
, sizeof(realm
));
122 StringToKey(str
, realm
, key
);
124 Andrew_StringToKey(str
, realm
, key
);
128 /* This prints out a prompt and reads a string from the terminal, turning off
129 echoing. If verify is requested it requests that the string be entered
130 again and the two strings are compared. The string is then converted to a
131 DES encryption key. */
134 KAREADPW - some error returned from read_pw_string
138 ka_ReadPassword(char *prompt
, int verify
, char *cell
,
139 struct ktc_encryptionKey
*key
)
141 char password
[BUFSIZ
];
145 memset(key
, 0, sizeof(struct ktc_encryptionKey
));
146 code
= UI_UTIL_read_pw_string(password
, sizeof(password
), prompt
, verify
);
151 if (strlen(password
) == 0) {
153 return KANULLPASSWORD
;
155 ka_StringToKey(password
, cell
, key
);
160 /* This performs the backslash quoting defined by AC_ParseLoginName. */
163 map_char(char *str
, int *ip
)
168 if ((c
>= '0') && (c
<= '7')) {
170 c
= (c
* 8) + (str
[++(*ip
)] - '0');
171 c
= (c
* 8) + (str
[++(*ip
)] - '0');
177 /* This routine parses a string that might be entered by a user from the
178 terminal. It defines a syntax to allow a user to specify his identity in
179 terms of his name, instance and cell with a single string. These three
180 output strings must be allocated by the caller to their maximum length. The
181 syntax is very simple: the first dot ('.') separates the name from the
182 instance and the first atsign ('@') begins the cell name. A backslash ('\')
183 can be used to quote these special characters. A backslash followed by an
184 octal digit (zero through seven) introduces a three digit octal number which
185 is interpreted as the ascii value of a single character. */
188 KABADARGUMENT - if no output parameters are specified.
189 KABADNAME - if a component of the user name is too long or if a cell was
190 specified but the cell parameter was null.
194 ka_ParseLoginName(char *login
, char name
[MAXKTCNAMELEN
],
195 char inst
[MAXKTCNAMELEN
], char cell
[MAXKTCREALMLEN
])
197 int login_len
= strlen(login
);
206 return KABADARGUMENT
;
215 while (i
< login_len
) {
217 c
= map_char(login
, &i
);
221 name
[j
] = 0; /* finish name */
222 reading
= READCELL
; /* but instance is null */
226 if (inst
&& (rc
== '.')) {
227 name
[j
] = 0; /* finish name */
232 if (j
>= MAXKTCNAMELEN
- 1)
240 inst
[j
] = 0; /* finish name */
245 if (j
>= MAXKTCNAMELEN
- 1)
252 if (j
>= MAXKTCREALMLEN
- 1)
259 if (reading
== READNAME
)
261 else if (reading
== READINST
) {
266 } else if (reading
== READCELL
) {
273 /* the cell is really an authDomain and therefore is really a realm */
275 ucstring(cell
, cell
, MAXKTCREALMLEN
);
279 /* Client side applications should call this to initialize error tables and
280 connect to the correct CellServDB file. */
284 { /* reserved for future use. */
286 static int inited
= 0;
294 initialize_U_error_table();
295 initialize_KA_error_table();
296 initialize_RXK_error_table();
297 initialize_KTC_error_table();
298 initialize_ACFG_error_table();
299 code
= ka_CellConfig(AFSDIR_CLIENT_ETC_DIRPATH
);
310 struct ktc_encryptionKey key
;
313 char name
[MAXKTCNAMELEN
];
314 char instance
[MAXKTCNAMELEN
];
315 char cell
[MAXKTCREALMLEN
];
317 printf("Enter login:");
318 fgets(line
, 255, stdin
);
319 ka_ParseLoginName(line
, name
, instance
, cell
);
320 printf("'%s' '%s' '%s'\n", name
, instance
, cell
);