passdb-pam.c revision f153c0c2c4f52ecb93046bb33f5d951b6aac59fe
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/*
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Based on auth_pam.c from popa3d by Solar Designer <solar@openwall.com>.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen You're allowed to do whatever you like with this software (including
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen re-distribution in source and/or binary form, with or without
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen modification), provided that credit is given where it is due and any
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen modified versions are marked as such. There's absolutely no warranty.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen*/
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
463e82bdf0e990f4f2252d2b53ea23a5abe5883cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef PASSDB_PAM
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen#include "buffer.h"
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen#include "ioloop.h"
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen#include "network.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "passdb.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "mycrypt.h"
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen#include "safe-memset.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include <stdlib.h>
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include <fcntl.h>
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include <unistd.h>
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include <sys/wait.h>
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen#ifdef HAVE_SECURITY_PAM_APPL_H
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen# include <security/pam_appl.h>
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen#elif defined(HAVE_PAM_PAM_APPL_H)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen# include <pam/pam_appl.h>
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#endif
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#if !defined(_SECURITY_PAM_APPL_H) && !defined(LINUX_PAM) && !defined(_OPENPAM)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen/* Sun's PAM doesn't use const. we use a bit dirty hack to check it.
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen Originally it was just __sun__ check, but HP/UX also uses Sun's PAM
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen so I thought this might work better. */
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen# define linux_const
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#else
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen# define linux_const const
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#endif
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainentypedef linux_const void *pam_item_t;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#ifdef AUTH_PAM_USERPASS
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen# include <security/pam_client.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
c21c33a8c98972c45349066fc76ac9e2c05013c1Timo Sirainen# ifndef PAM_BP_RCONTROL
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen/* Linux-PAM prior to 0.74 */
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen# define PAM_BP_RCONTROL PAM_BP_CONTROL
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen# define PAM_BP_WDATA PAM_BP_DATA
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen# define PAM_BP_RDATA PAM_BP_DATA
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen# endif
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen# define USERPASS_AGENT_ID "userpass"
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen# define USERPASS_AGENT_ID_LENGTH 8
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen# define USERPASS_USER_MASK 0x03
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen# define USERPASS_USER_REQUIRED 1
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen# define USERPASS_USER_KNOWN 2
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen# define USERPASS_USER_FIXED 3
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen#endif
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainenstruct pam_passdb_module {
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen struct passdb_module module;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen bool pam_setcred, pam_session;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const char *service_name, *pam_cache_key;
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen struct timeout *to_wait;
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen};
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainenstruct pam_auth_request {
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen int fd;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct io *io;
538c58fc95200fcc5e91abdda8b912b574a2f968Timo Sirainen
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainen struct auth_request *request;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen verify_plain_callback_t *callback;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen};
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenstruct pam_userpass {
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen const char *user;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *pass;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen};
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenstatic int pam_userpass_conv(int num_msg, linux_const struct pam_message **msg,
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen struct pam_response **resp, void *appdata_ptr)
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen{
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen /* @UNSAFE */
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainen struct pam_userpass *userpass = (struct pam_userpass *) appdata_ptr;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen#ifdef AUTH_PAM_USERPASS
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen pamc_bp_t prompt;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *input;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen char *output;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen char flags;
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen size_t userlen, passlen;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen if (num_msg != 1 || msg[0]->msg_style != PAM_BINARY_PROMPT)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return PAM_CONV_ERR;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen prompt = (pamc_bp_t)msg[0]->msg;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen input = PAM_BP_RDATA(prompt);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (PAM_BP_RCONTROL(prompt) != PAM_BPC_SELECT ||
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen strncmp(input, USERPASS_AGENT_ID "/", USERPASS_AGENT_ID_LENGTH + 1))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return PAM_CONV_ERR;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen flags = input[USERPASS_AGENT_ID_LENGTH + 1];
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen input += USERPASS_AGENT_ID_LENGTH + 1 + 1;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if ((flags & USERPASS_USER_MASK) == USERPASS_USER_FIXED &&
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen strcmp(input, userpass->user))
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return PAM_CONV_AGAIN;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (!(*resp = malloc(sizeof(struct pam_response))))
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return PAM_CONV_ERR;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen userlen = strlen(userpass->user);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen passlen = strlen(userpass->pass);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen prompt = NULL;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen PAM_BP_RENEW(&prompt, PAM_BPC_DONE, userlen + 1 + passlen);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen output = PAM_BP_WDATA(prompt);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(output, userpass->user, userlen + 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(output + userlen + 1, userpass->pass, passlen);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen (*resp)[0].resp_retcode = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (*resp)[0].resp = (char *)prompt;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen#else
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen char *string;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen int i;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (!(*resp = malloc(num_msg * sizeof(struct pam_response))))
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return PAM_CONV_ERR;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen for (i = 0; i < num_msg; i++) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen switch (msg[i]->msg_style) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen case PAM_PROMPT_ECHO_ON:
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen string = strdup(userpass->user);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (string == NULL)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen i_fatal_status(FATAL_OUTOFMEM, "Out of memory");
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case PAM_PROMPT_ECHO_OFF:
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen string = strdup(userpass->pass);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (string == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal_status(FATAL_OUTOFMEM, "Out of memory");
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen break;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen case PAM_ERROR_MSG:
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen case PAM_TEXT_INFO:
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen string = NULL;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen break;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen default:
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen while (--i >= 0) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if ((*resp)[i].resp == NULL)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen continue;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen safe_memset((*resp)[i].resp, 0,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen strlen((*resp)[i].resp));
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen free((*resp)[i].resp);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen (*resp)[i].resp = NULL;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen free(*resp);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen *resp = NULL;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return PAM_CONV_ERR;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen (*resp)[i].resp_retcode = PAM_SUCCESS;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen (*resp)[i].resp = string;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen }
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen#endif
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return PAM_SUCCESS;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen
23079bf0a6e7489c5f542b0b897a71bdfd884a51Timo Sirainenstatic int pam_auth(struct auth_request *request,
23079bf0a6e7489c5f542b0b897a71bdfd884a51Timo Sirainen pam_handle_t *pamh, const char **error)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct passdb_module *_module = request->passdb->passdb;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct pam_passdb_module *module = (struct pam_passdb_module *)_module;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen void *item;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen int status;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen *error = NULL;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((status = pam_authenticate(pamh, 0)) != PAM_SUCCESS) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen *error = t_strdup_printf("pam_authenticate() failed: %s",
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen pam_strerror(pamh, status));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return status;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen#ifdef HAVE_PAM_SETCRED
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (module->pam_setcred) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if ((status = pam_setcred(pamh, PAM_ESTABLISH_CRED)) !=
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen PAM_SUCCESS) {
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen *error = t_strdup_printf("pam_setcred() failed: %s",
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen pam_strerror(pamh, status));
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen return status;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen }
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((status = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS) {
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen *error = t_strdup_printf("pam_acct_mgmt() failed: %s",
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen pam_strerror(pamh, status));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return status;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (module->pam_session) {
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen if ((status = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen *error = t_strdup_printf(
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen "pam_open_session() failed: %s",
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen pam_strerror(pamh, status));
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody return status;
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen }
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen if ((status = pam_close_session(pamh, 0)) != PAM_SUCCESS) {
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen *error = t_strdup_printf(
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen "pam_close_session() failed: %s",
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen pam_strerror(pamh, status));
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen return status;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen status = pam_get_item(pamh, PAM_USER, (linux_const void **)&item);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody if (status != PAM_SUCCESS) {
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody *error = t_strdup_printf("pam_get_item() failed: %s",
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody pam_strerror(pamh, status));
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody return status;
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody }
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody auth_request_set_field(request, "user", item, NULL);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody return PAM_SUCCESS;
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody}
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmodystatic void
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmodypam_verify_plain_child(struct auth_request *request, const char *service,
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody const char *password, int fd)
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody{
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody pam_handle_t *pamh;
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen struct pam_userpass userpass;
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen struct pam_conv conv;
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen enum passdb_result result;
070df93a3014ad4b2eb8754af65128c9f9a72e4ePhil Carmody int ret, status, status2;
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen const char *str;
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen size_t size;
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody buffer_t *buf;
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen
458b283a2f3db6e5aff20b4df1bbd18ada3900ddTimo Sirainen conv.conv = pam_userpass_conv;
458b283a2f3db6e5aff20b4df1bbd18ada3900ddTimo Sirainen conv.appdata_ptr = &userpass;
458b283a2f3db6e5aff20b4df1bbd18ada3900ddTimo Sirainen
458b283a2f3db6e5aff20b4df1bbd18ada3900ddTimo Sirainen userpass.user = request->user;
070df93a3014ad4b2eb8754af65128c9f9a72e4ePhil Carmody userpass.pass = password;
070df93a3014ad4b2eb8754af65128c9f9a72e4ePhil Carmody
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody status = pam_start(service, request->user, &conv, &pamh);
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody if (status != PAM_SUCCESS) {
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody result = PASSDB_RESULT_INTERNAL_FAILURE;
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody str = t_strdup_printf("pam_start() failed: %s",
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody pam_strerror(pamh, status));
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody } else {
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody const char *host = net_ip2addr(&request->remote_ip);
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmody /* Set some PAM items. They shouldn't fail, and we don't really
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody care if they do. */
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody if (host != NULL)
aba9cc9bf97576c0ca653d4e218567e617061029Phil Carmody (void)pam_set_item(pamh, PAM_RHOST, host);
aba9cc9bf97576c0ca653d4e218567e617061029Phil Carmody /* TTY is needed by eg. pam_access module */
aba9cc9bf97576c0ca653d4e218567e617061029Phil Carmody (void)pam_set_item(pamh, PAM_TTY, "dovecot");
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody status = pam_auth(request, pamh, &str);
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody if ((status2 = pam_end(pamh, status)) == PAM_SUCCESS) {
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmody /* FIXME: check for PASSDB_RESULT_UNKNOWN_USER
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmody somehow? */
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody result = status == PAM_SUCCESS ? PASSDB_RESULT_OK :
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody PASSDB_RESULT_PASSWORD_MISMATCH;
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody } else {
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody result = PASSDB_RESULT_INTERNAL_FAILURE;
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody str = t_strdup_printf("pam_end() failed: %s",
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody pam_strerror(pamh, status2));
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody }
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody }
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody buf = buffer_create_dynamic(pool_datastack_create(), 512);
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody buffer_append(buf, &result, sizeof(result));
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody if (str != NULL)
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody buffer_append(buf, str, strlen(str));
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody /* Don't send larger writes than what would block. truncated error
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody message isn't that bad.. */
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody size = I_MIN(buf->used, PIPE_BUF);
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody if ((ret = write(fd, buf->data, size)) != (int)size) {
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmody if (ret < 0)
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody i_error("write() failed: %m");
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody else {
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody i_error("write() failed: %d != %"PRIuSIZE_T,
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody ret, buf->used);
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody }
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody }
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody}
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainenstatic void pam_child_input(void *context)
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen{
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen struct pam_auth_request *request = context;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen struct auth_request *auth_request = request->request;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen enum passdb_result result;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen char buf[PIPE_BUF + 1];
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen ssize_t ret;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen /* POSIX guarantees that writing PIPE_BUF bytes or less to pipes is
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen atomic. We rely on that. */
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen ret = read(request->fd, buf, sizeof(buf)-1);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (ret < 0) {
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen auth_request_log_error(auth_request, "pam",
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen "read() from child process failed: %m");
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen result = PASSDB_RESULT_INTERNAL_FAILURE;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen } else if (ret == 0) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen /* it died */
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen auth_request_log_error(auth_request, "pam",
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen "Child process died");
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen result = PASSDB_RESULT_INTERNAL_FAILURE;
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen } else if ((size_t)ret < sizeof(result)) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen auth_request_log_error(auth_request, "pam",
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen "Child process returned only %d bytes", (int)ret);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen result = PASSDB_RESULT_INTERNAL_FAILURE;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen } else {
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen memcpy(&result, buf, sizeof(result));
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if ((size_t)ret > sizeof(result)) {
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen /* error message included */
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen buf[ret] = '\0';
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (result == PASSDB_RESULT_INTERNAL_FAILURE) {
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen auth_request_log_error(auth_request, "pam",
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen "%s", buf + sizeof(result));
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen } else {
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen auth_request_log_info(auth_request, "pam",
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen "%s", buf + sizeof(result));
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen io_remove(&request->io);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (close(request->fd) < 0) {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen auth_request_log_error(auth_request, "pam",
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen "close(child input) failed: %m");
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen request->callback(result, auth_request);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen auth_request_unref(&auth_request);
2b170a01b7e966c584fc7573034180d75b321d0dTimo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen i_free(request);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenstatic void wait_timeout(void *context)
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen{
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen struct pam_passdb_module *module = context;
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen int status;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen pid_t pid;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
76959d3d6fed45d5f5e1397fcdcf09a5adb87f24Timo Sirainen /* FIXME: if we ever do some other kind of forking, this needs fixing */
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen while ((pid = waitpid(-1, &status, WNOHANG)) != 0) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (pid == -1) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (errno == ECHILD)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen timeout_remove(&module->to_wait);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen else if (errno != EINTR)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen i_error("waitpid() failed: %m");
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (WIFSIGNALED(status)) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen i_error("PAM: Child %s died with signal %d",
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen dec2str(pid), WTERMSIG(status));
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainenstatic void
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenpam_verify_plain(struct auth_request *request, const char *password,
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen verify_plain_callback_t *callback)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen struct passdb_module *_module = request->passdb->passdb;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen struct pam_passdb_module *module = (struct pam_passdb_module *)_module;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen struct pam_auth_request *pam_auth_request;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen const char *service;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen int fd[2];
9887c39c5ba429169389153ca99de49e084a73f0Timo Sirainen pid_t pid;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen service = module->service_name != NULL ?
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen module->service_name : request->service;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (pipe(fd) < 0) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen auth_request_log_error(request, "pam", "pipe() failed: %m");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen pid = fork();
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (pid == -1) {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen auth_request_log_error(request, "pam", "fork() failed: %m");
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen callback(PASSDB_RESULT_INTERNAL_FAILURE, request);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen (void)close(fd[0]);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen (void)close(fd[1]);
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen return;
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen }
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (pid == 0) {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen (void)close(fd[0]);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen pam_verify_plain_child(request, service, password, fd[1]);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen _exit(0);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen }
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (close(fd[1]) < 0) {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen auth_request_log_error(request, "pam",
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen "close(fd[1]) failed: %m");
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen }
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen auth_request_ref(request);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen pam_auth_request = i_new(struct pam_auth_request, 1);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen pam_auth_request->fd = fd[0];
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen pam_auth_request->request = request;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen pam_auth_request->callback = callback;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
41bb0aa8e357876bc9a1916a37c9e3e78e5f8185Timo Sirainen pam_auth_request->io =
945565e0c9cf979b5feeba6fbd4efce3bf4484adTimo Sirainen io_add(fd[0], IO_READ, pam_child_input, pam_auth_request);
945565e0c9cf979b5feeba6fbd4efce3bf4484adTimo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (module->to_wait == NULL)
dd8de60250511cc729b67249e61dfc6b4debff11Timo Sirainen module->to_wait = timeout_add(1000, wait_timeout, module);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen}
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic struct passdb_module *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenpam_preinit(struct auth_passdb *auth_passdb, const char *args)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen struct pam_passdb_module *module;
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen const char *const *t_args;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int i;
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen module = p_new(auth_passdb->auth->pool, struct pam_passdb_module, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen module->service_name = "dovecot";
be8c8479f918875eda871c5685ab2b4067228e26Phil Carmody
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen t_push();
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen t_args = t_strsplit(args, " ");
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen for(i = 0; t_args[i] != NULL; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* -session for backwards compatibility */
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen if (strcmp(t_args[i], "-session") == 0 ||
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen strcmp(t_args[i], "session=yes") == 0)
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen module->pam_session = TRUE;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen else if (strcmp(t_args[i], "setcred=yes") == 0)
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen module->pam_setcred = TRUE;
41bb0aa8e357876bc9a1916a37c9e3e78e5f8185Timo Sirainen else if (strncmp(t_args[i], "cache_key=", 10) == 0) {
945565e0c9cf979b5feeba6fbd4efce3bf4484adTimo Sirainen module->module.cache_key =
945565e0c9cf979b5feeba6fbd4efce3bf4484adTimo Sirainen p_strdup(auth_passdb->auth->pool,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen t_args[i] + 10);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen } else if (strcmp(t_args[i], "*") == 0) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen module->service_name = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (t_args[i+1] == NULL) {
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen if (*t_args[i] != '\0') {
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen module->service_name =
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen p_strdup(auth_passdb->auth->pool,
be8c8479f918875eda871c5685ab2b4067228e26Phil Carmody t_args[i]);
be8c8479f918875eda871c5685ab2b4067228e26Phil Carmody }
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen } else {
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen i_fatal("Unexpected PAM parameter: %s", t_args[i]);
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen }
be8c8479f918875eda871c5685ab2b4067228e26Phil Carmody }
be8c8479f918875eda871c5685ab2b4067228e26Phil Carmody t_pop();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen return &module->module;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen}
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainenstatic void pam_deinit(struct passdb_module *_module)
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen{
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen struct pam_passdb_module *module = (struct pam_passdb_module *)_module;
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen if (module->to_wait != NULL)
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen timeout_remove(&module->to_wait);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstruct passdb_module_interface passdb_pam = {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen "pam",
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen pam_preinit,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen NULL,
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen pam_deinit,
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen pam_verify_plain,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen NULL
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen};
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen#endif
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen