/*
 * POP3Lite - 3lite POP3 Daemon
 * Copyright (C) 2000, 2001 Gergely Nagy <8@free.bsd.hu>
 *
 * This file is part of POP3Lite.
 *
 * POP3Lite 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 of the License, or
 * (at your option) any later version.
 *
 * POP3Lite 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include "main.h"

#include <pop3lite.h>
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>

#ifdef HAVE_CRYPT_H
#	include <crypt.h>
#endif /* HAVE_CRYPT_H */

#include <grp.h>
#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>

#ifdef HAVE_SHADOW_H
#	include <shadow.h>
#endif /* HAVE_SHADOW_H */

#include "core_sys.h"

static const char rcsid[]="$Id: core_sys.c,v 1.9 2001/01/12 15:58:59 algernon Exp $";

static GList *SYS_getinfo ( const char *user );

void
default_sys_openlog ( P3LControl *control )
{
	openlog ( "pop3lite", LOG_PID, LOG_MAIL );
}

void
default_sys_closelog ( P3LControl *control )
{
	closelog ();
}

void
default_sys_log ( P3LControl *control, int priority, const char *format, ... )
{
	char *tmp;
	va_list lst;

	if ( p3l_is_enabled ( P3L_GET_FIRST_OPTION ( "SYSLOG.DISABLE" ) ) )
		return;

	va_start ( lst, format );
	tmp = g_strdup_vprintf ( format, lst );
	va_end ( lst );

	syslog ( priority, "%s", tmp );

	g_free ( tmp );
}

UserInfo *
default_sys_getuinam ( P3LControl *control, const char *name )
{
	unsigned long i;
	UserInfo *ui;

	for ( i = 0; i < g_list_length ( control->system->users ); i++ )
	{
		ui = (UserInfo *) g_list_nth_data ( control->system->users, i );
		if ( ui != NULL && ui->name != NULL && ! strcmp ( ui->name, name ) )
				return ui;
	}

	return (UserInfo *) g_list_nth_data ( SYS_getinfo ( name ), 0 );
}

AuthResult
default_sys_authenticate ( P3LControl *control, const char *name, const char *pass )
{
	char *sys_pass, *supp_pass;
	char *salt;
	AuthResult result=AUTH_RESULT_FAIL;
	UserInfo *ui;
	GList *info;

#ifdef DEBUG
	control->system->log ( control, LOG_DEBUG, "%s:%d: Authenticating user: %s",
			       __FILE__, __LINE__, name );
#endif

	info = SYS_getinfo ( name );
	ui = (UserInfo *) g_list_nth_data ( SYS_getinfo ( name ), 0 );
	sys_pass = (char *) g_list_nth_data ( SYS_getinfo ( name ), 1 );

	salt = g_strndup ( sys_pass , 2 );

	if ( salt == NULL )
	{
		sleep ( 5 );
		return AUTH_RESULT_FAIL;
	}

	if ( !strcmp ( salt, "$1" ) )
	{
		g_free ( salt );
		salt = ( char * ) g_malloc ( 12 );
		salt = g_strndup ( sys_pass, 11 );
	}

	supp_pass = crypt ( pass, salt );

	if ( ! strcmp ( sys_pass, supp_pass ) )
	{
		result = AUTH_RESULT_OK;
		control->system->users = g_list_append ( control->system->users, ui );
	} else
		sleep ( 5 );

	g_free ( salt );

	p3l_clear ( sys_pass );
	p3l_clear ( supp_pass );

	return result;
}

void
default_sys_drop_privileges ( P3LControl *control )
{
	UserInfo *ui;
	char *user;
	char *group;
	gid_t gid;

#ifdef DEBUG
	control->system->log ( control, LOG_DEBUG, "%s:%d: Dropping privileges",
			       __FILE__, __LINE__ );
#endif

	user = P3L_GET_DATA ( "USER" );
	ui = control->system->getuinam ( control, user );

	group = P3L_GET_FIRST_OPTION ( "RUN_GID" );
	gid = ( group == NULL ) ? ui->gid : atoi ( group );

	setgid ( gid );
	setuid ( ui->uid );
}

static GList *
SYS_getinfo ( const char *name )
{
#ifdef HAVE_SHADOW_H
	struct spwd *spwentry;
#endif
	struct passwd *pwentry;
	UserInfo *ui;
	char *sys_pass;
	GList *info = NULL;

#ifdef HAVE_SHADOW_H
	spwentry = getspnam ( name );
#endif
	pwentry = getpwnam ( name );

	if ( pwentry == NULL )
		return NULL;

	ui = (UserInfo *) g_malloc ( sizeof (UserInfo) );

#ifdef HAVE_SHADOW_H
	if ( spwentry == NULL )
	{
#endif
		sys_pass = pwentry->pw_passwd;
		ui->expire = 0;
#ifdef HAVE_SHADOW_H
	}
	else
	{
		sys_pass = spwentry->sp_pwdp;
		ui -> expire = spwentry->sp_expire;
	}
#endif

	ui -> name = g_strdup ( name );
	ui -> uid = pwentry->pw_uid;
	ui -> gid = pwentry->pw_gid;
	ui -> gecos = pwentry->pw_gecos;
	ui -> home = pwentry->pw_dir;
	ui -> shell = pwentry->pw_shell;

	info = g_list_append ( info, ui );
	info = g_list_append ( info, sys_pass );

	return info;
}


syntax highlighted by Code2HTML, v. 0.9.1