passdb-checkpassword.c revision 3ccab0bac68040f179a7de45c516cec258e28fdb
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* Copyright (c) 2004-2008 Dovecot authors, see the included COPYING file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland const char *checkpassword_path, *checkpassword_reply_path;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic struct child_wait *checkpassword_passdb_children = NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void checkpassword_request_finish(struct chkpw_auth_request *request,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct passdb_module *_module = request->request->passdb->passdb;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct checkpassword_passdb_module *module =
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (struct checkpassword_passdb_module *)_module;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (verify_plain_callback_t *)request->callback;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland hash_table_remove(module->clients, POINTER_CAST(request->pid));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (strchr(str_c(request->input_buf), '\n') != NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "checkpassword",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "LF characters in checkpassword reply");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland t_strsplit(str_c(request->input_buf), "\t"),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandcheckpassword_request_half_finish(struct chkpw_auth_request *request)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!request->exited || request->fd_in != -1)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* vpopmail exit codes: */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland case 3: /* password fail / vpopmail user not found */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland case 20: /* invalid user/domain characters */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland case 22: /* system user shadow entry not found */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* standard checkpassword exit codes: */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* (1 is additionally defined in vpopmail for
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland auth_request_log_info(request->request, "checkpassword",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "Login failed (status=%d)",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland checkpassword_request_finish(request, PASSDB_RESULT_OK);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* missing input - fall through */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* checkpassword is called with wrong
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland parameters? unlikely */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* temporary problem, treat as internal error */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* whatever error.. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland auth_request_log_error(request->request, "checkpassword",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "Child %s exited with status %d",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland dec2str(request->pid), request->exit_status);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void sigchld_handler(const struct child_wait_status *status,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct checkpassword_passdb_module *module)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland hash_table_lookup(module->clients, POINTER_CAST(status->pid));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland switch (checkpassword_sigchld_handler(status, request)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland checkpassword_request_half_finish(request);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandcheckpassword_verify_plain_child(struct auth_request *request,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct checkpassword_passdb_module *module,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (dup2(fd_out, 3) < 0 || dup2(fd_in, 4) < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland auth_request_log_error(request, "checkpassword",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "dup2() failed: %m");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* very simple argument splitting. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland cmd = t_strconcat(module->checkpassword_path, " ",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland auth_request_log_debug(request, "checkpassword",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland auth_request_log_error(request, "checkpassword",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandcheckpassword_verify_plain(struct auth_request *request, const char *password,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct passdb_module *_module = request->passdb->passdb;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct checkpassword_passdb_module *module =
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (struct checkpassword_passdb_module *)_module;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct chkpw_auth_request *chkpw_auth_request;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland auth_request_log_error(request, "checkpassword",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "pipe() failed: %m");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland auth_request_log_error(request, "checkpassword",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "fork() failed: %m");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland checkpassword_verify_plain_child(request, module,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* not reached */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland auth_request_log_error(request, "checkpassword",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "close(fd_in[1]) failed: %m");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland auth_request_log_error(request, "checkpassword",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "close(fd_out[0]) failed: %m");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland chkpw_auth_request = i_new(struct chkpw_auth_request, 1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland chkpw_auth_request->password = i_strdup(password);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland chkpw_auth_request->internal_failure_code =
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland io_add(fd_in[0], IO_READ, checkpassword_child_input,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland io_add(fd_out[1], IO_WRITE, checkpassword_child_output,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland hash_table_insert(module->clients, POINTER_CAST(pid),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland child_wait_add_pid(checkpassword_passdb_children, pid);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland child_wait_new_with_pid(pid, sigchld_handler, module);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandcheckpassword_preinit(struct auth_passdb *auth_passdb, const char *args)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct checkpassword_passdb_module *module;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland module->checkpassword_path = p_strdup(auth_passdb->auth->pool, args);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland hash_table_create(default_pool, default_pool, 0, NULL, NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void checkpassword_deinit(struct passdb_module *_module)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct checkpassword_passdb_module *module =
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (struct checkpassword_passdb_module *)_module;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland iter = hash_table_iterate_init(module->clients);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while (hash_table_iterate(iter, &key, &value)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland child_wait_free(&checkpassword_passdb_children);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstruct passdb_module_interface passdb_checkpassword = {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "checkpassword",