/* Copyright (C) 1999 Beau Kuiper

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

#include "ftpd.h"
#include "auth.h"

#define GOT_USER 	1
#define NOT_GOT_USER 	0

/* This file contains code to autheticate against custom password files */

typedef struct 
{
	char *udata;
	char *password;
	char *username;
	char *homedir;
	char *rootdir;
} PASSWDSTRUCT;

int internalauth_config(char *username, char *data, int line, void *h)
{
	PASSWDSTRUCT *handle = (PASSWDSTRUCT *)h;
	
	if (strcmp(username, handle->username) == 0)
	{
		handle->udata = strdupwrapper(data);
		return(GOT_USER);
	}
	return(NOT_GOT_USER);
}

void *internalauth_gethandle(FTPSTATE *peer, TOKENSET *tset, char *username, int *err)
{
	PASSWDSTRUCT *newhandle;
	int result, error, line;
	char *passwdfile = NULL;
	
	/* assume we don't find the user */
	*err = AUTH_USERNKNOW;
	
	newhandle = mallocwrapper(sizeof(PASSWDSTRUCT));
	newhandle->username = strdupwrapper(username);

	passwdfile = mktokconfstr(tset, auth_getcursectionid(peer), "internal_passfile", NULL);
	if (passwdfile == NULL)
		goto logerror;
		
	/* make sure that the password file is secure */
	result = loadconfigfile(passwdfile, internalauth_config, newhandle, TRUE, &error, &line);
	
	switch (result)
	{
		case CONFIG_OK:
			goto error;
		case CONFIG_HANDLER_ERROR:
			break;		/* found the user */
		default:
			goto logerror;
	}

	if (strchrcount(newhandle->udata, ':') != 2)
	{
		freewrapper(newhandle->udata);
		goto error;
	}

	newhandle->password = newhandle->udata;
	newhandle->homedir = strchr(newhandle->udata, ':') + 1;

	/* lets hope this doesn't cause heart attacks. It may not 
	   work with flakey C compilers */
	newhandle->homedir[-1] = 0;
	newhandle->rootdir = strchr(newhandle->homedir, ':') + 1;
	newhandle->rootdir[-1] = 0;
	
	*err = AUTH_OK;
	freewrapper(passwdfile);
	return(newhandle);

logerror:
	if (passwdfile == NULL)
		log_addentry(MYLOG_INFO, NULL, "You didn't specify a password file for internal authentication!");
	else
		log_giveentry(MYLOG_INFO, NULL, safe_snprintf("Error loading '%s': %s", passwdfile, config_errorstr(result)));
	*err = AUTH_ERROR;

error:
	freeifnotnull(passwdfile);
	freewrapper(newhandle->username);
	freewrapper(newhandle);

	return(NULL);
}

void internalauth_freehandle(void *h)
{
	PASSWDSTRUCT *handle = (PASSWDSTRUCT *)h;
	
	freewrapper(handle->udata);
	freewrapper(handle->username);
	freewrapper(handle);
}

int internalauth_checkpasswd(void *h, char *password, char **errmsg)
{
	PASSWDSTRUCT *handle = (PASSWDSTRUCT *)h;
	return(chkpassword(handle->password, password));
}

char *internalauth_gethomedir(void *h)
{
	return(((PASSWDSTRUCT *)h)->homedir);
}

char *internalauth_getrootdir(void *h)
{
	return(((PASSWDSTRUCT *)h)->rootdir);
}

PERMSTRUCT internalauth_commands =
{
	internalauth_checkpasswd,
	internalauth_gethomedir,
	internalauth_getrootdir,
	NULL,
	NULL,
	NULL,
	internalauth_gethandle,
	internalauth_freehandle,
	NULL,
};
