#include "mit-copyright.h"
#include <stdio.h>
#include <string.h>
#include "des.h"
/*#include "des_internal.h"*/

/*
 * The Kerberos header is needed to pickup the local cell name. 
 * This satisfies a requirement of afs_string_to_key
 */

#include "krb.h"

int
passwd_to_afskey(user,instance,realm,passwd,key)
    char *user, *instance, *realm, *passwd;
    C_Block key;
{
  if (passwd != NULL) 
    afs_string_to_key(passwd, key, realm, 0);
  
  return(0);
}


/*
 * afs_string_to_key()
 *
 * For compatibility with Transarc AFS Kaserver
 */

int INTERFACE
afs_string_to_key(str,key,realm)
    char * str;
    des_cblock key;
    char * realm;
{
    char password[64]; /* Max passlen for Kaserver may be larger than this */
    long length;
    int i;
    des_key_schedule key_sked;

    des_cblock ikey;
    des_cblock tkey;

    length = strlen(str);
    if ((length <= 8) && (length > 0)) {
      
      /*
       * For passwords 8 chars or less.
       */

	strncpy(password, realm, 8);
	for (i=0; i<8; i++)
	   if (isupper(password[i]))
		password[i] = tolower(password[i]);
	for (i=0; i<length; i++)
	    password[i] ^= str[i];
	for (i=0; i<8; i++)
	    if (password[i] == '\0')
		password[i] = 'X';
        (void)strncpy(key, (char *)crypt(password, "#~") + 2, 8);
	for (i=0; i<8; i++)
	    key[i] <<= 1;
	/* now fix up key parity again */
	des_fixup_key_parity(key);
    } 
    if (length > 8) {

      /* 
       * for passwords larger than 8 chars
       */

	strncpy (password, str, sizeof(password));
	for (i=length; i<sizeof(password) && *realm; i++) {
	    password[i] = *realm++;
	    if (isupper(password[i]))
		password[i] = tolower(password[i]);
    }

	/*
	 * generate the ciphered key
	 */

     memcpy(ikey, "kerberos", sizeof(ikey) );
     memcpy(tkey, ikey, sizeof(tkey) );

     des_fixup_key_parity(tkey);
     des_key_sched(tkey, key_sked);
     des_cbc_cksum(password, ikey, i, key_sked, ikey);

     memcpy(tkey, ikey, sizeof(ikey) );

     des_fixup_key_parity(tkey);
     des_key_sched(tkey, key_sked);
     des_cbc_cksum(password, key, i, key_sked, ikey);
	
     /* erase key_sked */
     memset( (char *)key_sked, 0, sizeof(key_sked));

     /* now fix up key parity again */
     des_fixup_key_parity(key);

    }

 return 0;

}
