From 32cb0660d22f3799840a6a2a88ae4c17f65af3da Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 9 May 2000 11:43:00 +0000 Subject: brought the winbindd code into head this does not yet compile, but I'm working on that. (This used to be commit 3fb862531a4e78dca13d16d958517b16e5bdd4e2) --- source3/nsswitch/pam_winbind.c | 388 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 388 insertions(+) create mode 100644 source3/nsswitch/pam_winbind.c (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c new file mode 100644 index 0000000000..549d8c9a8a --- /dev/null +++ b/source3/nsswitch/pam_winbind.c @@ -0,0 +1,388 @@ +/* pam_winbind module + + Copyright Andrew Tridgell 2000 + + largely based on pam_userdb by Christian Gafton +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "pam_winbind" +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT +#include +#include + +#define PAM_DEBUG_ARG (1<<0) +#define PAM_USE_AUTHTOK_ARG (1<<1) +#define PAM_UNKNOWN_OK_ARG (1<<2) + +#include "ntdom_config.h" +#include "winbindd_ntdom.h" + +/* prototypes from common.c */ +void init_request(struct winbindd_request *req,int rq_type); +int write_sock(void *buffer, int count); +int read_reply(struct winbindd_response *response); + +/* some syslogging */ +static void _pam_log(int err, const char *format, ...) +{ + va_list args; + + va_start(args, format); + openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH); + vsyslog(err, format, args); + va_end(args); + closelog(); +} + +static int ctrl = 0; + +static int _pam_parse(int argc, const char **argv) +{ + /* step through arguments */ + for (ctrl = 0; argc-- > 0; ++argv) { + + /* generic options */ + + if (!strcmp(*argv,"debug")) + ctrl |= PAM_DEBUG_ARG; + else if (!strcasecmp(*argv, "use_authtok")) + ctrl |= PAM_USE_AUTHTOK_ARG; + else if (!strcasecmp(*argv, "unknown_ok")) + ctrl |= PAM_UNKNOWN_OK_ARG; + else { + _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); + } + } + + return ctrl; +} + + +/* talk to winbindd */ +static int winbind_request(int req_type, const char *user, const char *pass) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + + strncpy(request.data.auth.user, user, sizeof(request.data.auth.user)-1); + strncpy(request.data.auth.pass, pass, sizeof(request.data.auth.pass)-1); + + /* Fill in request and send down pipe */ + init_request(&request, req_type); + + if (write_sock(&request, sizeof(request)) == -1) { + return -2; + } + + /* Wait for reply */ + if (read_reply(&response) == -1) { + return -2; + } + + /* Copy reply data from socket */ + if (response.result != WINBINDD_OK) { + return 1; + } + + return 0; +} + +/* + * Looks up an user name and checks the password + * + * return values: + * 1 = User not found + * 0 = OK + * -1 = Password incorrect + * -2 = System error + */ +static int user_lookup(const char *user, const char *pass) +{ + return winbind_request(WINBINDD_PAM_AUTH, user, pass); +} + +/* + * Checks if a user has an account + * + * return values: + * 1 = User not found + * 0 = OK + * -1 = System error + */ +static int valid_user(const char *user) +{ + if (getpwnam(user)) return 0; + return 1; +} + +/* --- authentication management functions --- */ + +/* + * dummy conversation function sending exactly one prompt + * and expecting exactly one response from the other party + */ +static int converse(pam_handle_t *pamh, + struct pam_message **message, + struct pam_response **response) +{ + int retval; + struct pam_conv *conv; + + retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ) ; + if (retval == PAM_SUCCESS) + retval = conv->conv(1, (const struct pam_message **)message, + response, conv->appdata_ptr); + + return retval; /* propagate error status */ +} + + +static char *_pam_delete(register char *xx) +{ + _pam_overwrite(xx); + _pam_drop(xx); + return NULL; +} + +/* + * This is a conversation function to obtain the user's password + */ +static int conversation(pam_handle_t *pamh) +{ + struct pam_message msg[2],*pmsg[2]; + struct pam_response *resp; + int retval; + char * token; + + pmsg[0] = &msg[0]; + msg[0].msg_style = PAM_PROMPT_ECHO_OFF; + msg[0].msg = "Password: "; + + /* so call the conversation expecting i responses */ + resp = NULL; + retval = converse(pamh, pmsg, &resp); + + if (resp != NULL) { + char * const item; + /* interpret the response */ + if (retval == PAM_SUCCESS) { /* a good conversation */ + token = x_strdup(resp[0].resp); + if (token == NULL) { + return PAM_AUTHTOK_RECOVER_ERR; + } + } + + /* set the auth token */ + retval = pam_set_item(pamh, PAM_AUTHTOK, token); + token = _pam_delete(token); /* clean it up */ + if ( (retval != PAM_SUCCESS) || + (retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &item)) != PAM_SUCCESS ) { + return retval; + } + + _pam_drop_reply(resp, 1); + } else { + retval = (retval == PAM_SUCCESS) + ? PAM_AUTHTOK_RECOVER_ERR:retval ; + } + + return retval; +} + + +PAM_EXTERN +int pam_sm_authenticate(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + const char *username; + const char *password; + int retval = PAM_AUTH_ERR; + + /* parse arguments */ + ctrl = _pam_parse(argc, argv); + + /* Get the username */ + retval = pam_get_user(pamh, &username, NULL); + if ((retval != PAM_SUCCESS) || (!username)) { + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_DEBUG,"can not get the username"); + return PAM_SERVICE_ERR; + } + + if ((ctrl & PAM_USE_AUTHTOK_ARG) == 0) { + /* Converse just to be sure we have the password */ + retval = conversation(pamh); + if (retval != PAM_SUCCESS) { + _pam_log(LOG_ERR, "could not obtain password for `%s'", + username); + return PAM_CONV_ERR; + } + } + + /* Get the password */ + retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &password); + if (retval != PAM_SUCCESS) { + _pam_log(LOG_ERR, "Could not retrive user's password"); + return PAM_AUTHTOK_ERR; + } + + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_INFO, "Verify user `%s' with password `%s'", + username, password); + + /* Now use the username to look up password */ + retval = user_lookup(username, password); + switch (retval) { + case -2: + /* some sort of system error. The log was already printed */ + return PAM_SERVICE_ERR; + case -1: + /* incorrect password */ + _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", username); + return PAM_AUTH_ERR; + case 1: + /* the user does not exist */ + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_NOTICE, "user `%s' not found", + username); + if (ctrl & PAM_UNKNOWN_OK_ARG) { + return PAM_IGNORE; + } + return PAM_USER_UNKNOWN; + case 0: + /* Otherwise, the authentication looked good */ + _pam_log(LOG_NOTICE, "user '%s' granted acces", username); + return PAM_SUCCESS; + default: + /* we don't know anything about this return value */ + _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s'", + retval, username); + return PAM_SERVICE_ERR; + } + /* should not be reached */ + return PAM_IGNORE; +} + +PAM_EXTERN +int pam_sm_setcred(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + return PAM_SUCCESS; +} + +/* + * Account management. We want to verify that the account exists + * before returning PAM_SUCCESS + */ +PAM_EXTERN +int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + const char *username; + int retval = PAM_USER_UNKNOWN; + + /* parse arguments */ + ctrl = _pam_parse(argc, argv); + + /* Get the username */ + retval = pam_get_user(pamh, &username, NULL); + if ((retval != PAM_SUCCESS) || (!username)) { + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_DEBUG,"can not get the username"); + return PAM_SERVICE_ERR; + } + + /* Verify the username */ + retval = valid_user(username); + switch (retval) { + case -1: + /* some sort of system error. The log was already printed */ + return PAM_SERVICE_ERR; + case 1: + /* the user does not exist */ + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_NOTICE, "user `%s' not found", + username); + if (ctrl & PAM_UNKNOWN_OK_ARG) + return PAM_IGNORE; + return PAM_USER_UNKNOWN; + case 0: + /* Otherwise, the authentication looked good */ + _pam_log(LOG_NOTICE, "user '%s' granted acces", username); + return PAM_SUCCESS; + default: + /* we don't know anything about this return value */ + _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s'", + retval, username); + return PAM_SERVICE_ERR; + } + + /* should not be reached */ + return PAM_IGNORE; +} + + +#ifdef PAM_STATIC + +/* static module data */ + +struct pam_module _pam_userdb_modstruct = { + MODULE_NAME, + pam_sm_authenticate, + pam_sm_setcred, + pam_sm_acct_mgmt, + NULL, + NULL, + NULL, +}; + +#endif + +/* + * Copyright (c) Andrew Tridgell 2000 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ -- cgit From 4f21301ea65886f3ad73706ea63d06912d899ad1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 May 2000 14:17:21 +0000 Subject: in head as well ... renamed ntdom to winbind I think that using winbind in /etc/nsswitch.conf is better than ntdom (This used to be commit 80f85b5359c26dc26f8f88b984f27cfa4ac34e61) --- source3/nsswitch/pam_winbind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 549d8c9a8a..ece504411b 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -26,8 +26,8 @@ #define PAM_USE_AUTHTOK_ARG (1<<1) #define PAM_UNKNOWN_OK_ARG (1<<2) -#include "ntdom_config.h" -#include "winbindd_ntdom.h" +#include "winbind_nss_config.h" +#include "winbindd_nss.h" /* prototypes from common.c */ void init_request(struct winbindd_request *req,int rq_type); -- cgit From 401b3cc7a7a4994df073e6435a60ad7f22ae62e4 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 4 May 2001 00:43:20 +0000 Subject: Merge from TNG branch. (This used to be commit 1e7b1c71b9c409859bcf0aeb3d5785acc4aee027) --- source3/nsswitch/pam_winbind.c | 240 +++++++++++++++++++++++++++++++---------- 1 file changed, 183 insertions(+), 57 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index ece504411b..b3dea202c2 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -5,29 +5,7 @@ largely based on pam_userdb by Christian Gafton */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MODULE_NAME "pam_winbind" -#define PAM_SM_AUTH -#define PAM_SM_ACCOUNT -#include -#include - -#define PAM_DEBUG_ARG (1<<0) -#define PAM_USE_AUTHTOK_ARG (1<<1) -#define PAM_UNKNOWN_OK_ARG (1<<2) - -#include "winbind_nss_config.h" -#include "winbindd_nss.h" +#include "pam_winbind.h" /* prototypes from common.c */ void init_request(struct winbindd_request *req,int rq_type); @@ -69,38 +47,78 @@ static int _pam_parse(int argc, const char **argv) return ctrl; } - -/* talk to winbindd */ -static int winbind_request(int req_type, const char *user, const char *pass) +static int winbind_request(enum winbindd_cmd req_type, + struct winbindd_request *request, + struct winbindd_response *response) { - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - - strncpy(request.data.auth.user, user, sizeof(request.data.auth.user)-1); - strncpy(request.data.auth.pass, pass, sizeof(request.data.auth.pass)-1); - /* Fill in request and send down pipe */ - init_request(&request, req_type); + init_request(request, req_type); - if (write_sock(&request, sizeof(request)) == -1) { + if (write_sock(request, sizeof(*request)) == -1) { return -2; } /* Wait for reply */ - if (read_reply(&response) == -1) { + if (read_reply(response) == -1) { return -2; } /* Copy reply data from socket */ - if (response.result != WINBINDD_OK) { + if (response->result != WINBINDD_OK) { return 1; } return 0; } +/* talk to winbindd */ +static int winbind_auth_request(const char *user, const char *pass) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + + strncpy(request.data.auth.user, user, + sizeof(request.data.auth.user)-1); + + strncpy(request.data.auth.pass, pass, + sizeof(request.data.auth.pass)-1); + + return winbind_request(WINBINDD_PAM_AUTH, &request, &response); +} + +/* talk to winbindd */ +static int winbind_chauthtok_request(const char *user, const char *oldpass, + const char *newpass) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + + if (request.data.chauthtok.user == NULL) return -2; + + strncpy(request.data.chauthtok.user, user, + sizeof(request.data.chauthtok.user) - 1); + + if (oldpass != NULL) { + strncpy(request.data.chauthtok.oldpass, oldpass, + sizeof(request.data.chauthtok.oldpass) - 1); + } else { + request.data.chauthtok.oldpass[0] = '\0'; + } + + if (newpass != NULL) { + strncpy(request.data.chauthtok.newpass, newpass, + sizeof(request.data.chauthtok.newpass) - 1); + } else { + request.data.chauthtok.newpass[0] = '\0'; + } + + return winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response); +} + /* * Looks up an user name and checks the password * @@ -112,7 +130,7 @@ static int winbind_request(int req_type, const char *user, const char *pass) */ static int user_lookup(const char *user, const char *pass) { - return winbind_request(WINBINDD_PAM_AUTH, user, pass); + return winbind_auth_request(user, pass); } /* @@ -131,11 +149,9 @@ static int valid_user(const char *user) /* --- authentication management functions --- */ -/* - * dummy conversation function sending exactly one prompt - * and expecting exactly one response from the other party - */ -static int converse(pam_handle_t *pamh, +/* Attempt a conversation */ + +static int converse(pam_handle_t *pamh, int nargs, struct pam_message **message, struct pam_response **response) { @@ -143,9 +159,10 @@ static int converse(pam_handle_t *pamh, struct pam_conv *conv; retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ) ; - if (retval == PAM_SUCCESS) - retval = conv->conv(1, (const struct pam_message **)message, + if (retval == PAM_SUCCESS) { + retval = conv->conv(nargs, (const struct pam_message **)message, response, conv->appdata_ptr); + } return retval; /* propagate error status */ } @@ -161,20 +178,20 @@ static char *_pam_delete(register char *xx) /* * This is a conversation function to obtain the user's password */ -static int conversation(pam_handle_t *pamh) +static int auth_conversation(pam_handle_t *pamh) { - struct pam_message msg[2],*pmsg[2]; + struct pam_message msg, *pmsg; struct pam_response *resp; int retval; - char * token; + char * token = NULL; - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_PROMPT_ECHO_OFF; - msg[0].msg = "Password: "; + pmsg = &msg; + msg.msg_style = PAM_PROMPT_ECHO_OFF; + msg.msg = "Password: "; /* so call the conversation expecting i responses */ resp = NULL; - retval = converse(pamh, pmsg, &resp); + retval = converse(pamh, 1, &pmsg, &resp); if (resp != NULL) { char * const item; @@ -203,7 +220,6 @@ static int conversation(pam_handle_t *pamh) return retval; } - PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) @@ -225,7 +241,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, if ((ctrl & PAM_USE_AUTHTOK_ARG) == 0) { /* Converse just to be sure we have the password */ - retval = conversation(pamh); + retval = auth_conversation(pamh); if (retval != PAM_SUCCESS) { _pam_log(LOG_ERR, "could not obtain password for `%s'", username); @@ -336,24 +352,134 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, } +PAM_EXTERN +int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + int retval; + char *newpw, *oldpw; + const char *user; + + /* Get name of a user */ + + retval = pam_get_user(pamh, &user, "Username: "); + + if (retval != PAM_SUCCESS) { + return retval; + } + + /* XXX check in domain format */ + + /* Perform preliminary check and store requested password for updating + later on */ + + if (flags & PAM_PRELIM_CHECK) { + struct pam_message msg[3], *pmsg[3]; + struct pam_response *resp; + + /* Converse to ensure we have the current password */ + + retval = auth_conversation(pamh); + + if (retval != PAM_SUCCESS) { + return retval; + } + + /* Obtain and verify current password */ + + pmsg[0] = &msg[0]; + msg[0].msg_style = PAM_TEXT_INFO; + msg[0].msg = "Changing password for user %s"; + + pmsg[1] = &msg[1]; + msg[1].msg_style = PAM_PROMPT_ECHO_OFF; + msg[1].msg = "New NT password: "; + + pmsg[2] = &msg[2]; + msg[2].msg_style = PAM_PROMPT_ECHO_OFF; + msg[2].msg = "Retype new NT password: "; + + resp = NULL; + + retval = converse(pamh, 3, pmsg, &resp); + + if (resp != NULL) { + + if (retval == PAM_SUCCESS) { + + /* Check password entered correctly */ + + if (strcmp(resp[1].resp, resp[2].resp) != 0) { + struct pam_response *resp2; + + msg[0].msg_style = PAM_ERROR_MSG; + msg[0].msg = "Sorry, passwords do not match"; + + converse(pamh, 1, pmsg, &resp2); + + _pam_drop_reply(resp, 3); + _pam_drop_reply(resp2, 1); + + return PAM_AUTHTOK_RECOVER_ERR; + } + + /* Store passwords */ + + retval = pam_set_item(pamh, PAM_OLDAUTHTOK, resp[1].resp); + _pam_drop_reply(resp, 3); + } + } + + /* XXX What happens if root? */ + /* XXX try first pass and use first pass args */ + + return retval; + } + + if (flags & PAM_UPDATE_AUTHTOK) { + + retval = pam_get_item(pamh, PAM_OLDAUTHTOK, (const void **)&newpw); + if (retval != PAM_SUCCESS) { + return PAM_AUTHTOK_ERR; + } + + retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&oldpw); + if (retval != PAM_SUCCESS) { + return PAM_AUTHTOK_ERR; + } + + fprintf(stderr, "oldpw = %s, newpw = %s\n", oldpw, newpw); + + if (retval == PAM_SUCCESS && + winbind_chauthtok_request(user, oldpw, newpw) == 0) { + return PAM_SUCCESS; + } + + return PAM_AUTHTOK_ERR; + } + + return PAM_SERVICE_ERR; +} + #ifdef PAM_STATIC /* static module data */ -struct pam_module _pam_userdb_modstruct = { +struct pam_module _pam_winbind_modstruct = { MODULE_NAME, pam_sm_authenticate, pam_sm_setcred, pam_sm_acct_mgmt, NULL, NULL, - NULL, + pam_sm_chauthtok }; #endif /* * Copyright (c) Andrew Tridgell 2000 + * Copyright (c) Tim Potter 2000 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions -- cgit From 105e35a6e45188bd3a253c2df5cdd14ee9bfe53c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 7 Jan 2002 02:57:06 +0000 Subject: Don't log the password in pam_sm_authenticate() unless DEBUG_PASSWORD is defined. This is done with --enable-developer mode. (This used to be commit caff5dc1d66953cb52f94cd6407778b23e1810eb) --- source3/nsswitch/pam_winbind.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index b3dea202c2..7cb2cd8bf1 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -256,10 +256,18 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, return PAM_AUTHTOK_ERR; } - if (ctrl & PAM_DEBUG_ARG) + if (ctrl & PAM_DEBUG_ARG) { + + /* Let's not give too much away in the log file */ + +#ifdef DEBUG_PASSWORD _pam_log(LOG_INFO, "Verify user `%s' with password `%s'", username, password); - +#else + _pam_log(LOG_INFO, "Verify user `%s'", username); +#endif + } + /* Now use the username to look up password */ retval = user_lookup(username, password); switch (retval) { -- cgit From 4b9839c58a99cb17cd891c6490e7d194f0311b81 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 30 Jan 2002 03:14:20 +0000 Subject: Removed silly fprintf(stderr, ...) debug. Part of Samuel Ziegler's patch to get winbind password changing working again in HEAD. (This used to be commit b5540bee7be957d1def62ee85a84488e0250624b) --- source3/nsswitch/pam_winbind.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 7cb2cd8bf1..ab4cb7712b 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1,6 +1,7 @@ /* pam_winbind module Copyright Andrew Tridgell 2000 + Copyright Tim Potter 2000 largely based on pam_userdb by Christian Gafton */ @@ -456,8 +457,6 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, return PAM_AUTHTOK_ERR; } - fprintf(stderr, "oldpw = %s, newpw = %s\n", oldpw, newpw); - if (retval == PAM_SUCCESS && winbind_chauthtok_request(user, oldpw, newpw) == 0) { return PAM_SUCCESS; -- cgit From ed389ee8dc9246b2d6c4e483cee16f7255b9a7f5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 5 Feb 2002 09:40:36 +0000 Subject: Drastic impromvents to pam_winbind. This adds code to do generic PAM -> NTSTATUS and NTSTATUS -> PAM error conversions, and uses them to make the error handling in pam_winbind sane. In particular, pam_winbind now uses PAM error codes, not silly '-1, -2 ...' stuff, and logs the NTSTATUS error that winbind now sends over the pipe. Added code to wbinfo to display these - makes a big difference in debugging winbindd. The main change here is the code to allow pam_winbind password changing to correctly stack - This code ripped from pam_unix, and the copyright attached. (Same as for all pam modules, including pam_winbind) Andrew Bartlett (This used to be commit dc1a72f896b83bc1ad3c7bf6c12c36ace3967280) --- source3/nsswitch/pam_winbind.c | 684 ++++++++++++++++++++++++++--------------- 1 file changed, 439 insertions(+), 245 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index ab4cb7712b..cc259ab041 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -2,8 +2,11 @@ Copyright Andrew Tridgell 2000 Copyright Tim Potter 2000 + Copyright Andrew Bartlettt 2002 largely based on pam_userdb by Christian Gafton + also contains large slabs of code from pam_unix by Elliot Lee + (see copyright below for full details) */ #include "pam_winbind.h" @@ -13,6 +16,10 @@ void init_request(struct winbindd_request *req,int rq_type); int write_sock(void *buffer, int count); int read_reply(struct winbindd_response *response); +/* data tokens */ + +#define MAX_PASSWD_TRIES 3 + /* some syslogging */ static void _pam_log(int err, const char *format, ...) { @@ -25,27 +32,71 @@ static void _pam_log(int err, const char *format, ...) closelog(); } -static int ctrl = 0; - static int _pam_parse(int argc, const char **argv) { - /* step through arguments */ - for (ctrl = 0; argc-- > 0; ++argv) { - - /* generic options */ - - if (!strcmp(*argv,"debug")) - ctrl |= PAM_DEBUG_ARG; - else if (!strcasecmp(*argv, "use_authtok")) - ctrl |= PAM_USE_AUTHTOK_ARG; - else if (!strcasecmp(*argv, "unknown_ok")) - ctrl |= PAM_UNKNOWN_OK_ARG; - else { - _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); - } - } + int ctrl; + /* step through arguments */ + for (ctrl = 0; argc-- > 0; ++argv) { + + /* generic options */ + + if (!strcmp(*argv,"debug")) + ctrl |= WINBIND_DEBUG_ARG; + else if (!strcasecmp(*argv, "use_authtok")) + ctrl |= WINBIND_USE_AUTHTOK_ARG; + else if (!strcasecmp(*argv, "use_first_pass")) + ctrl |= WINBIND_TRY_FIRST_PASS_ARG; + else if (!strcasecmp(*argv, "try_first_pass")) + ctrl |= WINBIND_USE_FIRST_PASS_ARG; + else if (!strcasecmp(*argv, "unknown_ok")) + ctrl |= WINBIND_UNKNOWN_OK_ARG; + else { + _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); + } + } + + return ctrl; +} + +/* --- authentication management functions --- */ + +/* Attempt a conversation */ - return ctrl; +static int converse(pam_handle_t *pamh, int nargs, + struct pam_message **message, + struct pam_response **response) +{ + int retval; + struct pam_conv *conv; + + retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ) ; + if (retval == PAM_SUCCESS) { + retval = conv->conv(nargs, (const struct pam_message **)message, + response, conv->appdata_ptr); + } + + return retval; /* propagate error status */ +} + + +int _make_remark(pam_handle_t * pamh, int type, const char *text) +{ + int retval = PAM_SUCCESS; + + struct pam_message *pmsg[1], msg[1]; + struct pam_response *resp; + + pmsg[0] = &msg[0]; + msg[0].msg = text; + msg[0].msg_style = type; + + resp = NULL; + retval = converse(pamh, 1, pmsg, &resp); + + if (resp) { + _pam_drop_reply(resp, 1); + } + return retval; } static int winbind_request(enum winbindd_cmd req_type, @@ -56,27 +107,38 @@ static int winbind_request(enum winbindd_cmd req_type, init_request(request, req_type); if (write_sock(request, sizeof(*request)) == -1) { - return -2; + _pam_log(LOG_ERR, "write to socket failed!"); + return PAM_SERVICE_ERR; } /* Wait for reply */ if (read_reply(response) == -1) { - return -2; + _pam_log(LOG_ERR, "read from socket failed!"); + return PAM_SERVICE_ERR; } /* Copy reply data from socket */ if (response->result != WINBINDD_OK) { - return 1; + if (response->data.auth.pam_error != PAM_SUCCESS) { + _pam_log(LOG_ERR, "request failed, PAM error was %d, NT error was %s", + response->data.auth.pam_error, + response->data.auth.nt_status_string); + return response->data.auth.pam_error; + } else { + _pam_log(LOG_ERR, "request failed, but PAM error 0!"); + return PAM_SERVICE_ERR; + } } - return 0; + return PAM_SUCCESS; } /* talk to winbindd */ -static int winbind_auth_request(const char *user, const char *pass) +static int winbind_auth_request(const char *user, const char *pass, int ctrl) { struct winbindd_request request; struct winbindd_response response; + int retval; ZERO_STRUCT(request); @@ -86,7 +148,33 @@ static int winbind_auth_request(const char *user, const char *pass) strncpy(request.data.auth.pass, pass, sizeof(request.data.auth.pass)-1); - return winbind_request(WINBINDD_PAM_AUTH, &request, &response); + retval = winbind_request(WINBINDD_PAM_AUTH, &request, &response); + + switch (retval) { + case PAM_AUTH_ERR: + /* incorrect password */ + _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", user); + return retval; + case PAM_USER_UNKNOWN: + /* the user does not exist */ + if (ctrl & WINBIND_DEBUG_ARG) + _pam_log(LOG_NOTICE, "user `%s' not found", + user); + if (ctrl & WINBIND_UNKNOWN_OK_ARG) { + return PAM_IGNORE; + } + return retval; + case PAM_SUCCESS: + /* Otherwise, the authentication looked good */ + _pam_log(LOG_NOTICE, "user '%s' granted acces", user); + return retval; + default: + /* we don't know anything about this return value */ + _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s'", + retval, user); + return retval; + } + /* should not be reached */ } /* talk to winbindd */ @@ -120,20 +208,6 @@ static int winbind_chauthtok_request(const char *user, const char *oldpass, return winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response); } -/* - * Looks up an user name and checks the password - * - * return values: - * 1 = User not found - * 0 = OK - * -1 = Password incorrect - * -2 = System error - */ -static int user_lookup(const char *user, const char *pass) -{ - return winbind_auth_request(user, pass); -} - /* * Checks if a user has an account * @@ -148,27 +222,6 @@ static int valid_user(const char *user) return 1; } -/* --- authentication management functions --- */ - -/* Attempt a conversation */ - -static int converse(pam_handle_t *pamh, int nargs, - struct pam_message **message, - struct pam_response **response) -{ - int retval; - struct pam_conv *conv; - - retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ) ; - if (retval == PAM_SUCCESS) { - retval = conv->conv(nargs, (const struct pam_message **)message, - response, conv->appdata_ptr); - } - - return retval; /* propagate error status */ -} - - static char *_pam_delete(register char *xx) { _pam_overwrite(xx); @@ -177,48 +230,157 @@ static char *_pam_delete(register char *xx) } /* - * This is a conversation function to obtain the user's password + * obtain a password from the user */ -static int auth_conversation(pam_handle_t *pamh) + +int _winbind_read_password(pam_handle_t * pamh + ,unsigned int ctrl + ,const char *comment + ,const char *prompt1 + ,const char *prompt2 + ,const char **pass) { - struct pam_message msg, *pmsg; - struct pam_response *resp; - int retval; - char * token = NULL; - - pmsg = &msg; - msg.msg_style = PAM_PROMPT_ECHO_OFF; - msg.msg = "Password: "; - - /* so call the conversation expecting i responses */ - resp = NULL; - retval = converse(pamh, 1, &pmsg, &resp); - - if (resp != NULL) { - char * const item; - /* interpret the response */ - if (retval == PAM_SUCCESS) { /* a good conversation */ - token = x_strdup(resp[0].resp); - if (token == NULL) { - return PAM_AUTHTOK_RECOVER_ERR; - } + int authtok_flag; + int retval; + const char *item; + char *token; + + D(("called")); + + /* + * make sure nothing inappropriate gets returned + */ + + *pass = token = NULL; + + /* + * which authentication token are we getting? + */ + + authtok_flag = on(WINBIND__OLD_PASSWORD, ctrl) ? PAM_OLDAUTHTOK : PAM_AUTHTOK; + + /* + * should we obtain the password from a PAM item ? + */ + + if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { + retval = pam_get_item(pamh, authtok_flag, (const void **) &item); + if (retval != PAM_SUCCESS) { + /* very strange. */ + _pam_log(LOG_ALERT, + "pam_get_item returned error to unix-read-password" + ); + return retval; + } else if (item != NULL) { /* we have a password! */ + *pass = item; + item = NULL; + return PAM_SUCCESS; + } else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { + return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ + } else if (on(WINBIND_USE_AUTHTOK_ARG, ctrl) + && off(WINBIND__OLD_PASSWORD, ctrl)) { + return PAM_AUTHTOK_RECOVER_ERR; + } + } + /* + * getting here implies we will have to get the password from the + * user directly. + */ + + { + struct pam_message msg[3], *pmsg[3]; + struct pam_response *resp; + int i, replies; + + /* prepare to converse */ + + if (comment != NULL) { + pmsg[0] = &msg[0]; + msg[0].msg_style = PAM_TEXT_INFO; + msg[0].msg = comment; + i = 1; + } else { + i = 0; + } + + pmsg[i] = &msg[i]; + msg[i].msg_style = PAM_PROMPT_ECHO_OFF; + msg[i++].msg = prompt1; + replies = 1; + + if (prompt2 != NULL) { + pmsg[i] = &msg[i]; + msg[i].msg_style = PAM_PROMPT_ECHO_OFF; + msg[i++].msg = prompt2; + ++replies; + } + /* so call the conversation expecting i responses */ + resp = NULL; + retval = converse(pamh, i, pmsg, &resp); + + if (resp != NULL) { + + /* interpret the response */ + + if (retval == PAM_SUCCESS) { /* a good conversation */ + + token = x_strdup(resp[i - replies].resp); + if (token != NULL) { + if (replies == 2) { + + /* verify that password entered correctly */ + if (!resp[i - 1].resp + || strcmp(token, resp[i - 1].resp)) { + _pam_delete(token); /* mistyped */ + retval = PAM_AUTHTOK_RECOVER_ERR; + _make_remark(pamh ,PAM_ERROR_MSG, MISTYPED_PASS); + } + } + } else { + _pam_log(LOG_NOTICE + ,"could not recover authentication token"); + } + + } + /* + * tidy up the conversation (resp_retcode) is ignored + * -- what is it for anyway? AGM + */ + + _pam_drop_reply(resp, i); + + } else { + retval = (retval == PAM_SUCCESS) + ? PAM_AUTHTOK_RECOVER_ERR : retval; + } } - /* set the auth token */ - retval = pam_set_item(pamh, PAM_AUTHTOK, token); - token = _pam_delete(token); /* clean it up */ - if ( (retval != PAM_SUCCESS) || - (retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &item)) != PAM_SUCCESS ) { - return retval; + if (retval != PAM_SUCCESS) { + if (on(WINBIND_DEBUG_ARG, ctrl)) + _pam_log(LOG_DEBUG, + "unable to obtain a password"); + return retval; } + /* 'token' is the entered password */ + + /* we store this password as an item */ - _pam_drop_reply(resp, 1); - } else { - retval = (retval == PAM_SUCCESS) - ? PAM_AUTHTOK_RECOVER_ERR:retval ; - } + retval = pam_set_item(pamh, authtok_flag, token); + _pam_delete(token); /* clean it up */ + if (retval != PAM_SUCCESS + || (retval = pam_get_item(pamh, authtok_flag + ,(const void **) &item)) + != PAM_SUCCESS) { + + _pam_log(LOG_CRIT, "error manipulating password"); + return retval; + + } - return retval; + *pass = item; + item = NULL; /* break link to password */ + + return PAM_SUCCESS; } PAM_EXTERN @@ -230,34 +392,26 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int retval = PAM_AUTH_ERR; /* parse arguments */ - ctrl = _pam_parse(argc, argv); + int ctrl = _pam_parse(argc, argv); /* Get the username */ retval = pam_get_user(pamh, &username, NULL); if ((retval != PAM_SUCCESS) || (!username)) { - if (ctrl & PAM_DEBUG_ARG) + if (ctrl & WINBIND_DEBUG_ARG) _pam_log(LOG_DEBUG,"can not get the username"); return PAM_SERVICE_ERR; } - if ((ctrl & PAM_USE_AUTHTOK_ARG) == 0) { - /* Converse just to be sure we have the password */ - retval = auth_conversation(pamh); - if (retval != PAM_SUCCESS) { - _pam_log(LOG_ERR, "could not obtain password for `%s'", - username); - return PAM_CONV_ERR; - } - } + retval = _winbind_read_password(pamh, ctrl, NULL, + "Password: ", NULL, + &password); - /* Get the password */ - retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &password); if (retval != PAM_SUCCESS) { _pam_log(LOG_ERR, "Could not retrive user's password"); return PAM_AUTHTOK_ERR; } - if (ctrl & PAM_DEBUG_ARG) { + if (ctrl & WINBIND_DEBUG_ARG) { /* Let's not give too much away in the log file */ @@ -270,36 +424,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, } /* Now use the username to look up password */ - retval = user_lookup(username, password); - switch (retval) { - case -2: - /* some sort of system error. The log was already printed */ - return PAM_SERVICE_ERR; - case -1: - /* incorrect password */ - _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", username); - return PAM_AUTH_ERR; - case 1: - /* the user does not exist */ - if (ctrl & PAM_DEBUG_ARG) - _pam_log(LOG_NOTICE, "user `%s' not found", - username); - if (ctrl & PAM_UNKNOWN_OK_ARG) { - return PAM_IGNORE; - } - return PAM_USER_UNKNOWN; - case 0: - /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted acces", username); - return PAM_SUCCESS; - default: - /* we don't know anything about this return value */ - _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s'", - retval, username); - return PAM_SERVICE_ERR; - } - /* should not be reached */ - return PAM_IGNORE; + return winbind_auth_request(username, password, ctrl); } PAM_EXTERN @@ -321,12 +446,12 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int retval = PAM_USER_UNKNOWN; /* parse arguments */ - ctrl = _pam_parse(argc, argv); + int ctrl = _pam_parse(argc, argv); /* Get the username */ retval = pam_get_user(pamh, &username, NULL); if ((retval != PAM_SUCCESS) || (!username)) { - if (ctrl & PAM_DEBUG_ARG) + if (ctrl & WINBIND_DEBUG_ARG) _pam_log(LOG_DEBUG,"can not get the username"); return PAM_SERVICE_ERR; } @@ -339,10 +464,10 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, return PAM_SERVICE_ERR; case 1: /* the user does not exist */ - if (ctrl & PAM_DEBUG_ARG) + if (ctrl & WINBIND_DEBUG_ARG) _pam_log(LOG_NOTICE, "user `%s' not found", username); - if (ctrl & PAM_UNKNOWN_OK_ARG) + if (ctrl & WINBIND_UNKNOWN_OK_ARG) return PAM_IGNORE; return PAM_USER_UNKNOWN; case 0: @@ -361,111 +486,174 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, } -PAM_EXTERN -int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, - const char **argv) +PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + int argc, const char **argv) { - int retval; - char *newpw, *oldpw; - const char *user; - - /* Get name of a user */ - - retval = pam_get_user(pamh, &user, "Username: "); - - if (retval != PAM_SUCCESS) { - return retval; - } - - /* XXX check in domain format */ - - /* Perform preliminary check and store requested password for updating - later on */ - - if (flags & PAM_PRELIM_CHECK) { - struct pam_message msg[3], *pmsg[3]; - struct pam_response *resp; - - /* Converse to ensure we have the current password */ - - retval = auth_conversation(pamh); - - if (retval != PAM_SUCCESS) { - return retval; - } - - /* Obtain and verify current password */ - - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_TEXT_INFO; - msg[0].msg = "Changing password for user %s"; + unsigned int lctrl; + int retval; + unsigned int ctrl = _pam_parse(argc, argv); - pmsg[1] = &msg[1]; - msg[1].msg_style = PAM_PROMPT_ECHO_OFF; - msg[1].msg = "New NT password: "; + /* */ + const char *user; + char *pass_old, *pass_new; + /* */ - pmsg[2] = &msg[2]; - msg[2].msg_style = PAM_PROMPT_ECHO_OFF; - msg[2].msg = "Retype new NT password: "; - - resp = NULL; - - retval = converse(pamh, 3, pmsg, &resp); - - if (resp != NULL) { - - if (retval == PAM_SUCCESS) { - - /* Check password entered correctly */ - - if (strcmp(resp[1].resp, resp[2].resp) != 0) { - struct pam_response *resp2; - - msg[0].msg_style = PAM_ERROR_MSG; - msg[0].msg = "Sorry, passwords do not match"; - - converse(pamh, 1, pmsg, &resp2); - - _pam_drop_reply(resp, 3); - _pam_drop_reply(resp2, 1); - - return PAM_AUTHTOK_RECOVER_ERR; - } - - /* Store passwords */ - - retval = pam_set_item(pamh, PAM_OLDAUTHTOK, resp[1].resp); - _pam_drop_reply(resp, 3); - } - } - - /* XXX What happens if root? */ - /* XXX try first pass and use first pass args */ - - return retval; - } - - if (flags & PAM_UPDATE_AUTHTOK) { - - retval = pam_get_item(pamh, PAM_OLDAUTHTOK, (const void **)&newpw); - if (retval != PAM_SUCCESS) { - return PAM_AUTHTOK_ERR; - } - - retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&oldpw); - if (retval != PAM_SUCCESS) { - return PAM_AUTHTOK_ERR; - } - - if (retval == PAM_SUCCESS && - winbind_chauthtok_request(user, oldpw, newpw) == 0) { - return PAM_SUCCESS; - } - - return PAM_AUTHTOK_ERR; - } + char *Announce; + + int retry = 0; + + D(("called.")); + + /* + * First get the name of a user + */ + retval = pam_get_user(pamh, &user, "Username: "); + if (retval == PAM_SUCCESS) { + if (user == NULL) { + _pam_log(LOG_ERR, "username was NULL!"); + return PAM_USER_UNKNOWN; + } + if (retval == PAM_SUCCESS && on(WINBIND_DEBUG_ARG, ctrl)) + _pam_log(LOG_DEBUG, "username [%s] obtained", + user); + } else { + if (on(WINBIND_DEBUG_ARG, ctrl)) + _pam_log(LOG_DEBUG, + "password - could not identify user"); + return retval; + } - return PAM_SERVICE_ERR; + D(("Got username of %s", user)); + + /* + * obtain and verify the current password (OLDAUTHTOK) for + * the user. + */ + + if (flags & PAM_PRELIM_CHECK) { + D(("prelim check")); + + /* instruct user what is happening */ +#define greeting "Changing password for " + Announce = (char *) malloc(sizeof(greeting) + strlen(user)); + if (Announce == NULL) { + _pam_log(LOG_CRIT, + "password - out of memory"); + return PAM_BUF_ERR; + } + (void) strcpy(Announce, greeting); + (void) strcpy(Announce + sizeof(greeting) - 1, user); +#undef greeting + + lctrl = ctrl | WINBIND__OLD_PASSWORD; + retval = _winbind_read_password(pamh, lctrl + ,Announce + ,"(current) NT password: " + ,NULL + ,(const char **) &pass_old); + free(Announce); + + if (retval != PAM_SUCCESS) { + _pam_log(LOG_NOTICE + ,"password - (old) token not obtained"); + return retval; + } + /* verify that this is the password for this user */ + + retval = winbind_auth_request(user, pass_old, ctrl); + + if (retval != PAM_ACCT_EXPIRED + && retval != PAM_NEW_AUTHTOK_REQD + && retval != PAM_SUCCESS) { + D(("Authentication failed")); + pass_old = NULL; + return retval; + } + + retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); + pass_old = NULL; + if (retval != PAM_SUCCESS) { + _pam_log(LOG_CRIT, + "failed to set PAM_OLDAUTHTOK"); + } + } else if (flags & PAM_UPDATE_AUTHTOK) { + + /* + * obtain the proposed password + */ + + D(("do update")); + + /* + * get the old token back. + */ + + retval = pam_get_item(pamh, PAM_OLDAUTHTOK + ,(const void **) &pass_old); + D(("pass_old [%s]", pass_old)); + + if (retval != PAM_SUCCESS) { + _pam_log(LOG_NOTICE, "user not authenticated"); + return retval; + } + + D(("get new password now")); + + lctrl = ctrl; + + if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { + ctrl = WINBIND_USE_FIRST_PASS_ARG | lctrl; + } + retry = 0; + retval = PAM_AUTHTOK_ERR; + while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { + /* + * use_authtok is to force the use of a previously entered + * password -- needed for pluggable password strength checking + */ + + retval = _winbind_read_password(pamh, lctrl + ,NULL + ,"Enter new NT password: " + ,"Retype new NT password: " + ,(const char **) &pass_new); + + if (retval != PAM_SUCCESS) { + if (on(WINBIND_DEBUG_ARG, ctrl)) { + _pam_log(LOG_ALERT + ,"password - new password not obtained"); + } + pass_old = NULL;/* tidy up */ + return retval; + } + D(("returned to main routine")); + + /* + * At this point we know who the user is and what they + * propose as their new password. Verify that the new + * password is acceptable. + */ + + if (pass_new[0] == '\0') {/* "\0" password = NULL */ + pass_new = NULL; + } + } + + /* + * By reaching here we have approved the passwords and must now + * rebuild the password database file. + */ + + retval = winbind_chauthtok_request(user, pass_old, pass_new); + _pam_overwrite(pass_new); + _pam_overwrite(pass_old); + pass_old = pass_new = NULL; + } else { + retval = PAM_SERVICE_ERR; + } + + D(("retval was %d", retval)); + return retval; } #ifdef PAM_STATIC @@ -485,8 +673,14 @@ struct pam_module _pam_winbind_modstruct = { #endif /* - * Copyright (c) Andrew Tridgell 2000 - * Copyright (c) Tim Potter 2000 + * Copyright (c) Andrew Tridgell 2000 + * Copyright (c) Tim Potter 2000 + * Copyright (c) Andrew Bartlettt 2002 + * Copyright (c) Jan Rêkorajski 1999. + * Copyright (c) Andrew G. Morgan 1996-8. + * Copyright (c) Alex O. Yuriev, 1996. + * Copyright (c) Cristian Gafton 1996. + * Copyright (C) Elliot Lee 1996, Red Hat Software. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions -- cgit From 40976c3bc606197c001ed497f8e9e5c2ad49056c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 11 Mar 2002 23:59:20 +0000 Subject: Removed bogus calles to D() debugging function. Perhaps these should be replaced by DEBUG() calls? (This used to be commit 33dd07d1fc6946e53d3bdaad025adfc20abfab77) --- source3/nsswitch/pam_winbind.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index cc259ab041..7de553da4d 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -245,8 +245,6 @@ int _winbind_read_password(pam_handle_t * pamh const char *item; char *token; - D(("called")); - /* * make sure nothing inappropriate gets returned */ @@ -502,8 +500,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, int retry = 0; - D(("called.")); - /* * First get the name of a user */ @@ -523,15 +519,12 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, return retval; } - D(("Got username of %s", user)); - /* * obtain and verify the current password (OLDAUTHTOK) for * the user. */ if (flags & PAM_PRELIM_CHECK) { - D(("prelim check")); /* instruct user what is happening */ #define greeting "Changing password for " @@ -565,7 +558,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (retval != PAM_ACCT_EXPIRED && retval != PAM_NEW_AUTHTOK_REQD && retval != PAM_SUCCESS) { - D(("Authentication failed")); pass_old = NULL; return retval; } @@ -582,23 +574,18 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * obtain the proposed password */ - D(("do update")); - /* * get the old token back. */ retval = pam_get_item(pamh, PAM_OLDAUTHTOK ,(const void **) &pass_old); - D(("pass_old [%s]", pass_old)); if (retval != PAM_SUCCESS) { _pam_log(LOG_NOTICE, "user not authenticated"); return retval; } - D(("get new password now")); - lctrl = ctrl; if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { @@ -626,8 +613,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, pass_old = NULL;/* tidy up */ return retval; } - D(("returned to main routine")); - + /* * At this point we know who the user is and what they * propose as their new password. Verify that the new @@ -652,7 +638,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, retval = PAM_SERVICE_ERR; } - D(("retval was %d", retval)); return retval; } -- cgit From 0ecd78fb8c6604b49f9673168d09e3f4ce16a859 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 13 Mar 2002 01:26:59 +0000 Subject: Fix typo in copyright (This used to be commit 54e69ed20adc74fdfe007a9642dcb3a55c02d856) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 7de553da4d..42cc29f320 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -2,7 +2,7 @@ Copyright Andrew Tridgell 2000 Copyright Tim Potter 2000 - Copyright Andrew Bartlettt 2002 + Copyright Andrew Bartlett 2002 largely based on pam_userdb by Christian Gafton also contains large slabs of code from pam_unix by Elliot Lee -- cgit From 657a24f476c90e0ffa8171f78b35a449171f54e1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 23 Mar 2002 08:28:19 +0000 Subject: Various winbind updates: - pam_winbind updates from vance, fixing a typo and making some the options work properly. - Extra parinoia in the winbind connection loop - Allow pam_winbind to compile on HP-UX (Don Mcall, more work to do). - Fix up configure.in to use the same method for building the test .so as the Makefile uses. Andrew Bartlett (This used to be commit 8e705dd9215b1cb3f44d6348094679d7dc6a7fbd) --- source3/nsswitch/pam_winbind.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 42cc29f320..cad75f7907 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -45,9 +45,9 @@ static int _pam_parse(int argc, const char **argv) else if (!strcasecmp(*argv, "use_authtok")) ctrl |= WINBIND_USE_AUTHTOK_ARG; else if (!strcasecmp(*argv, "use_first_pass")) - ctrl |= WINBIND_TRY_FIRST_PASS_ARG; - else if (!strcasecmp(*argv, "try_first_pass")) ctrl |= WINBIND_USE_FIRST_PASS_ARG; + else if (!strcasecmp(*argv, "try_first_pass")) + ctrl |= WINBIND_TRY_FIRST_PASS_ARG; else if (!strcasecmp(*argv, "unknown_ok")) ctrl |= WINBIND_UNKNOWN_OK_ARG; else { @@ -405,7 +405,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, &password); if (retval != PAM_SUCCESS) { - _pam_log(LOG_ERR, "Could not retrive user's password"); + _pam_log(LOG_ERR, "Could not retrieve user's password"); return PAM_AUTHTOK_ERR; } -- cgit From 6a0def755915f9cfa528625dc3899f4f939ba327 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 3 Apr 2002 21:39:01 +0000 Subject: More winbind for HPUX updates from Don Mccall. I think JRA has already applied these to 2.2. Andrew Bartlett (This used to be commit 51fe3324dda6b1f9a9a45deda7a76b1fff35399a) --- source3/nsswitch/pam_winbind.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index cad75f7907..b192a347f4 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -482,6 +482,27 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, /* should not be reached */ return PAM_IGNORE; } +PAM_EXTERN +int pam_sm_open_session(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + /* parse arguments */ + int ctrl = _pam_parse(argc, argv); + if (ctrl & WINBIND_DEBUG_ARG) + _pam_log(LOG_DEBUG,"libpam_winbind:pam_sm_open_session handler"); + return PAM_SUCCESS; +} +PAM_EXTERN +int pam_sm_close_session(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + /* parse arguments */ + int ctrl = _pam_parse(argc, argv); + if (ctrl & WINBIND_DEBUG_ARG) + _pam_log(LOG_DEBUG,"libpam_winbind:pam_sm_close_session handler"); + return PAM_SUCCESS; +} + PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, @@ -650,8 +671,8 @@ struct pam_module _pam_winbind_modstruct = { pam_sm_authenticate, pam_sm_setcred, pam_sm_acct_mgmt, - NULL, - NULL, + pam_sm_open_session, + pam_sm_close_session, pam_sm_chauthtok }; -- cgit From e90b65284812aaa5ff9e9935ce9bbad7791cbbcd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Jul 2002 10:35:28 +0000 Subject: updated the 3.0 branch from the head branch - ready for alpha18 (This used to be commit 03ac082dcb375b6f3ca3d810a6a6367542bc23ce) --- source3/nsswitch/pam_winbind.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index b192a347f4..4739cfbf7a 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -155,6 +155,14 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl) /* incorrect password */ _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", user); return retval; + case PAM_ACCT_EXPIRED: + /* account expired */ + _pam_log(LOG_WARNING, "user `%s' account expired", user); + return retval; + case PAM_AUTHTOK_EXPIRED: + /* password expired */ + _pam_log(LOG_WARNING, "user `%s' password expired", user); + return retval; case PAM_USER_UNKNOWN: /* the user does not exist */ if (ctrl & WINBIND_DEBUG_ARG) @@ -577,6 +585,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, retval = winbind_auth_request(user, pass_old, ctrl); if (retval != PAM_ACCT_EXPIRED + && retval != PAM_AUTHTOK_EXPIRED && retval != PAM_NEW_AUTHTOK_REQD && retval != PAM_SUCCESS) { pass_old = NULL; -- cgit From b2edf254eda92f775e7d3d9b6793b4d77f9000b6 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 17 Aug 2002 17:00:51 +0000 Subject: sync 3.0 branch with head (This used to be commit 3928578b52cfc949be5e0ef444fce1558d75f290) --- source3/nsswitch/pam_winbind.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 4739cfbf7a..29ceca4e79 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -79,7 +79,7 @@ static int converse(pam_handle_t *pamh, int nargs, } -int _make_remark(pam_handle_t * pamh, int type, const char *text) +static int _make_remark(pam_handle_t * pamh, int type, const char *text) { int retval = PAM_SUCCESS; @@ -163,6 +163,10 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl) /* password expired */ _pam_log(LOG_WARNING, "user `%s' password expired", user); return retval; + case PAM_NEW_AUTHTOK_REQD: + /* password expired */ + _pam_log(LOG_WARNING, "user `%s' new password required", user); + return retval; case PAM_USER_UNKNOWN: /* the user does not exist */ if (ctrl & WINBIND_DEBUG_ARG) @@ -241,12 +245,12 @@ static char *_pam_delete(register char *xx) * obtain a password from the user */ -int _winbind_read_password(pam_handle_t * pamh - ,unsigned int ctrl - ,const char *comment - ,const char *prompt1 - ,const char *prompt2 - ,const char **pass) +static int _winbind_read_password(pam_handle_t * pamh + ,unsigned int ctrl + ,const char *comment + ,const char *prompt1 + ,const char *prompt2 + ,const char **pass) { int authtok_flag; int retval; -- cgit From a834a73e341059be154426390304a42e4a011f72 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 25 Sep 2002 15:19:00 +0000 Subject: sync'ing up for 3.0alpha20 release (This used to be commit 65e7b5273bb58802bf0c389b77f7fcae0a1f6139) --- source3/nsswitch/pam_winbind.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 29ceca4e79..f95caefb4c 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -11,11 +11,6 @@ #include "pam_winbind.h" -/* prototypes from common.c */ -void init_request(struct winbindd_request *req,int rq_type); -int write_sock(void *buffer, int count); -int read_reply(struct winbindd_response *response); - /* data tokens */ #define MAX_PASSWD_TRIES 3 @@ -99,24 +94,30 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text) return retval; } -static int winbind_request(enum winbindd_cmd req_type, - struct winbindd_request *request, - struct winbindd_response *response) +static int pam_winbind_request(enum winbindd_cmd req_type, + struct winbindd_request *request, + struct winbindd_response *response) { + /* Fill in request and send down pipe */ init_request(request, req_type); if (write_sock(request, sizeof(*request)) == -1) { _pam_log(LOG_ERR, "write to socket failed!"); + close_sock(); return PAM_SERVICE_ERR; } /* Wait for reply */ if (read_reply(response) == -1) { _pam_log(LOG_ERR, "read from socket failed!"); + close_sock(); return PAM_SERVICE_ERR; } + /* We are done with the socket - close it and avoid mischeif */ + close_sock(); + /* Copy reply data from socket */ if (response->result != WINBINDD_OK) { if (response->data.auth.pam_error != PAM_SUCCESS) { @@ -148,7 +149,7 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl) strncpy(request.data.auth.pass, pass, sizeof(request.data.auth.pass)-1); - retval = winbind_request(WINBINDD_PAM_AUTH, &request, &response); + retval = pam_winbind_request(WINBINDD_PAM_AUTH, &request, &response); switch (retval) { case PAM_AUTH_ERR: @@ -217,7 +218,7 @@ static int winbind_chauthtok_request(const char *user, const char *oldpass, request.data.chauthtok.newpass[0] = '\0'; } - return winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response); + return pam_winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response); } /* -- cgit From 35ac9d287f000c27dc864789b341bebe7acb4c74 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 26 Oct 2002 02:20:59 +0000 Subject: Try to catch up on the code I've put into HEAD that should be in 3.0: - vorlan's hosts allow with DNS names patch - use x_fileno() in debug.c, not the struct directly. - check for server timeout on password change (was reporting success) - better error/status loggin in both the pam_winbind client and winbindd_pam server code. - (pdb_ldap) don't set the ldap version twice - we do it on every bind anyway. (This used to be commit 9fa1863d8e7788eda83911ca2610754486b33069) --- source3/nsswitch/pam_winbind.c | 56 ++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 19 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index f95caefb4c..7d0353664f 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -134,22 +134,15 @@ static int pam_winbind_request(enum winbindd_cmd req_type, return PAM_SUCCESS; } -/* talk to winbindd */ -static int winbind_auth_request(const char *user, const char *pass, int ctrl) +static int pam_winbind_request_log(enum winbindd_cmd req_type, + struct winbindd_request *request, + struct winbindd_response *response, + int ctrl, + const char *user) { - struct winbindd_request request; - struct winbindd_response response; int retval; - ZERO_STRUCT(request); - - strncpy(request.data.auth.user, user, - sizeof(request.data.auth.user)-1); - - strncpy(request.data.auth.pass, pass, - sizeof(request.data.auth.pass)-1); - - retval = pam_winbind_request(WINBINDD_PAM_AUTH, &request, &response); + retval = pam_winbind_request(req_type, request, response); switch (retval) { case PAM_AUTH_ERR: @@ -178,8 +171,16 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl) } return retval; case PAM_SUCCESS: - /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted acces", user); + if (req_type == WINBINDD_PAM_AUTH) { + /* Otherwise, the authentication looked good */ + _pam_log(LOG_NOTICE, "user '%s' granted acces", user); + } else if (req_type == WINBINDD_PAM_CHAUTHTOK) { + /* Otherwise, the authentication looked good */ + _pam_log(LOG_NOTICE, "user '%s' password changed", user); + } else { + /* Otherwise, the authentication looked good */ + _pam_log(LOG_NOTICE, "user '%s' OK", user); + } return retval; default: /* we don't know anything about this return value */ @@ -187,12 +188,29 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl) retval, user); return retval; } - /* should not be reached */ +} + +/* talk to winbindd */ +static int winbind_auth_request(const char *user, const char *pass, int ctrl) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + + strncpy(request.data.auth.user, user, + sizeof(request.data.auth.user)-1); + + strncpy(request.data.auth.pass, pass, + sizeof(request.data.auth.pass)-1); + + + return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user); } /* talk to winbindd */ static int winbind_chauthtok_request(const char *user, const char *oldpass, - const char *newpass) + const char *newpass, int ctrl) { struct winbindd_request request; struct winbindd_response response; @@ -218,7 +236,7 @@ static int winbind_chauthtok_request(const char *user, const char *oldpass, request.data.chauthtok.newpass[0] = '\0'; } - return pam_winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response); + return pam_winbind_request_log(WINBINDD_PAM_CHAUTHTOK, &request, &response, ctrl, user); } /* @@ -665,7 +683,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * rebuild the password database file. */ - retval = winbind_chauthtok_request(user, pass_old, pass_new); + retval = winbind_chauthtok_request(user, pass_old, pass_new, ctrl); _pam_overwrite(pass_new); _pam_overwrite(pass_old); pass_old = pass_new = NULL; -- cgit From 99cdb462083381c88689a4e698ca48b6ed4cf5ac Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 15 Jan 2003 18:57:41 +0000 Subject: *lots of small merges form HEAD *sync up configure.in *don't build torture tools in make all *make sure to remove torture tools as part of make clean (This used to be commit 0fb724b3216eeeb97e61ff12755ca3a31bcad6ef) --- source3/nsswitch/pam_winbind.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 7d0353664f..123f670366 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -121,7 +121,8 @@ static int pam_winbind_request(enum winbindd_cmd req_type, /* Copy reply data from socket */ if (response->result != WINBINDD_OK) { if (response->data.auth.pam_error != PAM_SUCCESS) { - _pam_log(LOG_ERR, "request failed, PAM error was %d, NT error was %s", + _pam_log(LOG_ERR, "request failed: %s, PAM error was %d, NT error was %s", + response->data.auth.error_string, response->data.auth.pam_error, response->data.auth.nt_status_string); return response->data.auth.pam_error; -- cgit From 33b2bc49306fcac00e7b38fa5c402c6568493938 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 18 Aug 2004 16:25:41 +0000 Subject: r1888: Bring the same level of "required_membership"-functionality that ntlm_auth uses, to pam_winbindd as well. This allows to make successfull authentication via PAM dependent on SID-membership. At the moment, both ntlm_auth and pam_winbindd.so accept user/group-names or sid-strings - as discussed, recursive membership (e.g. local aliases) will be added later. Guenther (This used to be commit 7494569655f8d112a0c883a2748a1012bb64ad3a) --- source3/nsswitch/pam_winbind.c | 60 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 5 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 123f670366..c98eb4c139 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -45,6 +45,8 @@ static int _pam_parse(int argc, const char **argv) ctrl |= WINBIND_TRY_FIRST_PASS_ARG; else if (!strcasecmp(*argv, "unknown_ok")) ctrl |= WINBIND_UNKNOWN_OK_ARG; + else if (!strncasecmp(*argv, "required_membership", strlen("required_membership"))) + ctrl |= WINBIND_REQUIRED_MEMBERSHIP; else { _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); } @@ -148,7 +150,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type, switch (retval) { case PAM_AUTH_ERR: /* incorrect password */ - _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", user); + _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password or invalid membership)", user); return retval; case PAM_ACCT_EXPIRED: /* account expired */ @@ -192,7 +194,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type, } /* talk to winbindd */ -static int winbind_auth_request(const char *user, const char *pass, int ctrl) +static int winbind_auth_request(const char *user, const char *pass, const char *member, int ctrl) { struct winbindd_request request; struct winbindd_response response; @@ -204,7 +206,35 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl) strncpy(request.data.auth.pass, pass, sizeof(request.data.auth.pass)-1); - + + if (member == NULL ) + return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user); + + /* lookup name? */ + if (!strncmp("S-", member, 2) == 0) { + + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response) + + if (ctrl & WINBIND_DEBUG_ARG) + _pam_log(LOG_DEBUG, "no sid given, looking up: %s\n", member); + + /* fortunatly winbindd can handle non-separated names */ + strcpy(request.data.name.name, member); + + if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &request, &response, ctrl, user)) { + _pam_log(LOG_INFO, "could not lookup name: %s\n", member); + return PAM_AUTH_ERR; + } + + member = strdup(response.data.sid.sid); + } + + strncpy(request.data.auth.required_membership_sid, member, + sizeof(request.data.auth.required_membership_sid)-1); return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user); } @@ -419,6 +449,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, { const char *username; const char *password; + const char *member = NULL; int retval = PAM_AUTH_ERR; /* parse arguments */ @@ -453,8 +484,26 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, #endif } + /* Retrieve membership-string here */ + int i; + for ( i=0; i Date: Fri, 20 Aug 2004 22:10:53 +0000 Subject: r1971: move counter. Guenther (This used to be commit 74287178d208fd2f5b152314a3b797dcfea698a7) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 119a45cbe8..de0738239c 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -451,6 +451,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, const char *password; const char *member = NULL; int retval = PAM_AUTH_ERR; + int i; /* parse arguments */ int ctrl = _pam_parse(argc, argv); @@ -485,7 +486,6 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, } /* Retrieve membership-string here */ - int i; for ( i=0; i Date: Wed, 22 Sep 2004 00:50:12 +0000 Subject: r2482: Fix from Arthur van Dongen to fix acces -> access typos. Jeremy. (This used to be commit a278dca1b2c103f368d154aee2d3a1edd5604687) --- source3/nsswitch/pam_winbind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index de0738239c..64e2173822 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -176,7 +176,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type, case PAM_SUCCESS: if (req_type == WINBINDD_PAM_AUTH) { /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted acces", user); + _pam_log(LOG_NOTICE, "user '%s' granted access", user); } else if (req_type == WINBINDD_PAM_CHAUTHTOK) { /* Otherwise, the authentication looked good */ _pam_log(LOG_NOTICE, "user '%s' password changed", user); @@ -551,7 +551,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, return PAM_USER_UNKNOWN; case 0: /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted acces", username); + _pam_log(LOG_NOTICE, "user '%s' granted access", username); return PAM_SUCCESS; default: /* we don't know anything about this return value */ -- cgit From f219db7d698438969be95186dad7dc60512b86a9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 1 Oct 2004 03:28:39 +0000 Subject: r2762: Remove silly conversion to and from UTF8 on the winbind pipe. Fix the naming of the require_membership_of parameter in pam_winbind and fix the error code for 'you didn't specify a domain' in ntlm_auth. Andrew Bartlett (This used to be commit 4bf0b94011fe6bfbec5635e58cafbfe3dc898569) --- source3/nsswitch/pam_winbind.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 64e2173822..9a00ac2886 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -45,7 +45,9 @@ static int _pam_parse(int argc, const char **argv) ctrl |= WINBIND_TRY_FIRST_PASS_ARG; else if (!strcasecmp(*argv, "unknown_ok")) ctrl |= WINBIND_UNKNOWN_OK_ARG; - else if (!strncasecmp(*argv, "required_membership", strlen("required_membership"))) + else if (!strncasecmp(*argv, "require_membership_of", strlen("require_membership_of"))) + ctrl |= WINBIND_REQUIRED_MEMBERSHIP; + else if (!strncasecmp(*argv, "require-membership-of", strlen("require-membership-of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; else { _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); @@ -213,8 +215,8 @@ static int winbind_auth_request(const char *user, const char *pass, const char * /* lookup name? */ if (!strncmp("S-", member, 2) == 0) { - struct winbindd_request request; - struct winbindd_response response; + struct winbindd_request sid_request; + struct winbindd_response sid_response; ZERO_STRUCT(request); ZERO_STRUCT(response); @@ -230,11 +232,11 @@ static int winbind_auth_request(const char *user, const char *pass, const char * return PAM_AUTH_ERR; } - member = strdup(response.data.sid.sid); + member = response.data.sid.sid; } - strncpy(request.data.auth.required_membership_sid, member, - sizeof(request.data.auth.required_membership_sid)-1); + strncpy(request.data.auth.require_membership_of_sid, member, + sizeof(request.data.auth.require_membership_of_sid)-1); return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user); } @@ -488,7 +490,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* Retrieve membership-string here */ for ( i=0; i Date: Sat, 2 Oct 2004 11:11:49 +0000 Subject: r2779: Some fixes to pam_winbind.c.: Allow 'require_membership_of' and 'require-membership-of'. Really use a different struct for the SID->Name lookup. Andrew Bartlett (This used to be commit 83dadcd089905aa8ff3392010177ffa1dc8237ba) --- source3/nsswitch/pam_winbind.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 9a00ac2886..9d4f0954ce 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -218,21 +218,21 @@ static int winbind_auth_request(const char *user, const char *pass, const char * struct winbindd_request sid_request; struct winbindd_response sid_response; - ZERO_STRUCT(request); - ZERO_STRUCT(response); + ZERO_STRUCT(sid_request); + ZERO_STRUCT(sid_response); if (ctrl & WINBIND_DEBUG_ARG) _pam_log(LOG_DEBUG, "no sid given, looking up: %s\n", member); /* fortunatly winbindd can handle non-separated names */ - strcpy(request.data.name.name, member); + strcpy(sid_request.data.name.name, member); - if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &request, &response, ctrl, user)) { + if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &sid_request, &sid_response, ctrl, user)) { _pam_log(LOG_INFO, "could not lookup name: %s\n", member); return PAM_AUTH_ERR; } - member = response.data.sid.sid; + member = sid_response.data.sid.sid; } strncpy(request.data.auth.require_membership_of_sid, member, @@ -490,13 +490,14 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* Retrieve membership-string here */ for ( i=0; i Date: Fri, 4 Feb 2005 00:25:33 +0000 Subject: r5207: patches from Jay Fenlason @ RedHat (scooped from their Fedora packages) (This used to be commit 9019a8436162d3606f6b8584701b0832cf5a7439) --- source3/nsswitch/pam_winbind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index bfd8dd45ee..ffe82b0bd2 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -4,7 +4,7 @@ Copyright Tim Potter 2000 Copyright Andrew Bartlett 2002 - largely based on pam_userdb by Christian Gafton + largely based on pam_userdb by Cristian Gafton also contains large slabs of code from pam_unix by Elliot Lee (see copyright below for full details) */ @@ -696,7 +696,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, lctrl = ctrl; if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { - ctrl = WINBIND_USE_FIRST_PASS_ARG | lctrl; + lctrl |= WINBIND_USE_FIRST_PASS_ARG; } retry = 0; retval = PAM_AUTHTOK_ERR; -- cgit From 9f38c321d0ebfb12be2cd6162659f8cb25fa8f5b Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 31 May 2005 16:21:06 +0000 Subject: r7145: reuse the WINBIND_REQUIRED_MEMBERSHIP constant. This is just cosmetic but prevents people from thinking that the pam_winbind "require_membership_of"-option is not yet implemented :) Guenther (This used to be commit ef80a49a858d7d81d427c7bac71fdac4fc0d1bd6) --- source3/nsswitch/pam_winbind.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index ffe82b0bd2..8d4f59101c 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -487,22 +487,24 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, #endif } - /* Retrieve membership-string here */ - for ( i=0; i Date: Mon, 19 Sep 2005 18:49:18 +0000 Subject: r10321: Fix winbindd recursion bug found by Ingo Steuwer . Jeremy. (This used to be commit 6795c818a3d63737d5b40faffa3a0b91c71b427b) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 8d4f59101c..a87ccb4972 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -106,7 +106,7 @@ static int pam_winbind_request(enum winbindd_cmd req_type, /* Fill in request and send down pipe */ init_request(request, req_type); - if (write_sock(request, sizeof(*request)) == -1) { + if (write_sock(request, sizeof(*request), 0) == -1) { _pam_log(LOG_ERR, "write to socket failed!"); close_sock(); return PAM_SERVICE_ERR; -- cgit From 29ba5c17cda35f4277e9d84e9ce2893685f3c683 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 13 Jan 2006 11:11:23 +0000 Subject: r12900: Merge from trunk: Correctly handle the case where users logon with an expired password. In that case pam_sm_authenticate has to return PAM_SUCESS instead of PAM_NEW_AUTHTOK_REQD or PAM_AUTHTOK_EXPIRED and pam_sm_acct_mgmt has to take care of requesting an immediate password change. (see the Linux PAM documentation). Fixes Bugzilla #1524, #3205. Tested with login, sshd, kdm and gdm on Linux. Thanks to Scott Barker . Guenther (This used to be commit 4cb662ffd76dbe30003c618c94ccf6ebd4afb48c) --- source3/nsswitch/pam_winbind.c | 44 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index a87ccb4972..61c01daa16 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -57,6 +57,11 @@ static int _pam_parse(int argc, const char **argv) return ctrl; } +static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_status) +{ + SAFE_FREE(data); +} + /* --- authentication management functions --- */ /* Attempt a conversation */ @@ -508,7 +513,22 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, } /* Now use the username to look up password */ - return winbind_auth_request(username, password, member, ctrl); + retval = winbind_auth_request(username, password, member, ctrl); + if (retval == PAM_NEW_AUTHTOK_REQD || + retval == PAM_AUTHTOK_EXPIRED) { + + char *buf; + + if (!asprintf(&buf, "%d", retval)) { + return PAM_BUF_ERR; + } + + pam_set_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (void *)buf, _pam_winbind_cleanup_func); + + return PAM_SUCCESS; + } + + return retval; } PAM_EXTERN @@ -527,6 +547,8 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { const char *username; + void *tmp = NULL; + int retval = PAM_USER_UNKNOWN; /* parse arguments */ @@ -555,6 +577,26 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, return PAM_IGNORE; return PAM_USER_UNKNOWN; case 0: + pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp); + + if (tmp != NULL) { + retval = atoi(tmp); + switch (retval) { + case PAM_AUTHTOK_EXPIRED: + /* fall through, since new token is required in this case */ + case PAM_NEW_AUTHTOK_REQD: + _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success but %s is set", + PAM_WINBIND_NEW_AUTHTOK_REQD); + _pam_log(LOG_NOTICE, "user '%s' needs new password", username); + /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */ + return PAM_NEW_AUTHTOK_REQD; + default: + _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success"); + _pam_log(LOG_NOTICE, "user '%s' granted access", username); + return PAM_SUCCESS; + } + } + /* Otherwise, the authentication looked good */ _pam_log(LOG_NOTICE, "user '%s' granted access", username); return PAM_SUCCESS; -- cgit From 0af1500fc0bafe61019f1b2ab1d9e1d369221240 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 3 Feb 2006 22:19:41 +0000 Subject: r13316: Let the carnage begin.... Sync with trunk as off r13315 (This used to be commit 17e63ac4ed8325c0d44fe62b2442449f3298559f) --- source3/nsswitch/pam_winbind.c | 991 ++++++++++++++++++++++++++++++----------- 1 file changed, 724 insertions(+), 267 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 61c01daa16..57e05dc4bb 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -3,12 +3,14 @@ Copyright Andrew Tridgell 2000 Copyright Tim Potter 2000 Copyright Andrew Bartlett 2002 + Copyright Guenther Deschner 2005-2006 largely based on pam_userdb by Cristian Gafton also contains large slabs of code from pam_unix by Elliot Lee (see copyright below for full details) */ +#include "includes.h" #include "pam_winbind.h" /* data tokens */ @@ -27,41 +29,122 @@ static void _pam_log(int err, const char *format, ...) closelog(); } +static void _pam_log_debug(int ctrl, int err, const char *format, ...) +{ + va_list args; + + if (!(ctrl & WINBIND_DEBUG_ARG)) { + return; + } + + va_start(args, format); + openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH); + vsyslog(err, format, args); + va_end(args); + closelog(); +} + static int _pam_parse(int argc, const char **argv) { - int ctrl; + int ctrl = 0; + + load_case_tables(); + + if (!lp_load(dyn_CONFIGFILE,True,False,False,True)) { + return -1; + } + + if (lp_parm_bool(-1, "pam_winbind", "cached_login", False)) { + ctrl |= WINBIND_CACHED_LOGIN; + } + if (lp_parm_bool(-1, "pam_winbind", "krb5_auth", False)) { + ctrl |= WINBIND_KRB5_AUTH; + } + if (lp_parm_const_string(-1, "pam_winbind", "krb5_ccache_type", NULL) != NULL) { + ctrl |= WINBIND_KRB5_CCACHE_TYPE; + } + if ((lp_parm_const_string(-1, "pam_winbind", "require-membership-of", NULL) != NULL) || + (lp_parm_const_string(-1, "pam_winbind", "require_membership_of", NULL) != NULL)) { + ctrl |= WINBIND_REQUIRED_MEMBERSHIP; + } + if (lp_parm_bool(-1, "pam_winbind", "create_homedir", False)) { + ctrl |= WINBIND_CREATE_HOMEDIR; + } + /* step through arguments */ - for (ctrl = 0; argc-- > 0; ++argv) { + for (; argc-- > 0; ++argv) { /* generic options */ - - if (!strcmp(*argv,"debug")) + + if (!StrCaseCmp(*argv, "debug")) ctrl |= WINBIND_DEBUG_ARG; - else if (!strcasecmp(*argv, "use_authtok")) + else if (strequal(*argv, "use_authtok")) ctrl |= WINBIND_USE_AUTHTOK_ARG; - else if (!strcasecmp(*argv, "use_first_pass")) + else if (strequal(*argv, "use_first_pass")) ctrl |= WINBIND_USE_FIRST_PASS_ARG; - else if (!strcasecmp(*argv, "try_first_pass")) + else if (strequal(*argv, "try_first_pass")) ctrl |= WINBIND_TRY_FIRST_PASS_ARG; - else if (!strcasecmp(*argv, "unknown_ok")) + else if (strequal(*argv, "unknown_ok")) ctrl |= WINBIND_UNKNOWN_OK_ARG; - else if (!strncasecmp(*argv, "require_membership_of", strlen("require_membership_of"))) + else if (strnequal(*argv, "require_membership_of", strlen("require_membership_of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; - else if (!strncasecmp(*argv, "require-membership-of", strlen("require-membership-of"))) + else if (strnequal(*argv, "require-membership-of", strlen("require-membership-of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; + else if (strequal(*argv, "krb5_auth")) + ctrl |= WINBIND_KRB5_AUTH; + else if (strnequal(*argv, "krb5_ccache_type", strlen("krb5_ccache_type"))) + ctrl |= WINBIND_KRB5_CCACHE_TYPE; + else if (strequal(*argv, "cached_login")) + ctrl |= WINBIND_CACHED_LOGIN; + else if (strequal(*argv, "create_homedir")) + ctrl |= WINBIND_CREATE_HOMEDIR; else { _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); } + } - return ctrl; -} +}; static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_status) { SAFE_FREE(data); } +static const struct ntstatus_errors { + const char *ntstatus_string; + const char *error_string; +} ntstatus_errors[] = { + {"NT_STATUS_OK", "Success"}, + {"NT_STATUS_BACKUP_CONTROLLER", "No primary Domain Controler available"}, + {"NT_STATUS_PWD_TOO_SHORT", "Password too short"}, + {"NT_STATUS_PWD_TOO_RECENT", "The password of this user is too recent to change"}, + {"NT_STATUS_PWD_HISTORY_CONFLICT", "Password is already in password history"}, + {"NT_STATUS_PASSWORD_EXPIRED", "Your password has expired"}, + {"NT_STATUS_PASSWORD_MUST_CHANGE", "You need to change your password now"}, + {"NT_STATUS_INVALID_WORKSTATION", "You are not allowed to logon from this workstation"}, + {"NT_STATUS_INVALID_LOGON_HOURS", "You are not allowed to logon at this time"}, + {"NT_STATUS_ACCOUNT_EXPIRED", "Your account has expired. Please contact your System administrator"}, /* SCNR */ + {"NT_STATUS_ACCOUNT_DISABLED", "Your account is disabled. Please contact your System administrator"}, /* SCNR */ + {"NT_STATUS_ACCOUNT_LOCKED_OUT", "Your account has been locked. Please contact your System administrator"}, /* SCNR */ + {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", "Invalid Trust Account"}, + {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", "Invalid Trust Account"}, + {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", "Invalid Trust Account"}, + {"NT_STATUS_ACCESS_DENIED", "Access is denied"}, + {NULL, NULL} +}; + +const char *_get_ntstatus_error_string(const char *nt_status_string) +{ + int i; + for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) { + if (strequal(ntstatus_errors[i].ntstatus_string, nt_status_string)) { + return ntstatus_errors[i].error_string; + } + } + return NULL; +} + /* --- authentication management functions --- */ /* Attempt a conversation */ @@ -70,16 +153,16 @@ static int converse(pam_handle_t *pamh, int nargs, struct pam_message **message, struct pam_response **response) { - int retval; - struct pam_conv *conv; - - retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ) ; - if (retval == PAM_SUCCESS) { - retval = conv->conv(nargs, (const struct pam_message **)message, - response, conv->appdata_ptr); - } + int retval; + struct pam_conv *conv; + + retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ); + if (retval == PAM_SUCCESS) { + retval = conv->conv(nargs, (const struct pam_message **)message, + response, conv->appdata_ptr); + } - return retval; /* propagate error status */ + return retval; /* propagate error status */ } @@ -103,11 +186,23 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text) return retval; } -static int pam_winbind_request(enum winbindd_cmd req_type, +static int _make_remark_format(pam_handle_t * pamh, int type, const char *format, ...) +{ + va_list args; + char *var; + + va_start(args, format); + vasprintf(&var, format, args); + va_end(args); + + return _make_remark(pamh, type, var); +} + +static int pam_winbind_request(pam_handle_t * pamh, int ctrl, + enum winbindd_cmd req_type, struct winbindd_request *request, struct winbindd_response *response) { - /* Fill in request and send down pipe */ init_request(request, req_type); @@ -140,19 +235,20 @@ static int pam_winbind_request(enum winbindd_cmd req_type, return PAM_SERVICE_ERR; } } - + return PAM_SUCCESS; } -static int pam_winbind_request_log(enum winbindd_cmd req_type, - struct winbindd_request *request, - struct winbindd_response *response, +static int pam_winbind_request_log(pam_handle_t * pamh, int ctrl, + enum winbindd_cmd req_type, + struct winbindd_request *request, + struct winbindd_response *response, const char *user) { int retval; - retval = pam_winbind_request(req_type, request, response); + retval = pam_winbind_request(pamh, ctrl, req_type, request, response); switch (retval) { case PAM_AUTH_ERR: @@ -168,13 +264,12 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type, _pam_log(LOG_WARNING, "user `%s' password expired", user); return retval; case PAM_NEW_AUTHTOK_REQD: - /* password expired */ + /* new password required */ _pam_log(LOG_WARNING, "user `%s' new password required", user); return retval; case PAM_USER_UNKNOWN: /* the user does not exist */ - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_NOTICE, "user `%s' not found", + _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found", user); if (ctrl & WINBIND_UNKNOWN_OK_ARG) { return PAM_IGNORE; @@ -191,6 +286,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type, /* Otherwise, the authentication looked good */ _pam_log(LOG_NOTICE, "user '%s' OK", user); } + return retval; default: /* we don't know anything about this return value */ @@ -201,24 +297,67 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type, } /* talk to winbindd */ -static int winbind_auth_request(const char *user, const char *pass, const char *member, int ctrl) +static int winbind_auth_request(pam_handle_t * pamh, + int ctrl, + const char *user, + const char *pass, + const char *member, + const char *cctype, + int process_result) { struct winbindd_request request; struct winbindd_response response; + int ret; ZERO_STRUCT(request); + ZERO_STRUCT(response); strncpy(request.data.auth.user, user, - sizeof(request.data.auth.user)-1); + sizeof(request.data.auth.user)-1); strncpy(request.data.auth.pass, pass, - sizeof(request.data.auth.pass)-1); + sizeof(request.data.auth.pass)-1); + + request.data.auth.krb5_cc_type[0] = '\0'; + request.data.auth.uid = -1; + + request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_CONTACT_TRUSTDOM; + + if (ctrl & WINBIND_KRB5_AUTH) { + + struct passwd *pwd = NULL; + + _pam_log_debug(ctrl, LOG_DEBUG, "enabling krb5 login flag\n"); + + request.flags |= WBFLAG_PAM_KRB5 | WBFLAG_PAM_FALLBACK_AFTER_KRB5; + + pwd = getpwnam(user); + if (pwd == NULL) { + return PAM_USER_UNKNOWN; + } + request.data.auth.uid = pwd->pw_uid; + } - if (member == NULL ) - return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user); + if (ctrl & WINBIND_CACHED_LOGIN) { + _pam_log_debug(ctrl, LOG_DEBUG, "enabling cached login flag\n"); + request.flags |= WBFLAG_PAM_CACHED_LOGIN; + } + + if (cctype != NULL) { + strncpy(request.data.auth.krb5_cc_type, cctype, + sizeof(request.data.auth.krb5_cc_type) - 1); + _pam_log_debug(ctrl, LOG_DEBUG, "enabling request for a %s krb5 ccache\n", cctype); + } + + request.data.auth.require_membership_of_sid[0] = '\0'; + + if (member != NULL) { + strncpy(request.data.auth.require_membership_of_sid, member, + sizeof(request.data.auth.require_membership_of_sid)-1); + } /* lookup name? */ - if (!strncmp("S-", member, 2) == 0) { + if ( (member != NULL) && (strncmp("S-", member, 2) != 0) ) { struct winbindd_request sid_request; struct winbindd_response sid_response; @@ -226,55 +365,195 @@ static int winbind_auth_request(const char *user, const char *pass, const char * ZERO_STRUCT(sid_request); ZERO_STRUCT(sid_response); - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_DEBUG, "no sid given, looking up: %s\n", member); + _pam_log_debug(ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", member); /* fortunatly winbindd can handle non-separated names */ - strcpy(sid_request.data.name.name, member); + fstrcpy(sid_request.data.name.name, member); - if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &sid_request, &sid_response, ctrl, user)) { + if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) { _pam_log(LOG_INFO, "could not lookup name: %s\n", member); return PAM_AUTH_ERR; } member = sid_response.data.sid.sid; + + strncpy(request.data.auth.require_membership_of_sid, member, + sizeof(request.data.auth.require_membership_of_sid)-1); } + + ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, &request, &response, user); - strncpy(request.data.auth.require_membership_of_sid, member, - sizeof(request.data.auth.require_membership_of_sid)-1); + if ((ctrl & WINBIND_KRB5_AUTH) && + response.data.auth.krb5ccname[0] != '\0') { + + char var[PATH_MAX]; + + _pam_log_debug(ctrl, LOG_DEBUG, "request returned KRB5CCNAME: %s", + response.data.auth.krb5ccname); - return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user); + snprintf(var, sizeof(var), "KRB5CCNAME=%s", response.data.auth.krb5ccname); + + ret = pam_putenv(pamh, var); + if (ret != PAM_SUCCESS) { + _pam_log(LOG_ERR, "failed to set KRB5CCNAME to %s", var); + return ret; + } + } + + if (!process_result) { + return ret; + } + + if (ret) { + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PASSWORD_EXPIRED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PASSWORD_MUST_CHANGE"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_INVALID_WORKSTATION"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_INVALID_LOGON_HOURS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_EXPIRED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_DISABLED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_LOCKED_OUT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"); + } + + /* handle the case where the auth was ok, but the password must expire right now */ + /* good catch from Ralf Haferkamp: an expiry of "never" is translated to -1 */ + if ((response.data.auth.policy.expire > 0) && + (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire < time(NULL))) { + + ret = PAM_AUTHTOK_EXPIRED; + + _pam_log_debug(ctrl, LOG_DEBUG,"Password has expired (Password was last set: %d, " + "the policy says it should expire here %d (now it's: %d)\n", + response.data.auth.info3.pass_last_set_time, + response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire, + time(NULL)); + + PAM_WB_REMARK_DIRECT_RET(pamh, "NT_STATUS_PASSWORD_EXPIRED"); + + } + + /* warn a user if the password is about to expire soon */ + if ((response.data.auth.policy.expire) && + (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire > time(NULL) ) ) { + + int days = response.data.auth.policy.expire / SECONDS_PER_DAY; + if (days <= DAYS_TO_WARN_BEFORE_PWD_EXPIRES) { + _make_remark_format(pamh, PAM_TEXT_INFO, "Your password will expire in %d days", days); + } + } + + if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) { + _make_remark(pamh, PAM_ERROR_MSG, "Logging on using cached account. Network ressources can be unavailable"); + } + + /* save the CIFS homedir for pam_cifs / pam_mount */ + if (response.data.auth.info3.home_dir[0] != '\0') { + char *buf; + + if (!asprintf(&buf, "%s", response.data.auth.info3.home_dir)) { + return PAM_BUF_ERR; + } + + pam_set_data( pamh, PAM_WINBIND_HOMEDIR, (void *)buf, _pam_winbind_cleanup_func); + } + + return ret; } /* talk to winbindd */ -static int winbind_chauthtok_request(const char *user, const char *oldpass, - const char *newpass, int ctrl) +static int winbind_chauthtok_request(pam_handle_t * pamh, + int ctrl, + const char *user, + const char *oldpass, + const char *newpass) { struct winbindd_request request; struct winbindd_response response; + int ret; ZERO_STRUCT(request); + ZERO_STRUCT(response); - if (request.data.chauthtok.user == NULL) return -2; + if (request.data.chauthtok.user == NULL) return -2; strncpy(request.data.chauthtok.user, user, - sizeof(request.data.chauthtok.user) - 1); - - if (oldpass != NULL) { - strncpy(request.data.chauthtok.oldpass, oldpass, - sizeof(request.data.chauthtok.oldpass) - 1); - } else { - request.data.chauthtok.oldpass[0] = '\0'; - } - - if (newpass != NULL) { - strncpy(request.data.chauthtok.newpass, newpass, - sizeof(request.data.chauthtok.newpass) - 1); - } else { - request.data.chauthtok.newpass[0] = '\0'; - } + sizeof(request.data.chauthtok.user) - 1); + + if (oldpass != NULL) { + strncpy(request.data.chauthtok.oldpass, oldpass, + sizeof(request.data.chauthtok.oldpass) - 1); + } else { + request.data.chauthtok.oldpass[0] = '\0'; + } - return pam_winbind_request_log(WINBINDD_PAM_CHAUTHTOK, &request, &response, ctrl, user); + if (newpass != NULL) { + strncpy(request.data.chauthtok.newpass, newpass, + sizeof(request.data.chauthtok.newpass) - 1); + } else { + request.data.chauthtok.newpass[0] = '\0'; + } + + if (ctrl & WINBIND_KRB5_AUTH) { + request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; + } + + ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_CHAUTHTOK, &request, &response, user); + + if (ret == PAM_SUCCESS) { + return ret; + } + + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_BACKUP_CONTROLLER"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCESS_DENIED"); + + /* TODO: tell the min pwd length ? */ + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_TOO_SHORT"); + + /* TODO: tell the minage ? */ + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_TOO_RECENT"); + + /* TODO: tell the history length ? */ + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_HISTORY_CONFLICT"); + + if (strequal(response.data.auth.nt_status_string, "NT_STATUS_PASSWORD_RESTRICTION")) { + + /* FIXME: avoid to send multiple PAM messages after another */ + switch (response.data.auth.reject_reason) { + case 0: + break; + case REJECT_REASON_TOO_SHORT: + PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_SHORT"); + break; + case REJECT_REASON_IN_HISTORY: + PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_HISTORY_CONFLICT"); + break; + case REJECT_REASON_NOT_COMPLEX: + _make_remark(pamh, PAM_ERROR_MSG, "Password does not meet complexity requirements"); + break; + default: + _pam_log_debug(ctrl, LOG_DEBUG, + "unknown password change reject reason: %d", + response.data.auth.reject_reason); + break; + } + + _make_remark_format(pamh, PAM_ERROR_MSG, + "Your password must be at least %d characters; " + "cannot repeat any of the your previous %d passwords" + "%s. " + "Please type a different password. " + "Type a password which meets these requirements in both text boxes.", + response.data.auth.policy.min_length_password, + response.data.auth.policy.password_history, + (response.data.auth.policy.password_properties & DOMAIN_PASSWORD_COMPLEX) ? + "; must contain capitals, numerals or punctuation; and cannot contain your account or full name" : + ""); + + } + + return ret; } /* @@ -293,21 +572,21 @@ static int valid_user(const char *user) static char *_pam_delete(register char *xx) { - _pam_overwrite(xx); - _pam_drop(xx); - return NULL; + _pam_overwrite(xx); + _pam_drop(xx); + return NULL; } /* * obtain a password from the user */ -static int _winbind_read_password(pam_handle_t * pamh - ,unsigned int ctrl - ,const char *comment - ,const char *prompt1 - ,const char *prompt2 - ,const char **pass) +static int _winbind_read_password(pam_handle_t * pamh, + unsigned int ctrl, + const char *comment, + const char *prompt1, + const char *prompt2, + const char **pass) { int authtok_flag; int retval; @@ -391,16 +670,15 @@ static int _winbind_read_password(pam_handle_t * pamh if (retval == PAM_SUCCESS) { /* a good conversation */ - token = x_strdup(resp[i - replies].resp); + token = SMB_STRDUP(resp[i - replies].resp); if (token != NULL) { if (replies == 2) { - /* verify that password entered correctly */ if (!resp[i - 1].resp - || strcmp(token, resp[i - 1].resp)) { + || StrCaseCmp(token, resp[i - 1].resp)) { _pam_delete(token); /* mistyped */ retval = PAM_AUTHTOK_RECOVER_ERR; - _make_remark(pamh ,PAM_ERROR_MSG, MISTYPED_PASS); + _make_remark(pamh, PAM_ERROR_MSG, MISTYPED_PASS); } } } else { @@ -423,8 +701,7 @@ static int _winbind_read_password(pam_handle_t * pamh } if (retval != PAM_SUCCESS) { - if (on(WINBIND_DEBUG_ARG, ctrl)) - _pam_log(LOG_DEBUG, + _pam_log_debug(ctrl, LOG_DEBUG, "unable to obtain a password"); return retval; } @@ -434,10 +711,8 @@ static int _winbind_read_password(pam_handle_t * pamh retval = pam_set_item(pamh, authtok_flag, token); _pam_delete(token); /* clean it up */ - if (retval != PAM_SUCCESS - || (retval = pam_get_item(pamh, authtok_flag - ,(const void **) &item)) - != PAM_SUCCESS) { + if (retval != PAM_SUCCESS || + (retval = pam_get_item(pamh, authtok_flag, (const void **) &item)) != PAM_SUCCESS) { _pam_log(LOG_CRIT, "error manipulating password"); return retval; @@ -450,92 +725,145 @@ static int _winbind_read_password(pam_handle_t * pamh return PAM_SUCCESS; } +const char *get_conf_item_string(int argc, + const char **argv, + int ctrl, + const char *item, + int flag) +{ + int i = 0; + char *parm = NULL; + const char *parm_opt = NULL; + + if (!(ctrl & flag)) { + goto out; + } + + /* let the pam opt take precedence over the smb.conf option */ + parm_opt = lp_parm_const_string(-1, "pam_winbind", item, NULL); + + for ( i=0; ipw_dir); + + if (directory_exist(pwd->pw_dir, &sbuf)) { + return PAM_SUCCESS; + } + + fstrcpy(create_dir, "/"); + while (next_token((const char **)&pwd->pw_dir, tok, "/", sizeof(tok))) { + + mode_t mode = 0755; + + fstrcat(create_dir, tok); + fstrcat(create_dir, "/"); + + if (!directory_exist(create_dir, &sbuf)) { + if (mkdir(create_dir, mode) != 0) { + _pam_log(LOG_ERR, "could not create dir: %s (%s)", + create_dir, strerror(errno)); + return PAM_SERVICE_ERR; + } + } + } + + if (sys_chown(create_dir, pwd->pw_uid, pwd->pw_gid) != 0) { + _pam_log(LOG_ERR, "failed to chown user homedir: %s (%s)", + create_dir, strerror(errno)); + return PAM_SERVICE_ERR; + } + } + + return PAM_SUCCESS; } + PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, - int argc, const char **argv) + int argc, const char **argv) { - /* parse arguments */ - int ctrl = _pam_parse(argc, argv); - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_DEBUG,"libpam_winbind:pam_sm_close_session handler"); - return PAM_SUCCESS; + /* parse arguments */ + int ctrl = _pam_parse(argc, argv); + if (ctrl == -1) { + return PAM_SYSTEM_ERR; + } + + _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_close_session handler"); + + if (!(flags & PAM_DELETE_CRED)) { + return PAM_SUCCESS; + } + + if (ctrl & WINBIND_KRB5_AUTH) { + + /* destroy the ccache here */ + struct winbindd_request request; + struct winbindd_response response; + const char *user; + const char *ccname = NULL; + struct passwd *pwd = NULL; + + int retval; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + retval = pam_get_user(pamh, &user, "Username: "); + if (retval == PAM_SUCCESS) { + if (user == NULL) { + _pam_log(LOG_ERR, "username was NULL!"); + return PAM_USER_UNKNOWN; + } + if (retval == PAM_SUCCESS) { + _pam_log_debug(ctrl, LOG_DEBUG, "username [%s] obtained", user); + } + } else { + _pam_log_debug(ctrl, LOG_DEBUG, "could not identify user"); + return retval; + } + + ccname = pam_getenv(pamh, "KRB5CCNAME"); + if (ccname == NULL) { + _pam_log_debug(ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment"); + return PAM_BUF_ERR; + } + + fstrcpy(request.data.logoff.user, user); + fstrcpy(request.data.logoff.krb5ccname, ccname); + + pwd = getpwnam(user); + if (pwd == NULL) { + return PAM_USER_UNKNOWN; + } + request.data.logoff.uid = pwd->pw_uid; + + request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; + + return pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_LOGOFF, &request, &response, user); + } + + return PAM_SUCCESS; } -PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - int argc, const char **argv) +PAM_EXTERN +int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + int argc, const char **argv) { unsigned int lctrl; int retval; - unsigned int ctrl = _pam_parse(argc, argv); + unsigned int ctrl; /* */ const char *user; - const char *member = NULL; char *pass_old, *pass_new; /* */ - char *Announce; + fstring Announce; int retry = 0; + ctrl = _pam_parse(argc, argv); + if (ctrl == -1) { + return PAM_SYSTEM_ERR; + } + + _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_chauthtok"); + /* * First get the name of a user */ @@ -659,13 +1111,13 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, _pam_log(LOG_ERR, "username was NULL!"); return PAM_USER_UNKNOWN; } - if (retval == PAM_SUCCESS && on(WINBIND_DEBUG_ARG, ctrl)) - _pam_log(LOG_DEBUG, "username [%s] obtained", + if (retval == PAM_SUCCESS) { + _pam_log_debug(ctrl, LOG_DEBUG, "username [%s] obtained", user); + } } else { - if (on(WINBIND_DEBUG_ARG, ctrl)) - _pam_log(LOG_DEBUG, - "password - could not identify user"); + _pam_log_debug(ctrl, LOG_DEBUG, + "password - could not identify user"); return retval; } @@ -678,33 +1130,24 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, /* instruct user what is happening */ #define greeting "Changing password for " - Announce = (char *) malloc(sizeof(greeting) + strlen(user)); - if (Announce == NULL) { - _pam_log(LOG_CRIT, - "password - out of memory"); - return PAM_BUF_ERR; - } - (void) strcpy(Announce, greeting); - (void) strcpy(Announce + sizeof(greeting) - 1, user); + fstrcpy(Announce, greeting); + fstrcat(Announce, user); #undef greeting lctrl = ctrl | WINBIND__OLD_PASSWORD; - retval = _winbind_read_password(pamh, lctrl - ,Announce - ,"(current) NT password: " - ,NULL - ,(const char **) &pass_old); - free(Announce); - + retval = _winbind_read_password(pamh, lctrl, + Announce, + "(current) NT password: ", + NULL, + (const char **) &pass_old); if (retval != PAM_SUCCESS) { - _pam_log(LOG_NOTICE - ,"password - (old) token not obtained"); + _pam_log(LOG_NOTICE, "password - (old) token not obtained"); return retval; } /* verify that this is the password for this user */ - retval = winbind_auth_request(user, pass_old, member, ctrl); - + retval = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, False); + if (retval != PAM_ACCT_EXPIRED && retval != PAM_AUTHTOK_EXPIRED && retval != PAM_NEW_AUTHTOK_REQD @@ -716,8 +1159,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); pass_old = NULL; if (retval != PAM_SUCCESS) { - _pam_log(LOG_CRIT, - "failed to set PAM_OLDAUTHTOK"); + _pam_log(LOG_CRIT, "failed to set PAM_OLDAUTHTOK"); } } else if (flags & PAM_UPDATE_AUTHTOK) { @@ -729,8 +1171,8 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * get the old token back. */ - retval = pam_get_item(pamh, PAM_OLDAUTHTOK - ,(const void **) &pass_old); + retval = pam_get_item(pamh, PAM_OLDAUTHTOK, + (const void **) &pass_old); if (retval != PAM_SUCCESS) { _pam_log(LOG_NOTICE, "user not authenticated"); @@ -750,17 +1192,15 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * password -- needed for pluggable password strength checking */ - retval = _winbind_read_password(pamh, lctrl - ,NULL - ,"Enter new NT password: " - ,"Retype new NT password: " - ,(const char **) &pass_new); + retval = _winbind_read_password(pamh, lctrl, + NULL, + "Enter new NT password: ", + "Retype new NT password: ", + (const char **) &pass_new); if (retval != PAM_SUCCESS) { - if (on(WINBIND_DEBUG_ARG, ctrl)) { - _pam_log(LOG_ALERT - ,"password - new password not obtained"); - } + _pam_log_debug(ctrl, LOG_ALERT + ,"password - new password not obtained"); pass_old = NULL;/* tidy up */ return retval; } @@ -781,14 +1221,30 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * rebuild the password database file. */ - retval = winbind_chauthtok_request(user, pass_old, pass_new, ctrl); - _pam_overwrite(pass_new); - _pam_overwrite(pass_old); - pass_old = pass_new = NULL; + retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new); + if (retval) { + _pam_overwrite(pass_new); + _pam_overwrite(pass_old); + pass_old = pass_new = NULL; + return retval; + } + + /* just in case we need krb5 creds after a password change over msrpc */ + + if (ctrl & WINBIND_KRB5_AUTH) { + + const char *member = get_member_from_config(argc, argv, ctrl); + const char *cctype = get_krb5_cc_type_from_config(argc, argv, ctrl); + + retval = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, False); + _pam_overwrite(pass_new); + _pam_overwrite(pass_old); + pass_old = pass_new = NULL; + } } else { retval = PAM_SERVICE_ERR; } - + return retval; } @@ -797,13 +1253,13 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, /* static module data */ struct pam_module _pam_winbind_modstruct = { - MODULE_NAME, - pam_sm_authenticate, - pam_sm_setcred, - pam_sm_acct_mgmt, - pam_sm_open_session, - pam_sm_close_session, - pam_sm_chauthtok + MODULE_NAME, + pam_sm_authenticate, + pam_sm_setcred, + pam_sm_acct_mgmt, + pam_sm_open_session, + pam_sm_close_session, + pam_sm_chauthtok }; #endif @@ -812,6 +1268,7 @@ struct pam_module _pam_winbind_modstruct = { * Copyright (c) Andrew Tridgell 2000 * Copyright (c) Tim Potter 2000 * Copyright (c) Andrew Bartlettt 2002 + * Copyright (c) Guenther Deschner 2005-2006 * Copyright (c) Jan Rêkorajski 1999. * Copyright (c) Andrew G. Morgan 1996-8. * Copyright (c) Alex O. Yuriev, 1996. -- cgit From 9cdab6ddc0ab8c9be7f257f971e14e7f2958bb95 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 7 Feb 2006 17:18:29 +0000 Subject: r13375: Match XP behaviour: Don't force 'Administrator' to change an expired password on logon. (this might be true for all domain admins as well). Guenther (This used to be commit 24c6b9fecb521380008cb44e6d987a6f495027dc) --- source3/nsswitch/pam_winbind.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 57e05dc4bb..0141c3fafa 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -419,7 +419,8 @@ static int winbind_auth_request(pam_handle_t * pamh, /* handle the case where the auth was ok, but the password must expire right now */ /* good catch from Ralf Haferkamp: an expiry of "never" is translated to -1 */ - if ((response.data.auth.policy.expire > 0) && + if ((response.data.auth.info3.user_rid != DOMAIN_USER_RID_ADMIN ) && + (response.data.auth.policy.expire > 0) && (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire < time(NULL))) { ret = PAM_AUTHTOK_EXPIRED; @@ -435,7 +436,8 @@ static int winbind_auth_request(pam_handle_t * pamh, } /* warn a user if the password is about to expire soon */ - if ((response.data.auth.policy.expire) && + if ((response.data.auth.info3.user_rid != DOMAIN_USER_RID_ADMIN ) && + (response.data.auth.policy.expire) && (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire > time(NULL) ) ) { int days = response.data.auth.policy.expire / SECONDS_PER_DAY; -- cgit From d5c5c856ae924fc4523e5fa4b9a790249e32b3ae Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Feb 2006 11:57:38 +0000 Subject: r13391: Only fall into password change when ACB_PWNOEXP is not set (got it wrong the first time as administrator has this flag set by default). Guenther (This used to be commit e9ccebf45a5db8964793084950fbb2c23b2469a3) --- source3/nsswitch/pam_winbind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 0141c3fafa..3848612c47 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -419,7 +419,7 @@ static int winbind_auth_request(pam_handle_t * pamh, /* handle the case where the auth was ok, but the password must expire right now */ /* good catch from Ralf Haferkamp: an expiry of "never" is translated to -1 */ - if ((response.data.auth.info3.user_rid != DOMAIN_USER_RID_ADMIN ) && + if ( ! (response.data.auth.info3.acct_flags & ACB_PWNOEXP) && (response.data.auth.policy.expire > 0) && (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire < time(NULL))) { @@ -436,7 +436,7 @@ static int winbind_auth_request(pam_handle_t * pamh, } /* warn a user if the password is about to expire soon */ - if ((response.data.auth.info3.user_rid != DOMAIN_USER_RID_ADMIN ) && + if ( ! (response.data.auth.info3.acct_flags & ACB_PWNOEXP) && (response.data.auth.policy.expire) && (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire > time(NULL) ) ) { -- cgit From f0ed0440c4d3b8736eb5e1ceba8b9257eb29cee3 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 13 Feb 2006 15:12:22 +0000 Subject: r13492: As noone objected on the mailing-list: Fix parse_domain_user to fail when splitting a full name like "DOM\user" when "winbind use default domain" and "winbind trusted domains only" are not enabled. This allows pam_winbind to behave correctly when more modules are stacked in the "account" or "password" PAM facility. pam_winbindd calls WINBINDD_GETPWNAM which can decide whether or not a user is a winbind user and return correct PAM error codes. Guenther (This used to be commit e6d52c1e9d8cec7be6d552c2a67a392df21c3ec9) --- source3/nsswitch/pam_winbind.c | 47 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 3848612c47..35f0efbcbd 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -566,10 +566,38 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, * 0 = OK * -1 = System error */ -static int valid_user(const char *user) +static int valid_user(const char *user, pam_handle_t *pamh, int ctrl) { - if (getpwnam(user)) return 0; - return 1; + /* check not only if the user is available over NSS calls, also make + * sure it's really a winbind user, this is important when stacking PAM + * modules in the 'account' or 'password' facility. */ + + struct passwd *pwd = NULL; + struct winbindd_request request; + struct winbindd_response response; + int ret; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + pwd = getpwnam(user); + if (pwd == NULL) { + return 1; + } + + fstrcpy(request.data.username, user); + + ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_GETPWNAM, &request, &response, user); + + switch (ret) { + case PAM_USER_UNKNOWN: + return 1; + case PAM_SUCCESS: + return 0; + default: + break; + } + return -1; } static char *_pam_delete(register char *xx) @@ -897,7 +925,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, } /* Verify the username */ - retval = valid_user(username); + retval = valid_user(username, pamh, ctrl); switch (retval) { case -1: /* some sort of system error. The log was already printed */ @@ -1123,6 +1151,17 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, return retval; } + /* check if this is really a user in winbindd, not only in NSS */ + retval = valid_user(user, pamh, ctrl); + switch (retval) { + case 1: + return PAM_USER_UNKNOWN; + case -1: + return PAM_SYSTEM_ERR; + default: + break; + } + /* * obtain and verify the current password (OLDAUTHTOK) for * the user. -- cgit From 0382d3c26b004ff4f850e6d683fccc3c55f77641 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 6 Mar 2006 20:18:18 +0000 Subject: r13895: As agreed upon with gd on the phone, remove WBFLAG_PAM_CONTACT_TRUSTDOM. This can not work for NTLM auth, where we only have a workstation account for our own domain. For the PAM Kerberos login we need to find a better way to do this, probably using Dsr_GetDCName and some winbind-crafted krb5.conf. Volker (This used to be commit bf7c608147bcbbedd89b3dcd24a929ea3e601bc8) --- source3/nsswitch/pam_winbind.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 35f0efbcbd..df5fc11d3e 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -321,7 +321,7 @@ static int winbind_auth_request(pam_handle_t * pamh, request.data.auth.krb5_cc_type[0] = '\0'; request.data.auth.uid = -1; - request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_CONTACT_TRUSTDOM; + request.flags = WBFLAG_PAM_INFO3_TEXT; if (ctrl & WINBIND_KRB5_AUTH) { @@ -498,7 +498,7 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, } if (ctrl & WINBIND_KRB5_AUTH) { - request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; + request.flags = WBFLAG_PAM_KRB5; } ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_CHAUTHTOK, &request, &response, user); @@ -1098,7 +1098,7 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, } request.data.logoff.uid = pwd->pw_uid; - request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; + request.flags = WBFLAG_PAM_KRB5; return pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_LOGOFF, &request, &response, user); } -- cgit From 3cbdb090b98bf724e69c5e5fc0d8b3e1b61f6b90 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 16 Mar 2006 23:54:05 +0000 Subject: r14496: Add WBFLAG_PAM_GET_PWD_POLICY bit to only callout for domain password policies when requested. No panic, the flags is uint32 so we are not running out of WBFLAG bits. Guenther (This used to be commit 2155bb0535656f294bd054d6a0a7d16a9a71c31b) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index df5fc11d3e..b09e974d07 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -321,7 +321,7 @@ static int winbind_auth_request(pam_handle_t * pamh, request.data.auth.krb5_cc_type[0] = '\0'; request.data.auth.uid = -1; - request.flags = WBFLAG_PAM_INFO3_TEXT; + request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_GET_PWD_POLICY; if (ctrl & WINBIND_KRB5_AUTH) { -- cgit From ed8bfb44d376d62b27650ced4114dfabc383428c Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 17 Mar 2006 10:43:33 +0000 Subject: r14508: Return PAM_SUCCESS in pam_sm_close_session when there is no KRB5CCNAME environment. Guenther (This used to be commit 1f1402e45db8d80a7c19208fae934e1b0f3da134) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index b09e974d07..fb4cc187e1 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1086,7 +1086,7 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, ccname = pam_getenv(pamh, "KRB5CCNAME"); if (ccname == NULL) { _pam_log_debug(ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment"); - return PAM_BUF_ERR; + return PAM_SUCCESS; } fstrcpy(request.data.logoff.user, user); -- cgit From ca09263d00c7c5493f4ab7214c7cfb2cf8a28eea Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 6 Apr 2006 09:23:34 +0000 Subject: r14940: Remove pam_winbind's ability to create home directories on it's own. Guenther (This used to be commit 87293802f3e0666c9a50eb3ca63bb1a7dccc50dc) --- source3/nsswitch/pam_winbind.c | 58 ------------------------------------------ 1 file changed, 58 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index fb4cc187e1..d78d65287e 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -67,9 +67,6 @@ static int _pam_parse(int argc, const char **argv) (lp_parm_const_string(-1, "pam_winbind", "require_membership_of", NULL) != NULL)) { ctrl |= WINBIND_REQUIRED_MEMBERSHIP; } - if (lp_parm_bool(-1, "pam_winbind", "create_homedir", False)) { - ctrl |= WINBIND_CREATE_HOMEDIR; - } /* step through arguments */ for (; argc-- > 0; ++argv) { @@ -96,8 +93,6 @@ static int _pam_parse(int argc, const char **argv) ctrl |= WINBIND_KRB5_CCACHE_TYPE; else if (strequal(*argv, "cached_login")) ctrl |= WINBIND_CACHED_LOGIN; - else if (strequal(*argv, "create_homedir")) - ctrl |= WINBIND_CREATE_HOMEDIR; else { _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); } @@ -983,59 +978,6 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_open_session handler"); - - if (ctrl & WINBIND_CREATE_HOMEDIR) { - - struct passwd *pwd = NULL; - const char *username; - int ret; - fstring tok; - fstring create_dir; - SMB_STRUCT_STAT sbuf; - - /* Get the username */ - ret = pam_get_user(pamh, &username, NULL); - if ((ret != PAM_SUCCESS) || (!username)) { - _pam_log_debug(ctrl, LOG_DEBUG, "can not get the username"); - return PAM_SERVICE_ERR; - } - - pwd = getpwnam(username); - if (pwd == NULL) { - _pam_log_debug(ctrl, LOG_DEBUG, "can not get the username"); - return PAM_SERVICE_ERR; - } - - _pam_log_debug(ctrl, LOG_DEBUG, "homedir is: %s", pwd->pw_dir); - - if (directory_exist(pwd->pw_dir, &sbuf)) { - return PAM_SUCCESS; - } - - fstrcpy(create_dir, "/"); - while (next_token((const char **)&pwd->pw_dir, tok, "/", sizeof(tok))) { - - mode_t mode = 0755; - - fstrcat(create_dir, tok); - fstrcat(create_dir, "/"); - - if (!directory_exist(create_dir, &sbuf)) { - if (mkdir(create_dir, mode) != 0) { - _pam_log(LOG_ERR, "could not create dir: %s (%s)", - create_dir, strerror(errno)); - return PAM_SERVICE_ERR; - } - } - } - - if (sys_chown(create_dir, pwd->pw_uid, pwd->pw_gid) != 0) { - _pam_log(LOG_ERR, "failed to chown user homedir: %s (%s)", - create_dir, strerror(errno)); - return PAM_SERVICE_ERR; - } - } - return PAM_SUCCESS; } -- cgit From bbf666e447132a5f6b206ddf9ca918298b756392 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sat, 8 Apr 2006 17:25:31 +0000 Subject: r15003: patch based on code from Arkady Glabek to ensure that global memory is freed when unloading pam_winbind.so (needs more testing on non-linux platforms) (This used to be commit 1e0b79e591d70352a96e0a0487d8f394dc7b36ba) --- source3/nsswitch/pam_winbind.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index d78d65287e..2db10b69a8 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -17,6 +17,16 @@ #define MAX_PASSWD_TRIES 3 +/******************************************************************* + Need this destructor to free global memory when the shared library + is unloaded +*******************************************************************/ + +void __attribute__ ((destructor)) _fini_pam_winbind(void) +{ + gfree_all(); +} + /* some syslogging */ static void _pam_log(int err, const char *format, ...) { -- cgit From 9608b4328d9ffd4b8d38e1dc872f68d80dd1cc22 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 11 Apr 2006 14:40:53 +0000 Subject: r15038: Replace all code in pam_winbind that relied on access to samba internals, mostly with the code that was in pam_winbind before. Also switch from using loadparm to use iniParser to read the new pam_winbind options from a configuration file. That still uses the old (parametric) option names which will be replaced next (as iniParser does not support parametric options). Guenther (This used to be commit 6f668ce67318f17bba79cd98b5d169cd19eafcd4) --- source3/nsswitch/pam_winbind.c | 233 ++++++++++++++++++++++++++--------------- 1 file changed, 148 insertions(+), 85 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 2db10b69a8..3aa73e6016 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -10,23 +10,12 @@ (see copyright below for full details) */ -#include "includes.h" #include "pam_winbind.h" /* data tokens */ #define MAX_PASSWD_TRIES 3 -/******************************************************************* - Need this destructor to free global memory when the shared library - is unloaded -*******************************************************************/ - -void __attribute__ ((destructor)) _fini_pam_winbind(void) -{ - gfree_all(); -} - /* some syslogging */ static void _pam_log(int err, const char *format, ...) { @@ -54,54 +43,77 @@ static void _pam_log_debug(int ctrl, int err, const char *format, ...) closelog(); } -static int _pam_parse(int argc, const char **argv) +static int _pam_parse(int argc, const char **argv, dictionary **d) { int ctrl = 0; + const char *config_file = NULL; - load_case_tables(); + if (d == NULL || *d == NULL) { + goto config_from_pam; + } - if (!lp_load(dyn_CONFIGFILE,True,False,False,True)) { + for (; argc-- > 0; ++argv) { + if (!strncasecmp(*argv, "config", strlen("config"))) { + ctrl |= WINBIND_CONFIG_FILE; + config_file = argv[argc]; + break; + } + } + + if (config_file == NULL) { + config_file = dyn_CONFIGFILE; + } + + *d = iniparser_load(CONST_DISCARD(char *, config_file)); + if (*d == NULL) { return -1; } - if (lp_parm_bool(-1, "pam_winbind", "cached_login", False)) { + if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:pam_winbind:debug"), False)) { + ctrl |= WINBIND_DEBUG_ARG; + } + + if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:pam_winbind:cached_login"), False)) { ctrl |= WINBIND_CACHED_LOGIN; } - if (lp_parm_bool(-1, "pam_winbind", "krb5_auth", False)) { + + if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:pam_winbind:krb5_auth"), False) == True) { ctrl |= WINBIND_KRB5_AUTH; } - if (lp_parm_const_string(-1, "pam_winbind", "krb5_ccache_type", NULL) != NULL) { + + if (iniparser_getstr(*d, CONST_DISCARD(char *,"global:pam_winbind:krb5_ccache_type")) != NULL) { ctrl |= WINBIND_KRB5_CCACHE_TYPE; } - if ((lp_parm_const_string(-1, "pam_winbind", "require-membership-of", NULL) != NULL) || - (lp_parm_const_string(-1, "pam_winbind", "require_membership_of", NULL) != NULL)) { + + if ((iniparser_getstr(*d, CONST_DISCARD(char *, "global:pam_winbind:require-membership-of")) != NULL) || + (iniparser_getstr(*d, CONST_DISCARD(char *, "global:pam_winbind:require_membership_of")) != NULL)) { ctrl |= WINBIND_REQUIRED_MEMBERSHIP; } +config_from_pam: /* step through arguments */ for (; argc-- > 0; ++argv) { /* generic options */ - - if (!StrCaseCmp(*argv, "debug")) + if (!strcmp(*argv,"debug")) ctrl |= WINBIND_DEBUG_ARG; - else if (strequal(*argv, "use_authtok")) + else if (!strcasecmp(*argv, "use_authtok")) ctrl |= WINBIND_USE_AUTHTOK_ARG; - else if (strequal(*argv, "use_first_pass")) + else if (!strcasecmp(*argv, "use_first_pass")) ctrl |= WINBIND_USE_FIRST_PASS_ARG; - else if (strequal(*argv, "try_first_pass")) + else if (!strcasecmp(*argv, "try_first_pass")) ctrl |= WINBIND_TRY_FIRST_PASS_ARG; - else if (strequal(*argv, "unknown_ok")) + else if (!strcasecmp(*argv, "unknown_ok")) ctrl |= WINBIND_UNKNOWN_OK_ARG; - else if (strnequal(*argv, "require_membership_of", strlen("require_membership_of"))) + else if (!strncasecmp(*argv, "require_membership_of", strlen("require_membership_of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; - else if (strnequal(*argv, "require-membership-of", strlen("require-membership-of"))) + else if (!strncasecmp(*argv, "require-membership-of", strlen("require-membership-of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; - else if (strequal(*argv, "krb5_auth")) + else if (!strcasecmp(*argv, "krb5_auth")) ctrl |= WINBIND_KRB5_AUTH; - else if (strnequal(*argv, "krb5_ccache_type", strlen("krb5_ccache_type"))) + else if (!strncasecmp(*argv, "krb5_ccache_type", strlen("krb5_ccache_type"))) ctrl |= WINBIND_KRB5_CCACHE_TYPE; - else if (strequal(*argv, "cached_login")) + else if (!strcasecmp(*argv, "cached_login")) ctrl |= WINBIND_CACHED_LOGIN; else { _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); @@ -143,7 +155,7 @@ const char *_get_ntstatus_error_string(const char *nt_status_string) { int i; for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) { - if (strequal(ntstatus_errors[i].ntstatus_string, nt_status_string)) { + if (!strcasecmp(ntstatus_errors[i].ntstatus_string, nt_status_string)) { return ntstatus_errors[i].error_string; } } @@ -373,7 +385,8 @@ static int winbind_auth_request(pam_handle_t * pamh, _pam_log_debug(ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", member); /* fortunatly winbindd can handle non-separated names */ - fstrcpy(sid_request.data.name.name, member); + strncpy(sid_request.data.name.name, member, + sizeof(sid_request.data.name.name) - 1); if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) { _pam_log(LOG_INFO, "could not lookup name: %s\n", member); @@ -524,7 +537,7 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, /* TODO: tell the history length ? */ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_HISTORY_CONFLICT"); - if (strequal(response.data.auth.nt_status_string, "NT_STATUS_PASSWORD_RESTRICTION")) { + if (!strcasecmp(response.data.auth.nt_status_string, "NT_STATUS_PASSWORD_RESTRICTION")) { /* FIXME: avoid to send multiple PAM messages after another */ switch (response.data.auth.reject_reason) { @@ -590,7 +603,8 @@ static int valid_user(const char *user, pam_handle_t *pamh, int ctrl) return 1; } - fstrcpy(request.data.username, user); + strncpy(request.data.username, user, + sizeof(request.data.username) - 1); ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_GETPWNAM, &request, &response, user); @@ -705,12 +719,12 @@ static int _winbind_read_password(pam_handle_t * pamh, if (retval == PAM_SUCCESS) { /* a good conversation */ - token = SMB_STRDUP(resp[i - replies].resp); + token = x_strdup(resp[i - replies].resp); if (token != NULL) { if (replies == 2) { /* verify that password entered correctly */ if (!resp[i - 1].resp - || StrCaseCmp(token, resp[i - 1].resp)) { + || strcmp(token, resp[i - 1].resp)) { _pam_delete(token); /* mistyped */ retval = PAM_AUTHTOK_RECOVER_ERR; _make_remark(pamh, PAM_ERROR_MSG, MISTYPED_PASS); @@ -762,27 +776,38 @@ static int _winbind_read_password(pam_handle_t * pamh, const char *get_conf_item_string(int argc, const char **argv, - int ctrl, + int ctrl, + dictionary *d, const char *item, int flag) { int i = 0; char *parm = NULL; const char *parm_opt = NULL; + char *key = NULL; if (!(ctrl & flag)) { goto out; } /* let the pam opt take precedence over the smb.conf option */ - parm_opt = lp_parm_const_string(-1, "pam_winbind", item, NULL); + + if (d != NULL) { + + if (!asprintf(&key, "global:pam_winbind:%s", item)) { + goto out; + } + + parm_opt = iniparser_getstr(d, key); + SAFE_FREE(key); + } for ( i=0; ipw_uid; request.flags = WBFLAG_PAM_KRB5; - return pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_LOGOFF, &request, &response, user); + retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_LOGOFF, &request, &response, user); } - - return PAM_SUCCESS; + +out: + if (d) { + iniparser_freedict(d); + } + return retval; } @@ -1073,13 +1121,15 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, char *pass_old, *pass_new; /* */ - fstring Announce; + char *Announce; int retry = 0; + dictionary *d; - ctrl = _pam_parse(argc, argv); + ctrl = _pam_parse(argc, argv, &d); if (ctrl == -1) { - return PAM_SYSTEM_ERR; + retval = PAM_SYSTEM_ERR; + goto out; } _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_chauthtok"); @@ -1091,7 +1141,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (retval == PAM_SUCCESS) { if (user == NULL) { _pam_log(LOG_ERR, "username was NULL!"); - return PAM_USER_UNKNOWN; + retval = PAM_USER_UNKNOWN; + goto out; } if (retval == PAM_SUCCESS) { _pam_log_debug(ctrl, LOG_DEBUG, "username [%s] obtained", @@ -1100,16 +1151,18 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, } else { _pam_log_debug(ctrl, LOG_DEBUG, "password - could not identify user"); - return retval; + goto out; } /* check if this is really a user in winbindd, not only in NSS */ retval = valid_user(user, pamh, ctrl); switch (retval) { case 1: - return PAM_USER_UNKNOWN; + retval = PAM_USER_UNKNOWN; + goto out; case -1: - return PAM_SYSTEM_ERR; + retval = PAM_SYSTEM_ERR; + goto out; default: break; } @@ -1123,8 +1176,14 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, /* instruct user what is happening */ #define greeting "Changing password for " - fstrcpy(Announce, greeting); - fstrcat(Announce, user); + Announce = (char *) malloc(sizeof(greeting) + strlen(user)); + if (Announce == NULL) { + _pam_log(LOG_CRIT, "password - out of memory"); + retval = PAM_BUF_ERR; + goto out; + } + (void) strcpy(Announce, greeting); + (void) strcpy(Announce + sizeof(greeting) - 1, user); #undef greeting lctrl = ctrl | WINBIND__OLD_PASSWORD; @@ -1135,7 +1194,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, (const char **) &pass_old); if (retval != PAM_SUCCESS) { _pam_log(LOG_NOTICE, "password - (old) token not obtained"); - return retval; + goto out; } /* verify that this is the password for this user */ @@ -1146,7 +1205,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, && retval != PAM_NEW_AUTHTOK_REQD && retval != PAM_SUCCESS) { pass_old = NULL; - return retval; + goto out; } retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); @@ -1169,7 +1228,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (retval != PAM_SUCCESS) { _pam_log(LOG_NOTICE, "user not authenticated"); - return retval; + goto out; } lctrl = ctrl; @@ -1195,7 +1254,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, _pam_log_debug(ctrl, LOG_ALERT ,"password - new password not obtained"); pass_old = NULL;/* tidy up */ - return retval; + goto out; } /* @@ -1219,15 +1278,15 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, _pam_overwrite(pass_new); _pam_overwrite(pass_old); pass_old = pass_new = NULL; - return retval; + goto out; } /* just in case we need krb5 creds after a password change over msrpc */ if (ctrl & WINBIND_KRB5_AUTH) { - const char *member = get_member_from_config(argc, argv, ctrl); - const char *cctype = get_krb5_cc_type_from_config(argc, argv, ctrl); + const char *member = get_member_from_config(argc, argv, ctrl, d); + const char *cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d); retval = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, False); _pam_overwrite(pass_new); @@ -1238,6 +1297,10 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, retval = PAM_SERVICE_ERR; } +out: + if (d) { + iniparser_freedict(d); + } return retval; } -- cgit From 33788e5883b2d4e08a0d613044159df663162200 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 11 Apr 2006 15:11:27 +0000 Subject: r15039: Fix an uninitialized variable. I _think_ this should default to PAM_SUCCESS. Günther, could you take a look? MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks, Volker (This used to be commit fc6effcd9c2bb2d15b7e8fba85cc3193d2d7ce1f) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 3aa73e6016..420f52122a 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1031,7 +1031,7 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { dictionary *d; - int retval; + int retval = PAM_SUCCESS; /* parse arguments */ int ctrl = _pam_parse(argc, argv, &d); -- cgit From adc0a34cebfcd84b1886a8b1ddb8eecfd6fb1e1a Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 11 Apr 2006 15:18:46 +0000 Subject: r15040: Stripping the parametric options in pam_winbind and use /etc/security/pam_winbind.conf as config file for the PAM module by default. Guenther (This used to be commit 41b79ee80c7b0f4836ded51d42c7dc91cba75ccd) --- source3/nsswitch/pam_winbind.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 420f52122a..b2c3a01164 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -61,7 +61,7 @@ static int _pam_parse(int argc, const char **argv, dictionary **d) } if (config_file == NULL) { - config_file = dyn_CONFIGFILE; + config_file = PAM_WINBIND_CONFIG_FILE; } *d = iniparser_load(CONST_DISCARD(char *, config_file)); @@ -69,24 +69,24 @@ static int _pam_parse(int argc, const char **argv, dictionary **d) return -1; } - if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:pam_winbind:debug"), False)) { + if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:debug"), False)) { ctrl |= WINBIND_DEBUG_ARG; } - if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:pam_winbind:cached_login"), False)) { + if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:cached_login"), False)) { ctrl |= WINBIND_CACHED_LOGIN; } - if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:pam_winbind:krb5_auth"), False) == True) { + if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:krb5_auth"), False)) { ctrl |= WINBIND_KRB5_AUTH; } - if (iniparser_getstr(*d, CONST_DISCARD(char *,"global:pam_winbind:krb5_ccache_type")) != NULL) { + if (iniparser_getstr(*d, CONST_DISCARD(char *,"global:krb5_ccache_type")) != NULL) { ctrl |= WINBIND_KRB5_CCACHE_TYPE; } - if ((iniparser_getstr(*d, CONST_DISCARD(char *, "global:pam_winbind:require-membership-of")) != NULL) || - (iniparser_getstr(*d, CONST_DISCARD(char *, "global:pam_winbind:require_membership_of")) != NULL)) { + if ((iniparser_getstr(*d, CONST_DISCARD(char *, "global:require-membership-of")) != NULL) || + (iniparser_getstr(*d, CONST_DISCARD(char *, "global:require_membership_of")) != NULL)) { ctrl |= WINBIND_REQUIRED_MEMBERSHIP; } @@ -794,7 +794,7 @@ const char *get_conf_item_string(int argc, if (d != NULL) { - if (!asprintf(&key, "global:pam_winbind:%s", item)) { + if (!asprintf(&key, "global:%s", item)) { goto out; } -- cgit From af3490061b83ce83efb363bddcbcccf9f8a14d89 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 2 May 2006 19:22:39 +0000 Subject: r15398: Attempt to send the correct warning when a password change was attempted too early. Guenther (This used to be commit 7f64a66d25f2a4aa48c2639da8e783c1759c5dd4) --- source3/nsswitch/pam_winbind.c | 45 +++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index b2c3a01164..b340b8c6a7 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -320,7 +320,8 @@ static int winbind_auth_request(pam_handle_t * pamh, const char *pass, const char *member, const char *cctype, - int process_result) + int process_result, + time_t *pwd_last_set) { struct winbindd_request request; struct winbindd_response response; @@ -329,6 +330,10 @@ static int winbind_auth_request(pam_handle_t * pamh, ZERO_STRUCT(request); ZERO_STRUCT(response); + if (pwd_last_set) { + *pwd_last_set = 0; + } + strncpy(request.data.auth.user, user, sizeof(request.data.auth.user)-1); @@ -401,6 +406,10 @@ static int winbind_auth_request(pam_handle_t * pamh, ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, &request, &response, user); + if (pwd_last_set) { + *pwd_last_set = response.data.auth.info3.pass_last_set_time; + } + if ((ctrl & WINBIND_KRB5_AUTH) && response.data.auth.krb5ccname[0] != '\0') { @@ -487,7 +496,8 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, int ctrl, const char *user, const char *oldpass, - const char *newpass) + const char *newpass, + time_t pwd_last_set) { struct winbindd_request request; struct winbindd_response response; @@ -541,7 +551,13 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, /* FIXME: avoid to send multiple PAM messages after another */ switch (response.data.auth.reject_reason) { - case 0: + case -1: + break; + case REJECT_REASON_OTHER: + if ((response.data.auth.policy.min_passwordage > 0)) && + (pwd_last_set + response.data.auth.policy.min_passwordage > time(NULL)) { + PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_RECENT"); + } break; case REJECT_REASON_TOO_SHORT: PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_SHORT"); @@ -892,7 +908,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d); /* Now use the username to look up password */ - retval = winbind_auth_request(pamh, ctrl, username, password, member, cctype, True); + retval = winbind_auth_request(pamh, ctrl, username, password, member, cctype, True, NULL); if (retval == PAM_NEW_AUTHTOK_REQD || retval == PAM_AUTHTOK_EXPIRED) { @@ -1174,6 +1190,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (flags & PAM_PRELIM_CHECK) { + time_t pwdlastset_prelim = 0; + /* instruct user what is happening */ #define greeting "Changing password for " Announce = (char *) malloc(sizeof(greeting) + strlen(user)); @@ -1198,16 +1216,18 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, } /* verify that this is the password for this user */ - retval = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, False); + retval = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, False, &pwdlastset_prelim); - if (retval != PAM_ACCT_EXPIRED - && retval != PAM_AUTHTOK_EXPIRED - && retval != PAM_NEW_AUTHTOK_REQD - && retval != PAM_SUCCESS) { + if (retval != PAM_ACCT_EXPIRED && + retval != PAM_AUTHTOK_EXPIRED && + retval != PAM_NEW_AUTHTOK_REQD && + retval != PAM_SUCCESS) { pass_old = NULL; goto out; } + pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, (void *)pwdlastset_prelim, _pam_winbind_cleanup_func); + retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); pass_old = NULL; if (retval != PAM_SUCCESS) { @@ -1215,6 +1235,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, } } else if (flags & PAM_UPDATE_AUTHTOK) { + time_t pwdlastset_update = 0; + /* * obtain the proposed password */ @@ -1272,8 +1294,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * By reaching here we have approved the passwords and must now * rebuild the password database file. */ + pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, (const void **)&pwdlastset_update); - retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new); + retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update); if (retval) { _pam_overwrite(pass_new); _pam_overwrite(pass_old); @@ -1288,7 +1311,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, const char *member = get_member_from_config(argc, argv, ctrl, d); const char *cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d); - retval = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, False); + retval = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, False, NULL); _pam_overwrite(pass_new); _pam_overwrite(pass_old); pass_old = pass_new = NULL; -- cgit From 1ef64a46df473bdd4e57f4a487ed2c0f77186cee Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 2 May 2006 20:03:30 +0000 Subject: r15399: Fix the build, sorry, Jerry :) Guenther (This used to be commit cc800ced60e5e6bbd923a3a0b7d58650c6e14121) --- source3/nsswitch/pam_winbind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index b340b8c6a7..96fd4d1089 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -554,8 +554,8 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, case -1: break; case REJECT_REASON_OTHER: - if ((response.data.auth.policy.min_passwordage > 0)) && - (pwd_last_set + response.data.auth.policy.min_passwordage > time(NULL)) { + if ((response.data.auth.policy.min_passwordage > 0) && + (pwd_last_set + response.data.auth.policy.min_passwordage > time(NULL))) { PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_RECENT"); } break; -- cgit From 627c4b381a1d94dc72587f414aaeaaa6a2a9db3b Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 3 May 2006 10:19:49 +0000 Subject: r15411: Small debug fixes for the PAM module. Guenther (This used to be commit 1856dc0f52b2a2ba2e59f1a7a77ccd32c27928c0) --- source3/nsswitch/pam_winbind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 96fd4d1089..a91129a805 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -286,8 +286,7 @@ static int pam_winbind_request_log(pam_handle_t * pamh, return retval; case PAM_USER_UNKNOWN: /* the user does not exist */ - _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found", - user); + _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found", user); if (ctrl & WINBIND_UNKNOWN_OK_ARG) { return PAM_IGNORE; } @@ -475,6 +474,7 @@ static int winbind_auth_request(pam_handle_t * pamh, if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) { _make_remark(pamh, PAM_ERROR_MSG, "Logging on using cached account. Network ressources can be unavailable"); + _pam_log_debug(ctrl, LOG_DEBUG,"User %s logged on using cached account\n", user); } /* save the CIFS homedir for pam_cifs / pam_mount */ -- cgit From 3cdd91112eb9045e65a294384a6d08d0cc6f0d36 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 3 May 2006 15:19:31 +0000 Subject: r15417: Don't use cached credentials when changing passwords. Guenther (This used to be commit 34b29c30b2f4b5a3c40a65ca8338c87a4c16f3ff) --- source3/nsswitch/pam_winbind.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index a91129a805..3b42e404a4 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -242,8 +242,9 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, /* Copy reply data from socket */ if (response->result != WINBINDD_OK) { if (response->data.auth.pam_error != PAM_SUCCESS) { - _pam_log(LOG_ERR, "request failed: %s, PAM error was %d, NT error was %s", + _pam_log(LOG_ERR, "request failed: %s, PAM error was %s (%d), NT error was %s", response->data.auth.error_string, + pam_strerror(pamh, response->data.auth.pam_error), response->data.auth.pam_error, response->data.auth.nt_status_string); return response->data.auth.pam_error; @@ -1150,6 +1151,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_chauthtok"); + /* clearing offline bit for the auth in the password change */ + ctrl &= ~WINBIND_CACHED_LOGIN; + /* * First get the name of a user */ -- cgit From 2e83035b8332889379127f3b4f123394eba2b7ba Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 6 May 2006 20:12:42 +0000 Subject: r15478: Likewise for bug # 3763 (This used to be commit 7188ec6bd81715c4df17528bca2b2e658173043f) --- source3/nsswitch/pam_winbind.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 3b42e404a4..239db5da5b 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -191,7 +191,7 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text) struct pam_response *resp; pmsg[0] = &msg[0]; - msg[0].msg = text; + msg[0].msg = CONST_DISCARD(char *, text); msg[0].msg_style = type; resp = NULL; @@ -709,7 +709,7 @@ static int _winbind_read_password(pam_handle_t * pamh, if (comment != NULL) { pmsg[0] = &msg[0]; msg[0].msg_style = PAM_TEXT_INFO; - msg[0].msg = comment; + msg[0].msg = CONST_DISCARD(char *, comment); i = 1; } else { i = 0; @@ -717,13 +717,13 @@ static int _winbind_read_password(pam_handle_t * pamh, pmsg[i] = &msg[i]; msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = prompt1; + msg[i++].msg = CONST_DISCARD(char *, prompt1); replies = 1; if (prompt2 != NULL) { pmsg[i] = &msg[i]; msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = prompt2; + msg[i++].msg = CONST_DISCARD(char *, prompt2); ++replies; } /* so call the conversation expecting i responses */ -- cgit From f65ff9d637d6d7c6fa005d77d1ea2844c0c87ce4 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 10 May 2006 21:12:10 +0000 Subject: r15528: Make the existance of the /etc/security/pam_winbind.conf file non-critical and fallback to only parse the argv options in that case. Guenther (This used to be commit 9dac3ab328e9c7ba374e0efc3fe16d940ecc9d3b) --- source3/nsswitch/pam_winbind.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 239db5da5b..e57114ec28 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -66,7 +66,7 @@ static int _pam_parse(int argc, const char **argv, dictionary **d) *d = iniparser_load(CONST_DISCARD(char *, config_file)); if (*d == NULL) { - return -1; + goto config_from_pam; } if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:debug"), False)) { @@ -807,7 +807,7 @@ const char *get_conf_item_string(int argc, goto out; } - /* let the pam opt take precedence over the smb.conf option */ + /* let the pam opt take precedence over the pam_winbind.conf option */ if (d != NULL) { @@ -836,7 +836,9 @@ const char *get_conf_item_string(int argc, } } - _pam_log_debug(ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt); + if (d != NULL) { + _pam_log_debug(ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt); + } out: SAFE_FREE(parm); return parm_opt; -- cgit From f01b0cca2ecedc9c074d5d7742c7cd7134dc26e3 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 12 May 2006 19:16:10 +0000 Subject: r15546: When debugging is enabled be just a little more verbose in logging in pam_winbind. Guenther (This used to be commit bf077fb2268b79faffd1fdda04847c37ffead32d) --- source3/nsswitch/pam_winbind.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index e57114ec28..43ac83a99a 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -877,7 +877,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, goto out; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_authenticate"); + _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_authenticate (flags: 0x%04x)", flags); /* Get the username */ retval = pam_get_user(pamh, &username, NULL); @@ -946,7 +946,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, return PAM_SYSTEM_ERR; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_setcred"); + _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_setcred (flags: 0x%04x)", flags); if (flags & PAM_DELETE_CRED) { return pam_sm_close_session(pamh, flags, argc, argv); @@ -973,7 +973,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, return PAM_SYSTEM_ERR; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_acct_mgmt"); + _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_acct_mgmt (flags: 0x%04x)", flags); /* Get the username */ @@ -1040,7 +1040,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, return PAM_SYSTEM_ERR; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_open_session handler"); + _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_open_session handler (flags: 0x%04x)", flags); return PAM_SUCCESS; } @@ -1059,7 +1059,7 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, goto out; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_close_session handler"); + _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_close_session handler (flags: 0x%04x)", flags); if (!(flags & PAM_DELETE_CRED)) { retval = PAM_SUCCESS; @@ -1151,7 +1151,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, goto out; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_chauthtok"); + _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_chauthtok (flags: 0x%04x)", flags); /* clearing offline bit for the auth in the password change */ ctrl &= ~WINBIND_CACHED_LOGIN; -- cgit From a6f5c7998006ef485ef50166a4c5bf478ae63dd5 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 31 May 2006 15:45:19 +0000 Subject: r15984: Correctly handle the case when there is no configuration file for pam_winbind. Guenther (This used to be commit 29758ea1c4e1b9b57d27765d539306058299fcd1) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 43ac83a99a..8110a02a68 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -48,7 +48,7 @@ static int _pam_parse(int argc, const char **argv, dictionary **d) int ctrl = 0; const char *config_file = NULL; - if (d == NULL || *d == NULL) { + if (d == NULL) { goto config_from_pam; } -- cgit From 6139f49d60a9f2554505bf5cf2781168478ded9d Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 11 Jul 2006 10:39:32 +0000 Subject: r16941: Fix crash bug when the pam conversation receives an empty token. Thanks to Bjoern Jacke for the report and test-case. Guenther (This used to be commit f2ebc0e3de396f44f49dabbfe42cb3ad1c1a7ec1) --- source3/nsswitch/pam_winbind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 8110a02a68..78776256e9 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -748,8 +748,8 @@ static int _winbind_read_password(pam_handle_t * pamh, } } } else { - _pam_log(LOG_NOTICE - ,"could not recover authentication token"); + _pam_log(LOG_NOTICE, "could not recover authentication token"); + retval = PAM_AUTHTOK_RECOVER_ERR; } } -- cgit From fbdcf2663b56007a438ac4f0d8d82436b1bfe688 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Jul 2006 18:01:26 +0000 Subject: r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need to do the upper layer directories but this is what everyone is waiting for.... Jeremy. (This used to be commit 9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8) --- source3/nsswitch/pam_winbind.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 78776256e9..118ba358e1 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -128,6 +128,24 @@ static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_ SAFE_FREE(data); } +/* + * Work around the pam API that has functions with void ** as parameters. + * These lead to strict aliasing warnings with gcc. + */ +static int _pam_get_item(const pam_handle_t *pamh, int item_type, + const void *_item) +{ + const void **item = (const void **)_item; + return pam_get_item(pamh, item_type, item); +} +static int _pam_get_data(const pam_handle_t *pamh, + const char *module_data_name, const void *_data) +{ + const void **data = (const void **)_data; + return pam_get_data(pamh, module_data_name, data); +} + + static const struct ntstatus_errors { const char *ntstatus_string; const char *error_string; @@ -173,7 +191,7 @@ static int converse(pam_handle_t *pamh, int nargs, int retval; struct pam_conv *conv; - retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ); + retval = _pam_get_item(pamh, PAM_CONV, &conv ); if (retval == PAM_SUCCESS) { retval = conv->conv(nargs, (const struct pam_message **)message, response, conv->appdata_ptr); @@ -676,7 +694,7 @@ static int _winbind_read_password(pam_handle_t * pamh, */ if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { - retval = pam_get_item(pamh, authtok_flag, (const void **) &item); + retval = _pam_get_item(pamh, authtok_flag, &item); if (retval != PAM_SUCCESS) { /* very strange. */ _pam_log(LOG_ALERT, @@ -778,7 +796,7 @@ static int _winbind_read_password(pam_handle_t * pamh, retval = pam_set_item(pamh, authtok_flag, token); _pam_delete(token); /* clean it up */ if (retval != PAM_SUCCESS || - (retval = pam_get_item(pamh, authtok_flag, (const void **) &item)) != PAM_SUCCESS) { + (retval = _pam_get_item(pamh, authtok_flag, &item)) != PAM_SUCCESS) { _pam_log(LOG_CRIT, "error manipulating password"); return retval; @@ -1251,8 +1269,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * get the old token back. */ - retval = pam_get_item(pamh, PAM_OLDAUTHTOK, - (const void **) &pass_old); + retval = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old); if (retval != PAM_SUCCESS) { _pam_log(LOG_NOTICE, "user not authenticated"); @@ -1300,7 +1317,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * By reaching here we have approved the passwords and must now * rebuild the password database file. */ - pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, (const void **)&pwdlastset_update); + _pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, + &pwdlastset_update); retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update); if (retval) { -- cgit From 803748b15dec1787ab5be9df3b039f59a34f8ee6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 13 Jul 2006 16:31:26 +0000 Subject: r17017: BUG 3916: fix pam config file parsing in pam_winbind. Patch from Dietrich Streifert (This used to be commit 8d6218825827a54ca69e462c00a3dc9e25ef3ddf) --- source3/nsswitch/pam_winbind.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 118ba358e1..393dc29245 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -47,15 +47,17 @@ static int _pam_parse(int argc, const char **argv, dictionary **d) { int ctrl = 0; const char *config_file = NULL; + int i; + const char **v; if (d == NULL) { goto config_from_pam; } - for (; argc-- > 0; ++argv) { - if (!strncasecmp(*argv, "config", strlen("config"))) { + for (i=argc,v=argv; i-- > 0; ++v) { + if (!strncasecmp(*v, "config", strlen("config"))) { ctrl |= WINBIND_CONFIG_FILE; - config_file = argv[argc]; + config_file = v[i]; break; } } @@ -92,31 +94,31 @@ static int _pam_parse(int argc, const char **argv, dictionary **d) config_from_pam: /* step through arguments */ - for (; argc-- > 0; ++argv) { + for (i=argc,v=argv; i-- > 0; ++v) { /* generic options */ - if (!strcmp(*argv,"debug")) + if (!strcmp(*v,"debug")) ctrl |= WINBIND_DEBUG_ARG; - else if (!strcasecmp(*argv, "use_authtok")) + else if (!strcasecmp(*v, "use_authtok")) ctrl |= WINBIND_USE_AUTHTOK_ARG; - else if (!strcasecmp(*argv, "use_first_pass")) + else if (!strcasecmp(*v, "use_first_pass")) ctrl |= WINBIND_USE_FIRST_PASS_ARG; - else if (!strcasecmp(*argv, "try_first_pass")) + else if (!strcasecmp(*v, "try_first_pass")) ctrl |= WINBIND_TRY_FIRST_PASS_ARG; - else if (!strcasecmp(*argv, "unknown_ok")) + else if (!strcasecmp(*v, "unknown_ok")) ctrl |= WINBIND_UNKNOWN_OK_ARG; - else if (!strncasecmp(*argv, "require_membership_of", strlen("require_membership_of"))) + else if (!strncasecmp(*v, "require_membership_of", strlen("require_membership_of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; - else if (!strncasecmp(*argv, "require-membership-of", strlen("require-membership-of"))) + else if (!strncasecmp(*v, "require-membership-of", strlen("require-membership-of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; - else if (!strcasecmp(*argv, "krb5_auth")) + else if (!strcasecmp(*v, "krb5_auth")) ctrl |= WINBIND_KRB5_AUTH; - else if (!strncasecmp(*argv, "krb5_ccache_type", strlen("krb5_ccache_type"))) + else if (!strncasecmp(*v, "krb5_ccache_type", strlen("krb5_ccache_type"))) ctrl |= WINBIND_KRB5_CCACHE_TYPE; - else if (!strcasecmp(*argv, "cached_login")) + else if (!strcasecmp(*v, "cached_login")) ctrl |= WINBIND_CACHED_LOGIN; else { - _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); + _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *v); } } -- cgit From 41449a85e64325d16c63ea4e6ee57254c8aac996 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 1 Aug 2006 15:17:18 +0000 Subject: r17365: Fix memleak. Guenther (This used to be commit 62a8e0b08919e71c6a575ce6d89d8a4a09acbd87) --- source3/nsswitch/pam_winbind.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 393dc29245..f96dd0ee9b 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -227,12 +227,15 @@ static int _make_remark_format(pam_handle_t * pamh, int type, const char *format { va_list args; char *var; + int ret; va_start(args, format); vasprintf(&var, format, args); va_end(args); - return _make_remark(pamh, type, var); + ret = _make_remark(pamh, type, var); + SAFE_FREE(var); + return ret; } static int pam_winbind_request(pam_handle_t * pamh, int ctrl, -- cgit From ec17ea6b069fee0dca351dc53bcbb1c2ebaa0690 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 1 Aug 2006 15:31:16 +0000 Subject: r17366: Save the logon script path from the info3 in the PAM session allowing other PAM modules to pick it up from there. Guenther (This used to be commit b3ac5a586ba37b1122b0dc941dfee648fc4fa6d5) --- source3/nsswitch/pam_winbind.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index f96dd0ee9b..1aef5c6c4a 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -503,13 +503,27 @@ static int winbind_auth_request(pam_handle_t * pamh, /* save the CIFS homedir for pam_cifs / pam_mount */ if (response.data.auth.info3.home_dir[0] != '\0') { - char *buf; - if (!asprintf(&buf, "%s", response.data.auth.info3.home_dir)) { - return PAM_BUF_ERR; + int ret2 = pam_set_data(pamh, PAM_WINBIND_HOMEDIR, + (void *) strdup(response.data.auth.info3.home_dir), + _pam_winbind_cleanup_func); + if (ret2) { + _pam_log_debug(ctrl, LOG_DEBUG, "Could not set data: %s", + pam_strerror(pamh, ret2)); } - pam_set_data( pamh, PAM_WINBIND_HOMEDIR, (void *)buf, _pam_winbind_cleanup_func); + } + + /* save the logon script path for other PAM modules */ + if (response.data.auth.info3.logon_script[0] != '\0') { + + int ret2 = pam_set_data(pamh, PAM_WINBIND_LOGONSCRIPT, + (void *) strdup(response.data.auth.info3.logon_script), + _pam_winbind_cleanup_func); + if (ret2) { + _pam_log_debug(ctrl, LOG_DEBUG, "Could not set data: %s", + pam_strerror(pamh, ret2)); + } } return ret; -- cgit From 0691ed55cade8093213db38555edb536ee0c557d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 17 Aug 2006 11:54:23 +0000 Subject: r17584: Some C++ Warnings (This used to be commit f6194cf4b263454bbdf180a7d014ffc3498df497) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 1aef5c6c4a..f2dacf241e 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1036,7 +1036,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, case 0: pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp); if (tmp != NULL) { - retval = atoi(tmp); + retval = atoi((const char *)tmp); switch (retval) { case PAM_AUTHTOK_EXPIRED: /* fall through, since new token is required in this case */ -- cgit From 975b15949013f86ffa43675537183b20f3519ed2 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 22 Aug 2006 22:53:08 +0000 Subject: r17723: * BUG 3969: Fix unsigned time comparison with expiration policy from AD DC * Merge patches from SLES10 to make sure we talk to the correct winbindd process when performing pam_auth (and pull the password policy info). (This used to be commit 43bd8c00abb38eb23a1497a255d194fb1bbffffb) --- source3/nsswitch/pam_winbind.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index f2dacf241e..ea50b1ac74 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -366,7 +366,7 @@ static int winbind_auth_request(pam_handle_t * pamh, request.data.auth.krb5_cc_type[0] = '\0'; request.data.auth.uid = -1; - request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_GET_PWD_POLICY; + request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_CONTACT_TRUSTDOM; if (ctrl & WINBIND_KRB5_AUTH) { @@ -564,7 +564,7 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, } if (ctrl & WINBIND_KRB5_AUTH) { - request.flags = WBFLAG_PAM_KRB5; + request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; } ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_CHAUTHTOK, &request, &response, user); @@ -1150,7 +1150,7 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, } request.data.logoff.uid = pwd->pw_uid; - request.flags = WBFLAG_PAM_KRB5; + request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_LOGOFF, &request, &response, user); } @@ -1391,7 +1391,7 @@ struct pam_module _pam_winbind_modstruct = { * Copyright (c) Tim Potter 2000 * Copyright (c) Andrew Bartlettt 2002 * Copyright (c) Guenther Deschner 2005-2006 - * Copyright (c) Jan Rêkorajski 1999. + * Copyright (c) Jan Rêkorajski 1999. * Copyright (c) Andrew G. Morgan 1996-8. * Copyright (c) Alex O. Yuriev, 1996. * Copyright (c) Cristian Gafton 1996. -- cgit From d2465b17300168c37230de34f71e99d5b02d306d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 5 Sep 2006 05:28:31 +0000 Subject: r18062: Fix to ensure the name used by pam matches the name that will be returned by winbindd. This (should) fix the bug where the user logs in with DOMAIN\user but winbindd returns only "user" for the username due to 'winbind use default domain' being set. Jeremy. (This used to be commit 1b2aa17354d50740902010f4a1e0217c8b1f7bdd) --- source3/nsswitch/pam_winbind.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index ea50b1ac74..78b0e8c28b 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -344,7 +344,8 @@ static int winbind_auth_request(pam_handle_t * pamh, const char *member, const char *cctype, int process_result, - time_t *pwd_last_set) + time_t *pwd_last_set, + char **user_ret) { struct winbindd_request request; struct winbindd_response response; @@ -388,6 +389,11 @@ static int winbind_auth_request(pam_handle_t * pamh, request.flags |= WBFLAG_PAM_CACHED_LOGIN; } + if (user_ret) { + *user_ret = NULL; + request.flags |= WBFLAG_PAM_UNIX_NAME; + } + if (cctype != NULL) { strncpy(request.data.auth.krb5_cc_type, cctype, sizeof(request.data.auth.krb5_cc_type) - 1); @@ -526,6 +532,12 @@ static int winbind_auth_request(pam_handle_t * pamh, } } + /* If winbindd returned a username, return the pointer to it here. */ + if (user_ret && response.extra_data.data) { + /* We have to trust it's a null terminated string. */ + *user_ret = response.extra_data.data; + } + return ret; } @@ -906,6 +918,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, const char *cctype = NULL; int retval = PAM_AUTH_ERR; dictionary *d; + char *username_ret = NULL; /* parse arguments */ int ctrl = _pam_parse(argc, argv, &d); @@ -948,7 +961,8 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d); /* Now use the username to look up password */ - retval = winbind_auth_request(pamh, ctrl, username, password, member, cctype, True, NULL); + retval = winbind_auth_request(pamh, ctrl, username, password, member, + cctype, True, NULL, &username_ret); if (retval == PAM_NEW_AUTHTOK_REQD || retval == PAM_AUTHTOK_EXPIRED) { @@ -967,6 +981,11 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, } out: + if (username_ret) { + pam_set_item (pamh, PAM_USER, username_ret); + free(username_ret); + } + if (d) { iniparser_freedict(d); } @@ -1259,7 +1278,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, } /* verify that this is the password for this user */ - retval = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, False, &pwdlastset_prelim); + retval = winbind_auth_request(pamh, ctrl, user, pass_old, + NULL, NULL, False, &pwdlastset_prelim, NULL); if (retval != PAM_ACCT_EXPIRED && retval != PAM_AUTHTOK_EXPIRED && @@ -1354,7 +1374,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, const char *member = get_member_from_config(argc, argv, ctrl, d); const char *cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d); - retval = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, False, NULL); + retval = winbind_auth_request(pamh, ctrl, user, pass_new, + member, cctype, False, NULL, NULL); _pam_overwrite(pass_new); _pam_overwrite(pass_old); pass_old = pass_new = NULL; -- cgit From 030cf71d618e5522f948b32292e3612c9dd4ef24 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 6 Sep 2006 10:59:39 +0000 Subject: r18158: Stop winbindd from accumulating memory creds infinitely when doing pam offline logons. Guenther (This used to be commit 95788cb291b89b431972e29e148b412992cc32a5) --- source3/nsswitch/pam_winbind.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 78b0e8c28b..bcc4d7e795 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1152,15 +1152,15 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, ccname = pam_getenv(pamh, "KRB5CCNAME"); if (ccname == NULL) { _pam_log_debug(ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment"); - retval = PAM_SUCCESS; - goto out; } strncpy(request.data.logoff.user, user, sizeof(request.data.logoff.user) - 1); - strncpy(request.data.logoff.krb5ccname, ccname, - sizeof(request.data.logoff.krb5ccname) - 1); + if (ccname) { + strncpy(request.data.logoff.krb5ccname, ccname, + sizeof(request.data.logoff.krb5ccname) - 1); + } pwd = getpwnam(user); if (pwd == NULL) { -- cgit From 1f0b2e84d71e2a7b06de288dbb54d2f12b6ca0e1 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 13 Sep 2006 16:39:52 +0000 Subject: r18484: Start some cleanup on pam_winbind's syslogging: * as openlog() is non-reentrant and pam_winbind thereby overrides the syslog settings of the calling application, directly call syslog (or pam_vsyslog if available) * support the PAM_SILENT flag to avoid any log messages beeing created Guenther (This used to be commit 0f7e37ffc4759a4e29f63ab83f39ddb31c8240f6) --- source3/nsswitch/pam_winbind.c | 267 ++++++++++++++++++++++++----------------- 1 file changed, 154 insertions(+), 113 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index bcc4d7e795..64356e579a 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -16,40 +16,93 @@ #define MAX_PASSWD_TRIES 3 +/* + * Work around the pam API that has functions with void ** as parameters. + * These lead to strict aliasing warnings with gcc. + */ +static int _pam_get_item(const pam_handle_t *pamh, int item_type, + const void *_item) +{ + const void **item = (const void **)_item; + return pam_get_item(pamh, item_type, item); +} +static int _pam_get_data(const pam_handle_t *pamh, + const char *module_data_name, const void *_data) +{ + const void **data = (const void **)_data; + return pam_get_data(pamh, module_data_name, data); +} + /* some syslogging */ -static void _pam_log(int err, const char *format, ...) + +static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, va_list args) +{ + +#ifdef HAVE_PAM_VSYSLOG + pam_vsyslog(pamh, err, format, args); +#else + { + + char *format2 = NULL; + const char *service; + + _pam_get_item(pamh, PAM_SERVICE, &service); + + format2 = malloc(strlen(MODULE_NAME)+strlen(format)+strlen(service)+5); + if (format2 == NULL) { + /* what else todo ? */ + vsyslog(err, format, args); + return; + } + + sprintf(format2, "%s(%s): %s", MODULE_NAME, service, format); + vsyslog(err, format2, args); + SAFE_FREE(format2); + } +#endif +} + +static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) { va_list args; + if (ctrl & WINBIND_SILENT) { + return; + } + va_start(args, format); - openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(err, format, args); + _pam_log_int(pamh, err, format, args); va_end(args); - closelog(); } -static void _pam_log_debug(int ctrl, int err, const char *format, ...) +static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) { va_list args; + if (ctrl & WINBIND_SILENT) { + return; + } + if (!(ctrl & WINBIND_DEBUG_ARG)) { return; } va_start(args, format); - openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(err, format, args); + _pam_log_int(pamh, err, format, args); va_end(args); - closelog(); } -static int _pam_parse(int argc, const char **argv, dictionary **d) +static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char **argv, dictionary **d) { int ctrl = 0; const char *config_file = NULL; int i; const char **v; + if (flags & PAM_SILENT) { + ctrl |= WINBIND_SILENT; + } + if (d == NULL) { goto config_from_pam; } @@ -83,6 +136,10 @@ static int _pam_parse(int argc, const char **argv, dictionary **d) ctrl |= WINBIND_KRB5_AUTH; } + if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:silent"), False)) { + ctrl |= WINBIND_SILENT; + } + if (iniparser_getstr(*d, CONST_DISCARD(char *,"global:krb5_ccache_type")) != NULL) { ctrl |= WINBIND_KRB5_CCACHE_TYPE; } @@ -118,7 +175,7 @@ config_from_pam: else if (!strcasecmp(*v, "cached_login")) ctrl |= WINBIND_CACHED_LOGIN; else { - _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *v); + _pam_log(pamh, ctrl, LOG_ERR, "pam_parse: unknown option; %s", *v); } } @@ -130,23 +187,6 @@ static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_ SAFE_FREE(data); } -/* - * Work around the pam API that has functions with void ** as parameters. - * These lead to strict aliasing warnings with gcc. - */ -static int _pam_get_item(const pam_handle_t *pamh, int item_type, - const void *_item) -{ - const void **item = (const void **)_item; - return pam_get_item(pamh, item_type, item); -} -static int _pam_get_data(const pam_handle_t *pamh, - const char *module_data_name, const void *_data) -{ - const void **data = (const void **)_data; - return pam_get_data(pamh, module_data_name, data); -} - static const struct ntstatus_errors { const char *ntstatus_string; @@ -247,14 +287,14 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, init_request(request, req_type); if (write_sock(request, sizeof(*request), 0) == -1) { - _pam_log(LOG_ERR, "write to socket failed!"); + _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!"); close_sock(); return PAM_SERVICE_ERR; } /* Wait for reply */ if (read_reply(response) == -1) { - _pam_log(LOG_ERR, "read from socket failed!"); + _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: read from socket failed!"); close_sock(); return PAM_SERVICE_ERR; } @@ -265,14 +305,14 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, /* Copy reply data from socket */ if (response->result != WINBINDD_OK) { if (response->data.auth.pam_error != PAM_SUCCESS) { - _pam_log(LOG_ERR, "request failed: %s, PAM error was %s (%d), NT error was %s", + _pam_log(pamh, ctrl, LOG_ERR, "request failed: %s, PAM error was %s (%d), NT error was %s", response->data.auth.error_string, pam_strerror(pamh, response->data.auth.pam_error), response->data.auth.pam_error, response->data.auth.nt_status_string); return response->data.auth.pam_error; } else { - _pam_log(LOG_ERR, "request failed, but PAM error 0!"); + _pam_log(pamh, ctrl, LOG_ERR, "request failed, but PAM error 0!"); return PAM_SERVICE_ERR; } } @@ -280,7 +320,7 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, return PAM_SUCCESS; } -static int pam_winbind_request_log(pam_handle_t * pamh, +static int pam_winbind_request_log(pam_handle_t * pamh, int ctrl, enum winbindd_cmd req_type, struct winbindd_request *request, @@ -294,23 +334,23 @@ static int pam_winbind_request_log(pam_handle_t * pamh, switch (retval) { case PAM_AUTH_ERR: /* incorrect password */ - _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password or invalid membership)", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' denied access (incorrect password or invalid membership)", user); return retval; case PAM_ACCT_EXPIRED: /* account expired */ - _pam_log(LOG_WARNING, "user `%s' account expired", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' account expired", user); return retval; case PAM_AUTHTOK_EXPIRED: /* password expired */ - _pam_log(LOG_WARNING, "user `%s' password expired", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' password expired", user); return retval; case PAM_NEW_AUTHTOK_REQD: /* new password required */ - _pam_log(LOG_WARNING, "user `%s' new password required", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' new password required", user); return retval; case PAM_USER_UNKNOWN: /* the user does not exist */ - _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found", user); + _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", user); if (ctrl & WINBIND_UNKNOWN_OK_ARG) { return PAM_IGNORE; } @@ -318,26 +358,26 @@ static int pam_winbind_request_log(pam_handle_t * pamh, case PAM_SUCCESS: if (req_type == WINBINDD_PAM_AUTH) { /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted access", user); + _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", user); } else if (req_type == WINBINDD_PAM_CHAUTHTOK) { /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' password changed", user); + _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' password changed", user); } else { /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' OK", user); + _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' OK", user); } return retval; default: /* we don't know anything about this return value */ - _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s')", + _pam_log(pamh, ctrl, LOG_ERR, "internal module error (retval = %d, user = '%s')", retval, user); return retval; } } /* talk to winbindd */ -static int winbind_auth_request(pam_handle_t * pamh, +static int winbind_auth_request(pam_handle_t * pamh, int ctrl, const char *user, const char *pass, @@ -373,7 +413,7 @@ static int winbind_auth_request(pam_handle_t * pamh, struct passwd *pwd = NULL; - _pam_log_debug(ctrl, LOG_DEBUG, "enabling krb5 login flag\n"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling krb5 login flag\n"); request.flags |= WBFLAG_PAM_KRB5 | WBFLAG_PAM_FALLBACK_AFTER_KRB5; @@ -385,7 +425,7 @@ static int winbind_auth_request(pam_handle_t * pamh, } if (ctrl & WINBIND_CACHED_LOGIN) { - _pam_log_debug(ctrl, LOG_DEBUG, "enabling cached login flag\n"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling cached login flag\n"); request.flags |= WBFLAG_PAM_CACHED_LOGIN; } @@ -397,7 +437,7 @@ static int winbind_auth_request(pam_handle_t * pamh, if (cctype != NULL) { strncpy(request.data.auth.krb5_cc_type, cctype, sizeof(request.data.auth.krb5_cc_type) - 1); - _pam_log_debug(ctrl, LOG_DEBUG, "enabling request for a %s krb5 ccache\n", cctype); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling request for a %s krb5 ccache\n", cctype); } request.data.auth.require_membership_of_sid[0] = '\0'; @@ -416,14 +456,14 @@ static int winbind_auth_request(pam_handle_t * pamh, ZERO_STRUCT(sid_request); ZERO_STRUCT(sid_response); - _pam_log_debug(ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", member); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", member); /* fortunatly winbindd can handle non-separated names */ strncpy(sid_request.data.name.name, member, sizeof(sid_request.data.name.name) - 1); if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) { - _pam_log(LOG_INFO, "could not lookup name: %s\n", member); + _pam_log(pamh, ctrl, LOG_INFO, "could not lookup name: %s\n", member); return PAM_AUTH_ERR; } @@ -444,14 +484,14 @@ static int winbind_auth_request(pam_handle_t * pamh, char var[PATH_MAX]; - _pam_log_debug(ctrl, LOG_DEBUG, "request returned KRB5CCNAME: %s", + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "request returned KRB5CCNAME: %s", response.data.auth.krb5ccname); snprintf(var, sizeof(var), "KRB5CCNAME=%s", response.data.auth.krb5ccname); ret = pam_putenv(pamh, var); if (ret != PAM_SUCCESS) { - _pam_log(LOG_ERR, "failed to set KRB5CCNAME to %s", var); + _pam_log(pamh, ctrl, LOG_ERR, "failed to set KRB5CCNAME to %s", var); return ret; } } @@ -481,7 +521,7 @@ static int winbind_auth_request(pam_handle_t * pamh, ret = PAM_AUTHTOK_EXPIRED; - _pam_log_debug(ctrl, LOG_DEBUG,"Password has expired (Password was last set: %d, " + _pam_log_debug(pamh, ctrl, LOG_DEBUG,"Password has expired (Password was last set: %d, " "the policy says it should expire here %d (now it's: %d)\n", response.data.auth.info3.pass_last_set_time, response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire, @@ -504,7 +544,7 @@ static int winbind_auth_request(pam_handle_t * pamh, if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) { _make_remark(pamh, PAM_ERROR_MSG, "Logging on using cached account. Network ressources can be unavailable"); - _pam_log_debug(ctrl, LOG_DEBUG,"User %s logged on using cached account\n", user); + _pam_log_debug(pamh, ctrl, LOG_DEBUG,"User %s logged on using cached account\n", user); } /* save the CIFS homedir for pam_cifs / pam_mount */ @@ -514,7 +554,7 @@ static int winbind_auth_request(pam_handle_t * pamh, (void *) strdup(response.data.auth.info3.home_dir), _pam_winbind_cleanup_func); if (ret2) { - _pam_log_debug(ctrl, LOG_DEBUG, "Could not set data: %s", + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Could not set data: %s", pam_strerror(pamh, ret2)); } @@ -527,7 +567,7 @@ static int winbind_auth_request(pam_handle_t * pamh, (void *) strdup(response.data.auth.info3.logon_script), _pam_winbind_cleanup_func); if (ret2) { - _pam_log_debug(ctrl, LOG_DEBUG, "Could not set data: %s", + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Could not set data: %s", pam_strerror(pamh, ret2)); } } @@ -619,7 +659,7 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, _make_remark(pamh, PAM_ERROR_MSG, "Password does not meet complexity requirements"); break; default: - _pam_log_debug(ctrl, LOG_DEBUG, + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "unknown password change reject reason: %d", response.data.auth.reject_reason); break; @@ -650,7 +690,7 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, * 0 = OK * -1 = System error */ -static int valid_user(const char *user, pam_handle_t *pamh, int ctrl) +static int valid_user(pam_handle_t *pamh, int ctrl, const char *user) { /* check not only if the user is available over NSS calls, also make * sure it's really a winbind user, this is important when stacking PAM @@ -728,7 +768,7 @@ static int _winbind_read_password(pam_handle_t * pamh, retval = _pam_get_item(pamh, authtok_flag, &item); if (retval != PAM_SUCCESS) { /* very strange. */ - _pam_log(LOG_ALERT, + _pam_log(pamh, ctrl, LOG_ALERT, "pam_get_item returned error to unix-read-password" ); return retval; @@ -797,7 +837,7 @@ static int _winbind_read_password(pam_handle_t * pamh, } } } else { - _pam_log(LOG_NOTICE, "could not recover authentication token"); + _pam_log(pamh, ctrl, LOG_NOTICE, "could not recover authentication token"); retval = PAM_AUTHTOK_RECOVER_ERR; } @@ -816,7 +856,7 @@ static int _winbind_read_password(pam_handle_t * pamh, } if (retval != PAM_SUCCESS) { - _pam_log_debug(ctrl, LOG_DEBUG, + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "unable to obtain a password"); return retval; } @@ -829,7 +869,7 @@ static int _winbind_read_password(pam_handle_t * pamh, if (retval != PAM_SUCCESS || (retval = _pam_get_item(pamh, authtok_flag, &item)) != PAM_SUCCESS) { - _pam_log(LOG_CRIT, "error manipulating password"); + _pam_log(pamh, ctrl, LOG_CRIT, "error manipulating password"); return retval; } @@ -840,19 +880,20 @@ static int _winbind_read_password(pam_handle_t * pamh, return PAM_SUCCESS; } -const char *get_conf_item_string(int argc, +const char *get_conf_item_string(const pam_handle_t *pamh, + int argc, const char **argv, int ctrl, dictionary *d, const char *item, - int flag) + int config_flag) { int i = 0; char *parm = NULL; const char *parm_opt = NULL; char *key = NULL; - if (!(ctrl & flag)) { + if (!(ctrl & config_flag)) { goto out; } @@ -876,36 +917,36 @@ const char *get_conf_item_string(int argc, parm = strdup(argv[i]); if ( (p = strchr( parm, '=' )) == NULL) { - _pam_log(LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item); + _pam_log(pamh, ctrl, LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item); goto out; } SAFE_FREE(parm); - _pam_log_debug(ctrl, LOG_INFO, "PAM config: %s '%s'\n", item, p+1); + _pam_log_debug(pamh, ctrl, LOG_INFO, "PAM config: %s '%s'\n", item, p+1); return p + 1; } } if (d != NULL) { - _pam_log_debug(ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt); + _pam_log_debug(pamh, ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt); } out: SAFE_FREE(parm); return parm_opt; } -const char *get_krb5_cc_type_from_config(int argc, const char **argv, int ctrl, dictionary *d) +const char *get_krb5_cc_type_from_config(const pam_handle_t *pamh, int argc, const char **argv, int ctrl, dictionary *d) { - return get_conf_item_string(argc, argv, ctrl, d, "krb5_ccache_type", WINBIND_KRB5_CCACHE_TYPE); + return get_conf_item_string(pamh, argc, argv, ctrl, d, "krb5_ccache_type", WINBIND_KRB5_CCACHE_TYPE); } -const char *get_member_from_config(int argc, const char **argv, int ctrl, dictionary *d) +const char *get_member_from_config(const pam_handle_t *pamh, int argc, const char **argv, int ctrl, dictionary *d) { const char *ret = NULL; - ret = get_conf_item_string(argc, argv, ctrl, d, "require_membership_of", WINBIND_REQUIRED_MEMBERSHIP); + ret = get_conf_item_string(pamh, argc, argv, ctrl, d, "require_membership_of", WINBIND_REQUIRED_MEMBERSHIP); if (ret) { return ret; } - return get_conf_item_string(argc, argv, ctrl, d, "require-membership-of", WINBIND_REQUIRED_MEMBERSHIP); + return get_conf_item_string(pamh, argc, argv, ctrl, d, "require-membership-of", WINBIND_REQUIRED_MEMBERSHIP); } PAM_EXTERN @@ -921,18 +962,18 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, char *username_ret = NULL; /* parse arguments */ - int ctrl = _pam_parse(argc, argv, &d); + int ctrl = _pam_parse(pamh, flags, argc, argv, &d); if (ctrl == -1) { retval = PAM_SYSTEM_ERR; goto out; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_authenticate (flags: 0x%04x)", flags); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_authenticate (flags: 0x%04x)", flags); /* Get the username */ retval = pam_get_user(pamh, &username, NULL); if ((retval != PAM_SUCCESS) || (!username)) { - _pam_log_debug(ctrl, LOG_DEBUG, "can not get the username"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "can not get the username"); retval = PAM_SERVICE_ERR; goto out; } @@ -942,7 +983,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, &password); if (retval != PAM_SUCCESS) { - _pam_log(LOG_ERR, "Could not retrieve user's password"); + _pam_log(pamh, ctrl, LOG_ERR, "Could not retrieve user's password"); retval = PAM_AUTHTOK_ERR; goto out; } @@ -950,19 +991,19 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* Let's not give too much away in the log file */ #ifdef DEBUG_PASSWORD - _pam_log_debug(ctrl, LOG_INFO, "Verify user `%s' with password `%s'", + _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s' with password '%s'", username, password); #else - _pam_log_debug(ctrl, LOG_INFO, "Verify user `%s'", username); + _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s'", username); #endif - member = get_member_from_config(argc, argv, ctrl, d); + member = get_member_from_config(pamh, argc, argv, ctrl, d); - cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d); + cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); /* Now use the username to look up password */ retval = winbind_auth_request(pamh, ctrl, username, password, member, - cctype, True, NULL, &username_ret); + cctype, True, NULL, &username_ret); if (retval == PAM_NEW_AUTHTOK_REQD || retval == PAM_AUTHTOK_EXPIRED) { @@ -997,12 +1038,12 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { /* parse arguments */ - int ctrl = _pam_parse(argc, argv, NULL); + int ctrl = _pam_parse(pamh, flags, argc, argv, NULL); if (ctrl == -1) { return PAM_SYSTEM_ERR; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_setcred (flags: 0x%04x)", flags); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_setcred (flags: 0x%04x)", flags); if (flags & PAM_DELETE_CRED) { return pam_sm_close_session(pamh, flags, argc, argv); @@ -1024,30 +1065,30 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, void *tmp = NULL; /* parse arguments */ - int ctrl = _pam_parse(argc, argv, NULL); + int ctrl = _pam_parse(pamh, flags, argc, argv, NULL); if (ctrl == -1) { return PAM_SYSTEM_ERR; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_acct_mgmt (flags: 0x%04x)", flags); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_acct_mgmt (flags: 0x%04x)", flags); /* Get the username */ retval = pam_get_user(pamh, &username, NULL); if ((retval != PAM_SUCCESS) || (!username)) { - _pam_log_debug(ctrl, LOG_DEBUG,"can not get the username"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG,"can not get the username"); return PAM_SERVICE_ERR; } /* Verify the username */ - retval = valid_user(username, pamh, ctrl); + retval = valid_user(pamh, ctrl, username); switch (retval) { case -1: /* some sort of system error. The log was already printed */ return PAM_SERVICE_ERR; case 1: /* the user does not exist */ - _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found", username); + _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", username); if (ctrl & WINBIND_UNKNOWN_OK_ARG) { return PAM_IGNORE; } @@ -1060,24 +1101,24 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, case PAM_AUTHTOK_EXPIRED: /* fall through, since new token is required in this case */ case PAM_NEW_AUTHTOK_REQD: - _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success but %s is set", + _pam_log(pamh, ctrl, LOG_WARNING, "pam_sm_acct_mgmt success but %s is set", PAM_WINBIND_NEW_AUTHTOK_REQD); - _pam_log(LOG_NOTICE, "user '%s' needs new password", username); + _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' needs new password", username); /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */ return PAM_NEW_AUTHTOK_REQD; default: - _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success"); - _pam_log(LOG_NOTICE, "user '%s' granted access", username); + _pam_log(pamh, ctrl, LOG_WARNING, "pam_sm_acct_mgmt success"); + _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username); return PAM_SUCCESS; } } /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted access", username); + _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username); return PAM_SUCCESS; default: /* we don't know anything about this return value */ - _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s')", + _pam_log(pamh, ctrl, LOG_ERR, "internal module error (retval = %d, user = '%s')", retval, username); return PAM_SERVICE_ERR; } @@ -1091,12 +1132,12 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { /* parse arguments */ - int ctrl = _pam_parse(argc, argv, NULL); + int ctrl = _pam_parse(pamh, flags, argc, argv, NULL); if (ctrl == -1) { return PAM_SYSTEM_ERR; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_open_session handler (flags: 0x%04x)", flags); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_open_session handler (flags: 0x%04x)", flags); return PAM_SUCCESS; } @@ -1109,13 +1150,13 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, int retval = PAM_SUCCESS; /* parse arguments */ - int ctrl = _pam_parse(argc, argv, &d); + int ctrl = _pam_parse(pamh, flags, argc, argv, &d); if (ctrl == -1) { retval = PAM_SYSTEM_ERR; goto out; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_close_session handler (flags: 0x%04x)", flags); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_close_session handler (flags: 0x%04x)", flags); if (!(flags & PAM_DELETE_CRED)) { retval = PAM_SUCCESS; @@ -1137,21 +1178,21 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, retval = pam_get_user(pamh, &user, "Username: "); if (retval == PAM_SUCCESS) { if (user == NULL) { - _pam_log(LOG_ERR, "username was NULL!"); + _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); retval = PAM_USER_UNKNOWN; goto out; } if (retval == PAM_SUCCESS) { - _pam_log_debug(ctrl, LOG_DEBUG, "username [%s] obtained", user); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user); } } else { - _pam_log_debug(ctrl, LOG_DEBUG, "could not identify user"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "could not identify user"); goto out; } ccname = pam_getenv(pamh, "KRB5CCNAME"); if (ccname == NULL) { - _pam_log_debug(ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment"); } strncpy(request.data.logoff.user, user, @@ -1201,13 +1242,13 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, int retry = 0; dictionary *d; - ctrl = _pam_parse(argc, argv, &d); + ctrl = _pam_parse(pamh, flags, argc, argv, &d); if (ctrl == -1) { retval = PAM_SYSTEM_ERR; goto out; } - _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_chauthtok (flags: 0x%04x)", flags); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_chauthtok (flags: 0x%04x)", flags); /* clearing offline bit for the auth in the password change */ ctrl &= ~WINBIND_CACHED_LOGIN; @@ -1218,22 +1259,22 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, retval = pam_get_user(pamh, &user, "Username: "); if (retval == PAM_SUCCESS) { if (user == NULL) { - _pam_log(LOG_ERR, "username was NULL!"); + _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); retval = PAM_USER_UNKNOWN; goto out; } if (retval == PAM_SUCCESS) { - _pam_log_debug(ctrl, LOG_DEBUG, "username [%s] obtained", + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user); } } else { - _pam_log_debug(ctrl, LOG_DEBUG, + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "password - could not identify user"); goto out; } /* check if this is really a user in winbindd, not only in NSS */ - retval = valid_user(user, pamh, ctrl); + retval = valid_user(pamh, ctrl, user); switch (retval) { case 1: retval = PAM_USER_UNKNOWN; @@ -1258,7 +1299,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, #define greeting "Changing password for " Announce = (char *) malloc(sizeof(greeting) + strlen(user)); if (Announce == NULL) { - _pam_log(LOG_CRIT, "password - out of memory"); + _pam_log(pamh, ctrl, LOG_CRIT, "password - out of memory"); retval = PAM_BUF_ERR; goto out; } @@ -1273,7 +1314,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, NULL, (const char **) &pass_old); if (retval != PAM_SUCCESS) { - _pam_log(LOG_NOTICE, "password - (old) token not obtained"); + _pam_log(pamh, ctrl, LOG_NOTICE, "password - (old) token not obtained"); goto out; } /* verify that this is the password for this user */ @@ -1294,7 +1335,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); pass_old = NULL; if (retval != PAM_SUCCESS) { - _pam_log(LOG_CRIT, "failed to set PAM_OLDAUTHTOK"); + _pam_log(pamh, ctrl, LOG_CRIT, "failed to set PAM_OLDAUTHTOK"); } } else if (flags & PAM_UPDATE_AUTHTOK) { @@ -1311,7 +1352,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, retval = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old); if (retval != PAM_SUCCESS) { - _pam_log(LOG_NOTICE, "user not authenticated"); + _pam_log(pamh, ctrl, LOG_NOTICE, "user not authenticated"); goto out; } @@ -1335,7 +1376,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, (const char **) &pass_new); if (retval != PAM_SUCCESS) { - _pam_log_debug(ctrl, LOG_ALERT + _pam_log_debug(pamh, ctrl, LOG_ALERT ,"password - new password not obtained"); pass_old = NULL;/* tidy up */ goto out; @@ -1371,8 +1412,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (ctrl & WINBIND_KRB5_AUTH) { - const char *member = get_member_from_config(argc, argv, ctrl, d); - const char *cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d); + const char *member = get_member_from_config(pamh, argc, argv, ctrl, d); + const char *cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); retval = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, False, NULL, NULL); -- cgit From 4b57919051aefe93398acd800a98a285adeaf8bc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Sep 2006 09:27:10 +0000 Subject: r18507: Added debug log for returned username. Jeremy. (This used to be commit 7644fa70ba4f7c88d887930e23b5ee2e1632473b) --- source3/nsswitch/pam_winbind.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 64356e579a..eace97aa64 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1024,6 +1024,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, out: if (username_ret) { pam_set_item (pamh, PAM_USER, username_ret); + _pam_log_debug(pamh, ctrl, LOG_INFO, "Returned user was '%s'", username_ret); free(username_ret); } -- cgit From d52612a7d9336fff18d298aed7a7c9a756b9d31e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 19 Sep 2006 01:28:25 +0000 Subject: r18667: Two C++ warnings (This used to be commit 8c60e71229cd577f3b17345c5824363dd202eba9) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index eace97aa64..3bd90106ec 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -575,7 +575,7 @@ static int winbind_auth_request(pam_handle_t * pamh, /* If winbindd returned a username, return the pointer to it here. */ if (user_ret && response.extra_data.data) { /* We have to trust it's a null terminated string. */ - *user_ret = response.extra_data.data; + *user_ret = (char *)response.extra_data.data; } return ret; -- cgit From f1c239872387fbfd5d52de2fe60c62108a4a7926 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 26 Sep 2006 16:35:34 +0000 Subject: r18924: Minor cleanup. Guenther (This used to be commit 143a48927b0e21d31a9f54cfc720b5d04a4b6751) --- source3/nsswitch/pam_winbind.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 3bd90106ec..5d5e903c42 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -119,33 +119,33 @@ static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char config_file = PAM_WINBIND_CONFIG_FILE; } - *d = iniparser_load(CONST_DISCARD(char *, config_file)); + *d = iniparser_load(config_file); if (*d == NULL) { goto config_from_pam; } - if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:debug"), False)) { + if (iniparser_getboolean(*d, ("global:debug", False))) { ctrl |= WINBIND_DEBUG_ARG; } - if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:cached_login"), False)) { + if (iniparser_getboolean(*d, "global:cached_login", False)) { ctrl |= WINBIND_CACHED_LOGIN; } - if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:krb5_auth"), False)) { + if (iniparser_getboolean(*d, "global:krb5_auth", False)) { ctrl |= WINBIND_KRB5_AUTH; } - if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:silent"), False)) { + if (iniparser_getboolean(*d, "global:silent", False)) { ctrl |= WINBIND_SILENT; } - if (iniparser_getstr(*d, CONST_DISCARD(char *,"global:krb5_ccache_type")) != NULL) { + if (iniparser_getstr(*d, "global:krb5_ccache_type")) != NULL) { ctrl |= WINBIND_KRB5_CCACHE_TYPE; } - if ((iniparser_getstr(*d, CONST_DISCARD(char *, "global:require-membership-of")) != NULL) || - (iniparser_getstr(*d, CONST_DISCARD(char *, "global:require_membership_of")) != NULL)) { + if ((iniparser_getstr(*d, "global:require-membership-of") != NULL) || + (iniparser_getstr(*d, "global:require_membership_of") != NULL)) { ctrl |= WINBIND_REQUIRED_MEMBERSHIP; } -- cgit From b0e29c79e7195790de217d665737257be90b8454 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 26 Sep 2006 18:31:47 +0000 Subject: r18927: Fix build. *please* compile the code at least once before checking it in. (This used to be commit 4e464a2c35984752244f30ce9bb259eb16149e3f) --- source3/nsswitch/pam_winbind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 5d5e903c42..c1e1bc5244 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -124,7 +124,7 @@ static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char goto config_from_pam; } - if (iniparser_getboolean(*d, ("global:debug", False))) { + if (iniparser_getboolean(*d, "global:debug", False)) { ctrl |= WINBIND_DEBUG_ARG; } @@ -140,7 +140,7 @@ static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char ctrl |= WINBIND_SILENT; } - if (iniparser_getstr(*d, "global:krb5_ccache_type")) != NULL) { + if (iniparser_getstr(*d, "global:krb5_ccache_type") != NULL) { ctrl |= WINBIND_KRB5_CCACHE_TYPE; } -- cgit From e42f449fcc664852c92768450becc9e156bb488f Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 16 Oct 2006 22:41:24 +0000 Subject: r19348: Fix uninitialized dictionary handle, found by valgrind. Guenther (This used to be commit 9621bb420a13e634badcc922c73c8bfb30aa6120) --- source3/nsswitch/pam_winbind.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index c1e1bc5244..9d902e7e05 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -958,7 +958,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, const char *member = NULL; const char *cctype = NULL; int retval = PAM_AUTH_ERR; - dictionary *d; + dictionary *d = NULL; char *username_ret = NULL; /* parse arguments */ @@ -1147,7 +1147,7 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { - dictionary *d; + dictionary *d = NULL; int retval = PAM_SUCCESS; /* parse arguments */ @@ -1241,7 +1241,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, char *Announce; int retry = 0; - dictionary *d; + dictionary *d = NULL; ctrl = _pam_parse(pamh, flags, argc, argv, &d); if (ctrl == -1) { -- cgit From da6e42b47f0b14238d932e5818fee93d4fd932c4 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 16 Oct 2006 23:06:48 +0000 Subject: r19349: Fix invalid free on the PAM_WINBIND_PWD_LAST_SET data. Guenther (This used to be commit a4d17ee9c960abdf21b9af1601bd1042e0cd7636) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 9d902e7e05..034c7f1746 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1331,7 +1331,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, goto out; } - pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, (void *)pwdlastset_prelim, _pam_winbind_cleanup_func); + pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, (void *)pwdlastset_prelim, NULL); retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); pass_old = NULL; -- cgit From b26b8f95e95030506189d714ac62380788a5fe3e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 16 Oct 2006 23:13:56 +0000 Subject: r19351: Also export the info3 profilepath via the PAM_WINBIND_PROFILEPATH data field. Guenther (This used to be commit 66b92f27fa4edec180b8c8eee929ec8f31ef6a08) --- source3/nsswitch/pam_winbind.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 034c7f1746..0729fda62b 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -572,6 +572,18 @@ static int winbind_auth_request(pam_handle_t * pamh, } } + /* save the profile path for other PAM modules */ + if (response.data.auth.info3.profile_path[0] != '\0') { + + int ret2 = pam_set_data(pamh, PAM_WINBIND_PROFILEPATH, + (void *) strdup(response.data.auth.info3.profile_path), + _pam_winbind_cleanup_func); + if (ret2) { + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Could not set data: %s", + pam_strerror(pamh, ret2)); + } + } + /* If winbindd returned a username, return the pointer to it here. */ if (user_ret && response.extra_data.data) { /* We have to trust it's a null terminated string. */ -- cgit From b903eb231a1db429dca2120e392d49284e284bd3 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 14 Nov 2006 16:50:29 +0000 Subject: r19703: Don't free a string if you want to return it! (This used to be commit 3fed72ac3efd1fa7df8fb7d1e2cb9772d66bb4bd) --- source3/nsswitch/pam_winbind.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 0729fda62b..1d9053ff3e 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -932,7 +932,6 @@ const char *get_conf_item_string(const pam_handle_t *pamh, _pam_log(pamh, ctrl, LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item); goto out; } - SAFE_FREE(parm); _pam_log_debug(pamh, ctrl, LOG_INFO, "PAM config: %s '%s'\n", item, p+1); return p + 1; } -- cgit From 8f723972ae433d7ce707e9f9aab431c19c7aaeaf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 15 Nov 2006 02:06:58 +0000 Subject: r19710: Fix memory leak in get_conf_item_string(). As we're just doing strchr on a const string there's no need to strdup it before, we're never modifying it. Just remove the variable "parm". Jeremy. (This used to be commit 1af18f613b1399220e38e7ab40665c2ca177c5a7) --- source3/nsswitch/pam_winbind.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 1d9053ff3e..a61dceedce 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -901,7 +901,6 @@ const char *get_conf_item_string(const pam_handle_t *pamh, int config_flag) { int i = 0; - char *parm = NULL; const char *parm_opt = NULL; char *key = NULL; @@ -926,9 +925,7 @@ const char *get_conf_item_string(const pam_handle_t *pamh, if ((strncmp(argv[i], item, strlen(item)) == 0)) { char *p; - parm = strdup(argv[i]); - - if ( (p = strchr( parm, '=' )) == NULL) { + if ( (p = strchr( argv[i], '=' )) == NULL) { _pam_log(pamh, ctrl, LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item); goto out; } @@ -941,7 +938,6 @@ const char *get_conf_item_string(const pam_handle_t *pamh, _pam_log_debug(pamh, ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt); } out: - SAFE_FREE(parm); return parm_opt; } -- cgit From 86a11183f78e2413a25af60db779f5edd23af562 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Tue, 12 Dec 2006 22:05:48 +0000 Subject: r20136: Fix #4290. Properly compute time to password expiration in message from pam_winbind. Thanks to Andrew Benham (This used to be commit 0d03f5137936546253a8b3334995f536f3621d57) --- source3/nsswitch/pam_winbind.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index a61dceedce..24e27cb8c6 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -536,7 +536,8 @@ static int winbind_auth_request(pam_handle_t * pamh, (response.data.auth.policy.expire) && (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire > time(NULL) ) ) { - int days = response.data.auth.policy.expire / SECONDS_PER_DAY; + int days = (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire - + time(NULL))/ SECONDS_PER_DAY; if (days <= DAYS_TO_WARN_BEFORE_PWD_EXPIRES) { _make_remark_format(pamh, PAM_TEXT_INFO, "Your password will expire in %d days", days); } -- cgit From 63d81974532e755d67a903e4926ebde5c8e4ee13 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 15 Dec 2006 06:06:15 +0000 Subject: r20180: Ensure that pam returns the correct error messages when offline and or doing password changes. Jeremy. (This used to be commit 4a74c553845c960a355ddb86abaadfe0d550271f) --- source3/nsswitch/pam_winbind.c | 116 +++++++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 38 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 24e27cb8c6..b92ff5a8a0 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -194,6 +194,8 @@ static const struct ntstatus_errors { } ntstatus_errors[] = { {"NT_STATUS_OK", "Success"}, {"NT_STATUS_BACKUP_CONTROLLER", "No primary Domain Controler available"}, + {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", "No domain controllers found"}, + {"NT_STATUS_NO_LOGON_SERVERS", "No logon servers"}, {"NT_STATUS_PWD_TOO_SHORT", "Password too short"}, {"NT_STATUS_PWD_TOO_RECENT", "The password of this user is too recent to change"}, {"NT_STATUS_PWD_HISTORY_CONFLICT", "Password is already in password history"}, @@ -383,7 +385,7 @@ static int winbind_auth_request(pam_handle_t * pamh, const char *pass, const char *member, const char *cctype, - int process_result, + struct winbindd_response *p_response, time_t *pwd_last_set, char **user_ret) { @@ -496,7 +498,9 @@ static int winbind_auth_request(pam_handle_t * pamh, } } - if (!process_result) { + if (p_response) { + /* We want to process the response in the caller. */ + *p_response = response; return ret; } @@ -511,6 +515,8 @@ static int winbind_auth_request(pam_handle_t * pamh, PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"); PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"); PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NO_LOGON_SERVERS"); } /* handle the case where the auth was ok, but the password must expire right now */ @@ -639,6 +645,8 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, } PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_BACKUP_CONTROLLER"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NO_LOGON_SERVERS"); PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCESS_DENIED"); /* TODO: tell the min pwd length ? */ @@ -1011,7 +1019,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* Now use the username to look up password */ retval = winbind_auth_request(pamh, ctrl, username, password, member, - cctype, True, NULL, &username_ret); + cctype, NULL, NULL, &username_ret); if (retval == PAM_NEW_AUTHTOK_REQD || retval == PAM_AUTHTOK_EXPIRED) { @@ -1238,7 +1246,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, int argc, const char **argv) { unsigned int lctrl; - int retval; + int ret; unsigned int ctrl; /* */ @@ -1253,7 +1261,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, ctrl = _pam_parse(pamh, flags, argc, argv, &d); if (ctrl == -1) { - retval = PAM_SYSTEM_ERR; + ret = PAM_SYSTEM_ERR; goto out; } @@ -1265,14 +1273,14 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, /* * First get the name of a user */ - retval = pam_get_user(pamh, &user, "Username: "); - if (retval == PAM_SUCCESS) { + ret = pam_get_user(pamh, &user, "Username: "); + if (ret == PAM_SUCCESS) { if (user == NULL) { _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); - retval = PAM_USER_UNKNOWN; + ret = PAM_USER_UNKNOWN; goto out; } - if (retval == PAM_SUCCESS) { + if (ret == PAM_SUCCESS) { _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user); } @@ -1283,13 +1291,13 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, } /* check if this is really a user in winbindd, not only in NSS */ - retval = valid_user(pamh, ctrl, user); - switch (retval) { + ret = valid_user(pamh, ctrl, user); + switch (ret) { case 1: - retval = PAM_USER_UNKNOWN; + ret = PAM_USER_UNKNOWN; goto out; case -1: - retval = PAM_SYSTEM_ERR; + ret = PAM_SYSTEM_ERR; goto out; default: break; @@ -1301,7 +1309,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, */ if (flags & PAM_PRELIM_CHECK) { - + struct winbindd_response response; time_t pwdlastset_prelim = 0; /* instruct user what is happening */ @@ -1309,7 +1317,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, Announce = (char *) malloc(sizeof(greeting) + strlen(user)); if (Announce == NULL) { _pam_log(pamh, ctrl, LOG_CRIT, "password - out of memory"); - retval = PAM_BUF_ERR; + ret = PAM_BUF_ERR; goto out; } (void) strcpy(Announce, greeting); @@ -1317,33 +1325,50 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, #undef greeting lctrl = ctrl | WINBIND__OLD_PASSWORD; - retval = _winbind_read_password(pamh, lctrl, + ret = _winbind_read_password(pamh, lctrl, Announce, "(current) NT password: ", NULL, (const char **) &pass_old); - if (retval != PAM_SUCCESS) { + if (ret != PAM_SUCCESS) { _pam_log(pamh, ctrl, LOG_NOTICE, "password - (old) token not obtained"); goto out; } + + /* We don't need krb5 env set for password change test. */ + ctrl &= ~WINBIND_KRB5_AUTH; + /* verify that this is the password for this user */ - retval = winbind_auth_request(pamh, ctrl, user, pass_old, - NULL, NULL, False, &pwdlastset_prelim, NULL); + ret = winbind_auth_request(pamh, ctrl, user, pass_old, + NULL, NULL, &response, &pwdlastset_prelim, NULL); - if (retval != PAM_ACCT_EXPIRED && - retval != PAM_AUTHTOK_EXPIRED && - retval != PAM_NEW_AUTHTOK_REQD && - retval != PAM_SUCCESS) { + if (ret != PAM_ACCT_EXPIRED && + ret != PAM_AUTHTOK_EXPIRED && + ret != PAM_NEW_AUTHTOK_REQD && + ret != PAM_SUCCESS) { pass_old = NULL; - goto out; + if (d) { + iniparser_freedict(d); + } + /* Deal with offline errors. */ + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + response, + "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + response, + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + response, + "NT_STATUS_ACCESS_DENIED"); + return ret; } pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, (void *)pwdlastset_prelim, NULL); - retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); + ret = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); pass_old = NULL; - if (retval != PAM_SUCCESS) { + if (ret != PAM_SUCCESS) { _pam_log(pamh, ctrl, LOG_CRIT, "failed to set PAM_OLDAUTHTOK"); } } else if (flags & PAM_UPDATE_AUTHTOK) { @@ -1358,9 +1383,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * get the old token back. */ - retval = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old); + ret = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old); - if (retval != PAM_SUCCESS) { + if (ret != PAM_SUCCESS) { _pam_log(pamh, ctrl, LOG_NOTICE, "user not authenticated"); goto out; } @@ -1371,20 +1396,20 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, lctrl |= WINBIND_USE_FIRST_PASS_ARG; } retry = 0; - retval = PAM_AUTHTOK_ERR; - while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { + ret = PAM_AUTHTOK_ERR; + while ((ret != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { /* * use_authtok is to force the use of a previously entered * password -- needed for pluggable password strength checking */ - retval = _winbind_read_password(pamh, lctrl, + ret = _winbind_read_password(pamh, lctrl, NULL, "Enter new NT password: ", "Retype new NT password: ", (const char **) &pass_new); - if (retval != PAM_SUCCESS) { + if (ret != PAM_SUCCESS) { _pam_log_debug(pamh, ctrl, LOG_ALERT ,"password - new password not obtained"); pass_old = NULL;/* tidy up */ @@ -1409,8 +1434,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, _pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, &pwdlastset_update); - retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update); - if (retval) { + ret = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update); + if (ret) { _pam_overwrite(pass_new); _pam_overwrite(pass_old); pass_old = pass_new = NULL; @@ -1420,25 +1445,40 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, /* just in case we need krb5 creds after a password change over msrpc */ if (ctrl & WINBIND_KRB5_AUTH) { + struct winbindd_response response; const char *member = get_member_from_config(pamh, argc, argv, ctrl, d); const char *cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); - retval = winbind_auth_request(pamh, ctrl, user, pass_new, - member, cctype, False, NULL, NULL); + ret = winbind_auth_request(pamh, ctrl, user, pass_new, + member, cctype, &response, NULL, NULL); _pam_overwrite(pass_new); _pam_overwrite(pass_old); pass_old = pass_new = NULL; + if (d) { + iniparser_freedict(d); + } + /* Deal with offline errors. */ + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + response, + "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + response, + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + response, + "NT_STATUS_ACCESS_DENIED"); + return ret; } } else { - retval = PAM_SERVICE_ERR; + ret = PAM_SERVICE_ERR; } out: if (d) { iniparser_freedict(d); } - return retval; + return ret; } #ifdef PAM_STATIC -- cgit From 6fdbdfc86f49e1cd5ead670c1ff0243a598fcc6c Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 18 Dec 2006 15:29:05 +0000 Subject: r20239: Parse the configfile for pam_sm_setcred as well (e.g. to get the debug flag) Guenther (This used to be commit 2c549f71f15b066ac1f415544848b582558abd5d) --- source3/nsswitch/pam_winbind.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index b92ff5a8a0..0fb52404d5 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1054,14 +1054,20 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { + dictionary *d = NULL; + /* parse arguments */ - int ctrl = _pam_parse(pamh, flags, argc, argv, NULL); + int ctrl = _pam_parse(pamh, flags, argc, argv, &d); if (ctrl == -1) { return PAM_SYSTEM_ERR; } _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_setcred (flags: 0x%04x)", flags); + if (d) { + iniparser_freedict(d); + } + if (flags & PAM_DELETE_CRED) { return pam_sm_close_session(pamh, flags, argc, argv); } -- cgit From 619671a71892710b520d09b24c24e02347036e45 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 18 Dec 2006 15:33:57 +0000 Subject: r20240: Be a little more verbose about the credential flags when the debug flag is set. Guenther (This used to be commit ecbab58826a51ace2a0d1181a41391f5d170ff06) --- source3/nsswitch/pam_winbind.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 0fb52404d5..5bd4ec3934 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1068,8 +1068,22 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, iniparser_freedict(d); } - if (flags & PAM_DELETE_CRED) { - return pam_sm_close_session(pamh, flags, argc, argv); + switch (flags & ~PAM_SILENT) { + + case PAM_DELETE_CRED: + return pam_sm_close_session(pamh, flags, argc, argv); + + case PAM_REFRESH_CRED: + _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REFRESH_CRED not implemented"); + break; + case PAM_REINITIALIZE_CRED: + _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REINITIALIZE_CRED not implemented"); + break; + case PAM_ESTABLISH_CRED: + _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_ESTABLISH_CRED not implemented"); + break; + default: + break; } return PAM_SUCCESS; -- cgit From 9291e634c0ca97c642fba389e06f2ff31d70b3e0 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 18 Dec 2006 15:35:52 +0000 Subject: r20241: Slightly improve readability of the pam_vsyslog replacement function. Guenther (This used to be commit 222320373f8a251fc2cf3ff8c3fec93a7a48f9df) --- source3/nsswitch/pam_winbind.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 5bd4ec3934..7010936b9b 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -35,14 +35,14 @@ static int _pam_get_data(const pam_handle_t *pamh, /* some syslogging */ +#ifdef HAVE_PAM_VSYSLOG static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, va_list args) { - -#ifdef HAVE_PAM_VSYSLOG pam_vsyslog(pamh, err, format, args); +} #else - { - +static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, va_list args) +{ char *format2 = NULL; const char *service; @@ -58,9 +58,8 @@ static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, sprintf(format2, "%s(%s): %s", MODULE_NAME, service, format); vsyslog(err, format2, args); SAFE_FREE(format2); - } -#endif } +#endif /* HAVE_PAM_VSYSLOG */ static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) { -- cgit From fb6d54dbabefdb11c33125988b03ccf4080658e4 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 18 Dec 2006 22:10:09 +0000 Subject: r20249: Fail when parsing invalid options in _pam_parse. Guenther (This used to be commit f6c9421abdf5731e894cd2ccc1b7431a3c368bbf) --- source3/nsswitch/pam_winbind.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 7010936b9b..06d28a02c9 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -174,7 +174,8 @@ config_from_pam: else if (!strcasecmp(*v, "cached_login")) ctrl |= WINBIND_CACHED_LOGIN; else { - _pam_log(pamh, ctrl, LOG_ERR, "pam_parse: unknown option; %s", *v); + _pam_log(pamh, ctrl, LOG_ERR, "pam_parse: unknown option: %s", *v); + return -1; } } -- cgit From c1a05657b958476e081b6c9745f9e4e93bc1c174 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 21 Dec 2006 13:31:23 +0000 Subject: r20304: Smaller fixes for pam_winbind: * fail on invalid credential flags in pam_sm_setcred * parse config file for pam_sm_acct_mgmt and pam_sm_open_session Guenther (This used to be commit 2a428ac814d03880de63656ea97827126ccfec5c) --- source3/nsswitch/pam_winbind.c | 95 +++++++++++++++++++++++++++++------------- 1 file changed, 65 insertions(+), 30 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 06d28a02c9..c9e092fc3e 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1054,39 +1054,46 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { + int ret = PAM_SYSTEM_ERR; dictionary *d = NULL; /* parse arguments */ int ctrl = _pam_parse(pamh, flags, argc, argv, &d); if (ctrl == -1) { - return PAM_SYSTEM_ERR; + ret = PAM_SYSTEM_ERR; + goto out; } _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_setcred (flags: 0x%04x)", flags); - if (d) { - iniparser_freedict(d); - } - switch (flags & ~PAM_SILENT) { case PAM_DELETE_CRED: - return pam_sm_close_session(pamh, flags, argc, argv); - + ret = pam_sm_close_session(pamh, flags, argc, argv); + break; case PAM_REFRESH_CRED: _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REFRESH_CRED not implemented"); + ret = PAM_SUCCESS; break; case PAM_REINITIALIZE_CRED: _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REINITIALIZE_CRED not implemented"); + ret = PAM_SUCCESS; break; case PAM_ESTABLISH_CRED: _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_ESTABLISH_CRED not implemented"); + ret = PAM_SUCCESS; break; default: + ret = PAM_SYSTEM_ERR; break; } - return PAM_SUCCESS; + out: + if (d) { + iniparser_freedict(d); + } + + return ret; } /* @@ -1098,11 +1105,12 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { const char *username; - int retval = PAM_USER_UNKNOWN; + int ret = PAM_USER_UNKNOWN; void *tmp = NULL; + dictionary *d = NULL; /* parse arguments */ - int ctrl = _pam_parse(pamh, flags, argc, argv, NULL); + int ctrl = _pam_parse(pamh, flags, argc, argv, &d); if (ctrl == -1) { return PAM_SYSTEM_ERR; } @@ -1111,30 +1119,34 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, /* Get the username */ - retval = pam_get_user(pamh, &username, NULL); - if ((retval != PAM_SUCCESS) || (!username)) { + ret = pam_get_user(pamh, &username, NULL); + if ((ret != PAM_SUCCESS) || (!username)) { _pam_log_debug(pamh, ctrl, LOG_DEBUG,"can not get the username"); - return PAM_SERVICE_ERR; + ret = PAM_SERVICE_ERR; + goto out; } /* Verify the username */ - retval = valid_user(pamh, ctrl, username); - switch (retval) { + ret = valid_user(pamh, ctrl, username); + switch (ret) { case -1: /* some sort of system error. The log was already printed */ - return PAM_SERVICE_ERR; + ret = PAM_SERVICE_ERR; + goto out; case 1: /* the user does not exist */ _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", username); if (ctrl & WINBIND_UNKNOWN_OK_ARG) { - return PAM_IGNORE; + ret = PAM_IGNORE; + goto out; } - return PAM_USER_UNKNOWN; + ret = PAM_USER_UNKNOWN; + goto out; case 0: pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp); if (tmp != NULL) { - retval = atoi((const char *)tmp); - switch (retval) { + ret = atoi((const char *)tmp); + switch (ret) { case PAM_AUTHTOK_EXPIRED: /* fall through, since new token is required in this case */ case PAM_NEW_AUTHTOK_REQD: @@ -1142,41 +1154,64 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, PAM_WINBIND_NEW_AUTHTOK_REQD); _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' needs new password", username); /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */ - return PAM_NEW_AUTHTOK_REQD; + ret = PAM_NEW_AUTHTOK_REQD; + goto out; default: _pam_log(pamh, ctrl, LOG_WARNING, "pam_sm_acct_mgmt success"); _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username); - return PAM_SUCCESS; + ret = PAM_SUCCESS; + goto out; } } /* Otherwise, the authentication looked good */ _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username); - return PAM_SUCCESS; + ret = PAM_SUCCESS; + goto out; default: /* we don't know anything about this return value */ - _pam_log(pamh, ctrl, LOG_ERR, "internal module error (retval = %d, user = '%s')", - retval, username); - return PAM_SERVICE_ERR; + _pam_log(pamh, ctrl, LOG_ERR, "internal module error (ret = %d, user = '%s')", + ret, username); + ret = PAM_SERVICE_ERR; + goto out; } /* should not be reached */ - return PAM_IGNORE; + ret = PAM_IGNORE; + + out: + + if (d) { + iniparser_freedict(d); + } + + return ret; } PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { + int ret = PAM_SYSTEM_ERR; + dictionary *d = NULL; + /* parse arguments */ - int ctrl = _pam_parse(pamh, flags, argc, argv, NULL); + int ctrl = _pam_parse(pamh, flags, argc, argv, &d); if (ctrl == -1) { - return PAM_SYSTEM_ERR; + ret = PAM_SYSTEM_ERR; + goto out; } _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_open_session handler (flags: 0x%04x)", flags); - return PAM_SUCCESS; + ret = PAM_SUCCESS; + + out: + if (d) { + iniparser_freedict(d); + } + + return ret; } PAM_EXTERN -- cgit From 062a1a4904b58f17b4917677fad780d69b7c4f69 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 10 Jan 2007 12:34:24 +0000 Subject: r20651: Fix "password expires soon" warning message for pam_winbind. We were incorrectly calculating the days until the password expires and we also need to look at the info3 pass_must_change_time for expiry calculation. Guenther (This used to be commit 22d79237127a064a934928d175182adecc6300de) --- source3/nsswitch/pam_winbind.c | 79 +++++++++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 12 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index c9e092fc3e..6b683d682d 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -3,7 +3,7 @@ Copyright Andrew Tridgell 2000 Copyright Tim Potter 2000 Copyright Andrew Bartlett 2002 - Copyright Guenther Deschner 2005-2006 + Copyright Guenther Deschner 2005-2007 largely based on pam_userdb by Cristian Gafton also contains large slabs of code from pam_unix by Elliot Lee @@ -378,6 +378,70 @@ static int pam_winbind_request_log(pam_handle_t * pamh, } } +static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, time_t next_change, time_t now) +{ + int days = 0; + struct tm tm_now, tm_next_change; + + if ((next_change < 0) || + (next_change < now) || + (next_change > now + DAYS_TO_WARN_BEFORE_PWD_EXPIRES * SECONDS_PER_DAY)) { + return False; + } + + if ((localtime_r(&now, &tm_now) == NULL) || + (localtime_r(&next_change, &tm_next_change) == NULL)) { + return False; + } + + days = (tm_next_change.tm_yday+tm_next_change.tm_year*365) - (tm_now.tm_yday+tm_now.tm_year*365); + + if (days == 0) { + _make_remark(pamh, PAM_TEXT_INFO, "Your password expires today"); + return True; + } + + if (days > 0 && days < DAYS_TO_WARN_BEFORE_PWD_EXPIRES) { + _make_remark_format(pamh, PAM_TEXT_INFO, "Your password will expire in %d %s", + days, (days > 1) ? "days":"day"); + return True; + } + + return False; +} + +static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, struct winbindd_response *response) +{ + time_t now = time(NULL); + time_t next_change = 0; + + /* accounts with ACB_PWNOEXP set never receive a warning */ + if (response->data.auth.info3.acct_flags & ACB_PWNOEXP) { + return; + } + + /* check if the info3 must change timestamp has been set */ + next_change = response->data.auth.info3.pass_must_change_time; + + if (_pam_send_password_expiry_message(pamh, next_change, now)) { + return; + } + + /* now check for the global password policy */ + if (response->data.auth.policy.expire <= 0) { + return; + } + + next_change = response->data.auth.info3.pass_last_set_time + + response->data.auth.policy.expire; + + if (_pam_send_password_expiry_message(pamh, next_change, now)) { + return; + } + + /* no warning sent */ +} + /* talk to winbindd */ static int winbind_auth_request(pam_handle_t * pamh, int ctrl, @@ -538,16 +602,7 @@ static int winbind_auth_request(pam_handle_t * pamh, } /* warn a user if the password is about to expire soon */ - if ( ! (response.data.auth.info3.acct_flags & ACB_PWNOEXP) && - (response.data.auth.policy.expire) && - (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire > time(NULL) ) ) { - - int days = (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire - - time(NULL))/ SECONDS_PER_DAY; - if (days <= DAYS_TO_WARN_BEFORE_PWD_EXPIRES) { - _make_remark_format(pamh, PAM_TEXT_INFO, "Your password will expire in %d days", days); - } - } + _pam_warn_password_expires_in_future(pamh, &response); if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) { _make_remark(pamh, PAM_ERROR_MSG, "Logging on using cached account. Network ressources can be unavailable"); @@ -1556,7 +1611,7 @@ struct pam_module _pam_winbind_modstruct = { * Copyright (c) Andrew Tridgell 2000 * Copyright (c) Tim Potter 2000 * Copyright (c) Andrew Bartlettt 2002 - * Copyright (c) Guenther Deschner 2005-2006 + * Copyright (c) Guenther Deschner 2005-2007 * Copyright (c) Jan Rêkorajski 1999. * Copyright (c) Andrew G. Morgan 1996-8. * Copyright (c) Alex O. Yuriev, 1996. -- cgit From 0d538f7370f13b175f127f061d5bff18e631cd5e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 11 Jan 2007 15:41:02 +0000 Subject: r20687: Implement grace logons for offline authentications in pam_winbind. In case a user authenticated sucessfully and his password just expired while beeing disconnected, we should allow a user to logon (given a clear warning). We currently forced the user into a password change dialogue in that scenario; this did not make much sense while offline. Guenther (This used to be commit 668b278653acfc4de7807834988f7af557e608a5) --- source3/nsswitch/pam_winbind.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 6b683d682d..f0a60233c5 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -420,6 +420,11 @@ static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, struct winb return; } + /* no point in sending a warning if this is a grace logon */ + if (PAM_WB_GRACE_LOGON(response->data.auth.info3.user_flgs)) { + return; + } + /* check if the info3 must change timestamp has been set */ next_change = response->data.auth.info3.pass_must_change_time; @@ -586,6 +591,7 @@ static int winbind_auth_request(pam_handle_t * pamh, /* handle the case where the auth was ok, but the password must expire right now */ /* good catch from Ralf Haferkamp: an expiry of "never" is translated to -1 */ if ( ! (response.data.auth.info3.acct_flags & ACB_PWNOEXP) && + ! (PAM_WB_GRACE_LOGON(response.data.auth.info3.user_flgs)) && (response.data.auth.policy.expire > 0) && (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire < time(NULL))) { @@ -604,9 +610,20 @@ static int winbind_auth_request(pam_handle_t * pamh, /* warn a user if the password is about to expire soon */ _pam_warn_password_expires_in_future(pamh, &response); - if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) { - _make_remark(pamh, PAM_ERROR_MSG, "Logging on using cached account. Network ressources can be unavailable"); - _pam_log_debug(pamh, ctrl, LOG_DEBUG,"User %s logged on using cached account\n", user); + /* inform about logon type */ + if (PAM_WB_GRACE_LOGON(response.data.auth.info3.user_flgs)) { + + _make_remark(pamh, PAM_ERROR_MSG, + "Grace login. Please change your password as soon you're online again"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "User %s logged on using grace logon\n", user); + + } else if (PAM_WB_CACHED_LOGON(response.data.auth.info3.user_flgs)) { + + _make_remark(pamh, PAM_ERROR_MSG, + "Logging on using cached account. Network ressources can be unavailable"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "User %s logged on using cached account\n", user); } /* save the CIFS homedir for pam_cifs / pam_mount */ -- cgit From df1e2693dce2da22a40ae0d0e75d2d3f35bf852f Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 25 Jan 2007 00:47:27 +0000 Subject: r21009: Patch from Danilo Almeida @ Centeris (via me). Patch details: Support most options in pam_winbind.conf; support comma-separated names in require-membership-of. Details below: 1) Provides support for almost all config options in pam_winbind.conf (all except for use_first_pass, use_authtok, and unknown_ok). - That allows us to work well when invoked via call_modules from pam_unix2.conf as well as allowing use of spaces in names used w/require_membership_of. 2) Support for comma-separated list of names or SID strings in require_membership_of/require-membership-of. - Increased require_membership_of field in winbind request from fstring (256) to pstring (1024). - In PAM side, parse out multiple names or SID strings and convert all of them to SID strings. - In Winbind side, support membership check against multiple SID strings. (This used to be commit 4aca9864896b3e0890ffc9a6980d7ef1311138f7) --- source3/nsswitch/pam_winbind.c | 209 +++++++++++++++++++++++++++++++++-------- 1 file changed, 170 insertions(+), 39 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index f0a60233c5..8984b92df8 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -91,21 +91,18 @@ static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const ch va_end(args); } -static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char **argv, dictionary **d) +static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char **argv, dictionary **result_d) { int ctrl = 0; const char *config_file = NULL; int i; const char **v; + dictionary *d = NULL; if (flags & PAM_SILENT) { ctrl |= WINBIND_SILENT; } - if (d == NULL) { - goto config_from_pam; - } - for (i=argc,v=argv; i-- > 0; ++v) { if (!strncasecmp(*v, "config", strlen("config"))) { ctrl |= WINBIND_CONFIG_FILE; @@ -118,36 +115,40 @@ static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char config_file = PAM_WINBIND_CONFIG_FILE; } - *d = iniparser_load(config_file); - if (*d == NULL) { + d = iniparser_load(config_file); + if (d == NULL) { goto config_from_pam; } - if (iniparser_getboolean(*d, "global:debug", False)) { + if (iniparser_getboolean(d, "global:debug", False)) { ctrl |= WINBIND_DEBUG_ARG; } - if (iniparser_getboolean(*d, "global:cached_login", False)) { + if (iniparser_getboolean(d, "global:cached_login", False)) { ctrl |= WINBIND_CACHED_LOGIN; } - if (iniparser_getboolean(*d, "global:krb5_auth", False)) { + if (iniparser_getboolean(d, "global:krb5_auth", False)) { ctrl |= WINBIND_KRB5_AUTH; } - if (iniparser_getboolean(*d, "global:silent", False)) { + if (iniparser_getboolean(d, "global:silent", False)) { ctrl |= WINBIND_SILENT; } - if (iniparser_getstr(*d, "global:krb5_ccache_type") != NULL) { + if (iniparser_getstr(d, "global:krb5_ccache_type") != NULL) { ctrl |= WINBIND_KRB5_CCACHE_TYPE; } - if ((iniparser_getstr(*d, "global:require-membership-of") != NULL) || - (iniparser_getstr(*d, "global:require_membership_of") != NULL)) { + if ((iniparser_getstr(d, "global:require-membership-of") != NULL) || + (iniparser_getstr(d, "global:require_membership_of") != NULL)) { ctrl |= WINBIND_REQUIRED_MEMBERSHIP; } + if (iniparser_getboolean(d, "global:try_first_pass", False)) { + ctrl |= WINBIND_TRY_FIRST_PASS_ARG; + } + config_from_pam: /* step through arguments */ for (i=argc,v=argv; i-- > 0; ++v) { @@ -179,6 +180,15 @@ config_from_pam: } } + + if (result_d) { + *result_d = d; + } else { + if (d) { + iniparser_freedict(d); + } + } + return ctrl; }; @@ -447,6 +457,147 @@ static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, struct winb /* no warning sent */ } +#define IS_SID_STRING(name) (strncmp("S-", name, 2) == 0) + +int safe_append_string(char *dest, + const char *src, + int dest_buffer_size) +/** + * Append a string, making sure not to overflow and to always return a NULL-terminated + * string. + * + * @param dest Destination string buffer (must already be NULL-terminated). + * @param src Source string buffer. + * @param dest_buffer_size Size of dest buffer in bytes. + * + * @return 0 if dest buffer is not big enough (no bytes copied), non-zero on success. + */ +{ + int dest_length = strlen(dest); + int src_length = strlen(src); + + if ( dest_length + src_length + 1 > dest_buffer_size ) { + return 0; + } + + memcpy(dest + dest_length, src, src_length + 1); + return 1; +} + +static int winbind_name_to_sid_string(pam_handle_t *pamh, + int ctrl, + const char *user, + const char *name, + char *sid_list_buffer, + int sid_list_buffer_size) +/** + * Convert a names into a SID string, appending it to a buffer. + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * @param user User in PAM request. + * @param name Name to convert. + * @param sid_list_buffer Where to append the string sid. + * @param sid_list_buffer Size of sid_list_buffer (in bytes). + * + * @return 0 on failure, non-zero on success. + */ +{ + const char* sid_string; + struct winbindd_response sid_response; + + /* lookup name? */ + if (IS_SID_STRING(name)) { + sid_string = name; + } else { + struct winbindd_request sid_request; + + ZERO_STRUCT(sid_request); + ZERO_STRUCT(sid_response); + + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", name); + + /* fortunatly winbindd can handle non-separated names */ + strncpy(sid_request.data.name.name, name, + sizeof(sid_request.data.name.name) - 1); + + if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) { + _pam_log(pamh, ctrl, LOG_INFO, "could not lookup name: %s\n", name); + return 0; + } + + sid_string = sid_response.data.sid.sid; + } + + if (!safe_append_string(sid_list_buffer, sid_string, sid_list_buffer_size)) { + return 0; + } + + return 1; +} + +static int winbind_name_list_to_sid_string_list(pam_handle_t *pamh, + int ctrl, + const char *user, + const char *name_list, + char *sid_list_buffer, + int sid_list_buffer_size) +/** + * Convert a list of names into a list of sids. + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * @param user User in PAM request. + * @param name_list List of names or string sids, separated by commas. + * @param sid_list_buffer Where to put the list of string sids. + * @param sid_list_buffer Size of sid_list_buffer (in bytes). + * + * @return 0 on failure, non-zero on success. + */ +{ + int result = 0; + char *current_name = NULL; + const char *search_location; + const char *comma; + + if ( sid_list_buffer_size > 0 ) { + sid_list_buffer[0] = 0; + } + + search_location = name_list; + while ( (comma = strstr(search_location, ",")) != NULL ) { + current_name = strndup(search_location, comma - search_location); + if (NULL == current_name) { + goto out; + } + + if (!winbind_name_to_sid_string(pamh, ctrl, user, current_name, sid_list_buffer, sid_list_buffer_size)) { + goto out; + } + + free(current_name); + current_name = NULL; + + if (!safe_append_string(sid_list_buffer, ",", sid_list_buffer_size)) { + goto out; + } + + search_location = comma + 1; + } + + if (!winbind_name_to_sid_string(pamh, ctrl, user, search_location, sid_list_buffer, sid_list_buffer_size)) { + goto out; + } + + result = 1; + +out: + if (current_name != NULL) { + free(current_name); + } + return result; +} + /* talk to winbindd */ static int winbind_auth_request(pam_handle_t * pamh, int ctrl, @@ -514,36 +665,16 @@ static int winbind_auth_request(pam_handle_t * pamh, request.data.auth.require_membership_of_sid[0] = '\0'; if (member != NULL) { - strncpy(request.data.auth.require_membership_of_sid, member, - sizeof(request.data.auth.require_membership_of_sid)-1); - } - /* lookup name? */ - if ( (member != NULL) && (strncmp("S-", member, 2) != 0) ) { - - struct winbindd_request sid_request; - struct winbindd_response sid_response; + if (!winbind_name_list_to_sid_string_list(pamh, ctrl, user, member, + request.data.auth.require_membership_of_sid, + sizeof(request.data.auth.require_membership_of_sid))) { - ZERO_STRUCT(sid_request); - ZERO_STRUCT(sid_response); - - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", member); - - /* fortunatly winbindd can handle non-separated names */ - strncpy(sid_request.data.name.name, member, - sizeof(sid_request.data.name.name) - 1); - - if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) { - _pam_log(pamh, ctrl, LOG_INFO, "could not lookup name: %s\n", member); + _pam_log_debug(pamh, ctrl, LOG_ERR, "failed to serialize membership of sid \"%s\"\n", member); return PAM_AUTH_ERR; } - - member = sid_response.data.sid.sid; - - strncpy(request.data.auth.require_membership_of_sid, member, - sizeof(request.data.auth.require_membership_of_sid)-1); } - + ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, &request, &response, user); if (pwd_last_set) { -- cgit From 76fd8f8e1d774f247423ddfe0c76c3f89bbd3b48 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 25 Jan 2007 01:18:31 +0000 Subject: r21011: Another patch from Danilo Almeida @ Centeris (via me): Details: Reset the "new password prompt required" state whenever we do a new auth. In more detail, in pam_sm_authenticate, if not settting PAM_WINBIND_NEW_AUTHTOK_REQD, then clean any potentially present PAM_WINBIND_NEW_AUTHTOK_REQD. (This used to be commit 402e8594759b42c1986f4f8d69273f68ec5160af) --- source3/nsswitch/pam_winbind.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 8984b92df8..91a333b93d 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1179,6 +1179,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int retval = PAM_AUTH_ERR; dictionary *d = NULL; char *username_ret = NULL; + char *new_authtok_required = NULL; /* parse arguments */ int ctrl = _pam_parse(pamh, flags, argc, argv, &d); @@ -1227,14 +1228,12 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, if (retval == PAM_NEW_AUTHTOK_REQD || retval == PAM_AUTHTOK_EXPIRED) { - char *buf; - - if (!asprintf(&buf, "%d", retval)) { + if (!asprintf(&new_authtok_required, "%d", retval)) { retval = PAM_BUF_ERR; goto out; } - pam_set_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (void *)buf, _pam_winbind_cleanup_func); + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, new_authtok_required, _pam_winbind_cleanup_func); retval = PAM_SUCCESS; goto out; @@ -1296,6 +1295,10 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, iniparser_freedict(d); } + if (!new_authtok_required) { + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, NULL, NULL); + } + return ret; } -- cgit From 7e8a068a5edd6676353e80535660d803fc5bdfe4 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 25 Jan 2007 01:56:34 +0000 Subject: r21012: Patch from Danilo Almeida @ Centeris (via me): Details: Improve PAM logging - The improved logging is far tracking down PAM-related bugs - PAM_SILENT was being mis-used to suppress syslog output instead of suppressing user output. This lets PAM_SILENT still log to syslog. - Allow logging of item & data state via debug_state config file option. - Logging tracks the pam handle used. (This used to be commit cc1a13a9f06e5c15c8df19d0fbb31dbdeb81a9cc) --- source3/nsswitch/pam_winbind.c | 188 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 167 insertions(+), 21 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 91a333b93d..593adfe2f2 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -12,6 +12,18 @@ #include "pam_winbind.h" +#define _PAM_LOG_FUNCTION_ENTER(function, pamh, ctrl, flags) \ + do { \ + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] ENTER: " function " (flags: 0x%04x)", (uint32) pamh, flags); \ + _pam_log_state(pamh, ctrl); \ + } while (0) + +#define _PAM_LOG_FUNCTION_LEAVE(function, pamh, ctrl, retval) \ + do { \ + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] LEAVE: " function " returning %d", (uint32) pamh, retval); \ + _pam_log_state(pamh, ctrl); \ + } while (0) + /* data tokens */ #define MAX_PASSWD_TRIES 3 @@ -61,11 +73,16 @@ static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, } #endif /* HAVE_PAM_VSYSLOG */ +static inline int _pam_log_is_silent(int ctrl) +{ + return (ctrl & WINBIND_SILENT) ? 1 : 0; +} + static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) { va_list args; - if (ctrl & WINBIND_SILENT) { + if (_pam_log_is_silent(ctrl)) { return; } @@ -74,15 +91,37 @@ static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *fo va_end(args); } -static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) +static inline int _pam_log_is_debug_enabled(int ctrl) { - va_list args; + if (ctrl == -1) { + return 0; + } - if (ctrl & WINBIND_SILENT) { - return; + if (_pam_log_is_silent(ctrl)) { + return 0; } if (!(ctrl & WINBIND_DEBUG_ARG)) { + return 0; + } + + return 1; +} + +static inline int _pam_log_is_debug_state_enabled(int ctrl) +{ + if (!(ctrl & WINBIND_DEBUG_STATE)) { + return 0; + } + + return _pam_log_is_debug_enabled(ctrl); +} + +static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) +{ + va_list args; + + if (!_pam_log_is_debug_enabled(ctrl)) { return; } @@ -91,6 +130,74 @@ static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const ch va_end(args); } +static void _pam_log_state_datum(const pam_handle_t *pamh, int ctrl, int item_type, const char *key, int is_string) +{ + const void *data = NULL; + if (item_type != 0) { + pam_get_item(pamh, item_type, &data); + } else { + pam_get_data(pamh, key, &data); + } + if (data != NULL) { + const char *type = (item_type != 0) ? "ITEM" : "DATA"; + if (is_string != 0) { + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] STATE: %s(%s) = \"%s\" (0x%08x)", (uint32) pamh, type, key, (const char *) data, (uint32) data); + } else { + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] STATE: %s(%s) = 0x%08x", (uint32) pamh, type, key, (uint32) data); + } + } +} + +#define _PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, module_data_name) \ + _pam_log_state_datum(pamh, ctrl, 0, module_data_name, 0) + +#define _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, module_data_name) \ + _pam_log_state_datum(pamh, ctrl, 0, module_data_name, 1) + +#define _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, item_type) \ + _pam_log_state_datum(pamh, ctrl, item_type, #item_type, 0) + +#define _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, item_type) \ + _pam_log_state_datum(pamh, ctrl, item_type, #item_type, 1) + +#ifdef DEBUG_PASSWORD +#define _LOG_PASSWORD_AS_STRING 1 +#else +#define _LOG_PASSWORD_AS_STRING 0 +#endif + +#define _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, item_type) \ + _pam_log_state_datum(pamh, ctrl, item_type, #item_type, _LOG_PASSWORD_AS_STRING) + +static void _pam_log_state(const pam_handle_t *pamh, int ctrl) +{ + if (!_pam_log_is_debug_state_enabled(ctrl)) { + return; + } + + _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_SERVICE); + _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_USER); + _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_TTY); + _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_RHOST); + _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_RUSER); + _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, PAM_OLDAUTHTOK); + _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, PAM_AUTHTOK); + _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_USER_PROMPT); + _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_CONV); +#ifdef PAM_FAIL_DELAY + _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_FAIL_DELAY); +#endif +#ifdef PAM_REPOSITORY + _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_REPOSITORY); +#endif + + _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_HOMEDIR); + _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT); + _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_PROFILEPATH); + _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD); /* Use atoi to get PAM result code */ + _PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, PAM_WINBIND_PWD_LAST_SET); +} + static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char **argv, dictionary **result_d) { int ctrl = 0; @@ -124,6 +231,10 @@ static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char ctrl |= WINBIND_DEBUG_ARG; } + if (iniparser_getboolean(d, "global:debug_state", False)) { + ctrl |= WINBIND_DEBUG_STATE; + } + if (iniparser_getboolean(d, "global:cached_login", False)) { ctrl |= WINBIND_CACHED_LOGIN; } @@ -139,7 +250,7 @@ static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char if (iniparser_getstr(d, "global:krb5_ccache_type") != NULL) { ctrl |= WINBIND_KRB5_CCACHE_TYPE; } - + if ((iniparser_getstr(d, "global:require-membership-of") != NULL) || (iniparser_getstr(d, "global:require_membership_of") != NULL)) { ctrl |= WINBIND_REQUIRED_MEMBERSHIP; @@ -194,6 +305,10 @@ config_from_pam: static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_status) { + int ctrl = _pam_parse(pamh, 0, 0, NULL, NULL); + if (_pam_log_is_debug_state_enabled(ctrl)) { + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] CLEAN: cleaning up PAM data 0x%08x (error_status = %d)", (uint32) pamh, (uint32) data, error_status); + } SAFE_FREE(data); } @@ -275,21 +390,33 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text) return retval; } -static int _make_remark_format(pam_handle_t * pamh, int type, const char *format, ...) +static int _make_remark_v(pam_handle_t * pamh, int type, const char *format, va_list args) { - va_list args; char *var; int ret; - va_start(args, format); - vasprintf(&var, format, args); - va_end(args); + ret = vasprintf(&var, format, args); + if (ret < 0) { + _pam_log(pamh, 0, LOG_ERR, "memory allocation failure"); + return ret; + } ret = _make_remark(pamh, type, var); SAFE_FREE(var); return ret; } +static int _make_remark_format(pam_handle_t * pamh, int type, const char *format, ...) +{ + int ret; + va_list args; + + va_start(args, format); + ret = _make_remark_v(pamh, type, format, args); + va_end(args); + return ret; +} + static int pam_winbind_request(pam_handle_t * pamh, int ctrl, enum winbindd_cmd req_type, struct winbindd_request *request, @@ -972,6 +1099,8 @@ static int _winbind_read_password(pam_handle_t * pamh, const char *item; char *token; + _pam_log(pamh, ctrl, LOG_DEBUG, "getting password (0x%08x)", ctrl); + /* * make sure nothing inappropriate gets returned */ @@ -999,6 +1128,8 @@ static int _winbind_read_password(pam_handle_t * pamh, } else if (item != NULL) { /* we have a password! */ *pass = item; item = NULL; + _pam_log(pamh, ctrl, LOG_DEBUG, + "pam_get_item returned a password"); return PAM_SUCCESS; } else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ @@ -1188,7 +1319,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, goto out; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_authenticate (flags: 0x%04x)", flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_authenticate", pamh, ctrl, flags); /* Get the username */ retval = pam_get_user(pamh, &username, NULL); @@ -1249,6 +1380,13 @@ out: if (d) { iniparser_freedict(d); } + + if (!new_authtok_required) { + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, NULL, NULL); + } + + _PAM_LOG_FUNCTION_LEAVE("pam_sm_authenticate", pamh, ctrl, retval); + return retval; } @@ -1266,7 +1404,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, goto out; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_setcred (flags: 0x%04x)", flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_setcred", pamh, ctrl, flags); switch (flags & ~PAM_SILENT) { @@ -1295,10 +1433,8 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, iniparser_freedict(d); } - if (!new_authtok_required) { - pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, NULL, NULL); - } - + _PAM_LOG_FUNCTION_LEAVE("pam_sm_setcred", pamh, ctrl, ret); + return ret; } @@ -1321,7 +1457,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, return PAM_SYSTEM_ERR; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_acct_mgmt (flags: 0x%04x)", flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_acct_mgmt", pamh, ctrl, flags); /* Get the username */ @@ -1391,6 +1527,8 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, iniparser_freedict(d); } + _PAM_LOG_FUNCTION_LEAVE("pam_sm_acct_mgmt", pamh, ctrl, ret); + return ret; } @@ -1408,7 +1546,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, goto out; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_open_session handler (flags: 0x%04x)", flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_open_session", pamh, ctrl, flags); ret = PAM_SUCCESS; @@ -1417,6 +1555,8 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, iniparser_freedict(d); } + _PAM_LOG_FUNCTION_LEAVE("pam_sm_open_session", pamh, ctrl, ret); + return ret; } @@ -1434,7 +1574,7 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, goto out; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_close_session handler (flags: 0x%04x)", flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_close_session", pamh, ctrl, flags); if (!(flags & PAM_DELETE_CRED)) { retval = PAM_SUCCESS; @@ -1497,6 +1637,9 @@ out: if (d) { iniparser_freedict(d); } + + _PAM_LOG_FUNCTION_LEAVE("pam_sm_close_session", pamh, ctrl, retval); + return retval; } @@ -1526,7 +1669,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, goto out; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "pam_winbind: pam_sm_chauthtok (flags: 0x%04x)", flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_chauthtok", pamh, ctrl, flags); /* clearing offline bit for the auth in the password change */ ctrl &= ~WINBIND_CACHED_LOGIN; @@ -1739,6 +1882,9 @@ out: if (d) { iniparser_freedict(d); } + + _PAM_LOG_FUNCTION_LEAVE("pam_sm_chauthtok", pamh, ctrl, ret); + return ret; } -- cgit From 45aa381a7702779106bdb55b8cef1a371eb726c8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 25 Jan 2007 02:24:56 +0000 Subject: r21013: * Remove "inline" keyword * Remove anpther check for PAM_SILENT that prevents logging to syslog * Add missing check for TRY_FIRST_PASS when using authtok (missed from previous merge) (This used to be commit ed794f0872b749955f56112507fd3ae7a6c6e6f5) --- source3/nsswitch/pam_winbind.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 593adfe2f2..cc135ce76b 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -73,7 +73,7 @@ static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, } #endif /* HAVE_PAM_VSYSLOG */ -static inline int _pam_log_is_silent(int ctrl) +static int _pam_log_is_silent(int ctrl) { return (ctrl & WINBIND_SILENT) ? 1 : 0; } @@ -91,7 +91,7 @@ static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *fo va_end(args); } -static inline int _pam_log_is_debug_enabled(int ctrl) +static int _pam_log_is_debug_enabled(int ctrl) { if (ctrl == -1) { return 0; @@ -108,7 +108,7 @@ static inline int _pam_log_is_debug_enabled(int ctrl) return 1; } -static inline int _pam_log_is_debug_state_enabled(int ctrl) +static int _pam_log_is_debug_state_enabled(int ctrl) { if (!(ctrl & WINBIND_DEBUG_STATE)) { return 0; @@ -1406,7 +1406,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, _PAM_LOG_FUNCTION_ENTER("pam_sm_setcred", pamh, ctrl, flags); - switch (flags & ~PAM_SILENT) { + switch (flag) { case PAM_DELETE_CRED: ret = pam_sm_close_session(pamh, flags, argc, argv); @@ -1794,7 +1794,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, goto out; } - lctrl = ctrl; + lctrl = ctrl & ~WINBIND_TRY_FIRST_PASS_ARG; if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { lctrl |= WINBIND_USE_FIRST_PASS_ARG; -- cgit From 05ec6391273ca40ea49d4321618d8729327b2b75 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 25 Jan 2007 02:36:20 +0000 Subject: r21015: fix typo that breaks the build (This used to be commit f82a5175304a12b18abb2bc3d9fd9f7023998357) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index cc135ce76b..51a253d67a 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1406,7 +1406,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, _PAM_LOG_FUNCTION_ENTER("pam_sm_setcred", pamh, ctrl, flags); - switch (flag) { + switch (flags) { case PAM_DELETE_CRED: ret = pam_sm_close_session(pamh, flags, argc, argv); -- cgit From 3f9585018d2dac8f61dbc05e6d46e1550974e9b8 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 25 Jan 2007 10:29:04 +0000 Subject: r21016: Fix pam_sm_setcred again. Jerry, the switch statement must ignore the PAM_SILENT flag. Guenther (This used to be commit 46d23c72bf4f3bd04021a9caf8d6b1380352b811) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 51a253d67a..09f9eee7df 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1406,7 +1406,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, _PAM_LOG_FUNCTION_ENTER("pam_sm_setcred", pamh, ctrl, flags); - switch (flags) { + switch (flags & ~PAM_SILENT) { case PAM_DELETE_CRED: ret = pam_sm_close_session(pamh, flags, argc, argv); -- cgit From 74f38589b3f47715fd4bdc20ad97e425e091f9d9 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 25 Jan 2007 15:00:41 +0000 Subject: r21019: Fix typo. Guenther (This used to be commit adb40884e04069e7de7580b6531675ebaed5c117) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 09f9eee7df..8dc5f65f4b 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -879,7 +879,7 @@ static int winbind_auth_request(pam_handle_t * pamh, } else if (PAM_WB_CACHED_LOGON(response.data.auth.info3.user_flgs)) { _make_remark(pamh, PAM_ERROR_MSG, - "Logging on using cached account. Network ressources can be unavailable"); + "Logging on using cached account. Network resources can be unavailable"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, "User %s logged on using cached account\n", user); } -- cgit From b979bf5686e35e5da299b8429686e90cca6fc852 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 25 Jan 2007 15:05:23 +0000 Subject: r21020: Some pam_winbind fixes: * make debug_state also configurable from the config file * minor code cleanup Guenther (This used to be commit c562095953df55c91e3dad8f5c29c0b66664b62b) --- source3/nsswitch/pam_winbind.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 8dc5f65f4b..e8c0988923 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -73,9 +73,9 @@ static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, } #endif /* HAVE_PAM_VSYSLOG */ -static int _pam_log_is_silent(int ctrl) +static BOOL _pam_log_is_silent(int ctrl) { - return (ctrl & WINBIND_SILENT) ? 1 : 0; + return on(ctrl, WINBIND_SILENT); } static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) @@ -91,27 +91,27 @@ static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *fo va_end(args); } -static int _pam_log_is_debug_enabled(int ctrl) +static BOOL _pam_log_is_debug_enabled(int ctrl) { if (ctrl == -1) { - return 0; + return False; } if (_pam_log_is_silent(ctrl)) { - return 0; + return False; } if (!(ctrl & WINBIND_DEBUG_ARG)) { - return 0; + return False; } - return 1; + return True; } -static int _pam_log_is_debug_state_enabled(int ctrl) +static BOOL _pam_log_is_debug_state_enabled(int ctrl) { if (!(ctrl & WINBIND_DEBUG_STATE)) { - return 0; + return False; } return _pam_log_is_debug_enabled(ctrl); @@ -267,6 +267,8 @@ config_from_pam: /* generic options */ if (!strcmp(*v,"debug")) ctrl |= WINBIND_DEBUG_ARG; + else if (!strcasecmp(*v, "debug_state")) + ctrl |= WINBIND_DEBUG_STATE; else if (!strcasecmp(*v, "use_authtok")) ctrl |= WINBIND_USE_AUTHTOK_ARG; else if (!strcasecmp(*v, "use_first_pass")) @@ -702,8 +704,7 @@ static int winbind_name_list_to_sid_string_list(pam_handle_t *pamh, goto out; } - free(current_name); - current_name = NULL; + SAFE_FREE(current_name); if (!safe_append_string(sid_list_buffer, ",", sid_list_buffer_size)) { goto out; @@ -719,9 +720,7 @@ static int winbind_name_list_to_sid_string_list(pam_handle_t *pamh, result = 1; out: - if (current_name != NULL) { - free(current_name); - } + SAFE_FREE(current_name); return result; } -- cgit From 48191ddec6cd720b349de33979811a4d9db28172 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 2 Feb 2007 13:03:06 +0000 Subject: r21122: Simplify code in pam_winbind a bit. Guenther (This used to be commit 08ca5ea6f1b09506055b2508aa79704f39b3bbd7) --- source3/nsswitch/pam_winbind.c | 43 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 23 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index e8c0988923..d7fb838d9a 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1593,20 +1593,19 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, ZERO_STRUCT(response); retval = pam_get_user(pamh, &user, "Username: "); - if (retval == PAM_SUCCESS) { - if (user == NULL) { - _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); - retval = PAM_USER_UNKNOWN; - goto out; - } - if (retval == PAM_SUCCESS) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user); - } - } else { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "could not identify user"); + if (retval) { + _pam_log(pamh, ctrl, LOG_ERR, "could not identify user"); goto out; } + if (user == NULL) { + _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); + retval = PAM_USER_UNKNOWN; + goto out; + } + + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user); + ccname = pam_getenv(pamh, "KRB5CCNAME"); if (ccname == NULL) { _pam_log_debug(pamh, ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment"); @@ -1677,22 +1676,20 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * First get the name of a user */ ret = pam_get_user(pamh, &user, "Username: "); - if (ret == PAM_SUCCESS) { - if (user == NULL) { - _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); - ret = PAM_USER_UNKNOWN; - goto out; - } - if (ret == PAM_SUCCESS) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", - user); - } - } else { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + if (ret) { + _pam_log(pamh, ctrl, LOG_ERR, "password - could not identify user"); goto out; } + if (user == NULL) { + _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); + ret = PAM_USER_UNKNOWN; + goto out; + } + + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user); + /* check if this is really a user in winbindd, not only in NSS */ ret = valid_user(pamh, ctrl, user); switch (ret) { -- cgit From 4aa7205c3da08b6efb322980bf7cf2ebe12c67a8 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 5 Feb 2007 14:34:12 +0000 Subject: r21143: Fix wrong check for pam error codes for getpwnam and lookup winbind requests in pam_winbind (Bug #4094). Inspired by fix from Lars Heete. Guenther (This used to be commit 88e2185d2913e835e074dc3cc4ab1c631c3296a5) --- source3/nsswitch/pam_winbind.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index d7fb838d9a..2b8e9be528 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -444,21 +444,34 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, close_sock(); /* Copy reply data from socket */ - if (response->result != WINBINDD_OK) { - if (response->data.auth.pam_error != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_ERR, "request failed: %s, PAM error was %s (%d), NT error was %s", - response->data.auth.error_string, - pam_strerror(pamh, response->data.auth.pam_error), - response->data.auth.pam_error, - response->data.auth.nt_status_string); - return response->data.auth.pam_error; - } else { - _pam_log(pamh, ctrl, LOG_ERR, "request failed, but PAM error 0!"); - return PAM_SERVICE_ERR; - } + if (response->result == WINBINDD_OK) { + return PAM_SUCCESS; } - return PAM_SUCCESS; + /* no need to check for pam_error codes for getpwnam() */ + switch (req_type) { + + case WINBINDD_GETPWNAM: + case WINBINDD_LOOKUPNAME: + _pam_log(pamh, ctrl, LOG_ERR, "request failed: %s, NT error was %s", + response->data.auth.nt_status_string); + return PAM_USER_UNKNOWN; + default: + break; + } + + if (response->data.auth.pam_error != PAM_SUCCESS) { + _pam_log(pamh, ctrl, LOG_ERR, "request failed: %s, PAM error was %s (%d), NT error was %s", + response->data.auth.error_string, + pam_strerror(pamh, response->data.auth.pam_error), + response->data.auth.pam_error, + response->data.auth.nt_status_string); + return response->data.auth.pam_error; + } + + _pam_log(pamh, ctrl, LOG_ERR, "request failed, but PAM error 0!"); + + return PAM_SERVICE_ERR; } static int pam_winbind_request_log(pam_handle_t * pamh, -- cgit From 0b2bbb2704aa10a52b6fb111bd3549b1a36ad680 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 5 Feb 2007 14:43:06 +0000 Subject: r21144: Create more accurate warning message when the pam_winbind chauthtok has received NT_STATUS_PASSWORD_RESTRICTION. Guenther (This used to be commit 2ac9cb3bbd1980df54f1b6cc2cfb823be43f3230) --- source3/nsswitch/pam_winbind.c | 88 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 12 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 2b8e9be528..a8344db338 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -737,6 +737,75 @@ out: return result; } +/** + * Compose Password Restriction String for a PAM_ERROR_MSG conversation. + * + * @param response The struct winbindd_response. + * + * @return string (caller needs to free). + */ + +static char *_pam_compose_pwd_restriction_string(struct winbindd_response *response) +{ + char *str = NULL; + size_t offset = 0, ret = 0, str_size = 1024; + + str = (char *)malloc(str_size); + if (!str) { + return NULL; + } + + memset(str, '\0', str_size); + + offset = snprintf(str, str_size, "Your password "); + if (offset == -1) { + goto failed; + } + + if (response->data.auth.policy.min_length_password > 0) { + ret = snprintf(str+offset, str_size-offset, + "must be at least %d characters; ", + response->data.auth.policy.min_length_password); + if (ret == -1) { + goto failed; + } + offset += ret; + } + + if (response->data.auth.policy.password_history > 0) { + ret = snprintf(str+offset, str_size-offset, + "cannot repeat any of your previous %d passwords; ", + response->data.auth.policy.password_history); + if (ret == -1) { + goto failed; + } + offset += ret; + } + + if (response->data.auth.policy.password_properties & DOMAIN_PASSWORD_COMPLEX) { + ret = snprintf(str+offset, str_size-offset, + "must contain capitals, numerals or punctuation; " + "and cannot contain your account or full name; "); + if (ret == -1) { + goto failed; + } + offset += ret; + } + + ret = snprintf(str+offset, str_size-offset, + "Please type a different password. " + "Type a password which meets these requirements in both text boxes."); + if (ret == -1) { + goto failed; + } + + return str; + + failed: + SAFE_FREE(str); + return NULL; +} + /* talk to winbindd */ static int winbind_auth_request(pam_handle_t * pamh, int ctrl, @@ -1002,6 +1071,8 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, if (!strcasecmp(response.data.auth.nt_status_string, "NT_STATUS_PASSWORD_RESTRICTION")) { + char *pwd_restriction_string = NULL; + /* FIXME: avoid to send multiple PAM messages after another */ switch (response.data.auth.reject_reason) { case -1: @@ -1028,18 +1099,11 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, break; } - _make_remark_format(pamh, PAM_ERROR_MSG, - "Your password must be at least %d characters; " - "cannot repeat any of the your previous %d passwords" - "%s. " - "Please type a different password. " - "Type a password which meets these requirements in both text boxes.", - response.data.auth.policy.min_length_password, - response.data.auth.policy.password_history, - (response.data.auth.policy.password_properties & DOMAIN_PASSWORD_COMPLEX) ? - "; must contain capitals, numerals or punctuation; and cannot contain your account or full name" : - ""); - + pwd_restriction_string = _pam_compose_pwd_restriction_string(&response); + if (pwd_restriction_string) { + _make_remark(pamh, PAM_ERROR_MSG, pwd_restriction_string); + SAFE_FREE(pwd_restriction_string); + } } return ret; -- cgit From c622130a7dd52c6d22e546c955fda5ec9cedd363 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 5 Feb 2007 14:46:36 +0000 Subject: r21145: Convert some int to BOOL in pam_winbind (only in 3_0). Guenther (This used to be commit 1b82c5fa0e363942947453a8e1b74aa2b95d8733) --- source3/nsswitch/pam_winbind.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index a8344db338..6929c3f3db 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -601,7 +601,7 @@ static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, struct winb #define IS_SID_STRING(name) (strncmp("S-", name, 2) == 0) -int safe_append_string(char *dest, +static BOOL safe_append_string(char *dest, const char *src, int dest_buffer_size) /** @@ -612,21 +612,21 @@ int safe_append_string(char *dest, * @param src Source string buffer. * @param dest_buffer_size Size of dest buffer in bytes. * - * @return 0 if dest buffer is not big enough (no bytes copied), non-zero on success. + * @return False if dest buffer is not big enough (no bytes copied), True on success. */ { int dest_length = strlen(dest); int src_length = strlen(src); if ( dest_length + src_length + 1 > dest_buffer_size ) { - return 0; + return False; } memcpy(dest + dest_length, src, src_length + 1); - return 1; + return True; } -static int winbind_name_to_sid_string(pam_handle_t *pamh, +static BOOL winbind_name_to_sid_string(pam_handle_t *pamh, int ctrl, const char *user, const char *name, @@ -642,7 +642,7 @@ static int winbind_name_to_sid_string(pam_handle_t *pamh, * @param sid_list_buffer Where to append the string sid. * @param sid_list_buffer Size of sid_list_buffer (in bytes). * - * @return 0 on failure, non-zero on success. + * @return False on failure, True on success. */ { const char* sid_string; @@ -665,20 +665,20 @@ static int winbind_name_to_sid_string(pam_handle_t *pamh, if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) { _pam_log(pamh, ctrl, LOG_INFO, "could not lookup name: %s\n", name); - return 0; + return False; } sid_string = sid_response.data.sid.sid; } if (!safe_append_string(sid_list_buffer, sid_string, sid_list_buffer_size)) { - return 0; + return False; } - return 1; + return True; } -static int winbind_name_list_to_sid_string_list(pam_handle_t *pamh, +static BOOL winbind_name_list_to_sid_string_list(pam_handle_t *pamh, int ctrl, const char *user, const char *name_list, @@ -694,10 +694,10 @@ static int winbind_name_list_to_sid_string_list(pam_handle_t *pamh, * @param sid_list_buffer Where to put the list of string sids. * @param sid_list_buffer Size of sid_list_buffer (in bytes). * - * @return 0 on failure, non-zero on success. + * @return False on failure, True on success. */ { - int result = 0; + BOOL result = False; char *current_name = NULL; const char *search_location; const char *comma; @@ -730,7 +730,7 @@ static int winbind_name_list_to_sid_string_list(pam_handle_t *pamh, goto out; } - result = 1; + result = True; out: SAFE_FREE(current_name); -- cgit From 44512030b1f8b6d45c917dd2cb292c981bb7a543 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 5 Feb 2007 15:25:31 +0000 Subject: r21152: Correctly omit pam conversations when PAM_SILENT has been set by the calling application. Guenther (This used to be commit ebfae9a671d2c960178228ba7fdcd07cb2f49a05) --- source3/nsswitch/pam_winbind.c | 98 ++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 47 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 6929c3f3db..aeab270a86 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -372,13 +372,17 @@ static int converse(pam_handle_t *pamh, int nargs, } -static int _make_remark(pam_handle_t * pamh, int type, const char *text) +static int _make_remark(pam_handle_t * pamh, int flags, int type, const char *text) { int retval = PAM_SUCCESS; struct pam_message *pmsg[1], msg[1]; struct pam_response *resp; + if (flags & WINBIND_SILENT) { + return PAM_SUCCESS; + } + pmsg[0] = &msg[0]; msg[0].msg = CONST_DISCARD(char *, text); msg[0].msg_style = type; @@ -392,7 +396,7 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text) return retval; } -static int _make_remark_v(pam_handle_t * pamh, int type, const char *format, va_list args) +static int _make_remark_v(pam_handle_t * pamh, int flags, int type, const char *format, va_list args) { char *var; int ret; @@ -403,18 +407,18 @@ static int _make_remark_v(pam_handle_t * pamh, int type, const char *format, va_ return ret; } - ret = _make_remark(pamh, type, var); + ret = _make_remark(pamh, flags, type, var); SAFE_FREE(var); return ret; } -static int _make_remark_format(pam_handle_t * pamh, int type, const char *format, ...) +static int _make_remark_format(pam_handle_t * pamh, int flags, int type, const char *format, ...) { int ret; va_list args; va_start(args, format); - ret = _make_remark_v(pamh, type, format, args); + ret = _make_remark_v(pamh, flags, type, format, args); va_end(args); return ret; } @@ -530,7 +534,7 @@ static int pam_winbind_request_log(pam_handle_t * pamh, } } -static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, time_t next_change, time_t now) +static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, int ctrl, time_t next_change, time_t now) { int days = 0; struct tm tm_now, tm_next_change; @@ -549,12 +553,12 @@ static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, time_t next_ch days = (tm_next_change.tm_yday+tm_next_change.tm_year*365) - (tm_now.tm_yday+tm_now.tm_year*365); if (days == 0) { - _make_remark(pamh, PAM_TEXT_INFO, "Your password expires today"); + _make_remark(pamh, ctrl, PAM_TEXT_INFO, "Your password expires today"); return True; } if (days > 0 && days < DAYS_TO_WARN_BEFORE_PWD_EXPIRES) { - _make_remark_format(pamh, PAM_TEXT_INFO, "Your password will expire in %d %s", + _make_remark_format(pamh, ctrl, PAM_TEXT_INFO, "Your password will expire in %d %s", days, (days > 1) ? "days":"day"); return True; } @@ -562,7 +566,7 @@ static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, time_t next_ch return False; } -static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, struct winbindd_response *response) +static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, int ctrl, struct winbindd_response *response) { time_t now = time(NULL); time_t next_change = 0; @@ -580,7 +584,7 @@ static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, struct winb /* check if the info3 must change timestamp has been set */ next_change = response->data.auth.info3.pass_must_change_time; - if (_pam_send_password_expiry_message(pamh, next_change, now)) { + if (_pam_send_password_expiry_message(pamh, ctrl, next_change, now)) { return; } @@ -592,7 +596,7 @@ static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, struct winb next_change = response->data.auth.info3.pass_last_set_time + response->data.auth.policy.expire; - if (_pam_send_password_expiry_message(pamh, next_change, now)) { + if (_pam_send_password_expiry_message(pamh, ctrl, next_change, now)) { return; } @@ -913,18 +917,18 @@ static int winbind_auth_request(pam_handle_t * pamh, } if (ret) { - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PASSWORD_EXPIRED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PASSWORD_MUST_CHANGE"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_INVALID_WORKSTATION"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_INVALID_LOGON_HOURS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_EXPIRED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_DISABLED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_LOCKED_OUT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PASSWORD_EXPIRED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PASSWORD_MUST_CHANGE"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_INVALID_WORKSTATION"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_INVALID_LOGON_HOURS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_EXPIRED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_DISABLED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_LOCKED_OUT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); } /* handle the case where the auth was ok, but the password must expire right now */ @@ -942,24 +946,24 @@ static int winbind_auth_request(pam_handle_t * pamh, response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire, time(NULL)); - PAM_WB_REMARK_DIRECT_RET(pamh, "NT_STATUS_PASSWORD_EXPIRED"); + PAM_WB_REMARK_DIRECT_RET(pamh, ctrl, "NT_STATUS_PASSWORD_EXPIRED"); } /* warn a user if the password is about to expire soon */ - _pam_warn_password_expires_in_future(pamh, &response); + _pam_warn_password_expires_in_future(pamh, ctrl, &response); /* inform about logon type */ if (PAM_WB_GRACE_LOGON(response.data.auth.info3.user_flgs)) { - _make_remark(pamh, PAM_ERROR_MSG, + _make_remark(pamh, ctrl, PAM_ERROR_MSG, "Grace login. Please change your password as soon you're online again"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, "User %s logged on using grace logon\n", user); } else if (PAM_WB_CACHED_LOGON(response.data.auth.info3.user_flgs)) { - _make_remark(pamh, PAM_ERROR_MSG, + _make_remark(pamh, ctrl, PAM_ERROR_MSG, "Logging on using cached account. Network resources can be unavailable"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, "User %s logged on using cached account\n", user); @@ -1055,19 +1059,19 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, return ret; } - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_BACKUP_CONTROLLER"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCESS_DENIED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_BACKUP_CONTROLLER"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); /* TODO: tell the min pwd length ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_TOO_SHORT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_TOO_SHORT"); /* TODO: tell the minage ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_TOO_RECENT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_TOO_RECENT"); /* TODO: tell the history length ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_HISTORY_CONFLICT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_HISTORY_CONFLICT"); if (!strcasecmp(response.data.auth.nt_status_string, "NT_STATUS_PASSWORD_RESTRICTION")) { @@ -1080,17 +1084,17 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, case REJECT_REASON_OTHER: if ((response.data.auth.policy.min_passwordage > 0) && (pwd_last_set + response.data.auth.policy.min_passwordage > time(NULL))) { - PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_RECENT"); + PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_RECENT"); } break; case REJECT_REASON_TOO_SHORT: - PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_SHORT"); + PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_SHORT"); break; case REJECT_REASON_IN_HISTORY: - PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_HISTORY_CONFLICT"); + PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_HISTORY_CONFLICT"); break; case REJECT_REASON_NOT_COMPLEX: - _make_remark(pamh, PAM_ERROR_MSG, "Password does not meet complexity requirements"); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, "Password does not meet complexity requirements"); break; default: _pam_log_debug(pamh, ctrl, LOG_DEBUG, @@ -1101,7 +1105,7 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, pwd_restriction_string = _pam_compose_pwd_restriction_string(&response); if (pwd_restriction_string) { - _make_remark(pamh, PAM_ERROR_MSG, pwd_restriction_string); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, pwd_restriction_string); SAFE_FREE(pwd_restriction_string); } } @@ -1226,7 +1230,7 @@ static int _winbind_read_password(pam_handle_t * pamh, /* prepare to converse */ - if (comment != NULL) { + if (comment != NULL && off(ctrl, WINBIND_SILENT)) { pmsg[0] = &msg[0]; msg[0].msg_style = PAM_TEXT_INFO; msg[0].msg = CONST_DISCARD(char *, comment); @@ -1264,7 +1268,7 @@ static int _winbind_read_password(pam_handle_t * pamh, || strcmp(token, resp[i - 1].resp)) { _pam_delete(token); /* mistyped */ retval = PAM_AUTHTOK_RECOVER_ERR; - _make_remark(pamh, PAM_ERROR_MSG, MISTYPED_PASS); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, MISTYPED_PASS); } } } else { @@ -1829,13 +1833,13 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, iniparser_freedict(d); } /* Deal with offline errors. */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); return ret; @@ -1936,13 +1940,13 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, iniparser_freedict(d); } /* Deal with offline errors. */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); return ret; -- cgit From 0cf5662363b9ffbda9233df65072d2dfef1ac8b2 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 5 Feb 2007 17:12:13 +0000 Subject: r21154: Add PAM_WINBIND_LOGONSERVER, also merge the various pam_set_data calls. Guenther (This used to be commit 97a0b1b79499af10930500ce857c93ffbacfdb6e) --- source3/nsswitch/pam_winbind.c | 104 +++++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 36 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index aeab270a86..1cbf732489 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -741,6 +741,68 @@ out: return result; } +/** + * Set string into the PAM stack. + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * @param data_name Key name for pam_set_data. + * @param value String value. + * + * @return void. + */ + +static void _pam_set_data_string(pam_handle_t *pamh, int ctrl, const char *data_name, const char *value) +{ + int ret; + + if ( !data_name || !value || (strlen(data_name) == 0) || (strlen(value) == 0) ) { + return; + } + + ret = pam_set_data(pamh, data_name, (void *)strdup(value), _pam_winbind_cleanup_func); + if (ret) { + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Could not set data %s: %s\n", + data_name, pam_strerror(pamh, ret)); + } + +} + +/** + * Set info3 strings into the PAM stack. + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * @param data_name Key name for pam_set_data. + * @param value String value. + * + * @return void. + */ + +static void _pam_set_data_info3(pam_handle_t *pamh, int ctrl, struct winbindd_response *response) +{ + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_HOMEDIR, response->data.auth.info3.home_dir); + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT, response->data.auth.info3.logon_script); + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSERVER, response->data.auth.info3.logon_srv); + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_PROFILEPATH, response->data.auth.info3.profile_path); +} + +/** + * Free info3 strings in the PAM stack. + * + * @param pamh PAM handle + * + * @return void. + */ + +static void _pam_free_data_info3(pam_handle_t *pamh) +{ + pam_set_data(pamh, PAM_WINBIND_HOMEDIR, NULL, NULL); + pam_set_data(pamh, PAM_WINBIND_LOGONSCRIPT, NULL, NULL); + pam_set_data(pamh, PAM_WINBIND_LOGONSERVER, NULL, NULL); + pam_set_data(pamh, PAM_WINBIND_PROFILEPATH, NULL, NULL); +} + /** * Compose Password Restriction String for a PAM_ERROR_MSG conversation. * @@ -969,42 +1031,8 @@ static int winbind_auth_request(pam_handle_t * pamh, "User %s logged on using cached account\n", user); } - /* save the CIFS homedir for pam_cifs / pam_mount */ - if (response.data.auth.info3.home_dir[0] != '\0') { - - int ret2 = pam_set_data(pamh, PAM_WINBIND_HOMEDIR, - (void *) strdup(response.data.auth.info3.home_dir), - _pam_winbind_cleanup_func); - if (ret2) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Could not set data: %s", - pam_strerror(pamh, ret2)); - } - - } - - /* save the logon script path for other PAM modules */ - if (response.data.auth.info3.logon_script[0] != '\0') { - - int ret2 = pam_set_data(pamh, PAM_WINBIND_LOGONSCRIPT, - (void *) strdup(response.data.auth.info3.logon_script), - _pam_winbind_cleanup_func); - if (ret2) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Could not set data: %s", - pam_strerror(pamh, ret2)); - } - } - - /* save the profile path for other PAM modules */ - if (response.data.auth.info3.profile_path[0] != '\0') { - - int ret2 = pam_set_data(pamh, PAM_WINBIND_PROFILEPATH, - (void *) strdup(response.data.auth.info3.profile_path), - _pam_winbind_cleanup_func); - if (ret2) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Could not set data: %s", - pam_strerror(pamh, ret2)); - } - } + /* set some info3 info for other modules in the stack */ + _pam_set_data_info3(pamh, ctrl, &response); /* If winbindd returned a username, return the pointer to it here. */ if (user_ret && response.extra_data.data) { @@ -1465,6 +1493,10 @@ out: pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, NULL, NULL); } + if (retval != PAM_SUCCESS) { + _pam_free_data_info3(pamh); + } + _PAM_LOG_FUNCTION_LEAVE("pam_sm_authenticate", pamh, ctrl, retval); return retval; -- cgit From 462893a7be88d4c7bf87dd06b637668d36709f54 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 5 Feb 2007 17:14:30 +0000 Subject: r21155: Forgot one _PAM_LOG_STATE_DATA_STRING call (only in 3_0). Guenther (This used to be commit 86b34cd5d6675c8f0a0becdcded36de4a815c898) --- source3/nsswitch/pam_winbind.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 1cbf732489..ce98b44b56 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -193,6 +193,7 @@ static void _pam_log_state(const pam_handle_t *pamh, int ctrl) _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_HOMEDIR); _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT); + _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSERVER); _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_PROFILEPATH); _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD); /* Use atoi to get PAM result code */ _PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, PAM_WINBIND_PWD_LAST_SET); -- cgit From dbb94503127e1995802afbe749f94b9a9d86bbb4 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 5 Feb 2007 17:28:55 +0000 Subject: r21158: Add _pam_setup_krb5_env() and _pam_warn_logon_type() functions for pam_winbind. Guenther (This used to be commit 1feb961577475dceb97948cd2fdb987005890498) --- source3/nsswitch/pam_winbind.c | 101 ++++++++++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 31 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index ce98b44b56..44b37b6238 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -742,6 +742,42 @@ out: return result; } +/** + * put krb5ccname variable into environment + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * @param krb5ccname env variable retrieved from winbindd. + * + * @return void. + */ + +static void _pam_setup_krb5_env(pam_handle_t *pamh, int ctrl, const char *krb5ccname) +{ + char var[PATH_MAX]; + int ret; + + if (off(ctrl, WINBIND_KRB5_AUTH)) { + return; + } + + if (!krb5ccname || (strlen(krb5ccname) == 0)) { + return; + } + + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "request returned KRB5CCNAME: %s", krb5ccname); + + if (snprintf(var, sizeof(var), "KRB5CCNAME=%s", krb5ccname) == -1) { + return; + } + + ret = pam_putenv(pamh, var); + if (ret) { + _pam_log(pamh, ctrl, LOG_ERR, "failed to set KRB5CCNAME to %s: %s", + var, pam_strerror(pamh, ret)); + } +} + /** * Set string into the PAM stack. * @@ -804,6 +840,36 @@ static void _pam_free_data_info3(pam_handle_t *pamh) pam_set_data(pamh, PAM_WINBIND_PROFILEPATH, NULL, NULL); } +/** + * Send PAM_ERROR_MSG for cached or grace logons. + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * @param username User in PAM request. + * @param info3_user_flgs Info3 flags containing logon type bits. + * + * @return void. + */ + +static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *username, uint32 info3_user_flgs) +{ + /* inform about logon type */ + if (PAM_WB_GRACE_LOGON(info3_user_flgs)) { + + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Grace login. Please change your password as soon you're online again"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "User %s logged on using grace logon\n", username); + + } else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) { + + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Logging on using cached account. Network resources can be unavailable"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "User %s logged on using cached account\n", username); + } +} + /** * Compose Password Restriction String for a PAM_ERROR_MSG conversation. * @@ -956,23 +1022,6 @@ static int winbind_auth_request(pam_handle_t * pamh, *pwd_last_set = response.data.auth.info3.pass_last_set_time; } - if ((ctrl & WINBIND_KRB5_AUTH) && - response.data.auth.krb5ccname[0] != '\0') { - - char var[PATH_MAX]; - - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "request returned KRB5CCNAME: %s", - response.data.auth.krb5ccname); - - snprintf(var, sizeof(var), "KRB5CCNAME=%s", response.data.auth.krb5ccname); - - ret = pam_putenv(pamh, var); - if (ret != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_ERR, "failed to set KRB5CCNAME to %s", var); - return ret; - } - } - if (p_response) { /* We want to process the response in the caller. */ *p_response = response; @@ -1017,24 +1066,14 @@ static int winbind_auth_request(pam_handle_t * pamh, _pam_warn_password_expires_in_future(pamh, ctrl, &response); /* inform about logon type */ - if (PAM_WB_GRACE_LOGON(response.data.auth.info3.user_flgs)) { - - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - "Grace login. Please change your password as soon you're online again"); - _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "User %s logged on using grace logon\n", user); - - } else if (PAM_WB_CACHED_LOGON(response.data.auth.info3.user_flgs)) { - - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - "Logging on using cached account. Network resources can be unavailable"); - _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "User %s logged on using cached account\n", user); - } + _pam_warn_logon_type(pamh, ctrl, user, response.data.auth.info3.user_flgs); /* set some info3 info for other modules in the stack */ _pam_set_data_info3(pamh, ctrl, &response); + /* put krb5ccname into env */ + _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname); + /* If winbindd returned a username, return the pointer to it here. */ if (user_ret && response.extra_data.data) { /* We have to trust it's a null terminated string. */ -- cgit From 902a6e1da1720c00a91e627a32bd0091b1610b8e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 5 Feb 2007 17:35:25 +0000 Subject: r21159: Cleanup pam_sm_chauthtok() in pam_winbind: Set info3 strings, krb5ccname and returned username after we changed a password and sucessfully re-authenticated afterwards. In that case we ended up without this information. Guenther (This used to be commit 034d42ba7236e67303a8221b7a613799d1a61b83) --- source3/nsswitch/pam_winbind.c | 57 ++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 30 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 44b37b6238..bd5044cb5c 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1813,6 +1813,10 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, int retry = 0; dictionary *d = NULL; + char *username_ret = NULL; + struct winbindd_response response; + + ZERO_STRUCT(response); ctrl = _pam_parse(pamh, flags, argc, argv, &d); if (ctrl == -1) { @@ -1862,7 +1866,6 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, */ if (flags & PAM_PRELIM_CHECK) { - struct winbindd_response response; time_t pwdlastset_prelim = 0; /* instruct user what is happening */ @@ -1901,20 +1904,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, ret != PAM_NEW_AUTHTOK_REQD && ret != PAM_SUCCESS) { pass_old = NULL; - if (d) { - iniparser_freedict(d); - } - /* Deal with offline errors. */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, - response, - "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, - response, - "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, - response, - "NT_STATUS_ACCESS_DENIED"); - return ret; + goto out; } pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, (void *)pwdlastset_prelim, NULL); @@ -1998,30 +1988,32 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, /* just in case we need krb5 creds after a password change over msrpc */ if (ctrl & WINBIND_KRB5_AUTH) { - struct winbindd_response response; const char *member = get_member_from_config(pamh, argc, argv, ctrl, d); const char *cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); ret = winbind_auth_request(pamh, ctrl, user, pass_new, - member, cctype, &response, NULL, NULL); + member, cctype, &response, NULL, &username_ret); _pam_overwrite(pass_new); _pam_overwrite(pass_old); pass_old = pass_new = NULL; - if (d) { - iniparser_freedict(d); + + if (ret == PAM_SUCCESS) { + + /* set some info3 info for other modules in the stack */ + _pam_set_data_info3(pamh, ctrl, &response); + + /* put krb5ccname into env */ + _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname); + + if (username_ret) { + pam_set_item (pamh, PAM_USER, username_ret); + _pam_log_debug(pamh, ctrl, LOG_INFO, "Returned user was '%s'", username_ret); + free(username_ret); + } } - /* Deal with offline errors. */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, - response, - "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, - response, - "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, - response, - "NT_STATUS_ACCESS_DENIED"); - return ret; + + goto out; } } else { ret = PAM_SERVICE_ERR; @@ -2032,6 +2024,11 @@ out: iniparser_freedict(d); } + /* Deal with offline errors. */ + PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); + _PAM_LOG_FUNCTION_LEAVE("pam_sm_chauthtok", pamh, ctrl, ret); return ret; -- cgit From 7440e4255ca74a550ae85b7f0629ef4fe74820cb Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 5 Feb 2007 18:04:28 +0000 Subject: r21160: Some more pam_winbind fixes: * Consolidate all pam_winbind password expiry warnings in the one _pam_send_password_expiry_message() call. * Also convert some more NTSTATUS codes to error messages. * Add paranoia check to only do all the post-processing after PAM_SUCCESS. Guenther (This used to be commit 02713f314b65a14e659e801f7eebea453756ac44) --- source3/nsswitch/pam_winbind.c | 111 +++++++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 32 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index bd5044cb5c..1a1d7ffcdd 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -535,13 +535,36 @@ static int pam_winbind_request_log(pam_handle_t * pamh, } } -static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, int ctrl, time_t next_change, time_t now) +/** + * send a password expiry message if required + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * @param next_change expected (calculated) next expiry date. + * @param already_expired pointer to a boolean to indicate if the password is + * already expired. + * + * @return boolean Returns True if message has been sent, False if not. + */ + +static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, int ctrl, time_t next_change, time_t now, BOOL *already_expired) { int days = 0; struct tm tm_now, tm_next_change; + if (already_expired) { + *already_expired = False; + } + + if (next_change <= now) { + PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PASSWORD_EXPIRED"); + if (already_expired) { + *already_expired = True; + } + return True; + } + if ((next_change < 0) || - (next_change < now) || (next_change > now + DAYS_TO_WARN_BEFORE_PWD_EXPIRES * SECONDS_PER_DAY)) { return False; } @@ -567,11 +590,29 @@ static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, int ctrl, time return False; } -static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, int ctrl, struct winbindd_response *response) +/** + * Send a warning if the password expires in the near future + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * @param response The full authentication response structure. + * @param already_expired boolean, is the pwd already expired? + * + * @return void. + */ + +static void _pam_warn_password_expiry(pam_handle_t *pamh, + int flags, + const struct winbindd_response *response, + BOOL *already_expired) { time_t now = time(NULL); time_t next_change = 0; + if (already_expired) { + *already_expired = False; + } + /* accounts with ACB_PWNOEXP set never receive a warning */ if (response->data.auth.info3.acct_flags & ACB_PWNOEXP) { return; @@ -585,11 +626,14 @@ static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, int ctrl, s /* check if the info3 must change timestamp has been set */ next_change = response->data.auth.info3.pass_must_change_time; - if (_pam_send_password_expiry_message(pamh, ctrl, next_change, now)) { + if (_pam_send_password_expiry_message(pamh, flags, next_change, now, + already_expired)) { return; } /* now check for the global password policy */ + /* good catch from Ralf Haferkamp: an expiry of "never" is translated + * to -1 */ if (response->data.auth.policy.expire <= 0) { return; } @@ -597,7 +641,8 @@ static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, int ctrl, s next_change = response->data.auth.info3.pass_last_set_time + response->data.auth.policy.expire; - if (_pam_send_password_expiry_message(pamh, ctrl, next_change, now)) { + if (_pam_send_password_expiry_message(pamh, flags, next_change, now, + already_expired)) { return; } @@ -953,6 +998,7 @@ static int winbind_auth_request(pam_handle_t * pamh, struct winbindd_request request; struct winbindd_response response; int ret; + BOOL already_expired = False; ZERO_STRUCT(request); ZERO_STRUCT(response); @@ -1041,43 +1087,41 @@ static int winbind_auth_request(pam_handle_t * pamh, PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"); PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_WRONG_PASSWORD"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); } - /* handle the case where the auth was ok, but the password must expire right now */ - /* good catch from Ralf Haferkamp: an expiry of "never" is translated to -1 */ - if ( ! (response.data.auth.info3.acct_flags & ACB_PWNOEXP) && - ! (PAM_WB_GRACE_LOGON(response.data.auth.info3.user_flgs)) && - (response.data.auth.policy.expire > 0) && - (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire < time(NULL))) { - - ret = PAM_AUTHTOK_EXPIRED; - - _pam_log_debug(pamh, ctrl, LOG_DEBUG,"Password has expired (Password was last set: %d, " - "the policy says it should expire here %d (now it's: %d)\n", - response.data.auth.info3.pass_last_set_time, - response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire, + /* warn a user if the password is about to expire soon */ + _pam_warn_password_expiry(pamh, ctrl, &response, &already_expired); + + if (already_expired == True) { + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Password has expired " + "(Password was last set: %d, the policy says " + "it should expire here %d (now it's: %d)\n", + response.data.auth.info3.pass_last_set_time, + response.data.auth.info3.pass_last_set_time + + response.data.auth.policy.expire, time(NULL)); - PAM_WB_REMARK_DIRECT_RET(pamh, ctrl, "NT_STATUS_PASSWORD_EXPIRED"); - + return PAM_AUTHTOK_EXPIRED; } - /* warn a user if the password is about to expire soon */ - _pam_warn_password_expires_in_future(pamh, ctrl, &response); + if (ret == PAM_SUCCESS) { - /* inform about logon type */ - _pam_warn_logon_type(pamh, ctrl, user, response.data.auth.info3.user_flgs); + /* inform about logon type */ + _pam_warn_logon_type(pamh, ctrl, user, response.data.auth.info3.user_flgs); - /* set some info3 info for other modules in the stack */ - _pam_set_data_info3(pamh, ctrl, &response); + /* set some info3 info for other modules in the stack */ + _pam_set_data_info3(pamh, ctrl, &response); - /* put krb5ccname into env */ - _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname); + /* put krb5ccname into env */ + _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname); - /* If winbindd returned a username, return the pointer to it here. */ - if (user_ret && response.extra_data.data) { - /* We have to trust it's a null terminated string. */ - *user_ret = (char *)response.extra_data.data; + /* If winbindd returned a username, return the pointer to it here. */ + if (user_ret && response.extra_data.data) { + /* We have to trust it's a null terminated string. */ + *user_ret = (char *)response.extra_data.data; + } } return ret; @@ -2000,6 +2044,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (ret == PAM_SUCCESS) { + /* warn a user if the password is about to expire soon */ + _pam_warn_password_expiry(pamh, ctrl, &response, NULL); + /* set some info3 info for other modules in the stack */ _pam_set_data_info3(pamh, ctrl, &response); -- cgit From 317d00514245097557c3c20c17e64d2d6a7f6aad Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 5 Feb 2007 18:11:41 +0000 Subject: r21161: Another fix for pam_winbind: Move the entire pwd expiry handling into the PAM_SUCCESS block. Guenther (This used to be commit f4a704745cb0bd2c5dc2a9b16619d8ee30fd7ba1) --- source3/nsswitch/pam_winbind.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 1a1d7ffcdd..1ee5dba457 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1091,22 +1091,22 @@ static int winbind_auth_request(pam_handle_t * pamh, PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); } - /* warn a user if the password is about to expire soon */ - _pam_warn_password_expiry(pamh, ctrl, &response, &already_expired); - - if (already_expired == True) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Password has expired " - "(Password was last set: %d, the policy says " - "it should expire here %d (now it's: %d)\n", - response.data.auth.info3.pass_last_set_time, - response.data.auth.info3.pass_last_set_time + - response.data.auth.policy.expire, - time(NULL)); + if (ret == PAM_SUCCESS) { - return PAM_AUTHTOK_EXPIRED; - } + /* warn a user if the password is about to expire soon */ + _pam_warn_password_expiry(pamh, ctrl, &response, &already_expired); - if (ret == PAM_SUCCESS) { + if (already_expired == True) { + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Password has expired " + "(Password was last set: %d, the policy says " + "it should expire here %d (now it's: %d))\n", + response.data.auth.info3.pass_last_set_time, + response.data.auth.info3.pass_last_set_time + + response.data.auth.policy.expire, + time(NULL)); + + return PAM_AUTHTOK_EXPIRED; + } /* inform about logon type */ _pam_warn_logon_type(pamh, ctrl, user, response.data.auth.info3.user_flgs); -- cgit From 826aa64c45afbdf00f6f172ec1f1fe41a57858ce Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 13 Feb 2007 10:56:04 +0000 Subject: r21309: Add PRINTF_ATTRIBUTE checks for log statements. Guenther (This used to be commit 968dfcc8218cacdd97c2c66929e95f5062ff464a) --- source3/nsswitch/pam_winbind.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 1ee5dba457..67e7767a0f 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -78,6 +78,7 @@ static BOOL _pam_log_is_silent(int ctrl) return on(ctrl, WINBIND_SILENT); } +static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5); static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) { va_list args; @@ -117,6 +118,7 @@ static BOOL _pam_log_is_debug_state_enabled(int ctrl) return _pam_log_is_debug_enabled(ctrl); } +static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5); static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) { va_list args; @@ -413,6 +415,7 @@ static int _make_remark_v(pam_handle_t * pamh, int flags, int type, const char * return ret; } +static int _make_remark_format(pam_handle_t * pamh, int flags, int type, const char *format, ...) PRINTF_ATTRIBUTE(4,5); static int _make_remark_format(pam_handle_t * pamh, int flags, int type, const char *format, ...) { int ret; -- cgit From 6dd654c3819db10dea6069ba5647b0563a3b7599 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 13 Feb 2007 11:04:10 +0000 Subject: r21310: Fix invalid printfs in pam_winbind. Guenther (This used to be commit 5a7b2fccb3cdc6a849aedcd256eea86faec1d54c) --- source3/nsswitch/pam_winbind.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 67e7767a0f..bf61b3791d 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -461,8 +461,12 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, case WINBINDD_GETPWNAM: case WINBINDD_LOOKUPNAME: - _pam_log(pamh, ctrl, LOG_ERR, "request failed: %s, NT error was %s", + if (strlen(response->data.auth.nt_status_string) > 0) { + _pam_log(pamh, ctrl, LOG_ERR, "request failed, NT error was %s", response->data.auth.nt_status_string); + } else { + _pam_log(pamh, ctrl, LOG_ERR, "request failed"); + } return PAM_USER_UNKNOWN; default: break; @@ -518,15 +522,19 @@ static int pam_winbind_request_log(pam_handle_t * pamh, } return retval; case PAM_SUCCESS: - if (req_type == WINBINDD_PAM_AUTH) { - /* Otherwise, the authentication looked good */ - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", user); - } else if (req_type == WINBINDD_PAM_CHAUTHTOK) { - /* Otherwise, the authentication looked good */ - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' password changed", user); - } else { - /* Otherwise, the authentication looked good */ - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' OK", user); + /* Otherwise, the authentication looked good */ + switch (req_type) { + case WINBINDD_INFO: + break; + case WINBINDD_PAM_AUTH: + _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", user); + break; + case WINBINDD_PAM_CHAUTHTOK: + _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' password changed", user); + break; + default: + _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' OK", user); + break; } return retval; @@ -1101,8 +1109,8 @@ static int winbind_auth_request(pam_handle_t * pamh, if (already_expired == True) { _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Password has expired " - "(Password was last set: %d, the policy says " - "it should expire here %d (now it's: %d))\n", + "(Password was last set: %lld, the policy says " + "it should expire here %lld (now it's: %lu))\n", response.data.auth.info3.pass_last_set_time, response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire, -- cgit From 3a46604800ec03dbedce8e7af42047a730a5b6f9 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 13 Feb 2007 15:56:09 +0000 Subject: r21318: Fix Bug #4225. Cached logon with pam_winbind should work now also for NT4 and samba3 domains. Guenther (This used to be commit b2f91154820219959b8008b15802c70e1d76d158) --- source3/nsswitch/pam_winbind.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index bf61b3791d..d2979ed71c 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1029,14 +1029,9 @@ static int winbind_auth_request(pam_handle_t * pamh, request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_CONTACT_TRUSTDOM; - if (ctrl & WINBIND_KRB5_AUTH) { - + if (ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) { struct passwd *pwd = NULL; - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling krb5 login flag\n"); - - request.flags |= WBFLAG_PAM_KRB5 | WBFLAG_PAM_FALLBACK_AFTER_KRB5; - pwd = getpwnam(user); if (pwd == NULL) { return PAM_USER_UNKNOWN; @@ -1044,6 +1039,13 @@ static int winbind_auth_request(pam_handle_t * pamh, request.data.auth.uid = pwd->pw_uid; } + if (ctrl & WINBIND_KRB5_AUTH) { + + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling krb5 login flag\n"); + + request.flags |= WBFLAG_PAM_KRB5 | WBFLAG_PAM_FALLBACK_AFTER_KRB5; + } + if (ctrl & WINBIND_CACHED_LOGIN) { _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling cached login flag\n"); request.flags |= WBFLAG_PAM_CACHED_LOGIN; -- cgit From 9684e353a16cd18424f5b35a5d84ae3c2a03ae70 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 22 Feb 2007 13:35:01 +0000 Subject: r21500: Fix inappropriate creation of a krb5 ticket refreshing event when a user changed a password via pam_chauthtok. Only do this if a) a user logs on using an expired password (or a password that needs to be changed immediately) or b) the user itself changes his password. Also make sure to delete the in-memory krb5 credential cache (when a user did not request a FILE based cred cache). Finally honor the krb5 settings in the first pam authentication in the chauthtok block (PAM_PRELIM_CHECK). This circumvents confusion when NTLM samlogon authentication is still possible with the old password after the password has been already changed (on w2k3 sp1 dcs). Guenther (This used to be commit c3005c48cd86bc1dd17fab80da05c2d34071b872) --- source3/nsswitch/pam_winbind.c | 62 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 6 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index d2979ed71c..ac87fcf32e 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -198,6 +198,7 @@ static void _pam_log_state(const pam_handle_t *pamh, int ctrl) _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSERVER); _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_PROFILEPATH); _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD); /* Use atoi to get PAM result code */ + _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH); _PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, PAM_WINBIND_PWD_LAST_SET); } @@ -1564,6 +1565,8 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, if (retval == PAM_NEW_AUTHTOK_REQD || retval == PAM_AUTHTOK_EXPIRED) { + char *new_authtok_required_during_auth = NULL; + if (!asprintf(&new_authtok_required, "%d", retval)) { retval = PAM_BUF_ERR; goto out; @@ -1572,6 +1575,15 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, new_authtok_required, _pam_winbind_cleanup_func); retval = PAM_SUCCESS; + + if (!asprintf(&new_authtok_required_during_auth, "%d", True)) { + retval = PAM_BUF_ERR; + goto out; + } + + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + new_authtok_required_during_auth, _pam_winbind_cleanup_func); + goto out; } @@ -1851,6 +1863,49 @@ out: return retval; } +/** + * evaluate whether we need to re-authenticate with kerberos after a password change + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * @param user The username + * + * @return boolean Returns True if required, False if not. + */ + +static BOOL _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, const char *user) +{ + + /* Make sure that we only do this if + * a) the chauthtok got initiated during a logon attempt (authenticate->acct_mgmt->chauthtok) + * b) any later password change via the "passwd" command if done by the user itself + */ + + char *new_authtok_reqd_during_auth = NULL; + struct passwd *pwd = NULL; + + if (!(ctrl & WINBIND_KRB5_AUTH)) { + return False; + } + + _pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, &new_authtok_reqd_during_auth); + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, NULL, NULL); + + if (new_authtok_reqd_during_auth) { + return True; + } + + pwd = getpwnam(user); + if (!pwd) { + return False; + } + + if (getuid() == pwd->pw_uid) { + return True; + } + + return False; +} PAM_EXTERN @@ -1948,9 +2003,6 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, goto out; } - /* We don't need krb5 env set for password change test. */ - ctrl &= ~WINBIND_KRB5_AUTH; - /* verify that this is the password for this user */ ret = winbind_auth_request(pamh, ctrl, user, pass_old, @@ -2042,9 +2094,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, goto out; } - /* just in case we need krb5 creds after a password change over msrpc */ - - if (ctrl & WINBIND_KRB5_AUTH) { + if (_pam_require_krb5_auth_after_chauthtok(pamh, ctrl, user)) { const char *member = get_member_from_config(pamh, argc, argv, ctrl, d); const char *cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); -- cgit From 2c51e492f9961277c27099e6beaa431db2acc6d1 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 1 Mar 2007 03:10:29 +0000 Subject: r21612: Make pam_winbind do the same username fixup on AIX as the WINBINDD LAM module does to work around a system that does not support >8 character usernames. Without the change, pam_winbind tries to authenticate _#uid in the domain. (This used to be commit 7f0ba72e05acbd958fbf768a04d16c29189dc8f7) --- source3/nsswitch/pam_winbind.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index ac87fcf32e..d21c985fee 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1517,6 +1517,8 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, dictionary *d = NULL; char *username_ret = NULL; char *new_authtok_required = NULL; + char *combined_member = NULL; + const char *real_username = NULL; /* parse arguments */ int ctrl = _pam_parse(pamh, flags, argc, argv, &d); @@ -1535,6 +1537,30 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, goto out; } +#if defined(AIX) + /* Decode the user name since AIX does not support logn user + names by default. The name is encoded as _#uid. */ + + if ( username[0] == '_' ) { + uid_t id = atoi( &username[1] ); + struct passwd *pw = NULL; + + if ( (id!=0) && ((pw = getpwuid( id )) != NULL) ) { + real_username = strdup( pw->pw_name ); + } + } +#endif + + if ( !real_username ) { + /* Just making a copy of the username we got from PAM */ + if ( (real_username = strdup( username )) == NULL ) { + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "memory allocation failure when copying username"); + retval = PAM_SERVICE_ERR; + goto out; + } + } + retval = _winbind_read_password(pamh, ctrl, NULL, "Password: ", NULL, &password); @@ -1549,9 +1575,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, #ifdef DEBUG_PASSWORD _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s' with password '%s'", - username, password); + real_username, password); #else - _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s'", username); + _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s'", real_username); #endif member = get_member_from_config(pamh, argc, argv, ctrl, d); @@ -1594,6 +1620,10 @@ out: free(username_ret); } + if ( real_username ) { + free( real_username ); + } + if (d) { iniparser_freedict(d); } -- cgit From 5f246689612bae257ebd01a226c360abac977d1e Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 1 Mar 2007 14:34:06 +0000 Subject: r21632: Remove ununsed variable (This used to be commit 82dc19f844af65a8815c629e4ec1f354d208a53f) --- source3/nsswitch/pam_winbind.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index d21c985fee..e16f44dff5 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1517,7 +1517,6 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, dictionary *d = NULL; char *username_ret = NULL; char *new_authtok_required = NULL; - char *combined_member = NULL; const char *real_username = NULL; /* parse arguments */ -- cgit From 3fdef9433a9e08064b32e34a16ce62a60ce144fb Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 19 Mar 2007 21:04:56 +0000 Subject: r21878: Fix a bug with smbd serving a windows terminal server: If winbind decides smbd to be idle it might happen that smbd needs to do a winbind operation (for example sid2name) as non-root. This then fails to get the privileged pipe. When later on on the same connection another authentication request comes in, we try to do the CRAP auth via the non-privileged pipe. This adds a winbindd_priv_request_response() request that kills the existing winbind pipe connection if it's not privileged. Volker (This used to be commit e5741e27c4c22702c9f8b07877641fecc7eef39c) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index e16f44dff5..66f9a09314 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -436,7 +436,7 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, /* Fill in request and send down pipe */ init_request(request, req_type); - if (write_sock(request, sizeof(*request), 0) == -1) { + if (write_sock(request, sizeof(*request), 0, 1) == -1) { _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!"); close_sock(); return PAM_SERVICE_ERR; -- cgit From e68ea1283de0d915656faaa599bd27054da7bf1c Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 22 Mar 2007 18:09:21 +0000 Subject: r21933: Change the write_sock() call in pam_winbind_request() to not request a privileged pipe operation for everything as this cannot be done from a process running under the context of a user (e.g. screensaver). Thanks to Danilo Almeida for the help in pointing out the change to write_sock(). (This used to be commit 80790f935abc8905542338b08f54d61ebacf2ff1) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 66f9a09314..9d52dc89d0 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -436,7 +436,7 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, /* Fill in request and send down pipe */ init_request(request, req_type); - if (write_sock(request, sizeof(*request), 0, 1) == -1) { + if (write_sock(request, sizeof(*request), 0, 0) == -1) { _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!"); close_sock(); return PAM_SERVICE_ERR; -- cgit From d7c8710a1d52ffe3e883fa83d6a12d4f240cda59 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 18 Apr 2007 22:25:17 +0000 Subject: r22348: 3_0 as well (This used to be commit ad57434faf806a6ad27beb0f75b73d5389a35382) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 9d52dc89d0..1249e184f5 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -921,7 +921,7 @@ static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *usern } else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) { _make_remark(pamh, ctrl, PAM_ERROR_MSG, - "Logging on using cached account. Network resources can be unavailable"); + "Domain Controller unreachable, using cached credentials. Network resources may be unavailable"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, "User %s logged on using cached account\n", username); } -- cgit From 20086f66cc32951da69aa357bc19c14d31a3913a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 19 Apr 2007 20:00:40 +0000 Subject: r22388: clearer message, thanks David (This used to be commit 7961476784713267efc19d305aa66c68275ccaa1) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 1249e184f5..9706d38f89 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -921,7 +921,7 @@ static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *usern } else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) { _make_remark(pamh, ctrl, PAM_ERROR_MSG, - "Domain Controller unreachable, using cached credentials. Network resources may be unavailable"); + "Domain Controller unreachable, using cached credentials instead. Network resources may be unavailable"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, "User %s logged on using cached account\n", username); } -- cgit From 2d8fbef1513a7f67190041bf448ce2174fc0ec35 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 19 Apr 2007 23:25:37 +0000 Subject: r22393: fix cut&paste error (This used to be commit 70878d698532aa8b0e151e7772894e251290186e) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 9706d38f89..56452bd0a3 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -923,7 +923,7 @@ static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *usern _make_remark(pamh, ctrl, PAM_ERROR_MSG, "Domain Controller unreachable, using cached credentials instead. Network resources may be unavailable"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "User %s logged on using cached account\n", username); + "User %s logged on using cached credentials\n", username); } } -- cgit From 04a70aaf1ce24e35f58eb79abf20287c79b30444 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 20 Apr 2007 10:54:55 +0000 Subject: r22402: Fix build warning. Guenther (This used to be commit bf9131fed30b3d6f80c41734c04450a1e6bcba5b) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 56452bd0a3..ec6361e52b 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1517,7 +1517,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, dictionary *d = NULL; char *username_ret = NULL; char *new_authtok_required = NULL; - const char *real_username = NULL; + char *real_username = NULL; /* parse arguments */ int ctrl = _pam_parse(pamh, flags, argc, argv, &d); -- cgit From fd5ff711b6fa4b1146776ba6f915a20e64786c53 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sun, 6 May 2007 20:33:33 +0000 Subject: r22712: Inform the user when logging in via pam_winbind and the krb5 tkt cache could not be created due to clock skew. (This used to be commit 24616f7d6be40b090dc74851b1ea7d09d6976811) --- source3/nsswitch/pam_winbind.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index ec6361e52b..6734cba0c4 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -927,6 +927,30 @@ static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *usern } } +/** + * Send PAM_ERROR_MSG for krb5 errors. + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * @param username User in PAM request. + * @param info3_user_flgs Info3 flags containing logon type bits. + * + * @return void. + */ + +static void _pam_warn_krb5_failure(pam_handle_t *pamh, int ctrl, const char *username, uint32 info3_user_flgs) +{ + if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) { + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Failed to establish your Kerberos Ticket cache " + "due time differences\n" + "with the domain controller. " + "Please verify the system time.\n"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "User %s: Clock skew when getting Krb5 TGT\n", username); + } +} + /** * Compose Password Restriction String for a PAM_ERROR_MSG conversation. * @@ -1125,6 +1149,9 @@ static int winbind_auth_request(pam_handle_t * pamh, /* inform about logon type */ _pam_warn_logon_type(pamh, ctrl, user, response.data.auth.info3.user_flgs); + /* inform about krb5 failures */ + _pam_warn_krb5_failure(pamh, ctrl, user, response.data.auth.info3.user_flgs); + /* set some info3 info for other modules in the stack */ _pam_set_data_info3(pamh, ctrl, &response); -- cgit From 67a45aa26bd119af54b3a22425d23b064201ab6f Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 11 May 2007 11:54:41 +0000 Subject: r22794: Add "debug_state" and "silent" to pam_winbind.conf template. Honor the silent argument when parsing pam configuration file options. Guenther (This used to be commit 5b4a4df26f32fe1947a0c4fb741a4cb89e308f92) --- source3/nsswitch/pam_winbind.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 6734cba0c4..81b9c0bc6c 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -273,6 +273,8 @@ config_from_pam: ctrl |= WINBIND_DEBUG_ARG; else if (!strcasecmp(*v, "debug_state")) ctrl |= WINBIND_DEBUG_STATE; + else if (!strcasecmp(*v, "silent")) + ctrl |= WINBIND_SILENT; else if (!strcasecmp(*v, "use_authtok")) ctrl |= WINBIND_USE_AUTHTOK_ARG; else if (!strcasecmp(*v, "use_first_pass")) -- cgit From a3de7e9b9dcd4d15a1c07244acae205b1edb934b Mon Sep 17 00:00:00 2001 From: Lars Müller Date: Wed, 4 Jul 2007 14:03:10 +0000 Subject: r23704: Add pam_pwd_expire feature as discussed on samba-technical. This is a slightly modified version to set warn_pwd_expire to the default value if 0, no, or a broken value is set. This version also has one if statement less in get_config_item_int(). Thanks a lot to Andreas 'GlaDiaC' Schneider for this feature! (This used to be commit d26914c978457ae0ec097cc40c8e33a7cee9ebcf) --- source3/nsswitch/pam_winbind.c | 104 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 10 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 81b9c0bc6c..836822a8a9 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -561,7 +561,12 @@ static int pam_winbind_request_log(pam_handle_t * pamh, * @return boolean Returns True if message has been sent, False if not. */ -static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, int ctrl, time_t next_change, time_t now, BOOL *already_expired) +static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, + int ctrl, + time_t next_change, + time_t now, + int warn_pwd_expire, + BOOL *already_expired) { int days = 0; struct tm tm_now, tm_next_change; @@ -579,7 +584,7 @@ static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, int ctrl, time } if ((next_change < 0) || - (next_change > now + DAYS_TO_WARN_BEFORE_PWD_EXPIRES * SECONDS_PER_DAY)) { + (next_change > now + warn_pwd_expire * SECONDS_PER_DAY)) { return False; } @@ -595,7 +600,7 @@ static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, int ctrl, time return True; } - if (days > 0 && days < DAYS_TO_WARN_BEFORE_PWD_EXPIRES) { + if (days > 0 && days < warn_pwd_expire) { _make_remark_format(pamh, ctrl, PAM_TEXT_INFO, "Your password will expire in %d %s", days, (days > 1) ? "days":"day"); return True; @@ -618,6 +623,7 @@ static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, int ctrl, time static void _pam_warn_password_expiry(pam_handle_t *pamh, int flags, const struct winbindd_response *response, + int warn_pwd_expire, BOOL *already_expired) { time_t now = time(NULL); @@ -640,7 +646,8 @@ static void _pam_warn_password_expiry(pam_handle_t *pamh, /* check if the info3 must change timestamp has been set */ next_change = response->data.auth.info3.pass_must_change_time; - if (_pam_send_password_expiry_message(pamh, flags, next_change, now, + if (_pam_send_password_expiry_message(pamh, flags, next_change, now, + warn_pwd_expire, already_expired)) { return; } @@ -655,7 +662,8 @@ static void _pam_warn_password_expiry(pam_handle_t *pamh, next_change = response->data.auth.info3.pass_last_set_time + response->data.auth.policy.expire; - if (_pam_send_password_expiry_message(pamh, flags, next_change, now, + if (_pam_send_password_expiry_message(pamh, flags, next_change, now, + warn_pwd_expire, already_expired)) { return; } @@ -1029,6 +1037,7 @@ static int winbind_auth_request(pam_handle_t * pamh, const char *pass, const char *member, const char *cctype, + const int warn_pwd_expire, struct winbindd_response *p_response, time_t *pwd_last_set, char **user_ret) @@ -1134,7 +1143,9 @@ static int winbind_auth_request(pam_handle_t * pamh, if (ret == PAM_SUCCESS) { /* warn a user if the password is about to expire soon */ - _pam_warn_password_expiry(pamh, ctrl, &response, &already_expired); + _pam_warn_password_expiry(pamh, ctrl, &response, + warn_pwd_expire, + &already_expired); if (already_expired == True) { _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Password has expired " @@ -1519,6 +1530,52 @@ out: return parm_opt; } +int get_config_item_int(const pam_handle_t *pamh, + int argc, + const char **argv, + int ctrl, + dictionary *d, + const char *item) +{ + int parm_opt = -1, i = 0; + char *key = NULL; + + /* let the pam opt take precedence over the pam_winbind.conf option */ + for (i = 0; i < argc; i++) { + + if ((strncmp(argv[i], item, strlen(item)) == 0)) { + char *p; + + if ( (p = strchr( argv[i], '=' )) == NULL) { + _pam_log(pamh, ctrl, LOG_INFO, + "no \"=\" delimiter for \"%s\" found\n", + item); + goto out; + } + parm_opt = atoi(p + 1); + _pam_log_debug(pamh, ctrl, LOG_INFO, + "PAM config: %s '%d'\n", + item, parm_opt); + return parm_opt; + } + } + + if (d != NULL) { + if (!asprintf(&key, "global:%s", item)) { + goto out; + } + + parm_opt = iniparser_getint(d, key, -1); + SAFE_FREE(key); + + _pam_log_debug(pamh, ctrl, LOG_INFO, + "CONFIG file: %s '%d'\n", + item, parm_opt); + } +out: + return parm_opt; +} + const char *get_krb5_cc_type_from_config(const pam_handle_t *pamh, int argc, const char **argv, int ctrl, dictionary *d) { return get_conf_item_string(pamh, argc, argv, ctrl, d, "krb5_ccache_type", WINBIND_KRB5_CCACHE_TYPE); @@ -1534,6 +1591,22 @@ const char *get_member_from_config(const pam_handle_t *pamh, int argc, const cha return get_conf_item_string(pamh, argc, argv, ctrl, d, "require-membership-of", WINBIND_REQUIRED_MEMBERSHIP); } +int get_warn_pwd_expire_from_config(const pam_handle_t *pamh, + int argc, + const char **argv, + int ctrl, + dictionary *d) +{ + int ret; + ret = get_config_item_int(pamh, argc, argv, ctrl, d, + "warn_pwd_expire"); + /* no or broken setting */ + if (ret <= 0) { + return DEFAULT_DAYS_TO_WARN_BEFORE_PWD_EXPIRES; + } + return ret; +} + PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) @@ -1542,6 +1615,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, const char *password; const char *member = NULL; const char *cctype = NULL; + int warn_pwd_expire; int retval = PAM_AUTH_ERR; dictionary *d = NULL; char *username_ret = NULL; @@ -1612,9 +1686,13 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); + warn_pwd_expire = get_warn_pwd_expire_from_config(pamh, argc, argv, + ctrl, d); + /* Now use the username to look up password */ retval = winbind_auth_request(pamh, ctrl, username, password, member, - cctype, NULL, NULL, &username_ret); + cctype, warn_pwd_expire, NULL, NULL, + &username_ret); if (retval == PAM_NEW_AUTHTOK_REQD || retval == PAM_AUTHTOK_EXPIRED) { @@ -2064,7 +2142,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, /* verify that this is the password for this user */ ret = winbind_auth_request(pamh, ctrl, user, pass_old, - NULL, NULL, &response, &pwdlastset_prelim, NULL); + NULL, NULL, 0, &response, + &pwdlastset_prelim, NULL); if (ret != PAM_ACCT_EXPIRED && ret != PAM_AUTHTOK_EXPIRED && @@ -2156,9 +2235,13 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, const char *member = get_member_from_config(pamh, argc, argv, ctrl, d); const char *cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); + const int warn_pwd_expire = + get_warn_pwd_expire_from_config(pamh, argc, argv, ctrl, + d); ret = winbind_auth_request(pamh, ctrl, user, pass_new, - member, cctype, &response, NULL, &username_ret); + member, cctype, 0, &response, + NULL, &username_ret); _pam_overwrite(pass_new); _pam_overwrite(pass_old); pass_old = pass_new = NULL; @@ -2166,7 +2249,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (ret == PAM_SUCCESS) { /* warn a user if the password is about to expire soon */ - _pam_warn_password_expiry(pamh, ctrl, &response, NULL); + _pam_warn_password_expiry(pamh, ctrl, &response, + warn_pwd_expire , NULL); /* set some info3 info for other modules in the stack */ _pam_set_data_info3(pamh, ctrl, &response); -- cgit From 2f6b9c1ec48a558ca6079044ddb5f1718efc6092 Mon Sep 17 00:00:00 2001 From: Lars Müller Date: Wed, 4 Jul 2007 19:52:51 +0000 Subject: r23707: - Move the asprintf() call to create the key even in get_conf_item_string() to the later if statement. - Also move the key definition to the later if statement in get_conf_item_string() and get_conf_item_int(). (This used to be commit 3a82ec943a3828b843dd47aaa0e360844d4dfb91) --- source3/nsswitch/pam_winbind.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 836822a8a9..8109eca4b9 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1491,24 +1491,12 @@ const char *get_conf_item_string(const pam_handle_t *pamh, { int i = 0; const char *parm_opt = NULL; - char *key = NULL; if (!(ctrl & config_flag)) { goto out; } /* let the pam opt take precedence over the pam_winbind.conf option */ - - if (d != NULL) { - - if (!asprintf(&key, "global:%s", item)) { - goto out; - } - - parm_opt = iniparser_getstr(d, key); - SAFE_FREE(key); - } - for ( i=0; i Date: Wed, 4 Jul 2007 20:25:29 +0000 Subject: r23708: - Add define for WINBIND_WARN_PWD_EXPIRE. - Add parameter config_flag to get_config_item_int() and do the same check as in get_conf_item_string. (This used to be commit d1d1baa264587911e1c97b3b35d5ed2bc56bf12b) --- source3/nsswitch/pam_winbind.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 8109eca4b9..db3a089329 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -264,6 +264,10 @@ static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char ctrl |= WINBIND_TRY_FIRST_PASS_ARG; } + if (iniparser_getint(d, "global:warn_pwd_expire", 0)) { + ctrl |= WINBIND_WARN_PWD_EXPIRE; + } + config_from_pam: /* step through arguments */ for (i=argc,v=argv; i-- > 0; ++v) { @@ -1532,10 +1536,15 @@ int get_config_item_int(const pam_handle_t *pamh, const char **argv, int ctrl, dictionary *d, - const char *item) + const char *item, + int config_flag) { int i, parm_opt = -1; + if (!(ctrl & config_flag)) { + goto out; + } + /* let the pam opt take precedence over the pam_winbind.conf option */ for (i = 0; i < argc; i++) { @@ -1597,7 +1606,7 @@ int get_warn_pwd_expire_from_config(const pam_handle_t *pamh, { int ret; ret = get_config_item_int(pamh, argc, argv, ctrl, d, - "warn_pwd_expire"); + "warn_pwd_expire", WINBIND_WARN_PWD_EXPIRE); /* no or broken setting */ if (ret <= 0) { return DEFAULT_DAYS_TO_WARN_BEFORE_PWD_EXPIRES; -- cgit From 40102ad546c1bb3d9627df786d884fd0ca026ac2 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 27 Aug 2007 20:09:37 +0000 Subject: r24722: Squashed commit of the following: commit fb52f971986dd298abbcd9745ddf702820ce0184 Author: Gerald Carter Date: Mon Aug 27 13:50:26 2007 -0500 Check correct return type for pam_winbind_request_log() wnibind_upn_to_username which is an int and not NSS_STATUS. commit 7382edf6fc0fe555df89d5b2a94d12b35049b279 Author: Gerald Carter Date: Mon Aug 27 13:30:26 2007 -0500 Allow wbinfo -n to convert a UPN to a SID commit 8266c0fe1ccf2141e5a983f3213356419e626dda Author: Gerald Carter Date: Fri Aug 3 09:53:16 2007 -0500 Merge some of Guenther UPN work for pam_winbind.c (check the winbind separator and better pam logging when converting a upn to a username). commit 15156c17bc81dbcadf32757015c4e5158823bf3f Author: Gerald Carter Date: Fri Aug 3 08:52:50 2007 -0500 Include Universal groups from the cached PAC/SamLogon info when generating the list of domain group SIDs for a user's token. commit 979053c0307b051954261d539445102c55f309c7 Author: Gerald Carter Date: Thu Aug 2 17:35:41 2007 -0500 merge upnlogon patch from my tree (This used to be commit 98fb5bcd5702d5086bdf9b58105a67efb90950f4) --- source3/nsswitch/pam_winbind.c | 101 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index db3a089329..a9b55372e9 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1614,6 +1614,89 @@ int get_warn_pwd_expire_from_config(const pam_handle_t *pamh, return ret; } +/** + * Retrieve the winbind separator. + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * + * @return string separator character. NULL on failure. + */ + +static char winbind_get_separator(pam_handle_t *pamh, int ctrl) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (pam_winbind_request_log(pamh, ctrl, WINBINDD_INFO, &request, &response, NULL)) { + return '\0'; + } + + return response.data.info.winbind_separator; +} + +/** + * Convert a upn to a name. + * + * @param pamh PAM handle + * @param ctrl PAM winbind options. + * @param upn USer UPN to be trabslated. + * + * @return converted name. NULL pointer on failure. Caller needs to free. + */ + +static char* winbind_upn_to_username(pam_handle_t *pamh, int ctrl, const char *upn) +{ + struct winbindd_request req; + struct winbindd_response resp; + int retval; + char *account_name; + int account_name_len; + char sep; + + /* This cannot work when the winbind separator = @ */ + + sep = winbind_get_separator(pamh, ctrl); + if (!sep || sep == '@') { + return NULL; + } + + /* Convert the UPN to a SID */ + + ZERO_STRUCT(req); + ZERO_STRUCT(resp); + + strncpy(req.data.name.dom_name, "", + sizeof(req.data.name.dom_name) - 1); + strncpy(req.data.name.name, upn, + sizeof(req.data.name.name) - 1); + retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, + &req, &resp, upn); + if ( retval != PAM_SUCCESS ) { + return NULL; + } + + /* Convert the the SID back to the sAMAccountName */ + + ZERO_STRUCT(req); + strncpy(req.data.sid, resp.data.sid.sid, sizeof(req.data.sid)-1); + ZERO_STRUCT(resp); + retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPSID, + &req, &resp, upn); + if ( retval != PAM_SUCCESS ) { + return NULL; + } + + account_name_len = asprintf(&account_name, "%s\\%s", + resp.data.name.dom_name, + resp.data.name.name); + + return account_name; +} + PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) @@ -1646,6 +1729,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, goto out; } + #if defined(AIX) /* Decode the user name since AIX does not support logn user names by default. The name is encoded as _#uid. */ @@ -1670,6 +1754,19 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, } } + /* Maybe this was a UPN */ + + if (strchr(real_username, '@') != NULL) { + char *samaccountname = NULL; + + samaccountname = winbind_upn_to_username(pamh, ctrl, + real_username); + if (samaccountname) { + free(real_username); + real_username = samaccountname; + } + } + retval = _winbind_read_password(pamh, ctrl, NULL, "Password: ", NULL, &password); @@ -1697,8 +1794,8 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, ctrl, d); /* Now use the username to look up password */ - retval = winbind_auth_request(pamh, ctrl, username, password, member, - cctype, warn_pwd_expire, NULL, NULL, + retval = winbind_auth_request(pamh, ctrl, real_username, password, member, + cctype, warn_pwd_expire, NULL, NULL, &username_ret); if (retval == PAM_NEW_AUTHTOK_REQD || -- cgit From 84999433384ab8efca899a7e23ac541b4697ab3c Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 29 Aug 2007 14:50:04 +0000 Subject: r24786: Fix another build warning. Guenther (This used to be commit 29a56dcc78c49653bcf72dea6313fd4852de8f72) --- source3/nsswitch/pam_winbind.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index a9b55372e9..25f7540e06 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -14,13 +14,13 @@ #define _PAM_LOG_FUNCTION_ENTER(function, pamh, ctrl, flags) \ do { \ - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] ENTER: " function " (flags: 0x%04x)", (uint32) pamh, flags); \ + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] ENTER: " function " (flags: 0x%04x)", pamh, flags); \ _pam_log_state(pamh, ctrl); \ } while (0) #define _PAM_LOG_FUNCTION_LEAVE(function, pamh, ctrl, retval) \ do { \ - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] LEAVE: " function " returning %d", (uint32) pamh, retval); \ + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] LEAVE: " function " returning %d", pamh, retval); \ _pam_log_state(pamh, ctrl); \ } while (0) @@ -143,9 +143,9 @@ static void _pam_log_state_datum(const pam_handle_t *pamh, int ctrl, int item_ty if (data != NULL) { const char *type = (item_type != 0) ? "ITEM" : "DATA"; if (is_string != 0) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] STATE: %s(%s) = \"%s\" (0x%08x)", (uint32) pamh, type, key, (const char *) data, (uint32) data); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] STATE: %s(%s) = \"%s\" (%p)", pamh, type, key, (const char *) data, data); } else { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] STATE: %s(%s) = 0x%08x", (uint32) pamh, type, key, (uint32) data); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] STATE: %s(%s) = %p", pamh, type, key, data); } } } @@ -319,7 +319,7 @@ static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_ { int ctrl = _pam_parse(pamh, 0, 0, NULL, NULL); if (_pam_log_is_debug_state_enabled(ctrl)) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: 0x%08x] CLEAN: cleaning up PAM data 0x%08x (error_status = %d)", (uint32) pamh, (uint32) data, error_status); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] CLEAN: cleaning up PAM data %p (error_status = %d)", pamh, data, error_status); } SAFE_FREE(data); } -- cgit From 52936b1c86afcc6a317807a7e1ad6421b2e09379 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Sep 2007 14:14:02 +0000 Subject: r25130: make use only of base types which are provided by libreplace in winbind client and nss/pam stuff metze (This used to be commit 2e13e05fa91788bd128e6940bccc0d2cc7140986) --- source3/nsswitch/pam_winbind.c | 112 ++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 56 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 25f7540e06..ab9be566da 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -73,7 +73,7 @@ static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, } #endif /* HAVE_PAM_VSYSLOG */ -static BOOL _pam_log_is_silent(int ctrl) +static bool _pam_log_is_silent(int ctrl) { return on(ctrl, WINBIND_SILENT); } @@ -92,27 +92,27 @@ static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *fo va_end(args); } -static BOOL _pam_log_is_debug_enabled(int ctrl) +static bool _pam_log_is_debug_enabled(int ctrl) { if (ctrl == -1) { - return False; + return false; } if (_pam_log_is_silent(ctrl)) { - return False; + return false; } if (!(ctrl & WINBIND_DEBUG_ARG)) { - return False; + return false; } - return True; + return true; } -static BOOL _pam_log_is_debug_state_enabled(int ctrl) +static bool _pam_log_is_debug_state_enabled(int ctrl) { if (!(ctrl & WINBIND_DEBUG_STATE)) { - return False; + return false; } return _pam_log_is_debug_enabled(ctrl); @@ -231,23 +231,23 @@ static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char goto config_from_pam; } - if (iniparser_getboolean(d, "global:debug", False)) { + if (iniparser_getboolean(d, "global:debug", false)) { ctrl |= WINBIND_DEBUG_ARG; } - if (iniparser_getboolean(d, "global:debug_state", False)) { + if (iniparser_getboolean(d, "global:debug_state", false)) { ctrl |= WINBIND_DEBUG_STATE; } - if (iniparser_getboolean(d, "global:cached_login", False)) { + if (iniparser_getboolean(d, "global:cached_login", false)) { ctrl |= WINBIND_CACHED_LOGIN; } - if (iniparser_getboolean(d, "global:krb5_auth", False)) { + if (iniparser_getboolean(d, "global:krb5_auth", false)) { ctrl |= WINBIND_KRB5_AUTH; } - if (iniparser_getboolean(d, "global:silent", False)) { + if (iniparser_getboolean(d, "global:silent", false)) { ctrl |= WINBIND_SILENT; } @@ -260,7 +260,7 @@ static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char ctrl |= WINBIND_REQUIRED_MEMBERSHIP; } - if (iniparser_getboolean(d, "global:try_first_pass", False)) { + if (iniparser_getboolean(d, "global:try_first_pass", false)) { ctrl |= WINBIND_TRY_FIRST_PASS_ARG; } @@ -394,7 +394,7 @@ static int _make_remark(pam_handle_t * pamh, int flags, int type, const char *te } pmsg[0] = &msg[0]; - msg[0].msg = CONST_DISCARD(char *, text); + msg[0].msg = discard_const_p(char, text); msg[0].msg_style = type; resp = NULL; @@ -562,55 +562,55 @@ static int pam_winbind_request_log(pam_handle_t * pamh, * @param already_expired pointer to a boolean to indicate if the password is * already expired. * - * @return boolean Returns True if message has been sent, False if not. + * @return boolean Returns true if message has been sent, false if not. */ -static BOOL _pam_send_password_expiry_message(pam_handle_t *pamh, +static bool _pam_send_password_expiry_message(pam_handle_t *pamh, int ctrl, time_t next_change, time_t now, int warn_pwd_expire, - BOOL *already_expired) + bool *already_expired) { int days = 0; struct tm tm_now, tm_next_change; if (already_expired) { - *already_expired = False; + *already_expired = false; } if (next_change <= now) { PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PASSWORD_EXPIRED"); if (already_expired) { - *already_expired = True; + *already_expired = true; } - return True; + return true; } if ((next_change < 0) || (next_change > now + warn_pwd_expire * SECONDS_PER_DAY)) { - return False; + return false; } if ((localtime_r(&now, &tm_now) == NULL) || (localtime_r(&next_change, &tm_next_change) == NULL)) { - return False; + return false; } days = (tm_next_change.tm_yday+tm_next_change.tm_year*365) - (tm_now.tm_yday+tm_now.tm_year*365); if (days == 0) { _make_remark(pamh, ctrl, PAM_TEXT_INFO, "Your password expires today"); - return True; + return true; } if (days > 0 && days < warn_pwd_expire) { _make_remark_format(pamh, ctrl, PAM_TEXT_INFO, "Your password will expire in %d %s", days, (days > 1) ? "days":"day"); - return True; + return true; } - return False; + return false; } /** @@ -628,13 +628,13 @@ static void _pam_warn_password_expiry(pam_handle_t *pamh, int flags, const struct winbindd_response *response, int warn_pwd_expire, - BOOL *already_expired) + bool *already_expired) { time_t now = time(NULL); time_t next_change = 0; if (already_expired) { - *already_expired = False; + *already_expired = false; } /* accounts with ACB_PWNOEXP set never receive a warning */ @@ -677,7 +677,7 @@ static void _pam_warn_password_expiry(pam_handle_t *pamh, #define IS_SID_STRING(name) (strncmp("S-", name, 2) == 0) -static BOOL safe_append_string(char *dest, +static bool safe_append_string(char *dest, const char *src, int dest_buffer_size) /** @@ -688,21 +688,21 @@ static BOOL safe_append_string(char *dest, * @param src Source string buffer. * @param dest_buffer_size Size of dest buffer in bytes. * - * @return False if dest buffer is not big enough (no bytes copied), True on success. + * @return false if dest buffer is not big enough (no bytes copied), true on success. */ { int dest_length = strlen(dest); int src_length = strlen(src); if ( dest_length + src_length + 1 > dest_buffer_size ) { - return False; + return false; } memcpy(dest + dest_length, src, src_length + 1); - return True; + return true; } -static BOOL winbind_name_to_sid_string(pam_handle_t *pamh, +static bool winbind_name_to_sid_string(pam_handle_t *pamh, int ctrl, const char *user, const char *name, @@ -718,7 +718,7 @@ static BOOL winbind_name_to_sid_string(pam_handle_t *pamh, * @param sid_list_buffer Where to append the string sid. * @param sid_list_buffer Size of sid_list_buffer (in bytes). * - * @return False on failure, True on success. + * @return false on failure, true on success. */ { const char* sid_string; @@ -741,20 +741,20 @@ static BOOL winbind_name_to_sid_string(pam_handle_t *pamh, if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) { _pam_log(pamh, ctrl, LOG_INFO, "could not lookup name: %s\n", name); - return False; + return false; } sid_string = sid_response.data.sid.sid; } if (!safe_append_string(sid_list_buffer, sid_string, sid_list_buffer_size)) { - return False; + return false; } - return True; + return true; } -static BOOL winbind_name_list_to_sid_string_list(pam_handle_t *pamh, +static bool winbind_name_list_to_sid_string_list(pam_handle_t *pamh, int ctrl, const char *user, const char *name_list, @@ -770,10 +770,10 @@ static BOOL winbind_name_list_to_sid_string_list(pam_handle_t *pamh, * @param sid_list_buffer Where to put the list of string sids. * @param sid_list_buffer Size of sid_list_buffer (in bytes). * - * @return False on failure, True on success. + * @return false on failure, true on success. */ { - BOOL result = False; + bool result = false; char *current_name = NULL; const char *search_location; const char *comma; @@ -806,7 +806,7 @@ static BOOL winbind_name_list_to_sid_string_list(pam_handle_t *pamh, goto out; } - result = True; + result = true; out: SAFE_FREE(current_name); @@ -922,7 +922,7 @@ static void _pam_free_data_info3(pam_handle_t *pamh) * @return void. */ -static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *username, uint32 info3_user_flgs) +static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *username, uint32_t info3_user_flgs) { /* inform about logon type */ if (PAM_WB_GRACE_LOGON(info3_user_flgs)) { @@ -952,7 +952,7 @@ static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *usern * @return void. */ -static void _pam_warn_krb5_failure(pam_handle_t *pamh, int ctrl, const char *username, uint32 info3_user_flgs) +static void _pam_warn_krb5_failure(pam_handle_t *pamh, int ctrl, const char *username, uint32_t info3_user_flgs) { if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) { _make_remark(pamh, ctrl, PAM_ERROR_MSG, @@ -1049,7 +1049,7 @@ static int winbind_auth_request(pam_handle_t * pamh, struct winbindd_request request; struct winbindd_response response; int ret; - BOOL already_expired = False; + bool already_expired = false; ZERO_STRUCT(request); ZERO_STRUCT(response); @@ -1151,7 +1151,7 @@ static int winbind_auth_request(pam_handle_t * pamh, warn_pwd_expire, &already_expired); - if (already_expired == True) { + if (already_expired == true) { _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Password has expired " "(Password was last set: %lld, the policy says " "it should expire here %lld (now it's: %lu))\n", @@ -1403,7 +1403,7 @@ static int _winbind_read_password(pam_handle_t * pamh, if (comment != NULL && off(ctrl, WINBIND_SILENT)) { pmsg[0] = &msg[0]; msg[0].msg_style = PAM_TEXT_INFO; - msg[0].msg = CONST_DISCARD(char *, comment); + msg[0].msg = discard_const_p(char, comment); i = 1; } else { i = 0; @@ -1411,13 +1411,13 @@ static int _winbind_read_password(pam_handle_t * pamh, pmsg[i] = &msg[i]; msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = CONST_DISCARD(char *, prompt1); + msg[i++].msg = discard_const_p(char, prompt1); replies = 1; if (prompt2 != NULL) { pmsg[i] = &msg[i]; msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = CONST_DISCARD(char *, prompt2); + msg[i++].msg = discard_const_p(char, prompt2); ++replies; } /* so call the conversation expecting i responses */ @@ -1812,7 +1812,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, retval = PAM_SUCCESS; - if (!asprintf(&new_authtok_required_during_auth, "%d", True)) { + if (!asprintf(&new_authtok_required_during_auth, "%d", true)) { retval = PAM_BUF_ERR; goto out; } @@ -2110,10 +2110,10 @@ out: * @param ctrl PAM winbind options. * @param user The username * - * @return boolean Returns True if required, False if not. + * @return boolean Returns true if required, false if not. */ -static BOOL _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, const char *user) +static bool _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, const char *user) { /* Make sure that we only do this if @@ -2125,26 +2125,26 @@ static BOOL _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, struct passwd *pwd = NULL; if (!(ctrl & WINBIND_KRB5_AUTH)) { - return False; + return false; } _pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, &new_authtok_reqd_during_auth); pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, NULL, NULL); if (new_authtok_reqd_during_auth) { - return True; + return true; } pwd = getpwnam(user); if (!pwd) { - return False; + return false; } if (getuid() == pwd->pw_uid) { - return True; + return true; } - return False; + return false; } -- cgit From 28d076d20f9ce8afbee9a5de157ec0c9e308c9cf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 14 Sep 2007 07:07:59 +0000 Subject: r25143: rename public functions from winbind_client.h init_request => winbindd_init_request free_response => winbindd_free_response read_reply => winbindd_read_reply write_sock => winbind_write_sock read_sock => winbind_read_sock close_sock => winbind_close_sock(void) metze (This used to be commit 8a95d7a7edcfa5e45bccc6eda5c45d9c308cb95d) --- source3/nsswitch/pam_winbind.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index ab9be566da..f4793f77c8 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -440,23 +440,23 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, struct winbindd_response *response) { /* Fill in request and send down pipe */ - init_request(request, req_type); + winbindd_init_request(request, req_type); - if (write_sock(request, sizeof(*request), 0, 0) == -1) { + if (winbind_write_sock(request, sizeof(*request), 0, 0) == -1) { _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!"); - close_sock(); + winbind_close_sock(); return PAM_SERVICE_ERR; } /* Wait for reply */ - if (read_reply(response) == -1) { + if (winbindd_read_reply(response) == -1) { _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: read from socket failed!"); - close_sock(); + winbind_close_sock(); return PAM_SERVICE_ERR; } /* We are done with the socket - close it and avoid mischeif */ - close_sock(); + winbind_close_sock(); /* Copy reply data from socket */ if (response->result == WINBINDD_OK) { -- cgit From 6005c4e657299355add620232d7570d8d1633213 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 14 Sep 2007 08:21:20 +0000 Subject: r25148: Adapt to coding conventions. Guenther (This used to be commit c3b423c52a2bf3f50870158d8c7ffd314c8ac935) --- source3/nsswitch/pam_winbind.c | 1111 +++++++++++++++++++++++++--------------- 1 file changed, 697 insertions(+), 414 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index f4793f77c8..fde5b03611 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -5,22 +5,24 @@ Copyright Andrew Bartlett 2002 Copyright Guenther Deschner 2005-2007 - largely based on pam_userdb by Cristian Gafton - also contains large slabs of code from pam_unix by Elliot Lee - (see copyright below for full details) + largely based on pam_userdb by Cristian Gafton also + contains large slabs of code from pam_unix by Elliot Lee + (see copyright below for full details) */ #include "pam_winbind.h" #define _PAM_LOG_FUNCTION_ENTER(function, pamh, ctrl, flags) \ do { \ - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] ENTER: " function " (flags: 0x%04x)", pamh, flags); \ + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] ENTER: " \ + function " (flags: 0x%04x)", pamh, flags); \ _pam_log_state(pamh, ctrl); \ } while (0) #define _PAM_LOG_FUNCTION_LEAVE(function, pamh, ctrl, retval) \ do { \ - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] LEAVE: " function " returning %d", pamh, retval); \ + _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] LEAVE: " \ + function " returning %d", pamh, retval); \ _pam_log_state(pamh, ctrl); \ } while (0) @@ -29,17 +31,19 @@ #define MAX_PASSWD_TRIES 3 /* - * Work around the pam API that has functions with void ** as parameters. + * Work around the pam API that has functions with void ** as parameters * These lead to strict aliasing warnings with gcc. */ -static int _pam_get_item(const pam_handle_t *pamh, int item_type, +static int _pam_get_item(const pam_handle_t *pamh, + int item_type, const void *_item) { const void **item = (const void **)_item; return pam_get_item(pamh, item_type, item); } static int _pam_get_data(const pam_handle_t *pamh, - const char *module_data_name, const void *_data) + const char *module_data_name, + const void *_data) { const void **data = (const void **)_data; return pam_get_data(pamh, module_data_name, data); @@ -48,12 +52,18 @@ static int _pam_get_data(const pam_handle_t *pamh, /* some syslogging */ #ifdef HAVE_PAM_VSYSLOG -static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, va_list args) +static void _pam_log_int(const pam_handle_t *pamh, + int err, + const char *format, + va_list args) { pam_vsyslog(pamh, err, format, args); } #else -static void _pam_log_int(const pam_handle_t *pamh, int err, const char *format, va_list args) +static void _pam_log_int(const pam_handle_t *pamh, + int err, + const char *format, + va_list args) { char *format2 = NULL; const char *service; @@ -132,7 +142,11 @@ static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const ch va_end(args); } -static void _pam_log_state_datum(const pam_handle_t *pamh, int ctrl, int item_type, const char *key, int is_string) +static void _pam_log_state_datum(const pam_handle_t *pamh, + int ctrl, + int item_type, + const char *key, + int is_string) { const void *data = NULL; if (item_type != 0) { @@ -143,9 +157,14 @@ static void _pam_log_state_datum(const pam_handle_t *pamh, int ctrl, int item_ty if (data != NULL) { const char *type = (item_type != 0) ? "ITEM" : "DATA"; if (is_string != 0) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] STATE: %s(%s) = \"%s\" (%p)", pamh, type, key, (const char *) data, data); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "[pamh: %p] STATE: %s(%s) = \"%s\" (%p)", + pamh, type, key, (const char *)data, + data); } else { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] STATE: %s(%s) = %p", pamh, type, key, data); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "[pamh: %p] STATE: %s(%s) = %p", + pamh, type, key, data); } } } @@ -169,7 +188,8 @@ static void _pam_log_state_datum(const pam_handle_t *pamh, int ctrl, int item_ty #endif #define _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, item_type) \ - _pam_log_state_datum(pamh, ctrl, item_type, #item_type, _LOG_PASSWORD_AS_STRING) + _pam_log_state_datum(pamh, ctrl, item_type, #item_type, \ + _LOG_PASSWORD_AS_STRING) static void _pam_log_state(const pam_handle_t *pamh, int ctrl) { @@ -197,12 +217,19 @@ static void _pam_log_state(const pam_handle_t *pamh, int ctrl) _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT); _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSERVER); _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_PROFILEPATH); - _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD); /* Use atoi to get PAM result code */ - _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH); + _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, + PAM_WINBIND_NEW_AUTHTOK_REQD); + /* Use atoi to get PAM result code */ + _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, + PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH); _PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, PAM_WINBIND_PWD_LAST_SET); } -static int _pam_parse(const pam_handle_t *pamh, int flags, int argc, const char **argv, dictionary **result_d) +static int _pam_parse(const pam_handle_t *pamh, + int flags, + int argc, + const char **argv, + dictionary **result_d) { int ctrl = 0; const char *config_file = NULL; @@ -287,18 +314,22 @@ config_from_pam: ctrl |= WINBIND_TRY_FIRST_PASS_ARG; else if (!strcasecmp(*v, "unknown_ok")) ctrl |= WINBIND_UNKNOWN_OK_ARG; - else if (!strncasecmp(*v, "require_membership_of", strlen("require_membership_of"))) + else if (!strncasecmp(*v, "require_membership_of", + strlen("require_membership_of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; - else if (!strncasecmp(*v, "require-membership-of", strlen("require-membership-of"))) + else if (!strncasecmp(*v, "require-membership-of", + strlen("require-membership-of"))) ctrl |= WINBIND_REQUIRED_MEMBERSHIP; else if (!strcasecmp(*v, "krb5_auth")) ctrl |= WINBIND_KRB5_AUTH; - else if (!strncasecmp(*v, "krb5_ccache_type", strlen("krb5_ccache_type"))) + else if (!strncasecmp(*v, "krb5_ccache_type", + strlen("krb5_ccache_type"))) ctrl |= WINBIND_KRB5_CCACHE_TYPE; else if (!strcasecmp(*v, "cached_login")) ctrl |= WINBIND_CACHED_LOGIN; else { - _pam_log(pamh, ctrl, LOG_ERR, "pam_parse: unknown option: %s", *v); + _pam_log(pamh, ctrl, LOG_ERR, + "pam_parse: unknown option: %s", *v); return -1; } @@ -315,11 +346,16 @@ config_from_pam: return ctrl; }; -static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_status) +static void _pam_winbind_cleanup_func(pam_handle_t *pamh, + void *data, + int error_status) { int ctrl = _pam_parse(pamh, 0, 0, NULL, NULL); if (_pam_log_is_debug_state_enabled(ctrl)) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] CLEAN: cleaning up PAM data %p (error_status = %d)", pamh, data, error_status); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "[pamh: %p] CLEAN: cleaning up PAM data %p " + "(error_status = %d)", pamh, data, + error_status); } SAFE_FREE(data); } @@ -329,32 +365,54 @@ static const struct ntstatus_errors { const char *ntstatus_string; const char *error_string; } ntstatus_errors[] = { - {"NT_STATUS_OK", "Success"}, - {"NT_STATUS_BACKUP_CONTROLLER", "No primary Domain Controler available"}, - {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", "No domain controllers found"}, - {"NT_STATUS_NO_LOGON_SERVERS", "No logon servers"}, - {"NT_STATUS_PWD_TOO_SHORT", "Password too short"}, - {"NT_STATUS_PWD_TOO_RECENT", "The password of this user is too recent to change"}, - {"NT_STATUS_PWD_HISTORY_CONFLICT", "Password is already in password history"}, - {"NT_STATUS_PASSWORD_EXPIRED", "Your password has expired"}, - {"NT_STATUS_PASSWORD_MUST_CHANGE", "You need to change your password now"}, - {"NT_STATUS_INVALID_WORKSTATION", "You are not allowed to logon from this workstation"}, - {"NT_STATUS_INVALID_LOGON_HOURS", "You are not allowed to logon at this time"}, - {"NT_STATUS_ACCOUNT_EXPIRED", "Your account has expired. Please contact your System administrator"}, /* SCNR */ - {"NT_STATUS_ACCOUNT_DISABLED", "Your account is disabled. Please contact your System administrator"}, /* SCNR */ - {"NT_STATUS_ACCOUNT_LOCKED_OUT", "Your account has been locked. Please contact your System administrator"}, /* SCNR */ - {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", "Invalid Trust Account"}, - {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", "Invalid Trust Account"}, - {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", "Invalid Trust Account"}, - {"NT_STATUS_ACCESS_DENIED", "Access is denied"}, + {"NT_STATUS_OK", + "Success"}, + {"NT_STATUS_BACKUP_CONTROLLER", + "No primary Domain Controler available"}, + {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", + "No domain controllers found"}, + {"NT_STATUS_NO_LOGON_SERVERS", + "No logon servers"}, + {"NT_STATUS_PWD_TOO_SHORT", + "Password too short"}, + {"NT_STATUS_PWD_TOO_RECENT", + "The password of this user is too recent to change"}, + {"NT_STATUS_PWD_HISTORY_CONFLICT", + "Password is already in password history"}, + {"NT_STATUS_PASSWORD_EXPIRED", + "Your password has expired"}, + {"NT_STATUS_PASSWORD_MUST_CHANGE", + "You need to change your password now"}, + {"NT_STATUS_INVALID_WORKSTATION", + "You are not allowed to logon from this workstation"}, + {"NT_STATUS_INVALID_LOGON_HOURS", + "You are not allowed to logon at this time"}, + {"NT_STATUS_ACCOUNT_EXPIRED", + "Your account has expired. " + "Please contact your System administrator"}, /* SCNR */ + {"NT_STATUS_ACCOUNT_DISABLED", + "Your account is disabled. " + "Please contact your System administrator"}, /* SCNR */ + {"NT_STATUS_ACCOUNT_LOCKED_OUT", + "Your account has been locked. " + "Please contact your System administrator"}, /* SCNR */ + {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", + "Invalid Trust Account"}, + {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", + "Invalid Trust Account"}, + {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", + "Invalid Trust Account"}, + {"NT_STATUS_ACCESS_DENIED", + "Access is denied"}, {NULL, NULL} }; -const char *_get_ntstatus_error_string(const char *nt_status_string) +const char *_get_ntstatus_error_string(const char *nt_status_string) { int i; for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) { - if (!strcasecmp(ntstatus_errors[i].ntstatus_string, nt_status_string)) { + if (!strcasecmp(ntstatus_errors[i].ntstatus_string, + nt_status_string)) { return ntstatus_errors[i].error_string; } } @@ -365,30 +423,35 @@ const char *_get_ntstatus_error_string(const char *nt_status_string) /* Attempt a conversation */ -static int converse(pam_handle_t *pamh, int nargs, +static int converse(pam_handle_t *pamh, + int nargs, struct pam_message **message, struct pam_response **response) { int retval; struct pam_conv *conv; - retval = _pam_get_item(pamh, PAM_CONV, &conv ); + retval = _pam_get_item(pamh, PAM_CONV, &conv); if (retval == PAM_SUCCESS) { - retval = conv->conv(nargs, (const struct pam_message **)message, + retval = conv->conv(nargs, + (const struct pam_message **)message, response, conv->appdata_ptr); } - + return retval; /* propagate error status */ } -static int _make_remark(pam_handle_t * pamh, int flags, int type, const char *text) +static int _make_remark(pam_handle_t * pamh, + int flags, + int type, + const char *text) { int retval = PAM_SUCCESS; struct pam_message *pmsg[1], msg[1]; struct pam_response *resp; - + if (flags & WINBIND_SILENT) { return PAM_SUCCESS; } @@ -396,17 +459,21 @@ static int _make_remark(pam_handle_t * pamh, int flags, int type, const char *te pmsg[0] = &msg[0]; msg[0].msg = discard_const_p(char, text); msg[0].msg_style = type; - + resp = NULL; retval = converse(pamh, 1, pmsg, &resp); - + if (resp) { _pam_drop_reply(resp, 1); } return retval; } -static int _make_remark_v(pam_handle_t * pamh, int flags, int type, const char *format, va_list args) +static int _make_remark_v(pam_handle_t *pamh, + int flags, + int type, + const char *format, + va_list args) { char *var; int ret; @@ -434,23 +501,26 @@ static int _make_remark_format(pam_handle_t * pamh, int flags, int type, const c return ret; } -static int pam_winbind_request(pam_handle_t * pamh, int ctrl, +static int pam_winbind_request(pam_handle_t *pamh, + int ctrl, enum winbindd_cmd req_type, struct winbindd_request *request, struct winbindd_response *response) { /* Fill in request and send down pipe */ winbindd_init_request(request, req_type); - + if (winbind_write_sock(request, sizeof(*request), 0, 0) == -1) { - _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!"); + _pam_log(pamh, ctrl, LOG_ERR, + "pam_winbind_request: write to socket failed!"); winbind_close_sock(); return PAM_SERVICE_ERR; } - + /* Wait for reply */ if (winbindd_read_reply(response) == -1) { - _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: read from socket failed!"); + _pam_log(pamh, ctrl, LOG_ERR, + "pam_winbind_request: read from socket failed!"); winbind_close_sock(); return PAM_SERVICE_ERR; } @@ -469,8 +539,9 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, case WINBINDD_GETPWNAM: case WINBINDD_LOOKUPNAME: if (strlen(response->data.auth.nt_status_string) > 0) { - _pam_log(pamh, ctrl, LOG_ERR, "request failed, NT error was %s", - response->data.auth.nt_status_string); + _pam_log(pamh, ctrl, LOG_ERR, + "request failed, NT error was %s", + response->data.auth.nt_status_string); } else { _pam_log(pamh, ctrl, LOG_ERR, "request failed"); } @@ -480,20 +551,22 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl, } if (response->data.auth.pam_error != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_ERR, "request failed: %s, PAM error was %s (%d), NT error was %s", + _pam_log(pamh, ctrl, LOG_ERR, + "request failed: %s, " + "PAM error was %s (%d), NT error was %s", response->data.auth.error_string, pam_strerror(pamh, response->data.auth.pam_error), response->data.auth.pam_error, response->data.auth.nt_status_string); return response->data.auth.pam_error; - } - + } + _pam_log(pamh, ctrl, LOG_ERR, "request failed, but PAM error 0!"); return PAM_SERVICE_ERR; } -static int pam_winbind_request_log(pam_handle_t * pamh, +static int pam_winbind_request_log(pam_handle_t *pamh, int ctrl, enum winbindd_cmd req_type, struct winbindd_request *request, @@ -507,26 +580,31 @@ static int pam_winbind_request_log(pam_handle_t * pamh, switch (retval) { case PAM_AUTH_ERR: /* incorrect password */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' denied access (incorrect password or invalid membership)", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' denied access " + "(incorrect password or invalid membership)", user); return retval; case PAM_ACCT_EXPIRED: /* account expired */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' account expired", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' account expired", + user); return retval; case PAM_AUTHTOK_EXPIRED: /* password expired */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' password expired", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' password expired", + user); return retval; case PAM_NEW_AUTHTOK_REQD: /* new password required */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' new password required", user); + _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' new password " + "required", user); return retval; case PAM_USER_UNKNOWN: /* the user does not exist */ - _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", user); + _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", + user); if (ctrl & WINBIND_UNKNOWN_OK_ARG) { return PAM_IGNORE; - } + } return retval; case PAM_SUCCESS: /* Otherwise, the authentication looked good */ @@ -534,20 +612,24 @@ static int pam_winbind_request_log(pam_handle_t * pamh, case WINBINDD_INFO: break; case WINBINDD_PAM_AUTH: - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", user); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' granted access", user); break; case WINBINDD_PAM_CHAUTHTOK: - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' password changed", user); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' password changed", user); break; default: - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' OK", user); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' OK", user); break; } - + return retval; default: /* we don't know anything about this return value */ - _pam_log(pamh, ctrl, LOG_ERR, "internal module error (retval = %d, user = '%s')", + _pam_log(pamh, ctrl, LOG_ERR, + "internal module error (retval = %d, user = '%s')", retval, user); return retval; } @@ -555,7 +637,7 @@ static int pam_winbind_request_log(pam_handle_t * pamh, /** * send a password expiry message if required - * + * * @param pamh PAM handle * @param ctrl PAM winbind options. * @param next_change expected (calculated) next expiry date. @@ -592,21 +674,24 @@ static bool _pam_send_password_expiry_message(pam_handle_t *pamh, return false; } - if ((localtime_r(&now, &tm_now) == NULL) || + if ((localtime_r(&now, &tm_now) == NULL) || (localtime_r(&next_change, &tm_next_change) == NULL)) { return false; } - days = (tm_next_change.tm_yday+tm_next_change.tm_year*365) - (tm_now.tm_yday+tm_now.tm_year*365); + days = (tm_next_change.tm_yday+tm_next_change.tm_year*365) - + (tm_now.tm_yday+tm_now.tm_year*365); if (days == 0) { - _make_remark(pamh, ctrl, PAM_TEXT_INFO, "Your password expires today"); + _make_remark(pamh, ctrl, PAM_TEXT_INFO, + "Your password expires today"); return true; - } - + } + if (days > 0 && days < warn_pwd_expire) { - _make_remark_format(pamh, ctrl, PAM_TEXT_INFO, "Your password will expire in %d %s", - days, (days > 1) ? "days":"day"); + _make_remark_format(pamh, ctrl, PAM_TEXT_INFO, + "Your password will expire in %d %s", + days, (days > 1) ? "days":"day"); return true; } @@ -624,8 +709,8 @@ static bool _pam_send_password_expiry_message(pam_handle_t *pamh, * @return void. */ -static void _pam_warn_password_expiry(pam_handle_t *pamh, - int flags, +static void _pam_warn_password_expiry(pam_handle_t *pamh, + int flags, const struct winbindd_response *response, int warn_pwd_expire, bool *already_expired) @@ -663,7 +748,7 @@ static void _pam_warn_password_expiry(pam_handle_t *pamh, return; } - next_change = response->data.auth.info3.pass_last_set_time + + next_change = response->data.auth.info3.pass_last_set_time + response->data.auth.policy.expire; if (_pam_send_password_expiry_message(pamh, flags, next_change, now, @@ -677,24 +762,26 @@ static void _pam_warn_password_expiry(pam_handle_t *pamh, #define IS_SID_STRING(name) (strncmp("S-", name, 2) == 0) -static bool safe_append_string(char *dest, - const char *src, - int dest_buffer_size) /** - * Append a string, making sure not to overflow and to always return a NULL-terminated - * string. + * Append a string, making sure not to overflow and to always return a + * NULL-terminated string. * * @param dest Destination string buffer (must already be NULL-terminated). * @param src Source string buffer. * @param dest_buffer_size Size of dest buffer in bytes. * - * @return false if dest buffer is not big enough (no bytes copied), true on success. + * @return false if dest buffer is not big enough (no bytes copied), true on + * success. */ + +static bool safe_append_string(char *dest, + const char *src, + int dest_buffer_size) { int dest_length = strlen(dest); int src_length = strlen(src); - if ( dest_length + src_length + 1 > dest_buffer_size ) { + if (dest_length + src_length + 1 > dest_buffer_size) { return false; } @@ -702,12 +789,6 @@ static bool safe_append_string(char *dest, return true; } -static bool winbind_name_to_sid_string(pam_handle_t *pamh, - int ctrl, - const char *user, - const char *name, - char *sid_list_buffer, - int sid_list_buffer_size) /** * Convert a names into a SID string, appending it to a buffer. * @@ -720,11 +801,17 @@ static bool winbind_name_to_sid_string(pam_handle_t *pamh, * * @return false on failure, true on success. */ +static bool winbind_name_to_sid_string(pam_handle_t *pamh, + int ctrl, + const char *user, + const char *name, + char *sid_list_buffer, + int sid_list_buffer_size) { const char* sid_string; struct winbindd_response sid_response; - /* lookup name? */ + /* lookup name? */ if (IS_SID_STRING(name)) { sid_string = name; } else { @@ -733,33 +820,32 @@ static bool winbind_name_to_sid_string(pam_handle_t *pamh, ZERO_STRUCT(sid_request); ZERO_STRUCT(sid_response); - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", name); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "no sid given, looking up: %s\n", name); /* fortunatly winbindd can handle non-separated names */ strncpy(sid_request.data.name.name, name, sizeof(sid_request.data.name.name) - 1); - if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) { - _pam_log(pamh, ctrl, LOG_INFO, "could not lookup name: %s\n", name); + if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, + &sid_request, &sid_response, + user)) { + _pam_log(pamh, ctrl, LOG_INFO, + "could not lookup name: %s\n", name); return false; } sid_string = sid_response.data.sid.sid; } - if (!safe_append_string(sid_list_buffer, sid_string, sid_list_buffer_size)) { + if (!safe_append_string(sid_list_buffer, sid_string, + sid_list_buffer_size)) { return false; } return true; } -static bool winbind_name_list_to_sid_string_list(pam_handle_t *pamh, - int ctrl, - const char *user, - const char *name_list, - char *sid_list_buffer, - int sid_list_buffer_size) /** * Convert a list of names into a list of sids. * @@ -772,37 +858,50 @@ static bool winbind_name_list_to_sid_string_list(pam_handle_t *pamh, * * @return false on failure, true on success. */ +static bool winbind_name_list_to_sid_string_list(pam_handle_t *pamh, + int ctrl, + const char *user, + const char *name_list, + char *sid_list_buffer, + int sid_list_buffer_size) { bool result = false; char *current_name = NULL; const char *search_location; const char *comma; - if ( sid_list_buffer_size > 0 ) { + if (sid_list_buffer_size > 0) { sid_list_buffer[0] = 0; } search_location = name_list; - while ( (comma = strstr(search_location, ",")) != NULL ) { - current_name = strndup(search_location, comma - search_location); + while ((comma = strstr(search_location, ",")) != NULL) { + current_name = strndup(search_location, + comma - search_location); if (NULL == current_name) { goto out; } - if (!winbind_name_to_sid_string(pamh, ctrl, user, current_name, sid_list_buffer, sid_list_buffer_size)) { + if (!winbind_name_to_sid_string(pamh, ctrl, user, + current_name, + sid_list_buffer, + sid_list_buffer_size)) { goto out; } SAFE_FREE(current_name); - if (!safe_append_string(sid_list_buffer, ",", sid_list_buffer_size)) { + if (!safe_append_string(sid_list_buffer, ",", + sid_list_buffer_size)) { goto out; } search_location = comma + 1; } - if (!winbind_name_to_sid_string(pamh, ctrl, user, search_location, sid_list_buffer, sid_list_buffer_size)) { + if (!winbind_name_to_sid_string(pamh, ctrl, user, search_location, + sid_list_buffer, + sid_list_buffer_size)) { goto out; } @@ -823,7 +922,9 @@ out: * @return void. */ -static void _pam_setup_krb5_env(pam_handle_t *pamh, int ctrl, const char *krb5ccname) +static void _pam_setup_krb5_env(pam_handle_t *pamh, + int ctrl, + const char *krb5ccname) { char var[PATH_MAX]; int ret; @@ -836,18 +937,20 @@ static void _pam_setup_krb5_env(pam_handle_t *pamh, int ctrl, const char *krb5cc return; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "request returned KRB5CCNAME: %s", krb5ccname); - + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "request returned KRB5CCNAME: %s", krb5ccname); + if (snprintf(var, sizeof(var), "KRB5CCNAME=%s", krb5ccname) == -1) { return; } - + ret = pam_putenv(pamh, var); if (ret) { - _pam_log(pamh, ctrl, LOG_ERR, "failed to set KRB5CCNAME to %s: %s", - var, pam_strerror(pamh, ret)); + _pam_log(pamh, ctrl, LOG_ERR, + "failed to set KRB5CCNAME to %s: %s", + var, pam_strerror(pamh, ret)); } -} +} /** * Set string into the PAM stack. @@ -860,18 +963,24 @@ static void _pam_setup_krb5_env(pam_handle_t *pamh, int ctrl, const char *krb5cc * @return void. */ -static void _pam_set_data_string(pam_handle_t *pamh, int ctrl, const char *data_name, const char *value) +static void _pam_set_data_string(pam_handle_t *pamh, + int ctrl, + const char *data_name, + const char *value) { int ret; - if ( !data_name || !value || (strlen(data_name) == 0) || (strlen(value) == 0) ) { + if (!data_name || !value || (strlen(data_name) == 0) || + (strlen(value) == 0)) { return; } - ret = pam_set_data(pamh, data_name, (void *)strdup(value), _pam_winbind_cleanup_func); + ret = pam_set_data(pamh, data_name, (void *)strdup(value), + _pam_winbind_cleanup_func); if (ret) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Could not set data %s: %s\n", - data_name, pam_strerror(pamh, ret)); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "Could not set data %s: %s\n", + data_name, pam_strerror(pamh, ret)); } } @@ -887,12 +996,18 @@ static void _pam_set_data_string(pam_handle_t *pamh, int ctrl, const char *data_ * @return void. */ -static void _pam_set_data_info3(pam_handle_t *pamh, int ctrl, struct winbindd_response *response) +static void _pam_set_data_info3(pam_handle_t *pamh, + int ctrl, + struct winbindd_response *response) { - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_HOMEDIR, response->data.auth.info3.home_dir); - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT, response->data.auth.info3.logon_script); - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSERVER, response->data.auth.info3.logon_srv); - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_PROFILEPATH, response->data.auth.info3.profile_path); + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_HOMEDIR, + response->data.auth.info3.home_dir); + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT, + response->data.auth.info3.logon_script); + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSERVER, + response->data.auth.info3.logon_srv); + _pam_set_data_string(pamh, ctrl, PAM_WINBIND_PROFILEPATH, + response->data.auth.info3.profile_path); } /** @@ -922,22 +1037,31 @@ static void _pam_free_data_info3(pam_handle_t *pamh) * @return void. */ -static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *username, uint32_t info3_user_flgs) +static void _pam_warn_logon_type(pam_handle_t *pamh, + int ctrl, + const char *username, + uint32_t info3_user_flgs) { /* inform about logon type */ if (PAM_WB_GRACE_LOGON(info3_user_flgs)) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - "Grace login. Please change your password as soon you're online again"); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Grace login. " + "Please change your password as soon you're " + "online again"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "User %s logged on using grace logon\n", username); + "User %s logged on using grace logon\n", + username); } else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, - "Domain Controller unreachable, using cached credentials instead. Network resources may be unavailable"); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Domain Controller unreachable, " + "using cached credentials instead. " + "Network resources may be unavailable"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "User %s logged on using cached credentials\n", username); + "User %s logged on using cached credentials\n", + username); } } @@ -952,16 +1076,20 @@ static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *usern * @return void. */ -static void _pam_warn_krb5_failure(pam_handle_t *pamh, int ctrl, const char *username, uint32_t info3_user_flgs) +static void _pam_warn_krb5_failure(pam_handle_t *pamh, + int ctrl, + const char *username, + uint32_t info3_user_flgs) { if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, + _make_remark(pamh, ctrl, PAM_ERROR_MSG, "Failed to establish your Kerberos Ticket cache " - "due time differences\n" + "due time differences\n" "with the domain controller. " - "Please verify the system time.\n"); + "Please verify the system time.\n"); _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "User %s: Clock skew when getting Krb5 TGT\n", username); + "User %s: Clock skew when getting Krb5 TGT\n", + username); } } @@ -992,37 +1120,42 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo if (response->data.auth.policy.min_length_password > 0) { ret = snprintf(str+offset, str_size-offset, - "must be at least %d characters; ", - response->data.auth.policy.min_length_password); + "must be at least %d characters; ", + response->data.auth.policy.min_length_password); if (ret == -1) { goto failed; } offset += ret; } - + if (response->data.auth.policy.password_history > 0) { ret = snprintf(str+offset, str_size-offset, - "cannot repeat any of your previous %d passwords; ", - response->data.auth.policy.password_history); + "cannot repeat any of your previous %d " + "passwords; ", + response->data.auth.policy.password_history); if (ret == -1) { goto failed; } offset += ret; } - - if (response->data.auth.policy.password_properties & DOMAIN_PASSWORD_COMPLEX) { + + if (response->data.auth.policy.password_properties & + DOMAIN_PASSWORD_COMPLEX) { ret = snprintf(str+offset, str_size-offset, - "must contain capitals, numerals or punctuation; " - "and cannot contain your account or full name; "); + "must contain capitals, numerals " + "or punctuation; " + "and cannot contain your account " + "or full name; "); if (ret == -1) { goto failed; } offset += ret; } - ret = snprintf(str+offset, str_size-offset, - "Please type a different password. " - "Type a password which meets these requirements in both text boxes."); + ret = snprintf(str+offset, str_size-offset, + "Please type a different password. " + "Type a password which meets these requirements in " + "both text boxes."); if (ret == -1) { goto failed; } @@ -1036,10 +1169,10 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo /* talk to winbindd */ static int winbind_auth_request(pam_handle_t * pamh, - int ctrl, - const char *user, - const char *pass, - const char *member, + int ctrl, + const char *user, + const char *pass, + const char *member, const char *cctype, const int warn_pwd_expire, struct winbindd_response *p_response, @@ -1058,16 +1191,17 @@ static int winbind_auth_request(pam_handle_t * pamh, *pwd_last_set = 0; } - strncpy(request.data.auth.user, user, + strncpy(request.data.auth.user, user, sizeof(request.data.auth.user)-1); - strncpy(request.data.auth.pass, pass, + strncpy(request.data.auth.pass, pass, sizeof(request.data.auth.pass)-1); request.data.auth.krb5_cc_type[0] = '\0'; request.data.auth.uid = -1; - - request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_CONTACT_TRUSTDOM; + + request.flags = WBFLAG_PAM_INFO3_TEXT | + WBFLAG_PAM_CONTACT_TRUSTDOM; if (ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) { struct passwd *pwd = NULL; @@ -1081,13 +1215,16 @@ static int winbind_auth_request(pam_handle_t * pamh, if (ctrl & WINBIND_KRB5_AUTH) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling krb5 login flag\n"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "enabling krb5 login flag\n"); - request.flags |= WBFLAG_PAM_KRB5 | WBFLAG_PAM_FALLBACK_AFTER_KRB5; + request.flags |= WBFLAG_PAM_KRB5 | + WBFLAG_PAM_FALLBACK_AFTER_KRB5; } if (ctrl & WINBIND_CACHED_LOGIN) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling cached login flag\n"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "enabling cached login flag\n"); request.flags |= WBFLAG_PAM_CACHED_LOGIN; } @@ -1097,25 +1234,31 @@ static int winbind_auth_request(pam_handle_t * pamh, } if (cctype != NULL) { - strncpy(request.data.auth.krb5_cc_type, cctype, + strncpy(request.data.auth.krb5_cc_type, cctype, sizeof(request.data.auth.krb5_cc_type) - 1); - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "enabling request for a %s krb5 ccache\n", cctype); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "enabling request for a %s krb5 ccache\n", + cctype); } request.data.auth.require_membership_of_sid[0] = '\0'; if (member != NULL) { - if (!winbind_name_list_to_sid_string_list(pamh, ctrl, user, member, + if (!winbind_name_list_to_sid_string_list(pamh, ctrl, user, + member, request.data.auth.require_membership_of_sid, sizeof(request.data.auth.require_membership_of_sid))) { - _pam_log_debug(pamh, ctrl, LOG_ERR, "failed to serialize membership of sid \"%s\"\n", member); + _pam_log_debug(pamh, ctrl, LOG_ERR, + "failed to serialize membership of sid " + "\"%s\"\n", member); return PAM_AUTH_ERR; } } - ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, &request, &response, user); + ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, + &request, &response, user); if (pwd_last_set) { *pwd_last_set = response.data.auth.info3.pass_last_set_time; @@ -1128,20 +1271,34 @@ static int winbind_auth_request(pam_handle_t * pamh, } if (ret) { - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PASSWORD_EXPIRED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PASSWORD_MUST_CHANGE"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_INVALID_WORKSTATION"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_INVALID_LOGON_HOURS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_EXPIRED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_DISABLED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCOUNT_LOCKED_OUT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_WRONG_PASSWORD"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_PASSWORD_EXPIRED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_PASSWORD_MUST_CHANGE"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_INVALID_WORKSTATION"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_INVALID_LOGON_HOURS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_ACCOUNT_EXPIRED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_ACCOUNT_DISABLED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_ACCOUNT_LOCKED_OUT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_WRONG_PASSWORD"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_ACCESS_DENIED"); } if (ret == PAM_SUCCESS) { @@ -1152,11 +1309,15 @@ static int winbind_auth_request(pam_handle_t * pamh, &already_expired); if (already_expired == true) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "Password has expired " - "(Password was last set: %lld, the policy says " - "it should expire here %lld (now it's: %lu))\n", - response.data.auth.info3.pass_last_set_time, - response.data.auth.info3.pass_last_set_time + + SMB_TIME_T last_set; + last_set = response.data.auth.info3.pass_last_set_time; + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "Password has expired " + "(Password was last set: %lld, " + "the policy says it should expire here " + "%lld (now it's: %lu))\n", + (long long int)last_set, + (long long int)last_set + response.data.auth.policy.expire, time(NULL)); @@ -1164,10 +1325,12 @@ static int winbind_auth_request(pam_handle_t * pamh, } /* inform about logon type */ - _pam_warn_logon_type(pamh, ctrl, user, response.data.auth.info3.user_flgs); + _pam_warn_logon_type(pamh, ctrl, user, + response.data.auth.info3.user_flgs); /* inform about krb5 failures */ - _pam_warn_krb5_failure(pamh, ctrl, user, response.data.auth.info3.user_flgs); + _pam_warn_krb5_failure(pamh, ctrl, user, + response.data.auth.info3.user_flgs); /* set some info3 info for other modules in the stack */ _pam_set_data_info3(pamh, ctrl, &response); @@ -1175,7 +1338,8 @@ static int winbind_auth_request(pam_handle_t * pamh, /* put krb5ccname into env */ _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname); - /* If winbindd returned a username, return the pointer to it here. */ + /* If winbindd returned a username, return the pointer to it + * here. */ if (user_ret && response.extra_data.data) { /* We have to trust it's a null terminated string. */ *user_ret = (char *)response.extra_data.data; @@ -1188,10 +1352,10 @@ static int winbind_auth_request(pam_handle_t * pamh, /* talk to winbindd */ static int winbind_chauthtok_request(pam_handle_t * pamh, int ctrl, - const char *user, + const char *user, const char *oldpass, const char *newpass, - time_t pwd_last_set) + time_t pwd_last_set) { struct winbindd_request request; struct winbindd_response response; @@ -1200,82 +1364,105 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, ZERO_STRUCT(request); ZERO_STRUCT(response); - if (request.data.chauthtok.user == NULL) return -2; + if (request.data.chauthtok.user == NULL) { + return -2; + } - strncpy(request.data.chauthtok.user, user, + strncpy(request.data.chauthtok.user, user, sizeof(request.data.chauthtok.user) - 1); if (oldpass != NULL) { - strncpy(request.data.chauthtok.oldpass, oldpass, + strncpy(request.data.chauthtok.oldpass, oldpass, sizeof(request.data.chauthtok.oldpass) - 1); } else { request.data.chauthtok.oldpass[0] = '\0'; } - + if (newpass != NULL) { - strncpy(request.data.chauthtok.newpass, newpass, + strncpy(request.data.chauthtok.newpass, newpass, sizeof(request.data.chauthtok.newpass) - 1); } else { request.data.chauthtok.newpass[0] = '\0'; } if (ctrl & WINBIND_KRB5_AUTH) { - request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; + request.flags = WBFLAG_PAM_KRB5 | + WBFLAG_PAM_CONTACT_TRUSTDOM; } - ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_CHAUTHTOK, &request, &response, user); + ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_CHAUTHTOK, + &request, &response, user); if (ret == PAM_SUCCESS) { return ret; } - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_BACKUP_CONTROLLER"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_BACKUP_CONTROLLER"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_ACCESS_DENIED"); /* TODO: tell the min pwd length ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_TOO_SHORT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_PWD_TOO_SHORT"); /* TODO: tell the minage ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_TOO_RECENT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_PWD_TOO_RECENT"); /* TODO: tell the history length ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, "NT_STATUS_PWD_HISTORY_CONFLICT"); + PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + "NT_STATUS_PWD_HISTORY_CONFLICT"); - if (!strcasecmp(response.data.auth.nt_status_string, "NT_STATUS_PASSWORD_RESTRICTION")) { + if (!strcasecmp(response.data.auth.nt_status_string, + "NT_STATUS_PASSWORD_RESTRICTION")) { char *pwd_restriction_string = NULL; + SMB_TIME_T min_pwd_age; + uint32_t reject_reason = response.data.auth.reject_reason; + min_pwd_age = response.data.auth.policy.min_passwordage; /* FIXME: avoid to send multiple PAM messages after another */ - switch (response.data.auth.reject_reason) { + switch (reject_reason) { case -1: break; case REJECT_REASON_OTHER: - if ((response.data.auth.policy.min_passwordage > 0) && - (pwd_last_set + response.data.auth.policy.min_passwordage > time(NULL))) { - PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_RECENT"); + if ((min_pwd_age > 0) && + (pwd_last_set + min_pwd_age > time(NULL))) { + PAM_WB_REMARK_DIRECT(pamh, ctrl, + "NT_STATUS_PWD_TOO_RECENT"); } break; case REJECT_REASON_TOO_SHORT: - PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_SHORT"); + PAM_WB_REMARK_DIRECT(pamh, ctrl, + "NT_STATUS_PWD_TOO_SHORT"); break; case REJECT_REASON_IN_HISTORY: - PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_HISTORY_CONFLICT"); + PAM_WB_REMARK_DIRECT(pamh, ctrl, + "NT_STATUS_PWD_HISTORY_CONFLICT"); break; case REJECT_REASON_NOT_COMPLEX: - _make_remark(pamh, ctrl, PAM_ERROR_MSG, "Password does not meet complexity requirements"); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + "Password does not meet " + "complexity requirements"); break; default: _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "unknown password change reject reason: %d", - response.data.auth.reject_reason); + "unknown password change " + "reject reason: %d", + reject_reason); break; } - pwd_restriction_string = _pam_compose_pwd_restriction_string(&response); + pwd_restriction_string = + _pam_compose_pwd_restriction_string(&response); if (pwd_restriction_string) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, pwd_restriction_string); + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + pwd_restriction_string); SAFE_FREE(pwd_restriction_string); } } @@ -1291,7 +1478,9 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, * 0 = OK * -1 = System error */ -static int valid_user(pam_handle_t *pamh, int ctrl, const char *user) +static int valid_user(pam_handle_t *pamh, + int ctrl, + const char *user) { /* check not only if the user is available over NSS calls, also make * sure it's really a winbind user, this is important when stacking PAM @@ -1313,7 +1502,8 @@ static int valid_user(pam_handle_t *pamh, int ctrl, const char *user) strncpy(request.data.username, user, sizeof(request.data.username) - 1); - ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_GETPWNAM, &request, &response, user); + ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_GETPWNAM, + &request, &response, user); switch (ret) { case PAM_USER_UNKNOWN: @@ -1361,28 +1551,33 @@ static int _winbind_read_password(pam_handle_t * pamh, * which authentication token are we getting? */ - authtok_flag = on(WINBIND__OLD_PASSWORD, ctrl) ? PAM_OLDAUTHTOK : PAM_AUTHTOK; + if (on(WINBIND__OLD_PASSWORD, ctrl)) { + authtok_flag = PAM_OLDAUTHTOK; + } else { + authtok_flag = PAM_AUTHTOK; + } /* * should we obtain the password from a PAM item ? */ - if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { + if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || + on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { retval = _pam_get_item(pamh, authtok_flag, &item); if (retval != PAM_SUCCESS) { /* very strange. */ - _pam_log(pamh, ctrl, LOG_ALERT, - "pam_get_item returned error to unix-read-password" - ); + _pam_log(pamh, ctrl, LOG_ALERT, + "pam_get_item returned error " + "to unix-read-password"); return retval; } else if (item != NULL) { /* we have a password! */ *pass = item; item = NULL; - _pam_log(pamh, ctrl, LOG_DEBUG, + _pam_log(pamh, ctrl, LOG_DEBUG, "pam_get_item returned a password"); return PAM_SUCCESS; } else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { - return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ + return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ } else if (on(WINBIND_USE_AUTHTOK_ARG, ctrl) && off(WINBIND__OLD_PASSWORD, ctrl)) { return PAM_AUTHTOK_RECOVER_ERR; @@ -1423,60 +1618,64 @@ static int _winbind_read_password(pam_handle_t * pamh, /* so call the conversation expecting i responses */ resp = NULL; retval = converse(pamh, i, pmsg, &resp); - - if (resp != NULL) { - - /* interpret the response */ - - if (retval == PAM_SUCCESS) { /* a good conversation */ - - token = x_strdup(resp[i - replies].resp); - if (token != NULL) { - if (replies == 2) { - /* verify that password entered correctly */ - if (!resp[i - 1].resp - || strcmp(token, resp[i - 1].resp)) { - _pam_delete(token); /* mistyped */ - retval = PAM_AUTHTOK_RECOVER_ERR; - _make_remark(pamh, ctrl, PAM_ERROR_MSG, MISTYPED_PASS); - } - } - } else { - _pam_log(pamh, ctrl, LOG_NOTICE, "could not recover authentication token"); - retval = PAM_AUTHTOK_RECOVER_ERR; - } - + if (resp == NULL) { + if (retval == PAM_SUCCESS) { + retval = PAM_AUTHTOK_RECOVER_ERR; } - /* - * tidy up the conversation (resp_retcode) is ignored - * -- what is it for anyway? AGM - */ - + goto done; + } + if (retval != PAM_SUCCESS) { _pam_drop_reply(resp, i); + goto done; + } - } else { - retval = (retval == PAM_SUCCESS) - ? PAM_AUTHTOK_RECOVER_ERR : retval; + /* interpret the response */ + + token = x_strdup(resp[i - replies].resp); + if (!token) { + _pam_log(pamh, ctrl, LOG_NOTICE, + "could not recover " + "authentication token"); + retval = PAM_AUTHTOK_RECOVER_ERR; + goto done; + } + + if (replies == 2) { + /* verify that password entered correctly */ + if (!resp[i - 1].resp || + strcmp(token, resp[i - 1].resp)) { + _pam_delete(token); /* mistyped */ + retval = PAM_AUTHTOK_RECOVER_ERR; + _make_remark(pamh, ctrl, PAM_ERROR_MSG, + MISTYPED_PASS); + } } + + /* + * tidy up the conversation (resp_retcode) is ignored + * -- what is it for anyway? AGM + */ + _pam_drop_reply(resp, i); } + done: if (retval != PAM_SUCCESS) { _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "unable to obtain a password"); + "unable to obtain a password"); return retval; } /* 'token' is the entered password */ /* we store this password as an item */ - + retval = pam_set_item(pamh, authtok_flag, token); _pam_delete(token); /* clean it up */ - if (retval != PAM_SUCCESS || + if (retval != PAM_SUCCESS || (retval = _pam_get_item(pamh, authtok_flag, &item)) != PAM_SUCCESS) { - + _pam_log(pamh, ctrl, LOG_CRIT, "error manipulating password"); return retval; - + } *pass = item; @@ -1486,11 +1685,11 @@ static int _winbind_read_password(pam_handle_t * pamh, } const char *get_conf_item_string(const pam_handle_t *pamh, - int argc, - const char **argv, + int argc, + const char **argv, int ctrl, dictionary *d, - const char *item, + const char *item, int config_flag) { int i = 0; @@ -1501,16 +1700,19 @@ const char *get_conf_item_string(const pam_handle_t *pamh, } /* let the pam opt take precedence over the pam_winbind.conf option */ - for ( i=0; ipw_name ); + if ((id!=0) && ((pw = getpwuid(id)) != NULL)) { + real_username = strdup(pw->pw_name); } } #endif - if ( !real_username ) { + if (!real_username) { /* Just making a copy of the username we got from PAM */ - if ( (real_username = strdup( username )) == NULL ) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, - "memory allocation failure when copying username"); + if ((real_username = strdup(username)) == NULL) { + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "memory allocation failure when copying " + "username"); retval = PAM_SERVICE_ERR; goto out; } - } + } /* Maybe this was a UPN */ if (strchr(real_username, '@') != NULL) { char *samaccountname = NULL; - - samaccountname = winbind_upn_to_username(pamh, ctrl, + + samaccountname = winbind_upn_to_username(pamh, ctrl, real_username); if (samaccountname) { free(real_username); @@ -1767,12 +1991,13 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, } } - retval = _winbind_read_password(pamh, ctrl, NULL, + retval = _winbind_read_password(pamh, ctrl, NULL, "Password: ", NULL, &password); if (retval != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_ERR, "Could not retrieve user's password"); + _pam_log(pamh, ctrl, LOG_ERR, + "Could not retrieve user's password"); retval = PAM_AUTHTOK_ERR; goto out; } @@ -1780,10 +2005,12 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* Let's not give too much away in the log file */ #ifdef DEBUG_PASSWORD - _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s' with password '%s'", + _pam_log_debug(pamh, ctrl, LOG_INFO, + "Verify user '%s' with password '%s'", real_username, password); #else - _pam_log_debug(pamh, ctrl, LOG_INFO, "Verify user '%s'", real_username); + _pam_log_debug(pamh, ctrl, LOG_INFO, + "Verify user '%s'", real_username); #endif member = get_member_from_config(pamh, argc, argv, ctrl, d); @@ -1794,9 +2021,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, ctrl, d); /* Now use the username to look up password */ - retval = winbind_auth_request(pamh, ctrl, real_username, password, member, - cctype, warn_pwd_expire, NULL, NULL, - &username_ret); + retval = winbind_auth_request(pamh, ctrl, real_username, password, + member, cctype, warn_pwd_expire, NULL, + NULL, &username_ret); if (retval == PAM_NEW_AUTHTOK_REQD || retval == PAM_AUTHTOK_EXPIRED) { @@ -1808,7 +2035,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, goto out; } - pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, new_authtok_required, _pam_winbind_cleanup_func); + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, + new_authtok_required, + _pam_winbind_cleanup_func); retval = PAM_SUCCESS; @@ -1817,8 +2046,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, goto out; } - pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, - new_authtok_required_during_auth, _pam_winbind_cleanup_func); + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + new_authtok_required_during_auth, + _pam_winbind_cleanup_func); goto out; } @@ -1826,14 +2056,15 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, out: if (username_ret) { pam_set_item (pamh, PAM_USER, username_ret); - _pam_log_debug(pamh, ctrl, LOG_INFO, "Returned user was '%s'", username_ret); + _pam_log_debug(pamh, ctrl, LOG_INFO, + "Returned user was '%s'", username_ret); free(username_ret); } - if ( real_username ) { - free( real_username ); - } - + if (real_username) { + free(real_username); + } + if (d) { iniparser_freedict(d); } @@ -1873,15 +2104,18 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, ret = pam_sm_close_session(pamh, flags, argc, argv); break; case PAM_REFRESH_CRED: - _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REFRESH_CRED not implemented"); + _pam_log_debug(pamh, ctrl, LOG_WARNING, + "PAM_REFRESH_CRED not implemented"); ret = PAM_SUCCESS; break; case PAM_REINITIALIZE_CRED: - _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_REINITIALIZE_CRED not implemented"); + _pam_log_debug(pamh, ctrl, LOG_WARNING, + "PAM_REINITIALIZE_CRED not implemented"); ret = PAM_SUCCESS; break; case PAM_ESTABLISH_CRED: - _pam_log_debug(pamh, ctrl, LOG_WARNING, "PAM_ESTABLISH_CRED not implemented"); + _pam_log_debug(pamh, ctrl, LOG_WARNING, + "PAM_ESTABLISH_CRED not implemented"); ret = PAM_SUCCESS; break; default: @@ -1895,12 +2129,12 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, } _PAM_LOG_FUNCTION_LEAVE("pam_sm_setcred", pamh, ctrl, ret); - + return ret; } /* - * Account management. We want to verify that the account exists + * Account management. We want to verify that the account exists * before returning PAM_SUCCESS */ PAM_EXTERN @@ -1924,7 +2158,8 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, /* Get the username */ ret = pam_get_user(pamh, &username, NULL); if ((ret != PAM_SUCCESS) || (!username)) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG,"can not get the username"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "can not get the username"); ret = PAM_SERVICE_ERR; goto out; } @@ -1938,7 +2173,8 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, goto out; case 1: /* the user does not exist */ - _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", username); + _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", + username); if (ctrl & WINBIND_UNKNOWN_OK_ARG) { ret = PAM_IGNORE; goto out; @@ -1946,34 +2182,42 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, ret = PAM_USER_UNKNOWN; goto out; case 0: - pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp); + pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, + (const void **)&tmp); if (tmp != NULL) { ret = atoi((const char *)tmp); switch (ret) { case PAM_AUTHTOK_EXPIRED: /* fall through, since new token is required in this case */ case PAM_NEW_AUTHTOK_REQD: - _pam_log(pamh, ctrl, LOG_WARNING, "pam_sm_acct_mgmt success but %s is set", + _pam_log(pamh, ctrl, LOG_WARNING, + "pam_sm_acct_mgmt success but %s is set", PAM_WINBIND_NEW_AUTHTOK_REQD); - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' needs new password", username); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' needs new password", + username); /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */ ret = PAM_NEW_AUTHTOK_REQD; goto out; default: - _pam_log(pamh, ctrl, LOG_WARNING, "pam_sm_acct_mgmt success"); - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username); + _pam_log(pamh, ctrl, LOG_WARNING, + "pam_sm_acct_mgmt success"); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' granted access", username); ret = PAM_SUCCESS; goto out; } } /* Otherwise, the authentication looked good */ - _pam_log(pamh, ctrl, LOG_NOTICE, "user '%s' granted access", username); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user '%s' granted access", username); ret = PAM_SUCCESS; goto out; default: /* we don't know anything about this return value */ - _pam_log(pamh, ctrl, LOG_ERR, "internal module error (ret = %d, user = '%s')", + _pam_log(pamh, ctrl, LOG_ERR, + "internal module error (ret = %d, user = '%s')", ret, username); ret = PAM_SERVICE_ERR; goto out; @@ -1989,7 +2233,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, } _PAM_LOG_FUNCTION_LEAVE("pam_sm_acct_mgmt", pamh, ctrl, ret); - + return ret; } @@ -2017,7 +2261,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, } _PAM_LOG_FUNCTION_LEAVE("pam_sm_open_session", pamh, ctrl, ret); - + return ret; } @@ -2056,21 +2300,25 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, retval = pam_get_user(pamh, &user, "Username: "); if (retval) { - _pam_log(pamh, ctrl, LOG_ERR, "could not identify user"); + _pam_log(pamh, ctrl, LOG_ERR, + "could not identify user"); goto out; } if (user == NULL) { - _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); + _pam_log(pamh, ctrl, LOG_ERR, + "username was NULL!"); retval = PAM_USER_UNKNOWN; goto out; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "username [%s] obtained", user); ccname = pam_getenv(pamh, "KRB5CCNAME"); if (ccname == NULL) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment"); + _pam_log_debug(pamh, ctrl, LOG_DEBUG, + "user has no KRB5CCNAME environment"); } strncpy(request.data.logoff.user, user, @@ -2088,9 +2336,12 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, } request.data.logoff.uid = pwd->pw_uid; - request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; + request.flags = WBFLAG_PAM_KRB5 | + WBFLAG_PAM_CONTACT_TRUSTDOM; - retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_LOGOFF, &request, &response, user); + retval = pam_winbind_request_log(pamh, ctrl, + WINBINDD_PAM_LOGOFF, + &request, &response, user); } out: @@ -2099,13 +2350,14 @@ out: } _PAM_LOG_FUNCTION_LEAVE("pam_sm_close_session", pamh, ctrl, retval); - + return retval; } /** - * evaluate whether we need to re-authenticate with kerberos after a password change - * + * evaluate whether we need to re-authenticate with kerberos after a + * password change + * * @param pamh PAM handle * @param ctrl PAM winbind options. * @param user The username @@ -2113,14 +2365,16 @@ out: * @return boolean Returns true if required, false if not. */ -static bool _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, const char *user) +static bool _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, + int ctrl, + const char *user) { - /* Make sure that we only do this if - * a) the chauthtok got initiated during a logon attempt (authenticate->acct_mgmt->chauthtok) - * b) any later password change via the "passwd" command if done by the user itself - */ - + /* Make sure that we only do this if a) the chauthtok got initiated + * during a logon attempt (authenticate->acct_mgmt->chauthtok) b) any + * later password change via the "passwd" command if done by the user + * itself */ + char *new_authtok_reqd_during_auth = NULL; struct passwd *pwd = NULL; @@ -2128,8 +2382,10 @@ static bool _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, return false; } - _pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, &new_authtok_reqd_during_auth); - pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, NULL, NULL); + _pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + &new_authtok_reqd_during_auth); + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + NULL, NULL); if (new_authtok_reqd_during_auth) { return true; @@ -2148,7 +2404,7 @@ static bool _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, } -PAM_EXTERN +PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, int argc, const char **argv) { @@ -2162,7 +2418,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, /* */ char *Announce; - + int retry = 0; dictionary *d = NULL; char *username_ret = NULL; @@ -2211,7 +2467,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, default: break; } - + /* * obtain and verify the current password (OLDAUTHTOK) for * the user. @@ -2219,19 +2475,20 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (flags & PAM_PRELIM_CHECK) { time_t pwdlastset_prelim = 0; - + /* instruct user what is happening */ #define greeting "Changing password for " Announce = (char *) malloc(sizeof(greeting) + strlen(user)); if (Announce == NULL) { - _pam_log(pamh, ctrl, LOG_CRIT, "password - out of memory"); + _pam_log(pamh, ctrl, LOG_CRIT, + "password - out of memory"); ret = PAM_BUF_ERR; goto out; } (void) strcpy(Announce, greeting); (void) strcpy(Announce + sizeof(greeting) - 1, user); #undef greeting - + lctrl = ctrl | WINBIND__OLD_PASSWORD; ret = _winbind_read_password(pamh, lctrl, Announce, @@ -2239,52 +2496,57 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, NULL, (const char **) &pass_old); if (ret != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_NOTICE, "password - (old) token not obtained"); + _pam_log(pamh, ctrl, LOG_NOTICE, + "password - (old) token not obtained"); goto out; } /* verify that this is the password for this user */ - + ret = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, 0, &response, &pwdlastset_prelim, NULL); - if (ret != PAM_ACCT_EXPIRED && + if (ret != PAM_ACCT_EXPIRED && ret != PAM_AUTHTOK_EXPIRED && ret != PAM_NEW_AUTHTOK_REQD && ret != PAM_SUCCESS) { pass_old = NULL; goto out; } - - pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, (void *)pwdlastset_prelim, NULL); - ret = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); + pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, + (void *)pwdlastset_prelim, NULL); + + ret = pam_set_item(pamh, PAM_OLDAUTHTOK, + (const void *) pass_old); pass_old = NULL; if (ret != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_CRIT, "failed to set PAM_OLDAUTHTOK"); + _pam_log(pamh, ctrl, LOG_CRIT, + "failed to set PAM_OLDAUTHTOK"); } } else if (flags & PAM_UPDATE_AUTHTOK) { - + time_t pwdlastset_update = 0; - + /* * obtain the proposed password */ - + /* - * get the old token back. + * get the old token back. */ - + ret = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old); - + if (ret != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_NOTICE, "user not authenticated"); + _pam_log(pamh, ctrl, LOG_NOTICE, + "user not authenticated"); goto out; } - + lctrl = ctrl & ~WINBIND_TRY_FIRST_PASS_ARG; - + if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { lctrl |= WINBIND_USE_FIRST_PASS_ARG; } @@ -2295,16 +2557,17 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * use_authtok is to force the use of a previously entered * password -- needed for pluggable password strength checking */ - + ret = _winbind_read_password(pamh, lctrl, - NULL, - "Enter new NT password: ", - "Retype new NT password: ", - (const char **) &pass_new); - + NULL, + "Enter new NT password: ", + "Retype new NT password: ", + (const char **)&pass_new); + if (ret != PAM_SUCCESS) { - _pam_log_debug(pamh, ctrl, LOG_ALERT - ,"password - new password not obtained"); + _pam_log_debug(pamh, ctrl, LOG_ALERT, + "password - " + "new password not obtained"); pass_old = NULL;/* tidy up */ goto out; } @@ -2314,20 +2577,21 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * propose as their new password. Verify that the new * password is acceptable. */ - + if (pass_new[0] == '\0') {/* "\0" password = NULL */ pass_new = NULL; } } - + /* * By reaching here we have approved the passwords and must now * rebuild the password database file. */ - _pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, - &pwdlastset_update); + _pam_get_data(pamh, PAM_WINBIND_PWD_LAST_SET, + &pwdlastset_update); - ret = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update); + ret = winbind_chauthtok_request(pamh, ctrl, user, pass_old, + pass_new, pwdlastset_update); if (ret) { _pam_overwrite(pass_new); _pam_overwrite(pass_old); @@ -2337,11 +2601,20 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (_pam_require_krb5_auth_after_chauthtok(pamh, ctrl, user)) { - const char *member = get_member_from_config(pamh, argc, argv, ctrl, d); - const char *cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); - const int warn_pwd_expire = - get_warn_pwd_expire_from_config(pamh, argc, argv, ctrl, - d); + const char *member = NULL; + const char *cctype = NULL; + int warn_pwd_expire; + + member = get_member_from_config(pamh, argc, argv, + ctrl, d); + cctype = get_krb5_cc_type_from_config(pamh, argc, argv, + ctrl, d); + warn_pwd_expire = get_warn_pwd_expire_from_config(pamh, + argc, + argv, + ctrl, + d); + ret = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, 0, &response, @@ -2351,20 +2624,27 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, pass_old = pass_new = NULL; if (ret == PAM_SUCCESS) { - - /* warn a user if the password is about to expire soon */ + + /* warn a user if the password is about to + * expire soon */ _pam_warn_password_expiry(pamh, ctrl, &response, - warn_pwd_expire , NULL); + warn_pwd_expire, + NULL); - /* set some info3 info for other modules in the stack */ + /* set some info3 info for other modules in the + * stack */ _pam_set_data_info3(pamh, ctrl, &response); /* put krb5ccname into env */ - _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname); + _pam_setup_krb5_env(pamh, ctrl, + response.data.auth.krb5ccname); if (username_ret) { - pam_set_item (pamh, PAM_USER, username_ret); - _pam_log_debug(pamh, ctrl, LOG_INFO, "Returned user was '%s'", username_ret); + pam_set_item(pamh, PAM_USER, + username_ret); + _pam_log_debug(pamh, ctrl, LOG_INFO, + "Returned user was '%s'", + username_ret); free(username_ret); } } @@ -2381,12 +2661,15 @@ out: } /* Deal with offline errors. */ - PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, "NT_STATUS_ACCESS_DENIED"); + PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, + "NT_STATUS_NO_LOGON_SERVERS"); + PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); + PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, + "NT_STATUS_ACCESS_DENIED"); _PAM_LOG_FUNCTION_LEAVE("pam_sm_chauthtok", pamh, ctrl, ret); - + return ret; } @@ -2415,7 +2698,7 @@ struct pam_module _pam_winbind_modstruct = { * Copyright (c) Andrew G. Morgan 1996-8. * Copyright (c) Alex O. Yuriev, 1996. * Copyright (c) Cristian Gafton 1996. - * Copyright (C) Elliot Lee 1996, Red Hat Software. + * Copyright (C) Elliot Lee 1996, Red Hat Software. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions -- cgit From 6765a8acfdd520006fc59847d137675c7f82592a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sat, 29 Sep 2007 08:25:44 +0000 Subject: r25426: Fix another implicit cast warning. Michael (This used to be commit 4a053d5bf9db82b5ae9ac342f68e90ef89ba292f) --- source3/nsswitch/pam_winbind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index fde5b03611..f00db39b45 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -70,7 +70,7 @@ static void _pam_log_int(const pam_handle_t *pamh, _pam_get_item(pamh, PAM_SERVICE, &service); - format2 = malloc(strlen(MODULE_NAME)+strlen(format)+strlen(service)+5); + format2 = (char *)malloc(strlen(MODULE_NAME)+strlen(format)+strlen(service)+5); if (format2 == NULL) { /* what else todo ? */ vsyslog(err, format, args); -- cgit From e3bb148b941e67b5caea3db2c8ef9efc984598fa Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 19 Dec 2007 17:53:14 +0100 Subject: Only retrieve password policies in pam_auth when WBFLAG_PAM_GET_PWD_POLICY is set. This essentially re-establishes r14496 (2155bb0535656f294bd054d6a0a7d16a9a71c31b) which was undone in r17723 (43bd8c00abb38eb23a1497a255d194fb1bbffffb) for reasons that are unclear to me. Maybe I am being too naive. Now we do again only retrieve the password policy when called from the pam_winbind module. This fixes logons delegated to AD trusted domain controllers: We need to connect to the sam to retrieve the password policy. But auhtenticated session setup is not possible when contacting the trusted domain dc and afterwards, SamrConnect also fails with whatever credentials and method used. Michael (This used to be commit 6d765e0de523211a2d0b43a2c4c4117f5f0c662f) --- source3/nsswitch/pam_winbind.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index f00db39b45..4d019072ac 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1201,6 +1201,7 @@ static int winbind_auth_request(pam_handle_t * pamh, request.data.auth.uid = -1; request.flags = WBFLAG_PAM_INFO3_TEXT | + WBFLAG_PAM_GET_PWD_POLICY | WBFLAG_PAM_CONTACT_TRUSTDOM; if (ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) { -- cgit From a92eb76688600efbf4a4056c2543f348e2fee8aa Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 17 Jan 2008 10:24:34 +0100 Subject: Finally enable pidl generated SAMR & NETLOGON headers and clients. Guenther (This used to be commit f7100156a7df7ac3ae84e45a47153b38d9375215) --- source3/nsswitch/pam_winbind.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 4d019072ac..89db0773ae 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1431,22 +1431,22 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, switch (reject_reason) { case -1: break; - case REJECT_REASON_OTHER: + case SAMR_REJECT_OTHER: if ((min_pwd_age > 0) && (pwd_last_set + min_pwd_age > time(NULL))) { PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_RECENT"); } break; - case REJECT_REASON_TOO_SHORT: + case SAMR_REJECT_TOO_SHORT: PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_TOO_SHORT"); break; - case REJECT_REASON_IN_HISTORY: + case SAMR_REJECT_IN_HISTORY: PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PWD_HISTORY_CONFLICT"); break; - case REJECT_REASON_NOT_COMPLEX: + case SAMR_REJECT_COMPLEXITY: _make_remark(pamh, ctrl, PAM_ERROR_MSG, "Password does not meet " "complexity requirements"); -- cgit From 76de025c724d68bef1b81c8ec6081db5e0f19c4a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 28 Feb 2008 13:29:47 +0100 Subject: winbind: use a struct element for WBFLAG_PAM_UNIX_NAME To not conflict with WBFLAG_PAM_INFO3_TEXT. This should fix pam_winbind. metze (This used to be commit 1b8ed6c0ffb2548442bb7e9d848117ce9b1c65c0) --- source3/nsswitch/pam_winbind.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 89db0773ae..81f5227410 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1341,9 +1341,10 @@ static int winbind_auth_request(pam_handle_t * pamh, /* If winbindd returned a username, return the pointer to it * here. */ - if (user_ret && response.extra_data.data) { + if (user_ret && response.data.auth.unix_username[0]) { /* We have to trust it's a null terminated string. */ - *user_ret = (char *)response.extra_data.data; + *user_ret = strndup(response.data.auth.unix_username, + sizeof(response.data.auth.unix_username) - 1); } } -- cgit From 0a4f742f0ac7846b4f104f1749095162883038cd Mon Sep 17 00:00:00 2001 From: "Gerald W. Carter" Date: Thu, 27 Mar 2008 11:57:26 -0500 Subject: Only add WBFLAG_PAM_CONTACT_TRUSTDOM when performing a krb5 auth request. NTLM logons must go against our DC. (This used to be commit 2e24f7c0243c67a00102c11258cfa6f61caf499f) --- source3/nsswitch/pam_winbind.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 81f5227410..d2aea66bcc 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1200,9 +1200,13 @@ static int winbind_auth_request(pam_handle_t * pamh, request.data.auth.krb5_cc_type[0] = '\0'; request.data.auth.uid = -1; - request.flags = WBFLAG_PAM_INFO3_TEXT | - WBFLAG_PAM_GET_PWD_POLICY | - WBFLAG_PAM_CONTACT_TRUSTDOM; + request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_GET_PWD_POLICY; + + /* Krb5 auth always has to go against the KDC of the user's realm */ + + if (ctrl & WINBIND_KRB5_AUTH) { + request.flags |= WBFLAG_PAM_CONTACT_TRUSTDOM; + } if (ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) { struct passwd *pwd = NULL; -- cgit From b592abf1ac7bfef2b56ee71a1e68128c8f73aed6 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 3 Apr 2008 13:06:14 +0200 Subject: Make more functions in pam_winbind static. Guenther (This used to be commit ea2175ee0e6288ccb132e86b9dd0bf8a0e4169c9) --- source3/nsswitch/pam_winbind.c | 60 +++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index d2aea66bcc..688462c5e5 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -407,7 +407,7 @@ static const struct ntstatus_errors { {NULL, NULL} }; -const char *_get_ntstatus_error_string(const char *nt_status_string) +static const char *_get_ntstatus_error_string(const char *nt_status_string) { int i; for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) { @@ -1690,13 +1690,13 @@ static int _winbind_read_password(pam_handle_t * pamh, return PAM_SUCCESS; } -const char *get_conf_item_string(const pam_handle_t *pamh, - int argc, - const char **argv, - int ctrl, - dictionary *d, - const char *item, - int config_flag) +static const char *get_conf_item_string(const pam_handle_t *pamh, + int argc, + const char **argv, + int ctrl, + dictionary *d, + const char *item, + int config_flag) { int i = 0; const char *parm_opt = NULL; @@ -1740,13 +1740,13 @@ out: return parm_opt; } -int get_config_item_int(const pam_handle_t *pamh, - int argc, - const char **argv, - int ctrl, - dictionary *d, - const char *item, - int config_flag) +static int get_config_item_int(const pam_handle_t *pamh, + int argc, + const char **argv, + int ctrl, + dictionary *d, + const char *item, + int config_flag) { int i, parm_opt = -1; @@ -1792,22 +1792,22 @@ out: return parm_opt; } -const char *get_krb5_cc_type_from_config(const pam_handle_t *pamh, - int argc, - const char **argv, - int ctrl, - dictionary *d) +static const char *get_krb5_cc_type_from_config(const pam_handle_t *pamh, + int argc, + const char **argv, + int ctrl, + dictionary *d) { return get_conf_item_string(pamh, argc, argv, ctrl, d, "krb5_ccache_type", WINBIND_KRB5_CCACHE_TYPE); } -const char *get_member_from_config(const pam_handle_t *pamh, - int argc, - const char **argv, - int ctrl, - dictionary *d) +static const char *get_member_from_config(const pam_handle_t *pamh, + int argc, + const char **argv, + int ctrl, + dictionary *d) { const char *ret = NULL; ret = get_conf_item_string(pamh, argc, argv, ctrl, d, @@ -1821,11 +1821,11 @@ const char *get_member_from_config(const pam_handle_t *pamh, WINBIND_REQUIRED_MEMBERSHIP); } -int get_warn_pwd_expire_from_config(const pam_handle_t *pamh, - int argc, - const char **argv, - int ctrl, - dictionary *d) +static int get_warn_pwd_expire_from_config(const pam_handle_t *pamh, + int argc, + const char **argv, + int ctrl, + dictionary *d) { int ret; ret = get_config_item_int(pamh, argc, argv, ctrl, d, -- cgit From a654ed60898da746b44ecff6eb60fbc962fb88b7 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 3 Apr 2008 13:23:34 +0200 Subject: Add _pam_winbind_init/free_context. Guenther (This used to be commit d62676cf886d910334b3d6f7ce0147b75ef53aec) --- source3/nsswitch/pam_winbind.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 688462c5e5..7c3c2b1666 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -346,6 +346,45 @@ config_from_pam: return ctrl; }; +static void _pam_winbind_free_context(struct pwb_context *ctx) +{ + if (ctx->dict) { + iniparser_freedict(ctx->dict); + } + + SAFE_FREE(ctx); +} + +static int _pam_winbind_init_context(const pam_handle_t *pamh, + int flags, + int argc, + const char **argv, + struct pwb_context **ctx_p) +{ + struct pwb_context *r = NULL; + + r = (struct pwb_context *)malloc(sizeof(struct pwb_context)); + if (!r) { + return PAM_BUF_ERR; + } + + ZERO_STRUCTP(r); + + r->pamh = pamh; + r->flags = flags; + r->argc = argc; + r->argv = argv; + r->ctrl = _pam_parse(pamh, flags, argc, argv, &r->dict); + if (r->ctrl == -1) { + _pam_winbind_free_context(r); + return PAM_SYSTEM_ERR; + } + + *ctx_p = r; + + return PAM_SUCCESS; +} + static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_status) -- cgit From 3020cd44ad6ac6be2ddddde1334aefec2e6741a4 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 3 Apr 2008 15:41:26 +0200 Subject: Use pwb_context in pam_winbind. Guenther (This used to be commit bf960f57e7adf09cdf096f2c72065ea1ff8b0daa) --- source3/nsswitch/pam_winbind.c | 734 +++++++++++++++++++---------------------- 1 file changed, 343 insertions(+), 391 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 7c3c2b1666..9a9bce7ad8 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -12,18 +12,18 @@ #include "pam_winbind.h" -#define _PAM_LOG_FUNCTION_ENTER(function, pamh, ctrl, flags) \ +#define _PAM_LOG_FUNCTION_ENTER(function, ctx) \ do { \ - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] ENTER: " \ - function " (flags: 0x%04x)", pamh, flags); \ - _pam_log_state(pamh, ctrl); \ + _pam_log_debug(ctx, LOG_DEBUG, "[pamh: %p] ENTER: " \ + function " (flags: 0x%04x)", ctx->pamh, ctx->flags); \ + _pam_log_state(ctx); \ } while (0) -#define _PAM_LOG_FUNCTION_LEAVE(function, pamh, ctrl, retval) \ +#define _PAM_LOG_FUNCTION_LEAVE(function, ctx, retval) \ do { \ - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] LEAVE: " \ - function " returning %d", pamh, retval); \ - _pam_log_state(pamh, ctrl); \ + _pam_log_debug(ctx, LOG_DEBUG, "[pamh: %p] LEAVE: " \ + function " returning %d", ctx->pamh, retval); \ + _pam_log_state(ctx); \ } while (0) /* data tokens */ @@ -88,8 +88,21 @@ static bool _pam_log_is_silent(int ctrl) return on(ctrl, WINBIND_SILENT); } -static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5); -static void _pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) +static void _pam_log(struct pwb_context *r, int err, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +static void _pam_log(struct pwb_context *r, int err, const char *format, ...) +{ + va_list args; + + if (_pam_log_is_silent(r->ctrl)) { + return; + } + + va_start(args, format); + _pam_log_int(r->pamh, err, format, args); + va_end(args); +} +static void __pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5); +static void __pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) { va_list args; @@ -128,8 +141,21 @@ static bool _pam_log_is_debug_state_enabled(int ctrl) return _pam_log_is_debug_enabled(ctrl); } -static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5); -static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) +static void _pam_log_debug(struct pwb_context *r, int err, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +static void _pam_log_debug(struct pwb_context *r, int err, const char *format, ...) +{ + va_list args; + + if (!_pam_log_is_debug_enabled(r->ctrl)) { + return; + } + + va_start(args, format); + _pam_log_int(r->pamh, err, format, args); + va_end(args); +} +static void __pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5); +static void __pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) { va_list args; @@ -142,44 +168,43 @@ static void _pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const ch va_end(args); } -static void _pam_log_state_datum(const pam_handle_t *pamh, - int ctrl, +static void _pam_log_state_datum(struct pwb_context *ctx, int item_type, const char *key, int is_string) { const void *data = NULL; if (item_type != 0) { - pam_get_item(pamh, item_type, &data); + pam_get_item(ctx->pamh, item_type, &data); } else { - pam_get_data(pamh, key, &data); + pam_get_data(ctx->pamh, key, &data); } if (data != NULL) { const char *type = (item_type != 0) ? "ITEM" : "DATA"; if (is_string != 0) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "[pamh: %p] STATE: %s(%s) = \"%s\" (%p)", - pamh, type, key, (const char *)data, + ctx->pamh, type, key, (const char *)data, data); } else { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "[pamh: %p] STATE: %s(%s) = %p", - pamh, type, key, data); + ctx->pamh, type, key, data); } } } -#define _PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, module_data_name) \ - _pam_log_state_datum(pamh, ctrl, 0, module_data_name, 0) +#define _PAM_LOG_STATE_DATA_POINTER(ctx, module_data_name) \ + _pam_log_state_datum(ctx, 0, module_data_name, 0) -#define _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, module_data_name) \ - _pam_log_state_datum(pamh, ctrl, 0, module_data_name, 1) +#define _PAM_LOG_STATE_DATA_STRING(ctx, module_data_name) \ + _pam_log_state_datum(ctx, 0, module_data_name, 1) -#define _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, item_type) \ - _pam_log_state_datum(pamh, ctrl, item_type, #item_type, 0) +#define _PAM_LOG_STATE_ITEM_POINTER(ctx, item_type) \ + _pam_log_state_datum(ctx, item_type, #item_type, 0) -#define _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, item_type) \ - _pam_log_state_datum(pamh, ctrl, item_type, #item_type, 1) +#define _PAM_LOG_STATE_ITEM_STRING(ctx, item_type) \ + _pam_log_state_datum(ctx, item_type, #item_type, 1) #ifdef DEBUG_PASSWORD #define _LOG_PASSWORD_AS_STRING 1 @@ -187,42 +212,42 @@ static void _pam_log_state_datum(const pam_handle_t *pamh, #define _LOG_PASSWORD_AS_STRING 0 #endif -#define _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, item_type) \ - _pam_log_state_datum(pamh, ctrl, item_type, #item_type, \ +#define _PAM_LOG_STATE_ITEM_PASSWORD(ctx, item_type) \ + _pam_log_state_datum(ctx, item_type, #item_type, \ _LOG_PASSWORD_AS_STRING) -static void _pam_log_state(const pam_handle_t *pamh, int ctrl) +static void _pam_log_state(struct pwb_context *ctx) { - if (!_pam_log_is_debug_state_enabled(ctrl)) { + if (!_pam_log_is_debug_state_enabled(ctx->ctrl)) { return; } - _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_SERVICE); - _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_USER); - _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_TTY); - _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_RHOST); - _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_RUSER); - _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, PAM_OLDAUTHTOK); - _PAM_LOG_STATE_ITEM_PASSWORD(pamh, ctrl, PAM_AUTHTOK); - _PAM_LOG_STATE_ITEM_STRING(pamh, ctrl, PAM_USER_PROMPT); - _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_CONV); + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_SERVICE); + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_USER); + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_TTY); + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_RHOST); + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_RUSER); + _PAM_LOG_STATE_ITEM_PASSWORD(ctx, PAM_OLDAUTHTOK); + _PAM_LOG_STATE_ITEM_PASSWORD(ctx, PAM_AUTHTOK); + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_USER_PROMPT); + _PAM_LOG_STATE_ITEM_POINTER(ctx, PAM_CONV); #ifdef PAM_FAIL_DELAY - _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_FAIL_DELAY); + _PAM_LOG_STATE_ITEM_POINTER(ctx, PAM_FAIL_DELAY); #endif #ifdef PAM_REPOSITORY - _PAM_LOG_STATE_ITEM_POINTER(pamh, ctrl, PAM_REPOSITORY); + _PAM_LOG_STATE_ITEM_POINTER(ctx, PAM_REPOSITORY); #endif - _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_HOMEDIR); - _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT); - _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSERVER); - _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_PROFILEPATH); - _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, + _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_HOMEDIR); + _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_LOGONSCRIPT); + _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_LOGONSERVER); + _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_PROFILEPATH); + _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_NEW_AUTHTOK_REQD); /* Use atoi to get PAM result code */ - _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, + _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH); - _PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, PAM_WINBIND_PWD_LAST_SET); + _PAM_LOG_STATE_DATA_POINTER(ctx, PAM_WINBIND_PWD_LAST_SET); } static int _pam_parse(const pam_handle_t *pamh, @@ -328,7 +353,7 @@ config_from_pam: else if (!strcasecmp(*v, "cached_login")) ctrl |= WINBIND_CACHED_LOGIN; else { - _pam_log(pamh, ctrl, LOG_ERR, + __pam_log(pamh, ctrl, LOG_ERR, "pam_parse: unknown option: %s", *v); return -1; } @@ -355,7 +380,7 @@ static void _pam_winbind_free_context(struct pwb_context *ctx) SAFE_FREE(ctx); } -static int _pam_winbind_init_context(const pam_handle_t *pamh, +static int _pam_winbind_init_context(pam_handle_t *pamh, int flags, int argc, const char **argv, @@ -391,7 +416,7 @@ static void _pam_winbind_cleanup_func(pam_handle_t *pamh, { int ctrl = _pam_parse(pamh, 0, 0, NULL, NULL); if (_pam_log_is_debug_state_enabled(ctrl)) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + __pam_log_debug(pamh, ctrl, LOG_DEBUG, "[pamh: %p] CLEAN: cleaning up PAM data %p " "(error_status = %d)", pamh, data, error_status); @@ -462,7 +487,7 @@ static const char *_get_ntstatus_error_string(const char *nt_status_string) /* Attempt a conversation */ -static int converse(pam_handle_t *pamh, +static int converse(const pam_handle_t *pamh, int nargs, struct pam_message **message, struct pam_response **response) @@ -481,8 +506,7 @@ static int converse(pam_handle_t *pamh, } -static int _make_remark(pam_handle_t * pamh, - int flags, +static int _make_remark(struct pwb_context *ctx, int type, const char *text) { @@ -491,7 +515,7 @@ static int _make_remark(pam_handle_t * pamh, struct pam_message *pmsg[1], msg[1]; struct pam_response *resp; - if (flags & WINBIND_SILENT) { + if (ctx->flags & WINBIND_SILENT) { return PAM_SUCCESS; } @@ -500,7 +524,7 @@ static int _make_remark(pam_handle_t * pamh, msg[0].msg_style = type; resp = NULL; - retval = converse(pamh, 1, pmsg, &resp); + retval = converse(ctx->pamh, 1, pmsg, &resp); if (resp) { _pam_drop_reply(resp, 1); @@ -508,8 +532,7 @@ static int _make_remark(pam_handle_t * pamh, return retval; } -static int _make_remark_v(pam_handle_t *pamh, - int flags, +static int _make_remark_v(struct pwb_context *ctx, int type, const char *format, va_list args) @@ -519,29 +542,28 @@ static int _make_remark_v(pam_handle_t *pamh, ret = vasprintf(&var, format, args); if (ret < 0) { - _pam_log(pamh, 0, LOG_ERR, "memory allocation failure"); + _pam_log(ctx, LOG_ERR, "memory allocation failure"); return ret; } - ret = _make_remark(pamh, flags, type, var); + ret = _make_remark(ctx, type, var); SAFE_FREE(var); return ret; } -static int _make_remark_format(pam_handle_t * pamh, int flags, int type, const char *format, ...) PRINTF_ATTRIBUTE(4,5); -static int _make_remark_format(pam_handle_t * pamh, int flags, int type, const char *format, ...) +static int _make_remark_format(struct pwb_context *ctx, int type, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +static int _make_remark_format(struct pwb_context *ctx, int type, const char *format, ...) { int ret; va_list args; va_start(args, format); - ret = _make_remark_v(pamh, flags, type, format, args); + ret = _make_remark_v(ctx, type, format, args); va_end(args); return ret; } -static int pam_winbind_request(pam_handle_t *pamh, - int ctrl, +static int pam_winbind_request(struct pwb_context *ctx, enum winbindd_cmd req_type, struct winbindd_request *request, struct winbindd_response *response) @@ -550,7 +572,7 @@ static int pam_winbind_request(pam_handle_t *pamh, winbindd_init_request(request, req_type); if (winbind_write_sock(request, sizeof(*request), 0, 0) == -1) { - _pam_log(pamh, ctrl, LOG_ERR, + _pam_log(ctx, LOG_ERR, "pam_winbind_request: write to socket failed!"); winbind_close_sock(); return PAM_SERVICE_ERR; @@ -558,7 +580,7 @@ static int pam_winbind_request(pam_handle_t *pamh, /* Wait for reply */ if (winbindd_read_reply(response) == -1) { - _pam_log(pamh, ctrl, LOG_ERR, + _pam_log(ctx, LOG_ERR, "pam_winbind_request: read from socket failed!"); winbind_close_sock(); return PAM_SERVICE_ERR; @@ -578,11 +600,11 @@ static int pam_winbind_request(pam_handle_t *pamh, case WINBINDD_GETPWNAM: case WINBINDD_LOOKUPNAME: if (strlen(response->data.auth.nt_status_string) > 0) { - _pam_log(pamh, ctrl, LOG_ERR, + _pam_log(ctx, LOG_ERR, "request failed, NT error was %s", response->data.auth.nt_status_string); } else { - _pam_log(pamh, ctrl, LOG_ERR, "request failed"); + _pam_log(ctx, LOG_ERR, "request failed"); } return PAM_USER_UNKNOWN; default: @@ -590,23 +612,22 @@ static int pam_winbind_request(pam_handle_t *pamh, } if (response->data.auth.pam_error != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_ERR, + _pam_log(ctx, LOG_ERR, "request failed: %s, " "PAM error was %s (%d), NT error was %s", response->data.auth.error_string, - pam_strerror(pamh, response->data.auth.pam_error), + pam_strerror(ctx->pamh, response->data.auth.pam_error), response->data.auth.pam_error, response->data.auth.nt_status_string); return response->data.auth.pam_error; } - _pam_log(pamh, ctrl, LOG_ERR, "request failed, but PAM error 0!"); + _pam_log(ctx, LOG_ERR, "request failed, but PAM error 0!"); return PAM_SERVICE_ERR; } -static int pam_winbind_request_log(pam_handle_t *pamh, - int ctrl, +static int pam_winbind_request_log(struct pwb_context *ctx, enum winbindd_cmd req_type, struct winbindd_request *request, struct winbindd_response *response, @@ -614,34 +635,34 @@ static int pam_winbind_request_log(pam_handle_t *pamh, { int retval; - retval = pam_winbind_request(pamh, ctrl, req_type, request, response); + retval = pam_winbind_request(ctx, req_type, request, response); switch (retval) { case PAM_AUTH_ERR: /* incorrect password */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' denied access " + _pam_log(ctx, LOG_WARNING, "user '%s' denied access " "(incorrect password or invalid membership)", user); return retval; case PAM_ACCT_EXPIRED: /* account expired */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' account expired", + _pam_log(ctx, LOG_WARNING, "user '%s' account expired", user); return retval; case PAM_AUTHTOK_EXPIRED: /* password expired */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' password expired", + _pam_log(ctx, LOG_WARNING, "user '%s' password expired", user); return retval; case PAM_NEW_AUTHTOK_REQD: /* new password required */ - _pam_log(pamh, ctrl, LOG_WARNING, "user '%s' new password " + _pam_log(ctx, LOG_WARNING, "user '%s' new password " "required", user); return retval; case PAM_USER_UNKNOWN: /* the user does not exist */ - _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", + _pam_log_debug(ctx, LOG_NOTICE, "user '%s' not found", user); - if (ctrl & WINBIND_UNKNOWN_OK_ARG) { + if (ctx->ctrl & WINBIND_UNKNOWN_OK_ARG) { return PAM_IGNORE; } return retval; @@ -651,15 +672,15 @@ static int pam_winbind_request_log(pam_handle_t *pamh, case WINBINDD_INFO: break; case WINBINDD_PAM_AUTH: - _pam_log(pamh, ctrl, LOG_NOTICE, + _pam_log(ctx, LOG_NOTICE, "user '%s' granted access", user); break; case WINBINDD_PAM_CHAUTHTOK: - _pam_log(pamh, ctrl, LOG_NOTICE, + _pam_log(ctx, LOG_NOTICE, "user '%s' password changed", user); break; default: - _pam_log(pamh, ctrl, LOG_NOTICE, + _pam_log(ctx, LOG_NOTICE, "user '%s' OK", user); break; } @@ -667,7 +688,7 @@ static int pam_winbind_request_log(pam_handle_t *pamh, return retval; default: /* we don't know anything about this return value */ - _pam_log(pamh, ctrl, LOG_ERR, + _pam_log(ctx, LOG_ERR, "internal module error (retval = %d, user = '%s')", retval, user); return retval; @@ -686,8 +707,7 @@ static int pam_winbind_request_log(pam_handle_t *pamh, * @return boolean Returns true if message has been sent, false if not. */ -static bool _pam_send_password_expiry_message(pam_handle_t *pamh, - int ctrl, +static bool _pam_send_password_expiry_message(struct pwb_context *ctx, time_t next_change, time_t now, int warn_pwd_expire, @@ -701,7 +721,7 @@ static bool _pam_send_password_expiry_message(pam_handle_t *pamh, } if (next_change <= now) { - PAM_WB_REMARK_DIRECT(pamh, ctrl, "NT_STATUS_PASSWORD_EXPIRED"); + PAM_WB_REMARK_DIRECT(ctx, "NT_STATUS_PASSWORD_EXPIRED"); if (already_expired) { *already_expired = true; } @@ -722,13 +742,13 @@ static bool _pam_send_password_expiry_message(pam_handle_t *pamh, (tm_now.tm_yday+tm_now.tm_year*365); if (days == 0) { - _make_remark(pamh, ctrl, PAM_TEXT_INFO, + _make_remark(ctx, PAM_TEXT_INFO, "Your password expires today"); return true; } if (days > 0 && days < warn_pwd_expire) { - _make_remark_format(pamh, ctrl, PAM_TEXT_INFO, + _make_remark_format(ctx, PAM_TEXT_INFO, "Your password will expire in %d %s", days, (days > 1) ? "days":"day"); return true; @@ -748,8 +768,7 @@ static bool _pam_send_password_expiry_message(pam_handle_t *pamh, * @return void. */ -static void _pam_warn_password_expiry(pam_handle_t *pamh, - int flags, +static void _pam_warn_password_expiry(struct pwb_context *ctx, const struct winbindd_response *response, int warn_pwd_expire, bool *already_expired) @@ -774,7 +793,7 @@ static void _pam_warn_password_expiry(pam_handle_t *pamh, /* check if the info3 must change timestamp has been set */ next_change = response->data.auth.info3.pass_must_change_time; - if (_pam_send_password_expiry_message(pamh, flags, next_change, now, + if (_pam_send_password_expiry_message(ctx, next_change, now, warn_pwd_expire, already_expired)) { return; @@ -790,7 +809,7 @@ static void _pam_warn_password_expiry(pam_handle_t *pamh, next_change = response->data.auth.info3.pass_last_set_time + response->data.auth.policy.expire; - if (_pam_send_password_expiry_message(pamh, flags, next_change, now, + if (_pam_send_password_expiry_message(ctx, next_change, now, warn_pwd_expire, already_expired)) { return; @@ -840,8 +859,7 @@ static bool safe_append_string(char *dest, * * @return false on failure, true on success. */ -static bool winbind_name_to_sid_string(pam_handle_t *pamh, - int ctrl, +static bool winbind_name_to_sid_string(struct pwb_context *ctx, const char *user, const char *name, char *sid_list_buffer, @@ -859,17 +877,17 @@ static bool winbind_name_to_sid_string(pam_handle_t *pamh, ZERO_STRUCT(sid_request); ZERO_STRUCT(sid_response); - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "no sid given, looking up: %s\n", name); /* fortunatly winbindd can handle non-separated names */ strncpy(sid_request.data.name.name, name, sizeof(sid_request.data.name.name) - 1); - if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, + if (pam_winbind_request_log(ctx, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) { - _pam_log(pamh, ctrl, LOG_INFO, + _pam_log(ctx, LOG_INFO, "could not lookup name: %s\n", name); return false; } @@ -897,8 +915,7 @@ static bool winbind_name_to_sid_string(pam_handle_t *pamh, * * @return false on failure, true on success. */ -static bool winbind_name_list_to_sid_string_list(pam_handle_t *pamh, - int ctrl, +static bool winbind_name_list_to_sid_string_list(struct pwb_context *ctx, const char *user, const char *name_list, char *sid_list_buffer, @@ -921,7 +938,7 @@ static bool winbind_name_list_to_sid_string_list(pam_handle_t *pamh, goto out; } - if (!winbind_name_to_sid_string(pamh, ctrl, user, + if (!winbind_name_to_sid_string(ctx, user, current_name, sid_list_buffer, sid_list_buffer_size)) { @@ -938,7 +955,7 @@ static bool winbind_name_list_to_sid_string_list(pam_handle_t *pamh, search_location = comma + 1; } - if (!winbind_name_to_sid_string(pamh, ctrl, user, search_location, + if (!winbind_name_to_sid_string(ctx, user, search_location, sid_list_buffer, sid_list_buffer_size)) { goto out; @@ -961,14 +978,13 @@ out: * @return void. */ -static void _pam_setup_krb5_env(pam_handle_t *pamh, - int ctrl, +static void _pam_setup_krb5_env(struct pwb_context *ctx, const char *krb5ccname) { char var[PATH_MAX]; int ret; - if (off(ctrl, WINBIND_KRB5_AUTH)) { + if (off(ctx->ctrl, WINBIND_KRB5_AUTH)) { return; } @@ -976,18 +992,18 @@ static void _pam_setup_krb5_env(pam_handle_t *pamh, return; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "request returned KRB5CCNAME: %s", krb5ccname); if (snprintf(var, sizeof(var), "KRB5CCNAME=%s", krb5ccname) == -1) { return; } - ret = pam_putenv(pamh, var); + ret = pam_putenv(ctx->pamh, var); if (ret) { - _pam_log(pamh, ctrl, LOG_ERR, + _pam_log(ctx, LOG_ERR, "failed to set KRB5CCNAME to %s: %s", - var, pam_strerror(pamh, ret)); + var, pam_strerror(ctx->pamh, ret)); } } @@ -1002,8 +1018,7 @@ static void _pam_setup_krb5_env(pam_handle_t *pamh, * @return void. */ -static void _pam_set_data_string(pam_handle_t *pamh, - int ctrl, +static void _pam_set_data_string(struct pwb_context *ctx, const char *data_name, const char *value) { @@ -1014,12 +1029,12 @@ static void _pam_set_data_string(pam_handle_t *pamh, return; } - ret = pam_set_data(pamh, data_name, (void *)strdup(value), + ret = pam_set_data(ctx->pamh, data_name, (void *)strdup(value), _pam_winbind_cleanup_func); if (ret) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "Could not set data %s: %s\n", - data_name, pam_strerror(pamh, ret)); + data_name, pam_strerror(ctx->pamh, ret)); } } @@ -1035,17 +1050,16 @@ static void _pam_set_data_string(pam_handle_t *pamh, * @return void. */ -static void _pam_set_data_info3(pam_handle_t *pamh, - int ctrl, +static void _pam_set_data_info3(struct pwb_context *ctx, struct winbindd_response *response) { - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_HOMEDIR, + _pam_set_data_string(ctx, PAM_WINBIND_HOMEDIR, response->data.auth.info3.home_dir); - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSCRIPT, + _pam_set_data_string(ctx, PAM_WINBIND_LOGONSCRIPT, response->data.auth.info3.logon_script); - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_LOGONSERVER, + _pam_set_data_string(ctx, PAM_WINBIND_LOGONSERVER, response->data.auth.info3.logon_srv); - _pam_set_data_string(pamh, ctrl, PAM_WINBIND_PROFILEPATH, + _pam_set_data_string(ctx, PAM_WINBIND_PROFILEPATH, response->data.auth.info3.profile_path); } @@ -1076,29 +1090,28 @@ static void _pam_free_data_info3(pam_handle_t *pamh) * @return void. */ -static void _pam_warn_logon_type(pam_handle_t *pamh, - int ctrl, +static void _pam_warn_logon_type(struct pwb_context *ctx, const char *username, uint32_t info3_user_flgs) { /* inform about logon type */ if (PAM_WB_GRACE_LOGON(info3_user_flgs)) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, + _make_remark(ctx, PAM_ERROR_MSG, "Grace login. " "Please change your password as soon you're " "online again"); - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "User %s logged on using grace logon\n", username); } else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, + _make_remark(ctx, PAM_ERROR_MSG, "Domain Controller unreachable, " "using cached credentials instead. " "Network resources may be unavailable"); - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "User %s logged on using cached credentials\n", username); } @@ -1115,18 +1128,17 @@ static void _pam_warn_logon_type(pam_handle_t *pamh, * @return void. */ -static void _pam_warn_krb5_failure(pam_handle_t *pamh, - int ctrl, +static void _pam_warn_krb5_failure(struct pwb_context *ctx, const char *username, uint32_t info3_user_flgs) { if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, + _make_remark(ctx, PAM_ERROR_MSG, "Failed to establish your Kerberos Ticket cache " "due time differences\n" "with the domain controller. " "Please verify the system time.\n"); - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "User %s: Clock skew when getting Krb5 TGT\n", username); } @@ -1207,8 +1219,7 @@ static char *_pam_compose_pwd_restriction_string(struct winbindd_response *respo } /* talk to winbindd */ -static int winbind_auth_request(pam_handle_t * pamh, - int ctrl, +static int winbind_auth_request(struct pwb_context *ctx, const char *user, const char *pass, const char *member, @@ -1243,11 +1254,11 @@ static int winbind_auth_request(pam_handle_t * pamh, /* Krb5 auth always has to go against the KDC of the user's realm */ - if (ctrl & WINBIND_KRB5_AUTH) { + if (ctx->ctrl & WINBIND_KRB5_AUTH) { request.flags |= WBFLAG_PAM_CONTACT_TRUSTDOM; } - if (ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) { + if (ctx->ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) { struct passwd *pwd = NULL; pwd = getpwnam(user); @@ -1257,17 +1268,17 @@ static int winbind_auth_request(pam_handle_t * pamh, request.data.auth.uid = pwd->pw_uid; } - if (ctrl & WINBIND_KRB5_AUTH) { + if (ctx->ctrl & WINBIND_KRB5_AUTH) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "enabling krb5 login flag\n"); request.flags |= WBFLAG_PAM_KRB5 | WBFLAG_PAM_FALLBACK_AFTER_KRB5; } - if (ctrl & WINBIND_CACHED_LOGIN) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + if (ctx->ctrl & WINBIND_CACHED_LOGIN) { + _pam_log_debug(ctx, LOG_DEBUG, "enabling cached login flag\n"); request.flags |= WBFLAG_PAM_CACHED_LOGIN; } @@ -1280,7 +1291,7 @@ static int winbind_auth_request(pam_handle_t * pamh, if (cctype != NULL) { strncpy(request.data.auth.krb5_cc_type, cctype, sizeof(request.data.auth.krb5_cc_type) - 1); - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "enabling request for a %s krb5 ccache\n", cctype); } @@ -1289,19 +1300,19 @@ static int winbind_auth_request(pam_handle_t * pamh, if (member != NULL) { - if (!winbind_name_list_to_sid_string_list(pamh, ctrl, user, + if (!winbind_name_list_to_sid_string_list(ctx, user, member, request.data.auth.require_membership_of_sid, sizeof(request.data.auth.require_membership_of_sid))) { - _pam_log_debug(pamh, ctrl, LOG_ERR, + _pam_log_debug(ctx, LOG_ERR, "failed to serialize membership of sid " "\"%s\"\n", member); return PAM_AUTH_ERR; } } - ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, + ret = pam_winbind_request_log(ctx, WINBINDD_PAM_AUTH, &request, &response, user); if (pwd_last_set) { @@ -1315,47 +1326,47 @@ static int winbind_auth_request(pam_handle_t * pamh, } if (ret) { - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_PASSWORD_EXPIRED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_PASSWORD_MUST_CHANGE"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_INVALID_WORKSTATION"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_INVALID_LOGON_HOURS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_ACCOUNT_EXPIRED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_ACCOUNT_DISABLED"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_ACCOUNT_LOCKED_OUT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_WRONG_PASSWORD"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_ACCESS_DENIED"); } if (ret == PAM_SUCCESS) { /* warn a user if the password is about to expire soon */ - _pam_warn_password_expiry(pamh, ctrl, &response, + _pam_warn_password_expiry(ctx, &response, warn_pwd_expire, &already_expired); if (already_expired == true) { SMB_TIME_T last_set; last_set = response.data.auth.info3.pass_last_set_time; - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "Password has expired " "(Password was last set: %lld, " "the policy says it should expire here " @@ -1369,18 +1380,18 @@ static int winbind_auth_request(pam_handle_t * pamh, } /* inform about logon type */ - _pam_warn_logon_type(pamh, ctrl, user, + _pam_warn_logon_type(ctx, user, response.data.auth.info3.user_flgs); /* inform about krb5 failures */ - _pam_warn_krb5_failure(pamh, ctrl, user, + _pam_warn_krb5_failure(ctx, user, response.data.auth.info3.user_flgs); /* set some info3 info for other modules in the stack */ - _pam_set_data_info3(pamh, ctrl, &response); + _pam_set_data_info3(ctx, &response); /* put krb5ccname into env */ - _pam_setup_krb5_env(pamh, ctrl, response.data.auth.krb5ccname); + _pam_setup_krb5_env(ctx, response.data.auth.krb5ccname); /* If winbindd returned a username, return the pointer to it * here. */ @@ -1395,8 +1406,7 @@ static int winbind_auth_request(pam_handle_t * pamh, } /* talk to winbindd */ -static int winbind_chauthtok_request(pam_handle_t * pamh, - int ctrl, +static int winbind_chauthtok_request(struct pwb_context *ctx, const char *user, const char *oldpass, const char *newpass, @@ -1430,37 +1440,37 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, request.data.chauthtok.newpass[0] = '\0'; } - if (ctrl & WINBIND_KRB5_AUTH) { + if (ctx->ctrl & WINBIND_KRB5_AUTH) { request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; } - ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_CHAUTHTOK, + ret = pam_winbind_request_log(ctx, WINBINDD_PAM_CHAUTHTOK, &request, &response, user); if (ret == PAM_SUCCESS) { return ret; } - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_BACKUP_CONTROLLER"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_ACCESS_DENIED"); /* TODO: tell the min pwd length ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_PWD_TOO_SHORT"); /* TODO: tell the minage ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_PWD_TOO_RECENT"); /* TODO: tell the history length ? */ - PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE_RET(ctx, response, "NT_STATUS_PWD_HISTORY_CONFLICT"); if (!strcasecmp(response.data.auth.nt_status_string, @@ -1478,25 +1488,25 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, case SAMR_REJECT_OTHER: if ((min_pwd_age > 0) && (pwd_last_set + min_pwd_age > time(NULL))) { - PAM_WB_REMARK_DIRECT(pamh, ctrl, + PAM_WB_REMARK_DIRECT(ctx, "NT_STATUS_PWD_TOO_RECENT"); } break; case SAMR_REJECT_TOO_SHORT: - PAM_WB_REMARK_DIRECT(pamh, ctrl, + PAM_WB_REMARK_DIRECT(ctx, "NT_STATUS_PWD_TOO_SHORT"); break; case SAMR_REJECT_IN_HISTORY: - PAM_WB_REMARK_DIRECT(pamh, ctrl, + PAM_WB_REMARK_DIRECT(ctx, "NT_STATUS_PWD_HISTORY_CONFLICT"); break; case SAMR_REJECT_COMPLEXITY: - _make_remark(pamh, ctrl, PAM_ERROR_MSG, + _make_remark(ctx, PAM_ERROR_MSG, "Password does not meet " "complexity requirements"); break; default: - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "unknown password change " "reject reason: %d", reject_reason); @@ -1506,7 +1516,7 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, pwd_restriction_string = _pam_compose_pwd_restriction_string(&response); if (pwd_restriction_string) { - _make_remark(pamh, ctrl, PAM_ERROR_MSG, + _make_remark(ctx, PAM_ERROR_MSG, pwd_restriction_string); SAFE_FREE(pwd_restriction_string); } @@ -1523,8 +1533,7 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, * 0 = OK * -1 = System error */ -static int valid_user(pam_handle_t *pamh, - int ctrl, +static int valid_user(struct pwb_context *ctx, const char *user) { /* check not only if the user is available over NSS calls, also make @@ -1547,7 +1556,7 @@ static int valid_user(pam_handle_t *pamh, strncpy(request.data.username, user, sizeof(request.data.username) - 1); - ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_GETPWNAM, + ret = pam_winbind_request_log(ctx, WINBINDD_GETPWNAM, &request, &response, user); switch (ret) { @@ -1572,7 +1581,7 @@ static char *_pam_delete(register char *xx) * obtain a password from the user */ -static int _winbind_read_password(pam_handle_t * pamh, +static int _winbind_read_password(struct pwb_context *ctx, unsigned int ctrl, const char *comment, const char *prompt1, @@ -1584,7 +1593,7 @@ static int _winbind_read_password(pam_handle_t * pamh, const char *item; char *token; - _pam_log(pamh, ctrl, LOG_DEBUG, "getting password (0x%08x)", ctrl); + _pam_log(ctx, LOG_DEBUG, "getting password (0x%08x)", ctrl); /* * make sure nothing inappropriate gets returned @@ -1608,17 +1617,17 @@ static int _winbind_read_password(pam_handle_t * pamh, if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { - retval = _pam_get_item(pamh, authtok_flag, &item); + retval = _pam_get_item(ctx->pamh, authtok_flag, &item); if (retval != PAM_SUCCESS) { /* very strange. */ - _pam_log(pamh, ctrl, LOG_ALERT, + _pam_log(ctx, LOG_ALERT, "pam_get_item returned error " "to unix-read-password"); return retval; } else if (item != NULL) { /* we have a password! */ *pass = item; item = NULL; - _pam_log(pamh, ctrl, LOG_DEBUG, + _pam_log(ctx, LOG_DEBUG, "pam_get_item returned a password"); return PAM_SUCCESS; } else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { @@ -1662,7 +1671,7 @@ static int _winbind_read_password(pam_handle_t * pamh, } /* so call the conversation expecting i responses */ resp = NULL; - retval = converse(pamh, i, pmsg, &resp); + retval = converse(ctx->pamh, i, pmsg, &resp); if (resp == NULL) { if (retval == PAM_SUCCESS) { retval = PAM_AUTHTOK_RECOVER_ERR; @@ -1678,7 +1687,7 @@ static int _winbind_read_password(pam_handle_t * pamh, token = x_strdup(resp[i - replies].resp); if (!token) { - _pam_log(pamh, ctrl, LOG_NOTICE, + _pam_log(ctx, LOG_NOTICE, "could not recover " "authentication token"); retval = PAM_AUTHTOK_RECOVER_ERR; @@ -1691,7 +1700,7 @@ static int _winbind_read_password(pam_handle_t * pamh, strcmp(token, resp[i - 1].resp)) { _pam_delete(token); /* mistyped */ retval = PAM_AUTHTOK_RECOVER_ERR; - _make_remark(pamh, ctrl, PAM_ERROR_MSG, + _make_remark(ctx, PAM_ERROR_MSG, MISTYPED_PASS); } } @@ -1705,7 +1714,7 @@ static int _winbind_read_password(pam_handle_t * pamh, done: if (retval != PAM_SUCCESS) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "unable to obtain a password"); return retval; } @@ -1713,12 +1722,12 @@ static int _winbind_read_password(pam_handle_t * pamh, /* we store this password as an item */ - retval = pam_set_item(pamh, authtok_flag, token); + retval = pam_set_item(ctx->pamh, authtok_flag, token); _pam_delete(token); /* clean it up */ if (retval != PAM_SUCCESS || - (retval = _pam_get_item(pamh, authtok_flag, &item)) != PAM_SUCCESS) { + (retval = _pam_get_item(ctx->pamh, authtok_flag, &item)) != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_CRIT, "error manipulating password"); + _pam_log(ctx, LOG_CRIT, "error manipulating password"); return retval; } @@ -1729,101 +1738,93 @@ static int _winbind_read_password(pam_handle_t * pamh, return PAM_SUCCESS; } -static const char *get_conf_item_string(const pam_handle_t *pamh, - int argc, - const char **argv, - int ctrl, - dictionary *d, +static const char *get_conf_item_string(struct pwb_context *ctx, const char *item, int config_flag) { int i = 0; const char *parm_opt = NULL; - if (!(ctrl & config_flag)) { + if (!(ctx->ctrl & config_flag)) { goto out; } /* let the pam opt take precedence over the pam_winbind.conf option */ - for (i=0; iargc; i++) { - if ((strncmp(argv[i], item, strlen(item)) == 0)) { + if ((strncmp(ctx->argv[i], item, strlen(item)) == 0)) { char *p; - if ((p = strchr(argv[i], '=')) == NULL) { - _pam_log(pamh, ctrl, LOG_INFO, + if ((p = strchr(ctx->argv[i], '=')) == NULL) { + _pam_log(ctx, LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item); goto out; } - _pam_log_debug(pamh, ctrl, LOG_INFO, + _pam_log_debug(ctx, LOG_INFO, "PAM config: %s '%s'\n", item, p+1); return p + 1; } } - if (d != NULL) { + if (ctx->dict) { char *key = NULL; if (!asprintf(&key, "global:%s", item)) { goto out; } - parm_opt = iniparser_getstr(d, key); + parm_opt = iniparser_getstr(ctx->dict, key); SAFE_FREE(key); - _pam_log_debug(pamh, ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", + _pam_log_debug(ctx, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt); } out: return parm_opt; } -static int get_config_item_int(const pam_handle_t *pamh, - int argc, - const char **argv, - int ctrl, - dictionary *d, +static int get_config_item_int(struct pwb_context *ctx, const char *item, int config_flag) { int i, parm_opt = -1; - if (!(ctrl & config_flag)) { + if (!(ctx->ctrl & config_flag)) { goto out; } /* let the pam opt take precedence over the pam_winbind.conf option */ - for (i = 0; i < argc; i++) { + for (i = 0; i < ctx->argc; i++) { - if ((strncmp(argv[i], item, strlen(item)) == 0)) { + if ((strncmp(ctx->argv[i], item, strlen(item)) == 0)) { char *p; - if ((p = strchr(argv[i], '=')) == NULL) { - _pam_log(pamh, ctrl, LOG_INFO, + if ((p = strchr(ctx->argv[i], '=')) == NULL) { + _pam_log(ctx, LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item); goto out; } parm_opt = atoi(p + 1); - _pam_log_debug(pamh, ctrl, LOG_INFO, + _pam_log_debug(ctx, LOG_INFO, "PAM config: %s '%d'\n", item, parm_opt); return parm_opt; } } - if (d != NULL) { + if (ctx->dict) { char *key = NULL; if (!asprintf(&key, "global:%s", item)) { goto out; } - parm_opt = iniparser_getint(d, key, -1); + parm_opt = iniparser_getint(ctx->dict, key, -1); SAFE_FREE(key); - _pam_log_debug(pamh, ctrl, LOG_INFO, + _pam_log_debug(ctx, LOG_INFO, "CONFIG file: %s '%d'\n", item, parm_opt); } @@ -1831,44 +1832,28 @@ out: return parm_opt; } -static const char *get_krb5_cc_type_from_config(const pam_handle_t *pamh, - int argc, - const char **argv, - int ctrl, - dictionary *d) +static const char *get_krb5_cc_type_from_config(struct pwb_context *ctx) { - return get_conf_item_string(pamh, argc, argv, ctrl, d, - "krb5_ccache_type", + return get_conf_item_string(ctx, "krb5_ccache_type", WINBIND_KRB5_CCACHE_TYPE); } -static const char *get_member_from_config(const pam_handle_t *pamh, - int argc, - const char **argv, - int ctrl, - dictionary *d) +static const char *get_member_from_config(struct pwb_context *ctx) { const char *ret = NULL; - ret = get_conf_item_string(pamh, argc, argv, ctrl, d, - "require_membership_of", + ret = get_conf_item_string(ctx, "require_membership_of", WINBIND_REQUIRED_MEMBERSHIP); if (ret) { return ret; } - return get_conf_item_string(pamh, argc, argv, ctrl, d, - "require-membership-of", + return get_conf_item_string(ctx, "require-membership-of", WINBIND_REQUIRED_MEMBERSHIP); } -static int get_warn_pwd_expire_from_config(const pam_handle_t *pamh, - int argc, - const char **argv, - int ctrl, - dictionary *d) +static int get_warn_pwd_expire_from_config(struct pwb_context *ctx) { int ret; - ret = get_config_item_int(pamh, argc, argv, ctrl, d, - "warn_pwd_expire", + ret = get_config_item_int(ctx, "warn_pwd_expire", WINBIND_WARN_PWD_EXPIRE); /* no or broken setting */ if (ret <= 0) { @@ -1886,8 +1871,7 @@ static int get_warn_pwd_expire_from_config(const pam_handle_t *pamh, * @return string separator character. NULL on failure. */ -static char winbind_get_separator(pam_handle_t *pamh, - int ctrl) +static char winbind_get_separator(struct pwb_context *ctx) { struct winbindd_request request; struct winbindd_response response; @@ -1895,7 +1879,7 @@ static char winbind_get_separator(pam_handle_t *pamh, ZERO_STRUCT(request); ZERO_STRUCT(response); - if (pam_winbind_request_log(pamh, ctrl, WINBINDD_INFO, + if (pam_winbind_request_log(ctx, WINBINDD_INFO, &request, &response, NULL)) { return '\0'; } @@ -1913,8 +1897,7 @@ static char winbind_get_separator(pam_handle_t *pamh, * @return converted name. NULL pointer on failure. Caller needs to free. */ -static char* winbind_upn_to_username(pam_handle_t *pamh, - int ctrl, +static char* winbind_upn_to_username(struct pwb_context *ctx, const char *upn) { struct winbindd_request req; @@ -1926,7 +1909,7 @@ static char* winbind_upn_to_username(pam_handle_t *pamh, /* This cannot work when the winbind separator = @ */ - sep = winbind_get_separator(pamh, ctrl); + sep = winbind_get_separator(ctx); if (!sep || sep == '@') { return NULL; } @@ -1940,7 +1923,7 @@ static char* winbind_upn_to_username(pam_handle_t *pamh, sizeof(req.data.name.dom_name) - 1); strncpy(req.data.name.name, upn, sizeof(req.data.name.name) - 1); - retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, + retval = pam_winbind_request_log(ctx, WINBINDD_LOOKUPNAME, &req, &resp, upn); if (retval != PAM_SUCCESS) { return NULL; @@ -1951,7 +1934,7 @@ static char* winbind_upn_to_username(pam_handle_t *pamh, ZERO_STRUCT(req); strncpy(req.data.sid, resp.data.sid.sid, sizeof(req.data.sid)-1); ZERO_STRUCT(resp); - retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPSID, + retval = pam_winbind_request_log(ctx, WINBINDD_LOOKUPSID, &req, &resp, upn); if (retval != PAM_SUCCESS) { return NULL; @@ -1974,24 +1957,22 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, const char *cctype = NULL; int warn_pwd_expire; int retval = PAM_AUTH_ERR; - dictionary *d = NULL; char *username_ret = NULL; char *new_authtok_required = NULL; char *real_username = NULL; + struct pwb_context *ctx = NULL; - /* parse arguments */ - int ctrl = _pam_parse(pamh, flags, argc, argv, &d); - if (ctrl == -1) { - retval = PAM_SYSTEM_ERR; + retval = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (retval) { goto out; } - _PAM_LOG_FUNCTION_ENTER("pam_sm_authenticate", pamh, ctrl, flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_authenticate", ctx); /* Get the username */ retval = pam_get_user(pamh, &username, NULL); if ((retval != PAM_SUCCESS) || (!username)) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "can not get the username"); retval = PAM_SERVICE_ERR; goto out; @@ -2015,7 +1996,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, if (!real_username) { /* Just making a copy of the username we got from PAM */ if ((real_username = strdup(username)) == NULL) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "memory allocation failure when copying " "username"); retval = PAM_SERVICE_ERR; @@ -2028,7 +2009,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, if (strchr(real_username, '@') != NULL) { char *samaccountname = NULL; - samaccountname = winbind_upn_to_username(pamh, ctrl, + samaccountname = winbind_upn_to_username(ctx, real_username); if (samaccountname) { free(real_username); @@ -2036,12 +2017,12 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, } } - retval = _winbind_read_password(pamh, ctrl, NULL, + retval = _winbind_read_password(ctx, ctx->ctrl, NULL, "Password: ", NULL, &password); if (retval != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_ERR, + _pam_log(ctx, LOG_ERR, "Could not retrieve user's password"); retval = PAM_AUTHTOK_ERR; goto out; @@ -2050,23 +2031,20 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* Let's not give too much away in the log file */ #ifdef DEBUG_PASSWORD - _pam_log_debug(pamh, ctrl, LOG_INFO, + _pam_log_debug(ctx, LOG_INFO, "Verify user '%s' with password '%s'", real_username, password); #else - _pam_log_debug(pamh, ctrl, LOG_INFO, + _pam_log_debug(ctx, LOG_INFO, "Verify user '%s'", real_username); #endif - member = get_member_from_config(pamh, argc, argv, ctrl, d); - - cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d); - - warn_pwd_expire = get_warn_pwd_expire_from_config(pamh, argc, argv, - ctrl, d); + member = get_member_from_config(ctx); + cctype = get_krb5_cc_type_from_config(ctx); + warn_pwd_expire = get_warn_pwd_expire_from_config(ctx); /* Now use the username to look up password */ - retval = winbind_auth_request(pamh, ctrl, real_username, password, + retval = winbind_auth_request(ctx, real_username, password, member, cctype, warn_pwd_expire, NULL, NULL, &username_ret); @@ -2101,7 +2079,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, out: if (username_ret) { pam_set_item (pamh, PAM_USER, username_ret); - _pam_log_debug(pamh, ctrl, LOG_INFO, + _pam_log_debug(ctx, LOG_INFO, "Returned user was '%s'", username_ret); free(username_ret); } @@ -2110,10 +2088,6 @@ out: free(real_username); } - if (d) { - iniparser_freedict(d); - } - if (!new_authtok_required) { pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, NULL, NULL); } @@ -2122,7 +2096,9 @@ out: _pam_free_data_info3(pamh); } - _PAM_LOG_FUNCTION_LEAVE("pam_sm_authenticate", pamh, ctrl, retval); + _PAM_LOG_FUNCTION_LEAVE("pam_sm_authenticate", ctx, retval); + + _pam_winbind_free_context(ctx); return retval; } @@ -2132,16 +2108,14 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { int ret = PAM_SYSTEM_ERR; - dictionary *d = NULL; + struct pwb_context *ctx = NULL; - /* parse arguments */ - int ctrl = _pam_parse(pamh, flags, argc, argv, &d); - if (ctrl == -1) { - ret = PAM_SYSTEM_ERR; + ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (ret) { goto out; } - _PAM_LOG_FUNCTION_ENTER("pam_sm_setcred", pamh, ctrl, flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_setcred", ctx); switch (flags & ~PAM_SILENT) { @@ -2149,17 +2123,17 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, ret = pam_sm_close_session(pamh, flags, argc, argv); break; case PAM_REFRESH_CRED: - _pam_log_debug(pamh, ctrl, LOG_WARNING, + _pam_log_debug(ctx, LOG_WARNING, "PAM_REFRESH_CRED not implemented"); ret = PAM_SUCCESS; break; case PAM_REINITIALIZE_CRED: - _pam_log_debug(pamh, ctrl, LOG_WARNING, + _pam_log_debug(ctx, LOG_WARNING, "PAM_REINITIALIZE_CRED not implemented"); ret = PAM_SUCCESS; break; case PAM_ESTABLISH_CRED: - _pam_log_debug(pamh, ctrl, LOG_WARNING, + _pam_log_debug(ctx, LOG_WARNING, "PAM_ESTABLISH_CRED not implemented"); ret = PAM_SUCCESS; break; @@ -2169,11 +2143,10 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, } out: - if (d) { - iniparser_freedict(d); - } - _PAM_LOG_FUNCTION_LEAVE("pam_sm_setcred", pamh, ctrl, ret); + _PAM_LOG_FUNCTION_LEAVE("pam_sm_setcred", ctx, ret); + + _pam_winbind_free_context(ctx); return ret; } @@ -2189,28 +2162,27 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, const char *username; int ret = PAM_USER_UNKNOWN; void *tmp = NULL; - dictionary *d = NULL; + struct pwb_context *ctx = NULL; - /* parse arguments */ - int ctrl = _pam_parse(pamh, flags, argc, argv, &d); - if (ctrl == -1) { - return PAM_SYSTEM_ERR; + ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (ret) { + goto out; } - _PAM_LOG_FUNCTION_ENTER("pam_sm_acct_mgmt", pamh, ctrl, flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_acct_mgmt", ctx); /* Get the username */ ret = pam_get_user(pamh, &username, NULL); if ((ret != PAM_SUCCESS) || (!username)) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "can not get the username"); ret = PAM_SERVICE_ERR; goto out; } /* Verify the username */ - ret = valid_user(pamh, ctrl, username); + ret = valid_user(ctx, username); switch (ret) { case -1: /* some sort of system error. The log was already printed */ @@ -2218,9 +2190,9 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, goto out; case 1: /* the user does not exist */ - _pam_log_debug(pamh, ctrl, LOG_NOTICE, "user '%s' not found", + _pam_log_debug(ctx, LOG_NOTICE, "user '%s' not found", username); - if (ctrl & WINBIND_UNKNOWN_OK_ARG) { + if (ctx->ctrl & WINBIND_UNKNOWN_OK_ARG) { ret = PAM_IGNORE; goto out; } @@ -2235,19 +2207,19 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, case PAM_AUTHTOK_EXPIRED: /* fall through, since new token is required in this case */ case PAM_NEW_AUTHTOK_REQD: - _pam_log(pamh, ctrl, LOG_WARNING, + _pam_log(ctx, LOG_WARNING, "pam_sm_acct_mgmt success but %s is set", PAM_WINBIND_NEW_AUTHTOK_REQD); - _pam_log(pamh, ctrl, LOG_NOTICE, + _pam_log(ctx, LOG_NOTICE, "user '%s' needs new password", username); /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */ ret = PAM_NEW_AUTHTOK_REQD; goto out; default: - _pam_log(pamh, ctrl, LOG_WARNING, + _pam_log(ctx, LOG_WARNING, "pam_sm_acct_mgmt success"); - _pam_log(pamh, ctrl, LOG_NOTICE, + _pam_log(ctx, LOG_NOTICE, "user '%s' granted access", username); ret = PAM_SUCCESS; goto out; @@ -2255,13 +2227,13 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, } /* Otherwise, the authentication looked good */ - _pam_log(pamh, ctrl, LOG_NOTICE, + _pam_log(ctx, LOG_NOTICE, "user '%s' granted access", username); ret = PAM_SUCCESS; goto out; default: /* we don't know anything about this return value */ - _pam_log(pamh, ctrl, LOG_ERR, + _pam_log(ctx, LOG_ERR, "internal module error (ret = %d, user = '%s')", ret, username); ret = PAM_SERVICE_ERR; @@ -2273,11 +2245,9 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, out: - if (d) { - iniparser_freedict(d); - } + _PAM_LOG_FUNCTION_LEAVE("pam_sm_acct_mgmt", ctx, ret); - _PAM_LOG_FUNCTION_LEAVE("pam_sm_acct_mgmt", pamh, ctrl, ret); + _pam_winbind_free_context(ctx); return ret; } @@ -2287,25 +2257,21 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { int ret = PAM_SYSTEM_ERR; - dictionary *d = NULL; + struct pwb_context *ctx = NULL; - /* parse arguments */ - int ctrl = _pam_parse(pamh, flags, argc, argv, &d); - if (ctrl == -1) { - ret = PAM_SYSTEM_ERR; + ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (ret) { goto out; } - _PAM_LOG_FUNCTION_ENTER("pam_sm_open_session", pamh, ctrl, flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_open_session", ctx); ret = PAM_SUCCESS; out: - if (d) { - iniparser_freedict(d); - } + _PAM_LOG_FUNCTION_LEAVE("pam_sm_open_session", ctx, ret); - _PAM_LOG_FUNCTION_LEAVE("pam_sm_open_session", pamh, ctrl, ret); + _pam_winbind_free_context(ctx); return ret; } @@ -2314,24 +2280,22 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { - dictionary *d = NULL; int retval = PAM_SUCCESS; + struct pwb_context *ctx = NULL; - /* parse arguments */ - int ctrl = _pam_parse(pamh, flags, argc, argv, &d); - if (ctrl == -1) { - retval = PAM_SYSTEM_ERR; + retval = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (retval) { goto out; } - _PAM_LOG_FUNCTION_ENTER("pam_sm_close_session", pamh, ctrl, flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_close_session", ctx); if (!(flags & PAM_DELETE_CRED)) { retval = PAM_SUCCESS; goto out; } - if (ctrl & WINBIND_KRB5_AUTH) { + if (ctx->ctrl & WINBIND_KRB5_AUTH) { /* destroy the ccache here */ struct winbindd_request request; @@ -2345,24 +2309,24 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, retval = pam_get_user(pamh, &user, "Username: "); if (retval) { - _pam_log(pamh, ctrl, LOG_ERR, + _pam_log(ctx, LOG_ERR, "could not identify user"); goto out; } if (user == NULL) { - _pam_log(pamh, ctrl, LOG_ERR, + _pam_log(ctx, LOG_ERR, "username was NULL!"); retval = PAM_USER_UNKNOWN; goto out; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "username [%s] obtained", user); ccname = pam_getenv(pamh, "KRB5CCNAME"); if (ccname == NULL) { - _pam_log_debug(pamh, ctrl, LOG_DEBUG, + _pam_log_debug(ctx, LOG_DEBUG, "user has no KRB5CCNAME environment"); } @@ -2384,17 +2348,16 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags, request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM; - retval = pam_winbind_request_log(pamh, ctrl, + retval = pam_winbind_request_log(ctx, WINBINDD_PAM_LOGOFF, &request, &response, user); } out: - if (d) { - iniparser_freedict(d); - } - _PAM_LOG_FUNCTION_LEAVE("pam_sm_close_session", pamh, ctrl, retval); + _PAM_LOG_FUNCTION_LEAVE("pam_sm_close_session", ctx, retval); + + _pam_winbind_free_context(ctx); return retval; } @@ -2410,8 +2373,7 @@ out: * @return boolean Returns true if required, false if not. */ -static bool _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, - int ctrl, +static bool _pam_require_krb5_auth_after_chauthtok(struct pwb_context *ctx, const char *user) { @@ -2423,13 +2385,13 @@ static bool _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, char *new_authtok_reqd_during_auth = NULL; struct passwd *pwd = NULL; - if (!(ctrl & WINBIND_KRB5_AUTH)) { + if (!(ctx->ctrl & WINBIND_KRB5_AUTH)) { return false; } - _pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + _pam_get_data(ctx->pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, &new_authtok_reqd_during_auth); - pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + pam_set_data(ctx->pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, NULL, NULL); if (new_authtok_reqd_during_auth) { @@ -2455,7 +2417,6 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, { unsigned int lctrl; int ret; - unsigned int ctrl; /* */ const char *user; @@ -2465,43 +2426,42 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, char *Announce; int retry = 0; - dictionary *d = NULL; char *username_ret = NULL; struct winbindd_response response; + struct pwb_context *ctx = NULL; ZERO_STRUCT(response); - ctrl = _pam_parse(pamh, flags, argc, argv, &d); - if (ctrl == -1) { - ret = PAM_SYSTEM_ERR; + ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (ret) { goto out; } - _PAM_LOG_FUNCTION_ENTER("pam_sm_chauthtok", pamh, ctrl, flags); + _PAM_LOG_FUNCTION_ENTER("pam_sm_chauthtok", ctx); /* clearing offline bit for the auth in the password change */ - ctrl &= ~WINBIND_CACHED_LOGIN; + ctx->ctrl &= ~WINBIND_CACHED_LOGIN; /* * First get the name of a user */ ret = pam_get_user(pamh, &user, "Username: "); if (ret) { - _pam_log(pamh, ctrl, LOG_ERR, + _pam_log(ctx, LOG_ERR, "password - could not identify user"); goto out; } if (user == NULL) { - _pam_log(pamh, ctrl, LOG_ERR, "username was NULL!"); + _pam_log(ctx, LOG_ERR, "username was NULL!"); ret = PAM_USER_UNKNOWN; goto out; } - _pam_log_debug(pamh, ctrl, LOG_DEBUG, "username [%s] obtained", user); + _pam_log_debug(ctx, LOG_DEBUG, "username [%s] obtained", user); /* check if this is really a user in winbindd, not only in NSS */ - ret = valid_user(pamh, ctrl, user); + ret = valid_user(ctx, user); switch (ret) { case 1: ret = PAM_USER_UNKNOWN; @@ -2525,7 +2485,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, #define greeting "Changing password for " Announce = (char *) malloc(sizeof(greeting) + strlen(user)); if (Announce == NULL) { - _pam_log(pamh, ctrl, LOG_CRIT, + _pam_log(ctx, LOG_CRIT, "password - out of memory"); ret = PAM_BUF_ERR; goto out; @@ -2534,21 +2494,21 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, (void) strcpy(Announce + sizeof(greeting) - 1, user); #undef greeting - lctrl = ctrl | WINBIND__OLD_PASSWORD; - ret = _winbind_read_password(pamh, lctrl, + lctrl = ctx->ctrl | WINBIND__OLD_PASSWORD; + ret = _winbind_read_password(ctx, lctrl, Announce, "(current) NT password: ", NULL, (const char **) &pass_old); if (ret != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_NOTICE, + _pam_log(ctx, LOG_NOTICE, "password - (old) token not obtained"); goto out; } /* verify that this is the password for this user */ - ret = winbind_auth_request(pamh, ctrl, user, pass_old, + ret = winbind_auth_request(ctx, user, pass_old, NULL, NULL, 0, &response, &pwdlastset_prelim, NULL); @@ -2567,7 +2527,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, (const void *) pass_old); pass_old = NULL; if (ret != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_CRIT, + _pam_log(ctx, LOG_CRIT, "failed to set PAM_OLDAUTHTOK"); } } else if (flags & PAM_UPDATE_AUTHTOK) { @@ -2585,12 +2545,12 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, ret = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old); if (ret != PAM_SUCCESS) { - _pam_log(pamh, ctrl, LOG_NOTICE, + _pam_log(ctx, LOG_NOTICE, "user not authenticated"); goto out; } - lctrl = ctrl & ~WINBIND_TRY_FIRST_PASS_ARG; + lctrl = ctx->ctrl & ~WINBIND_TRY_FIRST_PASS_ARG; if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { lctrl |= WINBIND_USE_FIRST_PASS_ARG; @@ -2603,14 +2563,14 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * password -- needed for pluggable password strength checking */ - ret = _winbind_read_password(pamh, lctrl, + ret = _winbind_read_password(ctx, lctrl, NULL, "Enter new NT password: ", "Retype new NT password: ", (const char **)&pass_new); if (ret != PAM_SUCCESS) { - _pam_log_debug(pamh, ctrl, LOG_ALERT, + _pam_log_debug(ctx, LOG_ALERT, "password - " "new password not obtained"); pass_old = NULL;/* tidy up */ @@ -2635,7 +2595,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, _pam_get_data(pamh, PAM_WINBIND_PWD_LAST_SET, &pwdlastset_update); - ret = winbind_chauthtok_request(pamh, ctrl, user, pass_old, + ret = winbind_chauthtok_request(ctx, user, pass_old, pass_new, pwdlastset_update); if (ret) { _pam_overwrite(pass_new); @@ -2644,24 +2604,17 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, goto out; } - if (_pam_require_krb5_auth_after_chauthtok(pamh, ctrl, user)) { + if (_pam_require_krb5_auth_after_chauthtok(ctx, user)) { const char *member = NULL; const char *cctype = NULL; int warn_pwd_expire; - member = get_member_from_config(pamh, argc, argv, - ctrl, d); - cctype = get_krb5_cc_type_from_config(pamh, argc, argv, - ctrl, d); - warn_pwd_expire = get_warn_pwd_expire_from_config(pamh, - argc, - argv, - ctrl, - d); + member = get_member_from_config(ctx); + cctype = get_krb5_cc_type_from_config(ctx); + warn_pwd_expire = get_warn_pwd_expire_from_config(ctx); - - ret = winbind_auth_request(pamh, ctrl, user, pass_new, + ret = winbind_auth_request(ctx, user, pass_new, member, cctype, 0, &response, NULL, &username_ret); _pam_overwrite(pass_new); @@ -2672,22 +2625,22 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, /* warn a user if the password is about to * expire soon */ - _pam_warn_password_expiry(pamh, ctrl, &response, + _pam_warn_password_expiry(ctx, &response, warn_pwd_expire, NULL); /* set some info3 info for other modules in the * stack */ - _pam_set_data_info3(pamh, ctrl, &response); + _pam_set_data_info3(ctx, &response); /* put krb5ccname into env */ - _pam_setup_krb5_env(pamh, ctrl, + _pam_setup_krb5_env(ctx, response.data.auth.krb5ccname); if (username_ret) { pam_set_item(pamh, PAM_USER, username_ret); - _pam_log_debug(pamh, ctrl, LOG_INFO, + _pam_log_debug(ctx, LOG_INFO, "Returned user was '%s'", username_ret); free(username_ret); @@ -2701,19 +2654,18 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, } out: - if (d) { - iniparser_freedict(d); - } /* Deal with offline errors. */ - PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE(ctx, response, "NT_STATUS_NO_LOGON_SERVERS"); - PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE(ctx, response, "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND"); - PAM_WB_REMARK_CHECK_RESPONSE(pamh, ctrl, response, + PAM_WB_REMARK_CHECK_RESPONSE(ctx, response, "NT_STATUS_ACCESS_DENIED"); - _PAM_LOG_FUNCTION_LEAVE("pam_sm_chauthtok", pamh, ctrl, ret); + _PAM_LOG_FUNCTION_LEAVE("pam_sm_chauthtok", ctx, ret); + + _pam_winbind_free_context(ctx); return ret; } -- cgit From e7553ab79ca7e68a9c66f0ffc1f8e93dedcf12b8 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 3 Apr 2008 17:23:22 +0200 Subject: Fix pam_winbind macros. Guenther (This used to be commit 37091859126167e84e55afe8a32025ac0f65065e) --- source3/nsswitch/pam_winbind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 9a9bce7ad8..47e0e3cd12 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -3,7 +3,7 @@ Copyright Andrew Tridgell 2000 Copyright Tim Potter 2000 Copyright Andrew Bartlett 2002 - Copyright Guenther Deschner 2005-2007 + Copyright Guenther Deschner 2005-2008 largely based on pam_userdb by Cristian Gafton also contains large slabs of code from pam_unix by Elliot Lee @@ -2690,7 +2690,7 @@ struct pam_module _pam_winbind_modstruct = { * Copyright (c) Andrew Tridgell 2000 * Copyright (c) Tim Potter 2000 * Copyright (c) Andrew Bartlettt 2002 - * Copyright (c) Guenther Deschner 2005-2007 + * Copyright (c) Guenther Deschner 2005-2008 * Copyright (c) Jan Rêkorajski 1999. * Copyright (c) Andrew G. Morgan 1996-8. * Copyright (c) Alex O. Yuriev, 1996. -- cgit From f4e93883c999ac30d4106149f341724a7243847f Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 6 Jun 2008 15:59:52 +0200 Subject: pam_winbind: fix pam_sm_chauthtok for storing modified cached creds. Thanks to Bo Yang for pointing this out. Guenther (This used to be commit 516a067016955938988ab37c777102a14b41e100) --- source3/nsswitch/pam_winbind.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 47e0e3cd12..7288d7af77 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -2417,6 +2417,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, { unsigned int lctrl; int ret; + bool cached_login = false; /* */ const char *user; @@ -2439,7 +2440,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, _PAM_LOG_FUNCTION_ENTER("pam_sm_chauthtok", ctx); - /* clearing offline bit for the auth in the password change */ + cached_login = (ctx->ctrl & WINBIND_CACHED_LOGIN); + + /* clearing offline bit for auth */ ctx->ctrl &= ~WINBIND_CACHED_LOGIN; /* @@ -2595,6 +2598,15 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, _pam_get_data(pamh, PAM_WINBIND_PWD_LAST_SET, &pwdlastset_update); + /* + * if cached creds were enabled, make sure to set the + * WINBIND_CACHED_LOGIN bit here in order to have winbindd + * update the cached creds storage - gd + */ + if (cached_login) { + ctx->ctrl |= WINBIND_CACHED_LOGIN; + } + ret = winbind_chauthtok_request(ctx, user, pass_old, pass_new, pwdlastset_update); if (ret) { @@ -2614,6 +2626,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, cctype = get_krb5_cc_type_from_config(ctx); warn_pwd_expire = get_warn_pwd_expire_from_config(ctx); + /* clearing offline bit for auth */ + ctx->ctrl &= ~WINBIND_CACHED_LOGIN; + ret = winbind_auth_request(ctx, user, pass_new, member, cctype, 0, &response, NULL, &username_ret); -- cgit From 8e240c460b8cd290acd70fa286811d92cc7d24b8 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 11 Jun 2008 09:52:56 +0200 Subject: pam_winbind: Update cached creds during password change. Fix is from Bo Yang @ Novell. Thanks! (This used to be commit e4eb9d347d14de8c9ba73b07f26fe8fd4f17eab5) --- source3/nsswitch/pam_winbind.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 7288d7af77..e42199cd0f 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -1445,6 +1445,10 @@ static int winbind_chauthtok_request(struct pwb_context *ctx, WBFLAG_PAM_CONTACT_TRUSTDOM; } + if (ctx->ctrl & WINBIND_CACHED_LOGIN) { + request.flags |= WBFLAG_PAM_CACHED_LOGIN; + } + ret = pam_winbind_request_log(ctx, WINBINDD_PAM_CHAUTHTOK, &request, &response, user); -- cgit From 06b3a79d1fb2b66c39e0d8667c5904bfaff26b03 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 Jul 2008 11:26:16 -0700 Subject: Allow authentication and memory credential refresh after password change from gdm/xdm. Patch from boyang . Jeremy. (This used to be commit 8cfc6afc7b4a6af9aea5f5a7cb5af7e3218c2d75) --- source3/nsswitch/pam_winbind.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index e42199cd0f..95b3d23dd4 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -2384,15 +2384,17 @@ static bool _pam_require_krb5_auth_after_chauthtok(struct pwb_context *ctx, /* Make sure that we only do this if a) the chauthtok got initiated * during a logon attempt (authenticate->acct_mgmt->chauthtok) b) any * later password change via the "passwd" command if done by the user - * itself */ + * itself + * NB. If we login from gdm or xdm and the password expires, + * we change the password, but there is no memory cache. + * Thus, even for passthrough login, we should do the + * authentication again to update memory cache. + * --- BoYang + * */ char *new_authtok_reqd_during_auth = NULL; struct passwd *pwd = NULL; - if (!(ctx->ctrl & WINBIND_KRB5_AUTH)) { - return false; - } - _pam_get_data(ctx->pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, &new_authtok_reqd_during_auth); pam_set_data(ctx->pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, @@ -2630,8 +2632,13 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, cctype = get_krb5_cc_type_from_config(ctx); warn_pwd_expire = get_warn_pwd_expire_from_config(ctx); - /* clearing offline bit for auth */ - ctx->ctrl &= ~WINBIND_CACHED_LOGIN; + /* Keep WINBIND_CACHED_LOGIN bit for + * authentication after changing the password. + * This will update the cached credentials in case + * that winbindd_dual_pam_chauthtok() fails + * to update them. + * --- BoYang + * */ ret = winbind_auth_request(ctx, user, pass_new, member, cctype, 0, &response, -- cgit From 299e6c799697e9cafce4eaba3baafa9a344bb802 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 14 Aug 2008 17:40:26 +0200 Subject: pam_winbind: add _pam_error_code_str(). Guenther (This used to be commit 693f90fd2394309ce40d3ca5fc007543058b342a) --- source3/nsswitch/pam_winbind.c | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 95b3d23dd4..872a1b72ea 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -12,6 +12,78 @@ #include "pam_winbind.h" +static const char *_pam_error_code_str(int err) +{ + switch (err) { + case PAM_SUCCESS: + return "PAM_SUCCESS"; + case PAM_OPEN_ERR: + return "PAM_OPEN_ERR"; + case PAM_SYMBOL_ERR: + return "PAM_SYMBOL_ERR"; + case PAM_SERVICE_ERR: + return "PAM_SERVICE_ERR"; + case PAM_SYSTEM_ERR: + return "PAM_SYSTEM_ERR"; + case PAM_BUF_ERR: + return "PAM_BUF_ERR"; + case PAM_PERM_DENIED: + return "PAM_PERM_DENIED"; + case PAM_AUTH_ERR: + return "PAM_AUTH_ERR"; + case PAM_CRED_INSUFFICIENT: + return "PAM_CRED_INSUFFICIENT"; + case PAM_AUTHINFO_UNAVAIL: + return "PAM_AUTHINFO_UNAVAIL"; + case PAM_USER_UNKNOWN: + return "PAM_USER_UNKNOWN"; + case PAM_MAXTRIES: + return "PAM_MAXTRIES"; + case PAM_NEW_AUTHTOK_REQD: + return "PAM_NEW_AUTHTOK_REQD"; + case PAM_ACCT_EXPIRED: + return "PAM_ACCT_EXPIRED"; + case PAM_SESSION_ERR: + return "PAM_SESSION_ERR"; + case PAM_CRED_UNAVAIL: + return "PAM_CRED_UNAVAIL"; + case PAM_CRED_EXPIRED: + return "PAM_CRED_EXPIRED"; + case PAM_CRED_ERR: + return "PAM_CRED_ERR"; + case PAM_NO_MODULE_DATA: + return "PAM_NO_MODULE_DATA"; + case PAM_CONV_ERR: + return "PAM_CONV_ERR"; + case PAM_AUTHTOK_ERR: + return "PAM_AUTHTOK_ERR"; + case PAM_AUTHTOK_RECOVERY_ERR: + return "PAM_AUTHTOK_RECOVERY_ERR"; + case PAM_AUTHTOK_LOCK_BUSY: + return "PAM_AUTHTOK_LOCK_BUSY"; + case PAM_AUTHTOK_DISABLE_AGING: + return "PAM_AUTHTOK_DISABLE_AGING"; + case PAM_TRY_AGAIN: + return "PAM_TRY_AGAIN"; + case PAM_IGNORE: + return "PAM_IGNORE"; + case PAM_ABORT: + return "PAM_ABORT"; + case PAM_AUTHTOK_EXPIRED: + return "PAM_AUTHTOK_EXPIRED"; + case PAM_MODULE_UNKNOWN: + return "PAM_MODULE_UNKNOWN"; + case PAM_BAD_ITEM: + return "PAM_BAD_ITEM"; + case PAM_CONV_AGAIN: + return "PAM_CONV_AGAIN"; + case PAM_INCOMPLETE: + return "PAM_INCOMPLETE"; + default: + return NULL; + } +} + #define _PAM_LOG_FUNCTION_ENTER(function, ctx) \ do { \ _pam_log_debug(ctx, LOG_DEBUG, "[pamh: %p] ENTER: " \ -- cgit From 1cef895f4be7d7a2cb8872adba30c82d490a70e1 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 14 Aug 2008 20:56:47 +0200 Subject: pam_winbind: use pam error string function to display result. Guenther (This used to be commit 8504a92ac55d6936df051be66207a59a76bf32a3) --- source3/nsswitch/pam_winbind.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 872a1b72ea..7532aeabcd 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -94,7 +94,8 @@ static const char *_pam_error_code_str(int err) #define _PAM_LOG_FUNCTION_LEAVE(function, ctx, retval) \ do { \ _pam_log_debug(ctx, LOG_DEBUG, "[pamh: %p] LEAVE: " \ - function " returning %d", ctx->pamh, retval); \ + function " returning %d (%s)", ctx->pamh, retval, \ + _pam_error_code_str(retval)); \ _pam_log_state(ctx); \ } while (0) -- cgit From bded7eb2af001f69617d2cb658400bfa6009ef6d Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 19 Aug 2008 16:19:54 +0200 Subject: pam_winbind: some doxygen fixes. Guenther (This used to be commit f2a2ed315e393353110aa7760b4eca4f1f49ca21) --- source3/nsswitch/pam_winbind.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) (limited to 'source3/nsswitch/pam_winbind.c') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 7532aeabcd..c28c5d2697 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -771,8 +771,7 @@ static int pam_winbind_request_log(struct pwb_context *ctx, /** * send a password expiry message if required * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * @param next_change expected (calculated) next expiry date. * @param already_expired pointer to a boolean to indicate if the password is * already expired. @@ -833,8 +832,7 @@ static bool _pam_send_password_expiry_message(struct pwb_context *ctx, /** * Send a warning if the password expires in the near future * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * @param response The full authentication response structure. * @param already_expired boolean, is the pwd already expired? * @@ -923,8 +921,7 @@ static bool safe_append_string(char *dest, /** * Convert a names into a SID string, appending it to a buffer. * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * @param user User in PAM request. * @param name Name to convert. * @param sid_list_buffer Where to append the string sid. @@ -979,8 +976,7 @@ static bool winbind_name_to_sid_string(struct pwb_context *ctx, /** * Convert a list of names into a list of sids. * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * @param user User in PAM request. * @param name_list List of names or string sids, separated by commas. * @param sid_list_buffer Where to put the list of string sids. @@ -1044,8 +1040,7 @@ out: /** * put krb5ccname variable into environment * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * @param krb5ccname env variable retrieved from winbindd. * * @return void. @@ -1083,8 +1078,7 @@ static void _pam_setup_krb5_env(struct pwb_context *ctx, /** * Set string into the PAM stack. * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * @param data_name Key name for pam_set_data. * @param value String value. * @@ -1115,8 +1109,7 @@ static void _pam_set_data_string(struct pwb_context *ctx, /** * Set info3 strings into the PAM stack. * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * @param data_name Key name for pam_set_data. * @param value String value. * @@ -1155,8 +1148,7 @@ static void _pam_free_data_info3(pam_handle_t *pamh) /** * Send PAM_ERROR_MSG for cached or grace logons. * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * @param username User in PAM request. * @param info3_user_flgs Info3 flags containing logon type bits. * @@ -1193,8 +1185,7 @@ static void _pam_warn_logon_type(struct pwb_context *ctx, /** * Send PAM_ERROR_MSG for krb5 errors. * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * @param username User in PAM request. * @param info3_user_flgs Info3 flags containing logon type bits. * @@ -1942,8 +1933,7 @@ static int get_warn_pwd_expire_from_config(struct pwb_context *ctx) /** * Retrieve the winbind separator. * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * * @return string separator character. NULL on failure. */ @@ -1967,8 +1957,7 @@ static char winbind_get_separator(struct pwb_context *ctx) /** * Convert a upn to a name. * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * @param upn USer UPN to be trabslated. * * @return converted name. NULL pointer on failure. Caller needs to free. @@ -2443,8 +2432,7 @@ out: * evaluate whether we need to re-authenticate with kerberos after a * password change * - * @param pamh PAM handle - * @param ctrl PAM winbind options. + * @param ctx PAM winbind context. * @param user The username * * @return boolean Returns true if required, false if not. -- cgit