passdb-checkpassword.c revision 00bde9ae9eab9e720462bf6ec9a4dd85e88c3bbf
/* Copyright (C) 2004-2005 Timo Sirainen */
#include "common.h"
#ifdef PASSDB_CHECKPASSWORD
#include "lib-signals.h"
#include "buffer.h"
#include "str.h"
#include "ioloop.h"
#include "hash.h"
#include "env-util.h"
#include "passdb.h"
#include "safe-memset.h"
#include <stdlib.h>
#include <unistd.h>
struct checkpassword_passdb_module {
struct passdb_module module;
const char *checkpassword_path, *checkpassword_reply_path;
struct hash_table *clients;
};
struct chkpw_auth_request {
char *password;
unsigned int write_pos;
struct auth_request *request;
int exit_status;
unsigned int exited:1;
};
{
i_error("checkpassword: close() failed: %m");
}
i_error("checkpassword: close() failed: %m");
}
}
enum passdb_result result)
{
struct checkpassword_passdb_module *module =
(struct checkpassword_passdb_module *)_module;
if (result == PASSDB_RESULT_OK) {
"checkpassword",
"LF characters in checkpassword reply");
} else {
NULL);
}
}
}
static void
{
return;
switch (request->exit_status) {
/* vpopmail exit codes: */
case 3: /* password fail / vpopmail user not found */
case 12: /* null user name given */
case 13: /* null password given */
case 15: /* user has no password */
case 21: /* system user not found */
case 22: /* system user shadow entry not found */
case 23: /* system password fail */
/* standard checkpassword exit codes: */
case 1:
/* (1 is additionally defined in vpopmail for
"Login failed (status=%d)",
break;
case 0:
break;
}
/* missing input - fall through */
case 2:
/* checkpassword is called with wrong
parameters? unlikely */
case 111:
/* temporary problem, treat as internal error */
default:
/* whatever error.. */
"Child %s exited with status %d",
break;
}
}
{
struct chkpw_auth_request *request;
int status;
/* FIXME: if we ever do some other kind of forking, this needs fixing */
if (pid == -1) {
i_error("waitpid() failed: %m");
return;
}
/* unknown child finished */
if (WIFSIGNALED(status)) {
i_error("checkpassword: Unknown child %s died "
}
continue;
}
if (WIFSIGNALED(status)) {
i_error("checkpassword: Child %s died with signal %d",
"checkpassword", "exit_status=%d",
} else {
/* shouldn't happen */
"checkpassword", "Child exited with status=%d",
status);
}
}
}
}
static void env_put_extra_fields(const char *extra_fields)
{
const char *const *tmp;
const char *key, *p;
if (p == NULL)
else
}
}
static void __attr_noreturn__
struct checkpassword_passdb_module *module,
{
"dup2() failed: %m");
} else {
/* Besides passing the standard username and password in a
pipe, also pass some other possibly interesting information
NULL));
/* FIXME: for backwards compatibility only,
remove some day */
NULL));
}
NULL));
/* FIXME: for backwards compatibility only,
remove some day */
NULL));
}
}
const char *fields =
/* extra fields could come from master db */
}
/* very simple argument splitting. */
"execute: %s", cmd);
"execv(%s) failed: %m", args[0]);
}
exit(2);
}
{
unsigned char buf[1024];
if (ret <= 0) {
if (ret < 0) {
"checkpassword", "read() failed: %m");
}
"Received no input");
} else {
}
}
{
/* Send: username \0 password \0 timestamp \0.
Must be 512 bytes or less. The "timestamp" parameter is actually
useful only for APOP authentication. We don't support it, so
keep it empty */
const unsigned char *data;
if (size > 512) {
return;
}
if (ret <= 0) {
if (ret < 0) {
"checkpassword", "write() failed: %m");
}
return;
}
return;
i_error("checkpassword: close() failed: %m");
}
static void
{
struct checkpassword_passdb_module *module =
(struct checkpassword_passdb_module *)_module;
struct chkpw_auth_request *chkpw_auth_request;
fd_in[0] = -1;
"pipe() failed: %m");
if (fd_in[0] != -1) {
}
return;
}
if (pid == -1) {
"fork() failed: %m");
return;
}
if (pid == 0) {
/* not reached */
}
"close(fd_in[1]) failed: %m");
}
"close(fd_out[0]) failed: %m");
}
}
static struct passdb_module *
{
struct checkpassword_passdb_module *module;
struct checkpassword_passdb_module, 1);
PKG_LIBEXECDIR"/checkpassword-reply";
}
const char *args __attr_unused__)
{
}
{
struct checkpassword_passdb_module *module =
(struct checkpassword_passdb_module *)_module;
struct hash_iterate_context *iter;
}
}
struct passdb_module_interface passdb_checkpassword = {
"checkpassword",
NULL,
};
#endif