passdb-checkpassword.c revision 1f1e81aab38d833d1c9cdc244c91fd762e0080d4
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "config.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#undef HAVE_CONFIG_H
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#ifdef PASSDB_CHECKPASSWORD
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "common.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "buffer.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "ioloop.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "hash.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "passdb.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "safe-memset.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <stdlib.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <unistd.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <sys/wait.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstruct chkpw_auth_request {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher int fd_out, fd_in;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct io *io_out, *io_in;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher pid_t pid;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buffer_t *input_buf;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher char *password;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher unsigned int write_pos;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct auth_request *request;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher verify_plain_callback_t *callback;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher};
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic char *checkpassword_path, *checkpassword_reply_path;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstruct hash_table *clients;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic struct timeout *to_wait;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_request_close(struct chkpw_auth_request *request)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (request->input_buf != NULL) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buffer_free(request->input_buf);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request->input_buf = NULL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (request->fd_in != -1) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (close(request->fd_in) < 0)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: close() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request->fd_in = -1;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (request->io_in != NULL) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher io_remove(request->io_in);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request->io_in = NULL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (request->io_out != NULL)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher io_remove(request->io_out);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (request->fd_out != -1) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (close(request->fd_out) < 0)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: close() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_request_finish(struct chkpw_auth_request *request,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher enum passdb_result result)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher hash_remove(clients, POINTER_CAST(request->pid));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* FIXME: store request->input_buf so userdb can fetch it */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (auth_request_unref(request->request))
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request->callback(result, request->request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_request_close(request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher safe_memset(request->password, 0, strlen(request->password));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_free(request->password);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_free(request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void wait_timeout(void *context __attr_unused__)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct chkpw_auth_request *request;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher int status;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher pid_t pid;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* FIXME: if we ever do some other kind of forking, this needs fixing */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher while ((pid = waitpid(-1, &status, WNOHANG)) != 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (pid == -1) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (errno == ECHILD) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher timeout_remove(to_wait);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher to_wait = NULL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher } else if (errno != EINTR)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("waitpid() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request = hash_lookup(clients, POINTER_CAST(pid));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (WIFSIGNALED(status)) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: Child %s died with signal %d",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher dec2str(pid), WTERMSIG(status));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher } else if (WIFEXITED(status) && request != NULL) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher switch (WEXITSTATUS(status)) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher case 0:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_request_finish(request,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher PASSDB_RESULT_OK);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request = NULL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher break;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher case 1:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_request_finish(request,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher PASSDB_RESULT_OK);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request = NULL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher break;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher case 2:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* checkpassword is called with wrong
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher parameters? unlikely */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher case 111:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* temporary problem, treat as internal error */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher default:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* whatever error.. */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Child %s exited with status %d",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher dec2str(pid), WEXITSTATUS(status));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher break;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (request != NULL) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_request_finish(request,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher PASSDB_RESULT_INTERNAL_FAILURE);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_verify_plain_child(int fd_in, int fd_out)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher char *args[3];
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (dup2(fd_out, 3) < 0)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: dup2() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher else if (dup2(fd_in, 4) < 0)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: dup2() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher else {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher args[0] = checkpassword_path;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher args[1] = checkpassword_reply_path;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher args[2] = NULL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher execv(checkpassword_path, args);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: execv(%s) failed: %m",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_path);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher exit(2);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_child_input(void *context)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct chkpw_auth_request *request = context;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher unsigned char buf[1024];
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ssize_t ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = read(request->fd_in, buf, sizeof(buf));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret <= 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret < 0)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: read() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_request_close(request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher } else {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (request->input_buf == NULL) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request->input_buf =
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buffer_create_dynamic(default_pool, 512);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buffer_append(request->input_buf, buf, ret);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_child_output(void *context)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* Send: username \0 password \0 timestamp \0.
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher Must be 512 bytes or less. The "timestamp" parameter is actually
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher useful only for APOP authentication. We don't support it, so
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher keep it empty */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct chkpw_auth_request *request = context;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct auth_request *auth_request = request->request;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buffer_t *buf;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const unsigned char *data;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher size_t size;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ssize_t ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buf = buffer_create_dynamic(pool_datastack_create(), 512+1);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buffer_append(buf, auth_request->user, strlen(auth_request->user)+1);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buffer_append(buf, request->password, strlen(request->password)+1);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buffer_append_c(buf, '\0');
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher data = buffer_get_data(buf, &size);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (size > 512) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: output larger than 512 bytes: "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "%"PRIuSIZE_T, size);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_request_close(request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = write(request->fd_out, data + request->write_pos,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher size - request->write_pos);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret <= 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret < 0)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: write() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_request_close(request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request->write_pos += ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (request->write_pos < size)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (close(request->fd_out) < 0)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: close() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request->fd_out = -1;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher io_remove(request->io_out);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request->io_out = NULL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghercheckpassword_verify_plain(struct auth_request *request, const char *password,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher verify_plain_callback_t *callback)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct chkpw_auth_request *chkpw_auth_request;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher int fd_in[2], fd_out[2];
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher pid_t pid;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher fd_in[0] = -1;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (pipe(fd_in) < 0 || pipe(fd_out) < 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword(%s): pipe() failed: %m",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher get_log_prefix(request));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (fd_in[0] != -1) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher (void)close(fd_in[0]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher (void)close(fd_in[1]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher pid = fork();
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (pid == -1) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword(%s): fork() failed: %m",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher get_log_prefix(request));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher (void)close(fd_in[0]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher (void)close(fd_in[1]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher (void)close(fd_out[0]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher (void)close(fd_out[1]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (pid == 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher (void)close(fd_in[0]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher (void)close(fd_out[1]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_verify_plain_child(fd_in[1], fd_out[0]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (close(fd_in[1]) < 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword(%s): close(fd_in[1]) failed: %m",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher get_log_prefix(request));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (close(fd_out[0]) < 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword(%s): close(fd_out[0]) failed: %m",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher get_log_prefix(request));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher auth_request_ref(request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request = i_new(struct chkpw_auth_request, 1);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request->fd_in = fd_in[0];
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request->fd_out = fd_out[1];
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request->pid = pid;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request->password = i_strdup(password);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request->request = request;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request->callback = callback;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request->io_in =
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher io_add(fd_in[0], IO_READ, checkpassword_child_input,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request->io_out =
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher io_add(fd_out[1], IO_WRITE, checkpassword_child_output,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher hash_insert(clients, POINTER_CAST(pid), chkpw_auth_request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (to_wait == NULL) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* FIXME: we could use SIGCHLD */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher to_wait = timeout_add(1000, wait_timeout, NULL);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_init(const char *args)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_path = i_strdup(args);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_reply_path =
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_strdup(PKG_LIBEXECDIR"/checkpassword-reply");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher to_wait = NULL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher clients = hash_create(default_pool, default_pool, 0, NULL, NULL);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_deinit(void)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct hash_iterate_context *iter;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher void *key, *value;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher iter = hash_iterate_init(clients);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher while (hash_iterate(iter, &key, &value)) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_request_finish(value,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher PASSDB_RESULT_INTERNAL_FAILURE);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher hash_iterate_deinit(iter);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher hash_destroy(clients);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (to_wait != NULL)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher timeout_remove(to_wait);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_free(checkpassword_path);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_free(checkpassword_reply_path);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstruct passdb_module passdb_checkpassword = {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "checkpassword",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher NULL,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_init,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_deinit,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_verify_plain,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher NULL
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher};
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#endif
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher