passdb-checkpassword.c revision 1f1e81aab38d833d1c9cdc244c91fd762e0080d4
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic char *checkpassword_path, *checkpassword_reply_path;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_request_close(struct chkpw_auth_request *request)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: close() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: close() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_request_finish(struct chkpw_auth_request *request,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher hash_remove(clients, POINTER_CAST(request->pid));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* FIXME: store request->input_buf so userdb can fetch it */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher request->callback(result, request->request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher safe_memset(request->password, 0, strlen(request->password));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void wait_timeout(void *context __attr_unused__)
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 request = hash_lookup(clients, POINTER_CAST(pid));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: Child %s died with signal %d",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher } else if (WIFEXITED(status) && request != NULL) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* checkpassword is called with wrong
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher parameters? unlikely */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* temporary problem, treat as internal error */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* whatever error.. */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Child %s exited with status %d",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_verify_plain_child(int fd_in, int fd_out)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: dup2() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: dup2() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: execv(%s) failed: %m",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_child_input(void *context)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct chkpw_auth_request *request = context;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = read(request->fd_in, buf, sizeof(buf));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: read() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher buffer_append(request->input_buf, buf, ret);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_child_output(void *context)
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 const unsigned char *data;
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 i_error("checkpassword: output larger than 512 bytes: "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = write(request->fd_out, data + request->write_pos,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: write() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword: close() failed: %m");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghercheckpassword_verify_plain(struct auth_request *request, const char *password,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct chkpw_auth_request *chkpw_auth_request;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (pipe(fd_in) < 0 || pipe(fd_out) < 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword(%s): pipe() failed: %m",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword(%s): fork() failed: %m",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher checkpassword_verify_plain_child(fd_in[1], fd_out[0]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword(%s): close(fd_in[1]) failed: %m",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_error("checkpassword(%s): close(fd_out[0]) failed: %m",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request = i_new(struct chkpw_auth_request, 1);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher chkpw_auth_request->password = i_strdup(password);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher io_add(fd_in[0], IO_READ, checkpassword_child_input,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher io_add(fd_out[1], IO_WRITE, checkpassword_child_output,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher hash_insert(clients, POINTER_CAST(pid), chkpw_auth_request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* FIXME: we could use SIGCHLD */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher to_wait = timeout_add(1000, wait_timeout, NULL);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void checkpassword_init(const char *args)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher i_strdup(PKG_LIBEXECDIR"/checkpassword-reply");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher clients = hash_create(default_pool, default_pool, 0, NULL, NULL);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher while (hash_iterate(iter, &key, &value)) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstruct passdb_module passdb_checkpassword = {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "checkpassword",