authenticate/authvlib.cc
author "Tomas Zeman <tzeman@volny.cz>"
Sun, 20 Jan 2008 00:22:09 +0100
changeset 2 b3afb9f1e801
parent 0 6f7a81934006
permissions -rw-r--r--
Imported vmailmgr-0.97

// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
//
// 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include <config.h>
#include <stdlib.h>
#include "ac/time.h"
#include <unistd.h>
#include "authvlib.h"
#include "misc/exec.h"
#include "misc/lookup.h"
#include "vdomain/vdomain.h"

#ifndef HAVE_GETHOSTNAME
int gethostname(char *name, size_t len);
#endif

void set_domain(mystring& name, mystring& domain)
{
  int sep = name.find_first_of(config->separators());
  if(sep >= 0) {
    domain = name.right(sep+1);
    name = name.left(sep);
  }
  else {
    domain = getenv("TCPLOCALHOST");
    if(!domain) {
      char tmp[256];
      if(gethostname(tmp, 256))
	fail_temporary("Error determining local host name");
      domain = tmp;
    }
  }
  if(!name)
    fail_login("Empty user name");
  if(!domain)
    fail_login("Empty domain name");
}

static vdomain* domain = 0;

void set_user(const pwentry* pw)
{
  pw->export_env();
  if(!!exec_presetuid && execute(exec_presetuid))
    fail_temporary("Execution of presetuid failed");
  if(setgid(pw->gid) == -1 ||
     setuid(pw->uid) == -1 ||
     chdir(pw->home.c_str()) == -1)
    fail_temporary("Bad user data in password file");
  domain = new vdomain(*pw);
  config = &domain->config;
}

static user_data* check(mystring fulluser, mystring password,
			bool virtual_only)
{
  mystring virtname;
  pwentry* basepw;
  if(!lookup_baseuser(fulluser, basepw, virtname))
    fail_login("Invalid or unknown base user or domain");
  presetenv("VUSER=", virtname);
  if(!virtname) {
    if(virtual_only)
      return 0;
    if(!basepw->authenticate(password))
      fail_login("Invalid or incorrect password");
    set_user(basepw);
    return new user_data(basepw, "", "");
  }
  else {
    set_user(basepw);
    vpwentry* vpw = domain->lookup(virtname);
    if(!vpw || !vpw->has_mailbox)
      fail_login("Invalid or unknown virtual user");
    if(!vpw->authenticate(password))
      fail_login("Invalid or incorrect password");
    if(vpw->expiry < (unsigned)time(0))
      fail_login("Account has expired");
    vpw->export_env();
    return new user_data(basepw, vpw->directory, vpw->name);
  }
}

user_data* authenticate(mystring name, mystring pass, mystring domain,
			bool virtual_only)
{
  mystring baseuser;
  if(!is_local(domain)) {
    mystring baseuser = find_virtual(domain);
    if(!!baseuser)
      name = baseuser + "-" + name;
  }
  user_data* result = check(name, pass, virtual_only);
  if(result && !!exec_postsetuid && execute(exec_postsetuid))
    fail_temporary("Execution of presetuid failed");
  return result;
}