[Dovecot] Help implementing username_format in auth PAM driver
lee at trager.us
lee at trager.us
Thu Apr 24 06:50:49 UTC 2014
While configuring my server with dovecot I noticed that the PAM
authentication driver does not support the username_format option as
does the password file driver. This didn't seem too hard to implement
so I through together a patch.
As you can see in the attached patch I only modify the username sent
to PAM. Despit doing this I run into the domain lost
issue(http://wiki2.dovecot.org/DomainLost). This prevents me from
using the domain name in my mail_location config string. What I don't
understand is why does changing the username string sent to PAM for
authentication trigger this issue? Shouldn't dovecot continue to use
the client supplied username as I am *not* changing it anywhere in my
config?
Thanks,
Lee
-------------- next part --------------
diff --git a/src/auth/passdb-pam.c b/src/auth/passdb-pam.c
index cf0b3c9..5f42a5a 100644
--- a/src/auth/passdb-pam.c
+++ b/src/auth/passdb-pam.c
@@ -37,6 +37,7 @@
typedef pam_const void *pam_item_t;
#define PASSDB_PAM_DEFAULT_MAX_REQUESTS 100
+#define PASSDB_PAM_DEFAULT_USERNAME_FORMAT "%u"
struct pam_passdb_module {
struct passdb_module module;
@@ -47,6 +48,7 @@ struct pam_passdb_module {
unsigned int pam_setcred:1;
unsigned int pam_session:1;
unsigned int failure_show_msg:1;
+ const char *username_format;
};
struct pam_conv_context {
@@ -55,6 +57,17 @@ struct pam_conv_context {
const char *failure_msg;
};
+inline const char*
+pam_username_lookup(struct auth_request *request)
+{
+ struct passdb_module *_module = request->passdb->passdb;
+ struct pam_passdb_module *module = (struct pam_passdb_module *)_module;
+ string_t *username = t_str_new(256);
+ var_expand(username, module->username_format,
+ auth_request_get_var_expand_table(request, auth_request_str_escape));
+ return str_c(username);
+}
+
static int
pam_userpass_conv(int num_msg, pam_const struct pam_message **msg,
struct pam_response **resp_r, void *appdata_ptr)
@@ -82,7 +95,7 @@ pam_userpass_conv(int num_msg, pam_const struct pam_message **msg,
case PAM_PROMPT_ECHO_ON:
/* Assume we're asking for user. We might not ever
get here because PAM already knows the user. */
- string = strdup(ctx->request->user);
+ string = strdup(pam_username_lookup(ctx->request));
if (string == NULL)
i_fatal_status(FATAL_OUTOFMEM, "Out of memory");
break;
@@ -240,7 +253,7 @@ static void set_pam_items(struct auth_request *request, pam_handle_t *pamh)
host = net_ip2addr(&request->remote_ip);
if (host != NULL)
(void)pam_set_item(pamh, PAM_RHOST, host);
- (void)pam_set_item(pamh, PAM_RUSER, request->user);
+ (void)pam_set_item(pamh, PAM_RUSER, pam_username_lookup(request));
/* TTY is needed by eg. pam_access module */
(void)pam_set_item(pamh, PAM_TTY, "dovecot");
}
@@ -262,7 +275,7 @@ pam_verify_plain_call(struct auth_request *request, const char *service,
ctx.request = request;
ctx.pass = password;
- status = pam_start(service, request->user, &conv, &pamh);
+ status = pam_start(service, pam_username_lookup(request), &conv, &pamh);
if (status != PAM_SUCCESS) {
auth_request_log_error(request, "pam", "pam_start() failed: %s",
pam_strerror(pamh, status));
@@ -331,6 +344,7 @@ pam_preinit(pool_t pool, const char *args)
{
struct pam_passdb_module *module;
const char *const *t_args;
+ const char *format = PASSDB_PAM_DEFAULT_USERNAME_FORMAT;
int i;
module = p_new(pool, struct pam_passdb_module, 1);
@@ -367,9 +381,14 @@ pam_preinit(pool_t pool, const char *args)
}
} else if (t_args[i+1] == NULL) {
module->service_name = p_strdup(pool, t_args[i]);
+ } else if (strncmp(t_args[i], "username_format=", 16) == 0) {
+ format = auth_cache_parse_key(pool, t_args[i] + 16);
} else {
i_fatal("pam: Unknown setting: %s", t_args[i]);
}
}
+
+ module->username_format = format;
+
return &module->module;
}
More information about the dovecot
mailing list