passdb-pam.c revision 72fe7206d6a695fee2dc43c390b38e1d39b9b543
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/*
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Based on auth_pam.c from popa3d by Solar Designer <solar@openwall.com>.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen You're allowed to do whatever you like with this software (including
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen re-distribution in source and/or binary form, with or without
1171f0abf442638bac1827bb24a0b6b8eb682a82Timo Sirainen modification), provided that credit is given where it is due and any
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen modified versions are marked as such. There's absolutely no warranty.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen*/
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef PASSDB_PAM
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ioloop.h"
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen#include "network.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "passdb.h"
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen#include "mycrypt.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "safe-memset.h"
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen#include <stdlib.h>
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen#include <fcntl.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <unistd.h>
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen#include <sys/wait.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen#ifdef HAVE_SECURITY_PAM_APPL_H
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# include <security/pam_appl.h>
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen#elif defined(HAVE_PAM_PAM_APPL_H)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# include <pam/pam_appl.h>
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen#if !defined(_SECURITY_PAM_APPL_H) && !defined(LINUX_PAM) && !defined(_OPENPAM)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Sun's PAM doesn't use const. we use a bit dirty hack to check it.
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen Originally it was just __sun__ check, but HP/UX also uses Sun's PAM
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen so I thought this might work better. */
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen# define linux_const
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen#else
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen# define linux_const const
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainentypedef linux_const void *pam_item_t;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen#ifdef AUTH_PAM_USERPASS
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# include <security/pam_client.h>
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# ifndef PAM_BP_RCONTROL
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen/* Linux-PAM prior to 0.74 */
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen# define PAM_BP_RCONTROL PAM_BP_CONTROL
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen# define PAM_BP_WDATA PAM_BP_DATA
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# define PAM_BP_RDATA PAM_BP_DATA
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# endif
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen# define USERPASS_AGENT_ID "userpass"
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen# define USERPASS_AGENT_ID_LENGTH 8
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen# define USERPASS_USER_MASK 0x03
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen# define USERPASS_USER_REQUIRED 1
aff3354de83df9d683587e27461697193ff36591Timo Sirainen# define USERPASS_USER_KNOWN 2
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen# define USERPASS_USER_FIXED 3
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen#endif
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstruct pam_auth_request {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen int fd;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen struct io *io;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct auth_request *request;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen verify_plain_callback_t *callback;
44c5e644cb413a6559bf2d4179cbe48f9a82f366Timo Sirainen};
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstruct pam_userpass {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen const char *user;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen const char *pass;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen};
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
aff3354de83df9d683587e27461697193ff36591Timo Sirainenstatic int pam_session;
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainenstatic char *service_name;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainenstatic struct timeout *to_wait;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainenstatic int pam_userpass_conv(int num_msg, linux_const struct pam_message **msg,
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen struct pam_response **resp, void *appdata_ptr)
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen{
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen /* @UNSAFE */
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen struct pam_userpass *userpass = (struct pam_userpass *) appdata_ptr;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen#ifdef AUTH_PAM_USERPASS
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen pamc_bp_t prompt;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen const char *input;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen char *output;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char flags;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen size_t userlen, passlen;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen if (num_msg != 1 || msg[0]->msg_style != PAM_BINARY_PROMPT)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return PAM_CONV_ERR;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen prompt = (pamc_bp_t)msg[0]->msg;
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen input = PAM_BP_RDATA(prompt);
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (PAM_BP_RCONTROL(prompt) != PAM_BPC_SELECT ||
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen strncmp(input, USERPASS_AGENT_ID "/", USERPASS_AGENT_ID_LENGTH + 1))
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen return PAM_CONV_ERR;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen flags = input[USERPASS_AGENT_ID_LENGTH + 1];
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen input += USERPASS_AGENT_ID_LENGTH + 1 + 1;
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen if ((flags & USERPASS_USER_MASK) == USERPASS_USER_FIXED &&
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen strcmp(input, userpass->user))
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen return PAM_CONV_AGAIN;
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (!(*resp = malloc(sizeof(struct pam_response))))
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return PAM_CONV_ERR;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen userlen = strlen(userpass->user);
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen passlen = strlen(userpass->pass);
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen prompt = NULL;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen PAM_BP_RENEW(&prompt, PAM_BPC_DONE, userlen + 1 + passlen);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen output = PAM_BP_WDATA(prompt);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen memcpy(output, userpass->user, userlen + 1);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen memcpy(output + userlen + 1, userpass->pass, passlen);
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen (*resp)[0].resp_retcode = 0;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen (*resp)[0].resp = (char *)prompt;
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen#else
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen char *string;
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen int i;
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen if (!(*resp = malloc(num_msg * sizeof(struct pam_response))))
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen return PAM_CONV_ERR;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen for (i = 0; i < num_msg; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen switch (msg[i]->msg_style) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen case PAM_PROMPT_ECHO_ON:
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen string = strdup(userpass->user);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (string == NULL)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_fatal_status(FATAL_OUTOFMEM, "Out of memory");
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen break;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen case PAM_PROMPT_ECHO_OFF:
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen string = strdup(userpass->pass);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (string == NULL)
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen i_fatal_status(FATAL_OUTOFMEM, "Out of memory");
73a44af966c790560a72a0447f37bb35b1031a83Timo Sirainen break;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen case PAM_ERROR_MSG:
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen case PAM_TEXT_INFO:
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen string = NULL;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen break;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen default:
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen while (--i >= 0) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if ((*resp)[i].resp == NULL)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen continue;
02166e32bcda5d0018ae1a2a38614126ab5c6025Timo Sirainen safe_memset((*resp)[i].resp, 0,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen strlen((*resp)[i].resp));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen free((*resp)[i].resp);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen (*resp)[i].resp = NULL;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen free(*resp);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen *resp = NULL;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return PAM_CONV_ERR;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen (*resp)[i].resp_retcode = PAM_SUCCESS;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen (*resp)[i].resp = string;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen#endif
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return PAM_SUCCESS;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenstatic int pam_auth(struct auth_request *request,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen pam_handle_t *pamh, const char **error)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen{
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen void *item;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen int status;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen *error = NULL;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if ((status = pam_authenticate(pamh, 0)) != PAM_SUCCESS) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen *error = t_strdup_printf("pam_authenticate() failed: %s",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen pam_strerror(pamh, status));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return status;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen#ifdef HAVE_PAM_SETCRED
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if ((status = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen *error = t_strdup_printf("pam_setcred() failed: %s",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen pam_strerror(pamh, status));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return status;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
58febed28f2af78b2d8a281c851d9b67160c4bd3Timo Sirainen#endif
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if ((status = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen *error = t_strdup_printf("pam_acct_mgmt() failed: %s",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen pam_strerror(pamh, status));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return status;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (pam_session) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if ((status = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen *error = t_strdup_printf(
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen "pam_open_session() failed: %s",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen pam_strerror(pamh, status));
5e4f94015f5bbc9eefb1f2cb7af81ed50dcd2b39Timo Sirainen return status;
5e4f94015f5bbc9eefb1f2cb7af81ed50dcd2b39Timo Sirainen }
5e4f94015f5bbc9eefb1f2cb7af81ed50dcd2b39Timo Sirainen
5e4f94015f5bbc9eefb1f2cb7af81ed50dcd2b39Timo Sirainen if ((status = pam_close_session(pamh, 0)) != PAM_SUCCESS) {
5e4f94015f5bbc9eefb1f2cb7af81ed50dcd2b39Timo Sirainen *error = t_strdup_printf(
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen "pam_close_session() failed: %s",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen pam_strerror(pamh, status));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return status;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen status = pam_get_item(pamh, PAM_USER, (linux_const void **)&item);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (status != PAM_SUCCESS) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen *error = t_strdup_printf("pam_get_item() failed: %s",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen pam_strerror(pamh, status));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return status;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen auth_request_set_field(request, "user", item, NULL);
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return PAM_SUCCESS;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenstatic void
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenpam_verify_plain_child(struct auth_request *request, const char *service,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen const char *password, int fd)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen{
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen pam_handle_t *pamh;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen struct pam_userpass userpass;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct pam_conv conv;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen enum passdb_result result;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen int status, status2;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen const char *str;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen char buf_data[512];
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen buffer_t *buf;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen conv.conv = pam_userpass_conv;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen conv.appdata_ptr = &userpass;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen userpass.user = request->user;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen userpass.pass = password;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen status = pam_start(service, request->user, &conv, &pamh);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (status != PAM_SUCCESS) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen result = PASSDB_RESULT_INTERNAL_FAILURE;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen str = t_strdup_printf("pam_start() failed: %s",
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen pam_strerror(pamh, status));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen } else {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen#ifdef PAM_RHOST
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen const char *host = net_ip2addr(&request->remote_ip);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (host != NULL)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen pam_set_item(pamh, PAM_RHOST, host);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#endif
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen status = pam_auth(request, pamh, &str);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if ((status2 = pam_end(pamh, status)) == PAM_SUCCESS) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* FIXME: check for PASSDB_RESULT_UNKNOWN_USER
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen somehow? */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen result = status == PAM_SUCCESS ? PASSDB_RESULT_OK :
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen PASSDB_RESULT_PASSWORD_MISMATCH;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen } else {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen result = PASSDB_RESULT_INTERNAL_FAILURE;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen str = t_strdup_printf("pam_end() failed: %s",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen pam_strerror(pamh, status2));
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen buf = buffer_create_data(pool_datastack_create(),
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen buf_data, sizeof(buf_data));
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen buffer_append(buf, &result, sizeof(result));
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen if (str != NULL) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen /* may truncate the error. tough luck. */
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen buffer_append(buf, str, strlen(str));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen write(fd, buf_data, buffer_get_used_size(buf));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void pam_child_input(void *context)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen{
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen struct pam_auth_request *request = context;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen struct auth_request *auth_request = request->request;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen enum passdb_result result;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen char buf[513];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ssize_t ret;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen /* POSIX guarantees that writing 512 bytes or less to pipes is atomic.
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen We rely on that. */
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen ret = read(request->fd, buf, sizeof(buf)-1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret < 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen auth_request_log_error(auth_request, "pam",
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen "read() from child process failed: %m");
f65602dff8a85170176ddaa790db6df56006d132Timo Sirainen result = PASSDB_RESULT_INTERNAL_FAILURE;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen } else if (ret == 0) {
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen /* it died */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request_log_error(auth_request, "pam",
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen "Child process died");
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen result = PASSDB_RESULT_INTERNAL_FAILURE;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen } else if ((size_t)ret < sizeof(result)) {
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen auth_request_log_error(auth_request, "pam",
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen "Child process returned only %d bytes", ret);
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen result = PASSDB_RESULT_INTERNAL_FAILURE;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen } else {
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen memcpy(&result, buf, sizeof(result));
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if ((size_t)ret > sizeof(result)) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen /* error message included */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen buf[ret] = '\0';
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (result == PASSDB_RESULT_INTERNAL_FAILURE) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen auth_request_log_error(auth_request, "pam",
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen "%s", buf + sizeof(result));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen } else {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen auth_request_log_info(auth_request, "pam",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen "%s", buf + sizeof(result));
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (close(request->fd) < 0) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen auth_request_log_error(auth_request, "pam",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen "close(child input) failed: %m");
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (auth_request_unref(auth_request))
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen request->callback(result, auth_request);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen io_remove(request->io);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_free(request);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainenstatic void wait_timeout(void *context __attr_unused__)
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen{
1171f0abf442638bac1827bb24a0b6b8eb682a82Timo Sirainen int status;
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen pid_t pid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen /* FIXME: if we ever do some other kind of forking, this needs fixing */
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen while ((pid = waitpid(-1, &status, WNOHANG)) != 0) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (pid == -1) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (errno == ECHILD) {
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen timeout_remove(to_wait);
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen to_wait = NULL;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen } else if (errno != EINTR)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_error("waitpid() failed: %m");
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen return;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (WIFSIGNALED(status)) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_error("PAM: Child %s died with signal %d",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen dec2str(pid), WTERMSIG(status));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen}
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenstatic void
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenpam_verify_plain(struct auth_request *request, const char *password,
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen verify_plain_callback_t *callback)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen{
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen struct pam_auth_request *pam_auth_request;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen const char *service;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen int fd[2];
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen pid_t pid;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen service = service_name != NULL ? service_name : request->service;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (pipe(fd) < 0) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen auth_request_log_error(request, "pam", "pipe() failed: %m");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen pid = fork();
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (pid == -1) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen auth_request_log_error(request, "pam", "fork() failed: %m");
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen (void)close(fd[0]);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen (void)close(fd[1]);
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (pid == 0) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen (void)close(fd[0]);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen pam_verify_plain_child(request, service, password, fd[1]);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen _exit(0);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (close(fd[1]) < 0) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen auth_request_log_error(request, "pam",
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen "close(fd[1]) failed: %m");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen auth_request_ref(request);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen pam_auth_request = i_new(struct pam_auth_request, 1);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen pam_auth_request->fd = fd[0];
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen pam_auth_request->request = request;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen pam_auth_request->callback = callback;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen pam_auth_request->io =
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen io_add(fd[0], IO_READ, pam_child_input, pam_auth_request);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (to_wait == NULL)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen to_wait = timeout_add(1000, wait_timeout, NULL);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainenstatic void pam_init(const char *args)
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen{
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen const char *const *t_args;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen int i;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen pam_session = FALSE;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen service_name = i_strdup("dovecot");
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen t_push();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_args = t_strsplit(args, " ");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for(i = 0; t_args[i] != NULL; i++) {
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen if (strcmp(t_args[i], "-session") == 0)
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen pam_session = TRUE;
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen else if (strcmp(t_args[i], "*") == 0) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen i_free(service_name);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen service_name = NULL;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen } else {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (*t_args[i] != '\0') {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_free(service_name);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen service_name = i_strdup(t_args[i]);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen t_pop();
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen to_wait = NULL;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainenstatic void pam_deinit(void)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (to_wait != NULL)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen timeout_remove(to_wait);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen i_free(service_name);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen}
65a5fb2343f9870713bfca0b24abb58dcade605eTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstruct passdb_module passdb_pam = {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen "pam",
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen NULL, NULL, FALSE,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen NULL,
2a21435425c50514fa4d0708110a4ed7f0d85661Timo Sirainen pam_init,
2a21435425c50514fa4d0708110a4ed7f0d85661Timo Sirainen pam_deinit,
2a21435425c50514fa4d0708110a4ed7f0d85661Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen pam_verify_plain,
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen NULL
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen};
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#endif
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen