diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/nsswitch/pam_winbind.c | 240 |
1 files changed, 183 insertions, 57 deletions
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 <gafton@redhat.com> */ -#include <features.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <syslog.h> -#include <stdarg.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> - -#define MODULE_NAME "pam_winbind" -#define PAM_SM_AUTH -#define PAM_SM_ACCOUNT -#include <security/pam_modules.h> -#include <security/_pam_macros.h> - -#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 <tridge@samba.org> 2000 + * Copyright (c) Tim Potter <tpot@samba.org> 2000 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions |