Add support for AFS string-to-key.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@4258 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997 Kungliga Tekniska H<>gskolan
|
* Copyright (c) 1997, 1998 Kungliga Tekniska H<>gskolan
|
||||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -183,6 +183,7 @@ rr13(unsigned char *buf, size_t len)
|
|||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX what's this function supposed to do anyway? */
|
||||||
static void
|
static void
|
||||||
add1(unsigned char *a, unsigned char *b, size_t len)
|
add1(unsigned char *a, unsigned char *b, size_t len)
|
||||||
{
|
{
|
||||||
@@ -252,6 +253,124 @@ DES3_string_to_key(const unsigned char *str, size_t len, des_cblock *keys)
|
|||||||
memset(tmp, 0, sizeof(tmp));
|
memset(tmp, 0, sizeof(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This defines the Andrew string_to_key function. It accepts a password
|
||||||
|
* string as input and converts its via a one-way encryption algorithm to a DES
|
||||||
|
* encryption key. It is compatible with the original Andrew authentication
|
||||||
|
* service password database.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
mklower(char *s)
|
||||||
|
{
|
||||||
|
for (; *s; s++)
|
||||||
|
if ('A' <= *s && *s <= 'Z')
|
||||||
|
*s = *s - 'A' + 'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Short passwords, i.e 8 characters or less.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
afs_cmu_StringToKey (const char *pw, size_t pw_len,
|
||||||
|
const char *cell, size_t cell_len,
|
||||||
|
des_cblock *key)
|
||||||
|
{
|
||||||
|
char password[8+1]; /* crypt is limited to 8 chars anyway */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset (password, 0, sizeof(password));
|
||||||
|
|
||||||
|
if(cell_len > 8) cell_len = 8;
|
||||||
|
strncpy (password, cell, cell_len);
|
||||||
|
|
||||||
|
if(pw_len > 8) pw_len = 8;
|
||||||
|
for (i=0; i < pw_len; i++)
|
||||||
|
password[i] ^= pw[i];
|
||||||
|
|
||||||
|
for (i=0; i<8; i++)
|
||||||
|
if (password[i] == '\0') password[i] = 'X';
|
||||||
|
|
||||||
|
/* crypt only considers the first 8 characters of password but for some
|
||||||
|
reason returns eleven characters of result (plus the two salt chars). */
|
||||||
|
strncpy((char *)key, (char *)crypt(password, "#~") + 2, sizeof(des_cblock));
|
||||||
|
|
||||||
|
/* parity is inserted into the LSB so leftshift each byte up one bit. This
|
||||||
|
allows ascii characters with a zero MSB to retain as much significance
|
||||||
|
as possible. */
|
||||||
|
{ char *keybytes = (char *)key;
|
||||||
|
unsigned int temp;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
temp = (unsigned int) keybytes[i];
|
||||||
|
keybytes[i] = (unsigned char) (temp << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
des_fixup_key_parity (key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Long passwords, i.e 9 characters or more.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
afs_transarc_StringToKey (const char *pw, size_t pw_len,
|
||||||
|
const char *cell, size_t cell_len,
|
||||||
|
des_cblock *key)
|
||||||
|
{
|
||||||
|
des_key_schedule schedule;
|
||||||
|
des_cblock temp_key;
|
||||||
|
des_cblock ivec;
|
||||||
|
char password[512];
|
||||||
|
size_t passlen;
|
||||||
|
|
||||||
|
memcpy(password, pw, min(pw_len, sizeof(password)));
|
||||||
|
if(pw_len < sizeof(password))
|
||||||
|
memcpy(password + pw_len, cell, min(cell_len,
|
||||||
|
sizeof(password) - pw_len));
|
||||||
|
passlen = min(sizeof(password), pw_len + cell_len);
|
||||||
|
memcpy(&ivec, "kerberos", 8);
|
||||||
|
memcpy(&temp_key, "kerberos", 8);
|
||||||
|
des_fixup_key_parity (&temp_key);
|
||||||
|
des_key_sched (&temp_key, schedule);
|
||||||
|
des_cbc_cksum ((des_cblock *)password, &ivec, passlen, schedule, &ivec);
|
||||||
|
|
||||||
|
memcpy(&temp_key, &ivec, 8);
|
||||||
|
des_fixup_key_parity (&temp_key);
|
||||||
|
des_key_sched (&temp_key, schedule);
|
||||||
|
des_cbc_cksum ((des_cblock *)password, key, passlen, schedule, &ivec);
|
||||||
|
memset(&schedule, 0, sizeof(schedule));
|
||||||
|
memset(&temp_key, 0, sizeof(temp_key));
|
||||||
|
memset(&ivec, 0, sizeof(ivec));
|
||||||
|
memset(password, 0, sizeof(password));
|
||||||
|
|
||||||
|
des_fixup_key_parity (key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AFS3_string_to_key(const char *pw, size_t pw_len,
|
||||||
|
const char *cell, size_t cell_len,
|
||||||
|
des_cblock *key)
|
||||||
|
{
|
||||||
|
if(pw_len > 8)
|
||||||
|
afs_transarc_StringToKey (pw, pw_len, cell, cell_len, key);
|
||||||
|
else
|
||||||
|
afs_cmu_StringToKey (pw, pw_len, cell, cell_len, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
get_str(const void *pw, size_t pw_len, const void *salt, size_t salt_len,
|
||||||
|
size_t *ret_len)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
size_t len = pw_len + salt_len;
|
||||||
|
len = (len + 7) & ~7;
|
||||||
|
p = malloc(len);
|
||||||
|
if(p == NULL)
|
||||||
|
return NULL;
|
||||||
|
memcpy(p, pw, pw_len);
|
||||||
|
memcpy(p + pw_len, salt, salt_len);
|
||||||
|
*ret_len = len;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
string_to_key_internal (const unsigned char *str,
|
string_to_key_internal (const unsigned char *str,
|
||||||
@@ -260,47 +379,51 @@ string_to_key_internal (const unsigned char *str,
|
|||||||
krb5_keytype ktype,
|
krb5_keytype ktype,
|
||||||
krb5_keyblock *key)
|
krb5_keyblock *key)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
unsigned char *s, *p;
|
unsigned char *s = NULL;
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
|
|
||||||
len = str_len + salt->length;
|
switch(ktype){
|
||||||
#if 1
|
case KEYTYPE_DES:{
|
||||||
len = (len + 7) / 8 * 8;
|
des_cblock tmpkey;
|
||||||
#endif
|
s = get_str(str, str_len, salt->data, salt->length, &len);
|
||||||
p = s = malloc (len);
|
if(s == NULL)
|
||||||
if (p == NULL)
|
return ENOMEM;
|
||||||
return ENOMEM;
|
DES_string_to_key(s, len, &tmpkey);
|
||||||
memset (s, 0, len);
|
ret = krb5_data_copy(&key->keyvalue, tmpkey, sizeof(des_cblock));
|
||||||
strncpy ((char *)p, (char *)str, str_len);
|
memset(&tmpkey, 0, sizeof(tmpkey));
|
||||||
p += str_len;
|
break;
|
||||||
memcpy (p, salt->data, salt->length);
|
}
|
||||||
|
case KEYTYPE_DES_AFS3:{
|
||||||
switch(ktype){
|
des_cblock tmpkey;
|
||||||
case KEYTYPE_DES:{
|
AFS3_string_to_key(str, str_len, salt->data, salt->length, &tmpkey);
|
||||||
des_cblock tmpkey;
|
ret = krb5_data_copy(&key->keyvalue, tmpkey, sizeof(des_cblock));
|
||||||
DES_string_to_key(s, len, &tmpkey);
|
key->keytype = KEYTYPE_DES;
|
||||||
ret = krb5_data_copy(&key->keyvalue, tmpkey, sizeof(des_cblock));
|
memset(&tmpkey, 0, sizeof(tmpkey));
|
||||||
memset(&tmpkey, 0, sizeof(tmpkey));
|
break;
|
||||||
break;
|
}
|
||||||
}
|
case KEYTYPE_DES3:{
|
||||||
case KEYTYPE_DES3:{
|
des_cblock keys[3];
|
||||||
des_cblock keys[3];
|
s = get_str(str, str_len, salt->data, salt->length, &len);
|
||||||
DES3_string_to_key(s, len, keys);
|
if(s == NULL)
|
||||||
ret = krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
|
return ENOMEM;
|
||||||
memset(keys, 0, sizeof(keys));
|
DES3_string_to_key(s, len, keys);
|
||||||
break;
|
ret = krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
|
||||||
}
|
memset(keys, 0, sizeof(keys));
|
||||||
default:
|
break;
|
||||||
ret = KRB5_PROG_KEYTYPE_NOSUPP;
|
}
|
||||||
break;
|
default:
|
||||||
}
|
ret = KRB5_PROG_KEYTYPE_NOSUPP;
|
||||||
memset(s, 0, len);
|
break;
|
||||||
free(s);
|
}
|
||||||
if(ret)
|
if(s){
|
||||||
return ret;
|
memset(s, 0, len);
|
||||||
key->keytype = ktype;
|
free(s);
|
||||||
return 0;
|
}
|
||||||
|
if(ret)
|
||||||
|
return ret;
|
||||||
|
key->keytype = ktype;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
krb5_error_code
|
krb5_error_code
|
||||||
|
Reference in New Issue
Block a user