#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <syslog.h>

#define PAM_SM_AUTH
#include <security/pam_modules.h>

#define SERVICE_NAME "PAM_delay"

PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags,
                                   int argc, const char **argv)
{
	int i;
	double total_delay=0;
	openlog(SERVICE_NAME, LOG_PID, LOG_AUTHPRIV);
#ifdef HAVE_PAM_FAIL_DELAY
	for (i=0; i<argc; i++)
	{
		int ret;
		double delay=0;
		char *buf=malloc(strlen(argv[i])+1);
		if (!buf)
		{
			syslog(LOG_CRIT, "malloc failed");
			return PAM_BUF_ERR;
		}
		ret=sscanf(argv[i], "%lf%s", &delay, buf);
		if (!ret)
		{
			syslog(LOG_ERR, "error parsing options - %s", argv[i]);
			goto next;
		}
		if (ret>1)
		{
			double units;
			if (!strcasecmp(buf, "m")) units=60;
			else if (!strcasecmp(buf, "s")) units=1;
			else if (!strcasecmp(buf, "ms")) units=0.001;
			else if (!strcasecmp(buf, "us")) units=0.000001;
			else 
			{
				syslog(LOG_ERR, "error parsing options - "
					"invalid unit %s - "
					"expected [m|s|ms|us]", argv[i]);
				free(buf);
				return PAM_SERVICE_ERR;
			}
			delay*=units;
		}
		total_delay+=delay;
	next:
		free(buf);
	}
	pam_fail_delay(pamh, (unsigned int)(total_delay*1000000));
	return PAM_SUCCESS;
#else
	syslog(LOG_ERR, "Compilation error - delays not in use");
	return PAM_SERVICE_ERR;
#endif
}

PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags,
	int argc, const char **argv)
{
	return PAM_SUCCESS;
}


