/*
 * snk_crypt
 *
 * Part of the SNK extension to logdaemon
 *
 * Written by William LeFebvre, Argonne National Laboratory
 */

#include <string.h>
#include <stdio.h>
#include <pwd.h>

#include "snk.h"

/* char *snk_crypt(char *pp, char *salt, struct passwd *pwd, int pwok)
 *	Verify user described by "pwd", using "pp" as the user-provided
 *	password and "salt" as the salt for "crypt".  If "pwok" is true,
 *	then either a correct SNK response or a correct Unix password
 *	will be accepted as verification, otherwise only the former will
 *	be accepted.  Upon positive verification, return the password
 *	found in pwd->pw_passwd, otherwise return ":".  This is for
 *	compatability with "crypt".  This function assumes that
 *	snk_challenge has already been called.
 */

char   *snk_crypt(pp, salt, pwd, pwok)
char   *pp;
char   *salt;
struct passwd *pwd;
int     pwok;
{
    char   *p;
    char   *crypt();
    struct scent  sc;
    struct snkent snk;

    /* initialization */
    snk.key = NULL;

    /* Try SNK authentication even when the UNIX password is permitted. */
    if (pwd != 0 && getscent(&sc, pwd->pw_name) == 0
	&& getsnkent(&snk, sc.serial) == 0
	&& snk_verify(&snk, pp))
    {
	/* cleanup memory */
	if (snk.key != NULL)
	{
	    memset(snk.key, 0, strlen(snk.key));
	}
	return (pwd->pw_passwd);
    }
    /* cleanup memory */
    if (snk.key != NULL)
    {
	memset(snk.key, 0, strlen(snk.key));
    }

    /* When SNK authentication does not work, always invoke crypt(). */
    p = crypt(pp, salt);
    if (pwok && pwd != 0 && strcmp(p, pwd->pw_passwd) == 0)
    {
	/* only valid when "pwok" is true */
	return (pwd->pw_passwd);
    }

    /* The user does not exist or entered bad input. */
    return (":");
}
