view src/auth/userinfo-vpopmail.c @ 903:fd8888f6f037 HEAD

Naming style changes, finally got tired of most of the typedefs. Also the previous enum -> macro change reverted so that we don't use the highest bit anymore, that's incompatible with old indexes so they will be rebuilt.
author Timo Sirainen <tss@iki.fi>
date Sun, 05 Jan 2003 15:09:51 +0200
parents 35abd7a5d381
children dd4b74885c43
line wrap: on
line source

/* Copyright (C) 2002 Timo Sirainen */

/* Thanks to Courier-IMAP for showing how the vpopmail API should be used */

#include "config.h"
#undef HAVE_CONFIG_H

#ifdef USERINFO_VPOPMAIL

#include "userinfo-passwd.h"
#include "mycrypt.h"

#include <stdio.h>
#include <vpopmail.h>
#include <vauth.h>

#define I_DEBUG(x) /* i_warning x */

/* Limit user and domain to 80 chars each (+1 for \0). I wouldn't recommend
   raising this limit at least much, vpopmail is full of potential buffer
   overflows. */
#define VPOPMAIL_LIMIT 81

static int vpopmail_verify_plain(const char *user, const char *password,
				 AuthCookieReplyData *reply)
{
	char vpop_user[VPOPMAIL_LIMIT], vpop_domain[VPOPMAIL_LIMIT];
	struct vqpasswd *vpw;
	int result;

	/* vpop_user must be zero-filled or parse_email() leaves an extra
	   character after the user name. we'll fill vpop_domain as well
	   just to be sure... */
	memset(vpop_user, '\0', sizeof(vpop_user));
	memset(vpop_domain, '\0', sizeof(vpop_domain));

	if (parse_email(t_strdup_noconst(user), vpop_user, vpop_domain,
			sizeof(vpop_user)-1) < 0) {
		I_DEBUG(("vpopmail: parse_email(%s) failed", user));
		return FALSE;
	}

	/* we have to get uid/gid separately, because the gid field in
	   struct vqpasswd isn't really gid at all but just some flags... */
	if (vget_assign(vpop_domain, NULL, 0,
			&reply->uid, &reply->gid) == NULL) {
		I_DEBUG(("vpopmail: vget_assign(%s) failed", vpop_domain));
		return FALSE;
	}

	vpw = vauth_getpw(vpop_user, vpop_domain);
	if (vpw != NULL && (vpw->pw_dir == NULL || vpw->pw_dir[0] == '\0')) {
		/* user's homedir doesn't exist yet, create it */
		I_DEBUG(("vpopmail: pw_dir isn't set, creating"));

		if (make_user_dir(vpop_user, vpop_domain,
				  reply->uid, reply->gid) == NULL) {
			i_error("vpopmail: make_user_dir(%s, %s) failed",
				vpop_user, vpop_domain);
			return FALSE;
		}

		vpw = vauth_getpw(vpop_user, vpop_domain);
	}

	if (vpw == NULL) {
		I_DEBUG(("vpopmail: vauth_getpw(%s, %s) failed",
		       vpop_user, vpop_domain));
		return FALSE;
	}

	if (vpw->pw_gid & NO_IMAP) {
		I_DEBUG(("vpopmail: IMAP disabled for %s@%s",
		       vpop_user, vpop_domain));
		return FALSE;
	}

	/* verify password */
	result = strcmp(mycrypt(password, vpw->pw_passwd), vpw->pw_passwd) == 0;
	safe_memset(vpw->pw_passwd, 0, strlen(vpw->pw_passwd));

	if (!result) {
		I_DEBUG(("vpopmail: password mismatch for user %s@%s",
		       vpop_user, vpop_domain));
		return FALSE;
	}

	if (strocpy(reply->system_user, vpw->pw_name,
		    sizeof(reply->system_user)) < 0) {
		i_panic("Username too large (%u > %u)",
			strlen(vpw->pw_name), sizeof(reply->system_user)-1);
	}
	if (strocpy(reply->virtual_user, vpw->pw_name,
		    sizeof(reply->virtual_user)) < 0) {
		i_panic("Username too large (%u > %u)",
			strlen(vpw->pw_name), sizeof(reply->virtual_user)-1);
	}
	if (strocpy(reply->home, vpw->pw_dir, sizeof(reply->home)) < 0) {
		i_panic("Home directory too large (%u > %u)",
			strlen(vpw->pw_dir), sizeof(reply->home)-1);
	}

	return TRUE;
}

static void vpopmail_deinit(void)
{
	vclose();
}

struct user_info_module userinfo_vpopmail = {
	NULL,
	vpopmail_deinit,

	vpopmail_verify_plain,
	NULL
};

#endif