/* PAM to automate Uni-Klu login tasks */

/* 
 * Albrecht Gebhardt <agebhard@uni-klu.ac.at>
 * Copyright: GPL, See COPYING.LIB-2.0
 *
 * Created Sun Jun 16 21:12:20 CEST 2002
 * 
 * Version:
 * $Id: pam_linux_uniklu_garble.c,v 1.6 2009-01-11 15:46:16 agebhard Exp $
 * 
 * Last Revised on
 * $Date: 2009-01-11 15:46:16 $
 * 
 * Changelog:
 *
 * $Log: pam_linux_uniklu_garble.c,v $
 * Revision 1.6  2009-01-11 15:46:16  agebhard
 * remove unused vars
 *
 * Revision 1.5  2009-01-11 15:38:07  agebhard
 * reduce compiler warnings
 *
 * Revision 1.4  2004/10/28 21:40:47  agebhard
 * working again (debian sarge)
 *
 * Revision 1.3  2002/06/18 13:25:08  agebhard
 * new debugging. still not working on madrake.
 * pam_sm_authenticate fails because it is called before entereing a password!
 *
 * Revision 1.2  2002/06/17 09:57:28  agebhard
 * more cvs keywords ...
 *
 * 
 */

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <syslog.h>
#include <security/pam_modules.h>
#include "pam_linux_uniklu.h"

void pam_linux_uniklu_cleanup_garble_key(pam_handle_t *pamh,
					 int *pam_linux_uniklu_garble_key, 
					 int error_status)
{
    *pam_linux_uniklu_garble_key = 0;
    free(pam_linux_uniklu_garble_key);
}

PAM_EXTERN int pam_linux_uniklu_garble_string(pam_handle_t *pamh,
					      char string[], int len)
{
    const char *procname="pam_linux_uniklu_garble_string";

    int	i, retval, *pam_linux_uniklu_garble_key=NULL;
    char rand_char;
    
#   ifdef DEBUG    
    syslog(LOG_DEBUG, "%s",procname);
#   endif
    retval = pam_get_data(pamh, "PAM_LINUX_UNIKLU_GARBLE_KEY",
    			  (void *) &pam_linux_uniklu_garble_key);
    if(pam_linux_uniklu_garble_key==NULL) {
	syslog(LOG_WARNING, 
	       "%s: pam_get_data for PAM_LINUX_UNIKLU_GARBLE_KEY failed: %s (first call?)",
	       procname,
	       pam_strerror(pamh,retval));
    };
    if (retval != PAM_SUCCESS)
	{
	    if ((pam_linux_uniklu_garble_key = (int *) malloc(sizeof(int))) 
		== NULL)
		{
		    syslog(LOG_CRIT, "%s: Out of memory!\n",procname);
		    return(PAM_AUTH_ERR);
		}
	    srand(time(NULL));
	    *pam_linux_uniklu_garble_key = rand();
	    retval = pam_set_data(pamh, "PAM_LINUX_UNIKLU_GARBLE_KEY",
				  pam_linux_uniklu_garble_key,
				  (void *) &pam_linux_uniklu_cleanup_garble_key);
	    if (retval != PAM_SUCCESS)
		{
		    syslog(LOG_CRIT, 
			   "%s: Can't cleanup 'pam_linux_uniklu_garble_key'!",
			   procname);
		    return(PAM_AUTH_ERR);
		}
	}
#   ifdef DEBUG    
    syslog(LOG_DEBUG, "%s: garble key: %d",procname,
	   *pam_linux_uniklu_garble_key);
#   endif
    srand(*pam_linux_uniklu_garble_key);
    for (i=0; i<len; i++)
	{
	    while ((rand_char = (char) rand() % 0xfe) == (char) 0);
	    string[i] = rand_char ^ string[i];
	    /* fixme: if string[i]=='\0' we should choose another
	     *        garble key because it will split the garbled 
	     *        password string !!
	     */
	}
    return(PAM_SUCCESS);
}
