/*
** Copyright 1998 - 2001 Double Precision, Inc.  See COPYING for
** distribution information.
*/

#if	HAVE_CONFIG_H
#include	"courier_auth_config.h"
#endif
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<errno.h>
#include	<pwd.h>
#if	HAVE_UNISTD_H
#include	<unistd.h>
#endif
#include	"auth.h"
#include	"courierauthdebug.h"
#include	<vpopmail.h>
#include	<vauth.h>
#include	"vpopmail_config.h"

/* make use of pw_flags only if available */
#ifndef VQPASSWD_HAS_PW_FLAGS
#define pw_flags pw_gid
#endif

extern FILE *authvchkpw_file(const char *, const char *);

static const char rcsid[]="$Id: preauthvchkpw.c,v 1.26 2007/04/22 18:53:30 mrsam Exp $";

/* This function is called by the auth_vchkpw() function
 *
 * This function does the following :
 *   - extract the username and domain from the supplied userid
 *   - lookup the passwd entry for that user from the auth backend
 *   - populate *and return) a courier authinfo structure with the values
 *     from the vpopmail passwd entry 
 * 
 * Return -1 on perm failure
 * Return  0 on success
 * Return  1 on temp failure
 *
 */

int auth_vchkpw_pre(
	const char *userid,
	const char *service,
        int (*callback)(struct authinfo *, void *),
	void *arg)
{
struct vqpasswd *vpw;
static uid_t uid;
gid_t	gid;
struct authinfo auth;
static char User[256];
static char Domain[256];
static char options[80];

	/* Make sure the auth struct is empty */
        memset(&auth, 0, sizeof(auth));

	/* Take the supplied userid, and split it out into the user and domain
         * parts. (If a domain was not supplied, then set the domain to be
	 * the default domain)
         */
        if ( parse_email(userid, User, Domain, 256) != 0) {
		/* Failed to successfully extract user and domain.
		 * So now exit with a permanent failure code
		 */
		DPRINTF("vchkpw: unable to split into user and domain");
		return(-1);
        }

	/* Check to see if the domain exists.
         * If so, on return vget_assign will :
         *   Rewrite Domain to be the real domain if it was sent as an alias domain
         *   Retrieve the domain's uid and gid
	 */
        if ( vget_assign(Domain,NULL,0,&uid, &gid) == NULL ) {
		/* Domain does not exist
		 * So now exit with a permanent failure code */
		DPRINTF("vchkpw: domain does not exist");
		return (-1);
	}

	/* Try and retrieve the user's passwd entry from the auth backend */
        if ( (vpw=vauth_getpw(User, Domain)) == NULL) {
		/* User does not exist
		 * So now exit with a permanent failure code
		 */
		DPRINTF("vchkpw: user does not exist");
		return (-1);
	}

	/* Check to see if the user has been allocated a dir yet.
	 * Some of the vpopmail backends (eg mysql) allow users to
	 * be manually inserted into the auth backend but without
	 * allocating a dir. A dir will be created when the user
	 * first trys to auth (or when they 1st receive mail)
	 */
	if (vpw->pw_dir == NULL || strlen(vpw->pw_dir) == 0 ) {
		/* user does not have a dir allocated yet */
		if ( make_user_dir(User, Domain, uid, gid) == NULL) {
			/* Could not allocate a user dir at this time
			 * so exit with a temp error code 
			 */
			DPRINTF("vchkpw: make_user_dir failed");
			return(1);
		}
		/* We have allocated the user a dir now.
		 * Go and grab the updated passwd entry
		 */
		if ( (vpw=vauth_getpw(User, Domain)) == NULL ) {
			/* Could not get the passwd entry
			 * So exit with a permanent failure code
			 */
			DPRINTF("vchkpw: could not get the password entry");
			return(-1);
		}
	}

	snprintf(options, sizeof(options),
		"disablewebmail=%d,disablepop3=%d,disableimap=%d",
                vpw->pw_flags & NO_WEBMAIL ? 1 : 0,
                vpw->pw_flags & NO_POP ? 1 : 0,
                vpw->pw_flags & NO_IMAP ? 1 : 0);

#ifdef HAVE_VSET_LASTAUTH
        /* if we are keeping track of their last auth time,
         * then store this value now. Note that this isnt 
	 * consistent with the authentication via vchkpw 
	 * because it only stores the lastauth attempt
	 * after the password has been verified. Here we are
	 * logging it after the user has been found to exist,
	 * but before the password has been verified. We could
	 * do the logging inside authvchkpw.c, but that would
	 * be a lot harder because we would have to go and
	 * parse_email() again there before calling vset_lastauth()
         */
        vset_lastauth(User, Domain, service);
#endif

	/* save the user's passwd fields into the appropriate 
	 * courier structure 
	 */
	/*auth.sysusername	= userid;*/
	auth.sysuserid		= &uid;
	auth.sysgroupid		= gid;
	auth.homedir		= vpw->pw_dir;
	auth.address		= userid;
	auth.fullname		= vpw->pw_gecos;
	auth.passwd		= vpw->pw_passwd;
	auth.clearpasswd	= vpw->pw_clear_passwd;
	auth.options		= options;
	courier_authdebug_authinfo("DEBUG: authvchkpw: ", &auth, 0, vpw->pw_passwd);

	return ((*callback)(&auth, arg));
}


syntax highlighted by Code2HTML, v. 0.9.1