/* pam_faildelay module */

/*
 * $Id: pam_faildelay.c,v 1.3 2005/07/18 04:12:56 dtucker Exp $
 *
 * Allows an admin to set the delay on failure per-application.
 * Provides "auth" interface only.
 *
 * Build with: gcc -shared -Xlinker -x -o pam_faildelay.so pam_faildelay.c
 *
 * Use by putting something like this in the relevant pam config:
 * auth    required        pam_faildelay.so delay=[microseconds]
 *
 * eg:
 * auth    required        pam_faildelay.so delay=10000000
 * will set the delay on failure to 10 seconds.
 *
 *
 * Based on pam_rootok and parts of pam_unix both by Andrew Morgan
 *  <morgan@linux.kernel.org>
 *
 * Portions Copyright (c) 2005 Darren Tucker <dtucker at zip com au>.
 *
 * Licenced under the same terms as LinuxPAM itself, specifically:
 *
 * Redistribution and use in source and binary forms of, with
 * or without modification, are permitted provided that the following
 * conditions are met:
 * 
 * 1. Redistributions of source code must retain any existing copyright
 *    notice, and this entire permission notice in its entirety,
 *    including the disclaimer of warranties.
 * 
 * 2. Redistributions in binary form must reproduce all prior and current
 *    copyright notices, this list of conditions, and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 * 
 * 3. The name of any author may not be used to endorse or promote
 *    products derived from this software without their specific prior
 *    written permission. 
 * 
 * ALTERNATIVELY, this product may be distributed under the terms of the
 * GNU General Public License, in which case the provisions of the GNU
 * GPL are required INSTEAD OF the above restrictions.  (This clause is
 * necessary due to a potential conflict between the GNU GPL and the
 * restrictions contained in a BSD-style copyright.)
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */

#define _GNU_SOURCE

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

/*
 * here, we make a definition for the externally accessible function
 * in this file (this definition is required for static a module
 * but strongly encouraged generally) it is used to instruct the
 * modules include file to define the function prototypes.
 */

#define PAM_SM_AUTH

#include <security/pam_modules.h>

/* some syslogging */

static void _pam_log(int err, const char *format, ...)
{
    va_list args;

    va_start(args, format);
    openlog("PAM-faildelay", LOG_CONS|LOG_PID, LOG_AUTH);
    vsyslog(err, format, args);
    va_end(args);
    closelog();
}

/* --- authentication management functions (only) --- */

PAM_EXTERN
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc
			,const char **argv)
{
    int i, result = PAM_AUTH_ERR;
    long int delay = 0;

    /* step through arguments */
    for (i = 0; i < argc; i++) {
	if (sscanf(argv[i], "delay=%ld", &delay) == 1) {
#ifdef HAVE_PAM_FAIL_DELAY
	    _pam_log(LOG_DEBUG, "setting fail delay to %ld", delay);
	    result = pam_fail_delay(pamh, delay);
#else
	    _pam_log(LOG_ERR, "pam_fail_delay not enabled");
	    result = PAM_SUCCESS;
#endif
	} else
	    _pam_log(LOG_ERR,"unknown option; %s", argv[i]);
    }
    return result;
}

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


#ifdef PAM_STATIC

/* static module data */

struct pam_module _pam_rootok_modstruct = {
    "pam_faildelay",
    pam_sm_authenticate,
    pam_sm_setcred,
    NULL,
    NULL,
    NULL,
    NULL,
};

#endif

/* end of module definition */
