From: Stefan Metzmacher Date: Mon, 15 Jul 2024 16:43:37 +0000 (+0200) Subject: third_party/pam_wrapper: add pam_matrix module X-Git-Tag: tdb-1.4.11~108 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=97f0408f776ecbde4bec6d3001d0bdc82f9d86eb;p=thirdparty%2Fsamba.git third_party/pam_wrapper: add pam_matrix module This allows testing pam with simple passwords. BUG: https://bugzilla.samba.org/show_bug.cgi?id=9705 Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider --- diff --git a/script/autobuild.py b/script/autobuild.py index 7d9dc008bcf..5bea99f1fde 100755 --- a/script/autobuild.py +++ b/script/autobuild.py @@ -998,7 +998,7 @@ tasks = { ("allprivate-def-configure", "./configure.developer " + samba_configure_params + " --private-libraries=ALL"), ("allprivate-def-make", "make -j"), # note wrapper libraries need to be public - ("allprivate-def-no-public", "ls ./bin/shared | egrep -v '^private$|lib[nprsu][saeoi][smscd].*-wrapper.so$|pam_set_items.so' | wc -l | grep -q '^0'"), + ("allprivate-def-no-public", "ls ./bin/shared | egrep -v '^private$|lib[nprsu][saeoi][smscd].*-wrapper.so$|pam_set_items.so|pam_matrix.so' | wc -l | grep -q '^0'"), ("allprivate-def-only-private-ext", "ls ./bin/shared/private | egrep 'private-samba' | wc -l | grep -q '^0' && exit 1; exit 0"), ("allprivate-def-no-non-private-ext", "ls ./bin/shared/private | egrep -v 'private-samba|^libpypamtest.so$' | wc -l | grep -q '^0'"), ("allprivate-def-test", make_test(TESTS="samba3.smb2.create.*nt4_dc")), @@ -1012,7 +1012,7 @@ tasks = { ("allprivate-ext-configure", "./configure.developer " + samba_configure_params + " --private-libraries=ALL --private-library-extension=private-library --private-extension-exception=pac,ndr"), ("allprivate-ext-make", "make -j"), # note wrapper libraries need to be public - ("allprivate-ext-no-public", "ls ./bin/shared | egrep -v '^private$|lib[nprsu][saeoi][smscd].*-wrapper.so$|pam_set_items.so' | wc -l | grep -q '^0'"), + ("allprivate-ext-no-public", "ls ./bin/shared | egrep -v '^private$|lib[nprsu][saeoi][smscd].*-wrapper.so$|pam_set_items.so|pam_matrix.so' | wc -l | grep -q '^0'"), ("allprivate-ext-no-private-default-ext", "ls ./bin/shared/private | grep 'private-samba' | wc -l | grep -q '^0'"), ("allprivate-ext-has-private-ext", "ls ./bin/shared/private | grep 'private-library' | wc -l | grep -q '^0' && exit 1; exit 0"), ("allprivate-ext-libndr-no-private-ext", "ls ./bin/shared/private | grep -v 'private-library' | grep 'libndr' | wc -l | grep -q '^1'"), diff --git a/script/compare_cc_results.py b/script/compare_cc_results.py index 9bf24adffec..d97050c1870 100755 --- a/script/compare_cc_results.py +++ b/script/compare_cc_results.py @@ -16,6 +16,7 @@ exceptions = [ 'LIBNSS_WRAPPER_SO_PATH', 'LIBPAM_WRAPPER_SO_PATH', 'PAM_SET_ITEMS_SO_PATH', + 'PAM_MATRIX_SO_PATH', 'LIBUID_WRAPPER_SO_PATH', 'LIBRESOLV_WRAPPER_SO_PATH', ] diff --git a/third_party/pam_wrapper/modules/pam_matrix.c b/third_party/pam_wrapper/modules/pam_matrix.c new file mode 100644 index 00000000000..cc6fbf37e82 --- /dev/null +++ b/third_party/pam_wrapper/modules/pam_matrix.c @@ -0,0 +1,842 @@ +/* + * Copyright (c) 2015 Andreas Schneider + * Copyright (c) 2015 Jakub Hrozek + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +#ifndef discard_const +#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) +#endif + +#ifndef discard_const_p +#define discard_const_p(type, ptr) ((type *)discard_const(ptr)) +#endif + +#ifdef HAVE_SECURITY_PAM_APPL_H +#include +#endif +#ifdef HAVE_SECURITY_PAM_MODULES_H +#include +#endif +#ifdef HAVE_SECURITY_PAM_EXT_H +#include +#endif + +#include "pwrap_compat.h" + +#define HOME_VAR "HOMEDIR" +#define HOME_VAR_SZ sizeof(HOME_VAR)-1 + +#define CRED_VAR "CRED" +#define CRED_VAR_SZ sizeof(CRED_VAR)-1 + +#define PAM_EXAMPLE_AUTH_DATA "pam_matrix:auth_data" + +#define PASSDB_KEY "passdb=" +#define VERBOSE_KEY "verbose" +#define ECHO_KEY "echo" + +#define PAM_MATRIX_FLG_VERBOSE (1 << 0) +#define PAM_MATRIX_FLG_ECHO (1 << 1) + +#define MAX_AUTHTOK_SIZE 1024 + +/* Walks over the key until a colon (:) is find + */ +#define NEXT_KEY(buf, key) do { \ + (key) = (buf) ? strpbrk((buf), ":") : NULL; \ + if ((key) != NULL) { \ + (key)[0] = '\0'; \ + (key)++; \ + } \ + while ((key) != NULL \ + && (isblank((int)(key)[0]))) { \ + (key)++; \ + } \ +} while(0); + +#define wipe_authtok(tok) do { \ + if (tok != NULL) { \ + char *__tk = tok; \ + while(*__tk != '\0') { \ + *__tk = '\0'; \ + } \ + } \ +} while(0); + +struct pam_lib_items { + const char *username; + const char *service; + char *password; +}; + +struct pam_matrix_mod_items { + char *password; + char *service; +}; + +struct pam_matrix_ctx { + const char *passdb; + int flags; + + struct pam_lib_items pli; + struct pam_matrix_mod_items pmi; +}; + +/* Search the passdb for user entry and fill his info into pmi */ +static int pam_matrix_mod_items_get(const char *db, + const char *username, + struct pam_matrix_mod_items *pmi) +{ + int rv; + FILE *fp = NULL; + char buf[BUFSIZ]; + char *file_user = NULL; + char *file_password = NULL; + char *file_svc = NULL; + + fp = fopen(db, "r"); + if (fp == NULL) { + rv = errno; + goto fail; + } + + while (fgets(buf, sizeof(buf), fp) != NULL) { + char *q; + + /* Find the user, his password and allowed service */ + file_user = buf; + file_password = NULL; + + /* Skip comments */ + if (file_user[0] == '#') { + continue; + } + + NEXT_KEY(file_user, file_password); + NEXT_KEY(file_password, file_svc); + + q = file_svc; + while(q[0] != '\n' && q[0] != '\0') { + q++; + } + q[0] = '\0'; + + if (file_password == NULL) { + continue; + } + + if (strcmp(file_user, username) == 0) { + pmi->password = strdup(file_password); + if (pmi->password == NULL) { + rv = errno; + goto fail; + } + + pmi->service = strdup(file_svc); + if (pmi->service == NULL) { + rv = errno; + goto fail; + } + + break; + } + } + + fclose(fp); + return 0; + +fail: + free(pmi->password); + free(pmi->service); + if (fp) { + fclose(fp); + } + return rv; +} + +/* Replace authtok of user in the database with the one from pli */ +static int pam_matrix_lib_items_put(const char *db, + struct pam_lib_items *pli) +{ + int rv; + mode_t old_mask; + FILE *fp = NULL; + FILE *fp_tmp = NULL; + char buf[BUFSIZ]; + char template[PATH_MAX] = { '\0' }; + char *file_user = NULL; + char *file_password = NULL; + char *file_svc = NULL; + + rv = snprintf(template, sizeof(template), + "%s.XXXXXX", db); + if (rv <= 0) { + rv = PAM_BUF_ERR; + goto done; + } + + /* We don't support concurrent runs.. */ + old_mask = umask(S_IRWXO | S_IRWXG); + rv = mkstemp(template); + umask(old_mask); + if (rv <= 0) { + rv = PAM_BUF_ERR; + goto done; + } + + fp = fopen(db, "r"); + fp_tmp = fopen(template, "w"); + if (fp == NULL || fp_tmp == NULL) { + rv = errno; + goto done; + } + + while (fgets(buf, sizeof(buf), fp) != NULL) { + char *q; + + file_user = buf; + file_password = NULL; + + /* Skip comments */ + if (file_user[0] == '#') { + continue; + } + + /* Find the user, his password and allowed service */ + NEXT_KEY(file_user, file_password); + NEXT_KEY(file_password, file_svc); + + q = file_svc; + while(q[0] != '\n' && q[0] != '\0') { + q++; + } + q[0] = '\0'; + + if (file_password == NULL) { + continue; + } + + if (strcmp(file_user, pli->username) == 0) { + if (pli->password) { + file_password = pli->password; + } + } + + rv = fprintf(fp_tmp, "%s:%s:%s\n", + file_user, file_password, file_svc); + if (rv < 0) { + rv = PAM_CRED_ERR; + goto done; + } + } + + rv = PAM_SUCCESS; +done: + if (fp != NULL) { + fclose(fp); + } + if (fp_tmp != NULL) { + fflush(fp_tmp); + fclose(fp_tmp); + } + + if (rv == PAM_SUCCESS) { + rv = rename(template, db); + if (rv == -1) { + rv = PAM_SYSTEM_ERR; + } + } + + if (template[0] != '\0') { + unlink(template); + }; + return rv; +} + +static void pam_matrix_mod_items_free(struct pam_matrix_mod_items *pmi) +{ + if (pmi == NULL) { + return; + } + + free(pmi->password); + free(pmi->service); +} + +static int pam_matrix_conv(pam_handle_t *pamh, + const int msg_style, + const char *msg, + char **answer) +{ + int ret; + const struct pam_conv *conv; + const struct pam_message *mesg[1]; + struct pam_response *resp = NULL; + struct pam_response **r = NULL; + struct pam_message *pam_msg; + + ret = pam_get_item(pamh, PAM_CONV, (const void **) &conv); + if (ret != PAM_SUCCESS) { + return ret; + } + + pam_msg = malloc(sizeof(struct pam_message)); + if (pam_msg == NULL) { + return PAM_BUF_ERR; + } + + pam_msg->msg_style = msg_style; + pam_msg->msg = discard_const_p(char, msg); + + if (msg_style == PAM_PROMPT_ECHO_ON || + msg_style == PAM_PROMPT_ECHO_OFF) { + r = &resp; + } + + mesg[0] = (const struct pam_message *) pam_msg; + ret = conv->conv(1, mesg, r, conv->appdata_ptr); + free(pam_msg); + if (ret != PAM_SUCCESS) { + free(resp); + return ret; + } + + if (msg_style == PAM_PROMPT_ECHO_OFF || + msg_style == PAM_PROMPT_ECHO_ON) { + if (resp == NULL) { + /* Response expected, but none find! */ + return PAM_SYSTEM_ERR; + } + + if (resp[0].resp == NULL) { + /* Empty password */ + *answer = NULL; + free(resp); + return PAM_SUCCESS; + } + + *answer = strndup(resp[0].resp, MAX_AUTHTOK_SIZE); + wipe_authtok(resp[0].resp); + free(resp[0].resp); + free(resp); + if (*answer == NULL) { + return PAM_BUF_ERR; + } + } + + return PAM_SUCCESS; +} + +/* Read user password. If both prompts are provided, then ask twice and + * assert that both passwords match. + * + * The authtok would be returned in _out_tok if needed and set in + * authtok_item as well + */ +static int pam_matrix_read_password(pam_handle_t *pamh, + int flags, + int authtok_item, + const char *prompt1, + const char *prompt2, + const void **_out_tok) +{ + int rv = PAM_AUTHTOK_RECOVERY_ERR; + char *authtok1 = NULL; + char *authtok2 = NULL; + const void *item; + int read_flg = PAM_PROMPT_ECHO_OFF; + + if (flags & PAM_MATRIX_FLG_ECHO) { + read_flg = PAM_PROMPT_ECHO_ON; + } + + rv = pam_matrix_conv(pamh, read_flg, prompt1, &authtok1); + if (authtok1 == NULL) { + goto done; + } + + if (rv == PAM_SUCCESS && prompt2 != NULL) { + rv = pam_matrix_conv(pamh, read_flg, + prompt2, &authtok2); + if (rv != PAM_SUCCESS) { + goto done; + } + + if (authtok2 == NULL) { + rv = PAM_AUTHTOK_RECOVERY_ERR; + goto done; + } + + if (strcmp(authtok1, authtok2) != 0) { + pam_matrix_conv(pamh, PAM_ERROR_MSG, + "Passwords do not match", + NULL); + rv = PAM_AUTHTOK_RECOVERY_ERR; + goto done; + } + wipe_authtok(authtok2); + free(authtok2); + authtok2 = NULL; + } + + if (rv != PAM_SUCCESS) { + goto done; + } + + rv = pam_set_item(pamh, authtok_item, authtok1); + wipe_authtok(authtok1); + free(authtok1); + authtok1 = NULL; + if (rv != PAM_SUCCESS) { + goto done; + } + + rv = pam_get_item(pamh, authtok_item, &item); + if (_out_tok) { + *_out_tok = item; + } + item = NULL; + if (rv != PAM_SUCCESS) { + goto done; + } + + rv = PAM_SUCCESS; +done: + wipe_authtok(authtok1); + wipe_authtok(authtok2); + return rv; +} + +/* Retrieve user info -- username and service that were provided by + * pam_start */ +static int pam_lib_items_get(pam_handle_t *pamh, + struct pam_lib_items *pli) +{ + int rv; + + rv = pam_get_item(pamh, PAM_USER, (const void **) &(pli->username)); + if (rv != PAM_SUCCESS) { + return rv; + } + + if (pli->username == NULL) { + return PAM_BAD_ITEM; + } + + rv = pam_get_item(pamh, PAM_SERVICE, (const void **) &(pli->service)); + if (rv != PAM_SUCCESS) { + return rv; + } + + return PAM_SUCCESS; +} + +/* Evaluate command line arguments and store info about them in the + * pam_matrix context + */ +static void eval_args(struct pam_matrix_ctx *pe_ctx, + int argc, + const char *argv[]) +{ + pe_ctx->flags = 0; + + for (; argc-- > 0; ++argv) { + if (strncmp(*argv, PASSDB_KEY, strlen(PASSDB_KEY)) == 0) { + if (*(*argv+strlen(PASSDB_KEY)) == '\0') { + pe_ctx->passdb = NULL; + } else { + pe_ctx->passdb = *argv+strlen(PASSDB_KEY); + } + } else if (strncmp(*argv, VERBOSE_KEY, + strlen(VERBOSE_KEY)) == 0) { + pe_ctx->flags |= PAM_MATRIX_FLG_VERBOSE; + } else if (strncmp(*argv, ECHO_KEY, + strlen(ECHO_KEY)) == 0) { + pe_ctx->flags |= PAM_MATRIX_FLG_ECHO; + } + } +} + +/* Retrieve info about the user who is logging in and find his + * record in the database + */ +static int pam_matrix_get(pam_handle_t *pamh, + int argc, + const char *argv[], + struct pam_matrix_ctx *pe_ctx) +{ + int rv; + + eval_args(pe_ctx, argc, argv); + + /* If no db is provided as argument, fall back to environment variable */ + if (pe_ctx->passdb == NULL) { + pe_ctx->passdb = getenv("PAM_MATRIX_PASSWD"); + if (pe_ctx->passdb == NULL) { + return PAM_AUTHINFO_UNAVAIL; + } + } + + + rv = pam_lib_items_get(pamh, &pe_ctx->pli); + if (rv != PAM_SUCCESS) { + return rv; + } + + rv = pam_matrix_mod_items_get(pe_ctx->passdb, + pe_ctx->pli.username, + &pe_ctx->pmi); + if (rv != PAM_SUCCESS) { + return PAM_AUTHINFO_UNAVAIL; + } + + return PAM_SUCCESS; +} + +static void pam_matrix_free(struct pam_matrix_ctx *pe_ctx) +{ + pam_matrix_mod_items_free(&pe_ctx->pmi); +} + +static int _pam_matrix_auth(struct pam_matrix_ctx *pctx) +{ + int rv = PAM_AUTH_ERR; + + if (pctx->pli.password == NULL) { + /* NULL passwords are not allowed */ + return PAM_CRED_ERR; + } + + if (pctx->pli.password != NULL && + pctx->pmi.password != NULL && + strcmp(pctx->pli.password, pctx->pmi.password) == 0) { + rv = PAM_SUCCESS; + } + + return rv; +} + +static int pam_matrix_auth(pam_handle_t *pamh, struct pam_matrix_ctx *pctx) +{ + int rv = PAM_AUTH_ERR; + + rv = _pam_matrix_auth(pctx); + + wipe_authtok(pctx->pli.password); + wipe_authtok(pctx->pmi.password); + + if (pctx->flags & PAM_MATRIX_FLG_VERBOSE) { + if (rv == PAM_SUCCESS) { + pam_matrix_conv(pamh, + PAM_TEXT_INFO, + "Authentication succeeded", + NULL); + } else { + pam_matrix_conv(pamh, + PAM_ERROR_MSG, + "Authentication failed", + NULL); + } + } + + return rv; +} + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + struct pam_matrix_ctx pctx; + int rv; + + (void) flags; /* unused */ + + memset(&pctx, 0, sizeof(struct pam_matrix_ctx)); + + /* Search the user info in database */ + rv = pam_matrix_get(pamh, argc, argv, &pctx); + if (rv != PAM_SUCCESS) { + goto done; + } + + rv = pam_matrix_read_password(pamh, pctx.flags, PAM_AUTHTOK, "Password: ", + NULL, (const void **) &pctx.pli.password); + if (rv != PAM_SUCCESS) { + rv = PAM_AUTHINFO_UNAVAIL; + goto done; + } + + /* Auth and get rid of the authtok */ + rv = pam_matrix_auth(pamh, &pctx); +done: + pam_matrix_free(&pctx); + return rv; +} + +/* Really silly setcred function that just sets a pam environment variable */ +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + struct pam_matrix_ctx pctx; + int rv; + char cred[PATH_MAX + CRED_VAR_SZ]; + + (void) flags; /* unused */ + + memset(&pctx, 0, sizeof(struct pam_matrix_ctx)); + + rv = pam_matrix_get(pamh, argc, argv, &pctx); + if (rv != PAM_SUCCESS) { + goto done; + } + + rv = snprintf(cred, sizeof(cred), + "%s=/tmp/%s", + CRED_VAR, pctx.pli.username); + if (rv <= 0) { + rv = PAM_BUF_ERR; + goto done; + } + + rv = pam_putenv(pamh, cred); + if (rv != PAM_SUCCESS) { + goto done; + } + + rv = PAM_SUCCESS; +done: + pam_matrix_free(&pctx); + return rv; +} + +PAM_EXTERN int +pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + struct pam_matrix_ctx pctx; + int rv; + + (void) flags; /* unused */ + + memset(&pctx, 0, sizeof(struct pam_matrix_ctx)); + + /* Search the user info in database */ + rv = pam_matrix_get(pamh, argc, argv, &pctx); + if (rv != PAM_SUCCESS) { + goto done; + } + + /* Check if the allowed service matches the PAM service */ + if (pctx.pli.service != NULL && + pctx.pmi.service != NULL && + strcmp(pctx.pli.service, pctx.pmi.service) == 0) { + rv = PAM_SUCCESS; + goto done; + } + + rv = PAM_PERM_DENIED; +done: + pam_matrix_free(&pctx); + return rv; +} + +/* Really silly session function that just sets a pam environment variable */ +PAM_EXTERN int +pam_sm_open_session(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + struct pam_matrix_ctx pctx; + int rv; + char home[PATH_MAX + HOME_VAR_SZ]; + + (void) flags; /* unused */ + + memset(&pctx, 0, sizeof(struct pam_matrix_ctx)); + + rv = pam_matrix_get(pamh, argc, argv, &pctx); + if (rv != PAM_SUCCESS) { + goto done; + } + + rv = snprintf(home, sizeof(home), + "%s=/home/%s", + HOME_VAR, pctx.pli.username); + if (rv <= 0) { + rv = PAM_BUF_ERR; + goto done; + } + + rv = pam_putenv(pamh, home); + if (rv != PAM_SUCCESS) { + goto done; + } + + rv = PAM_SUCCESS; +done: + pam_matrix_free(&pctx); + return rv; +} + +/* Just unsets whatever session set */ +PAM_EXTERN int +pam_sm_close_session(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + struct pam_matrix_ctx pctx; + int rv; + + (void) flags; /* unused */ + + memset(&pctx, 0, sizeof(struct pam_matrix_ctx)); + + rv = pam_matrix_get(pamh, argc, argv, &pctx); + if (rv != PAM_SUCCESS) { + goto done; + } + +#if HAVE_OPENPAM + /* OpenPAM does not support unsetting variable, set it to + * and empty string instead + */ + rv = pam_putenv(pamh, HOME_VAR"="); +#else + rv = pam_putenv(pamh, HOME_VAR); +#endif + if (rv != PAM_SUCCESS) { + goto done; + } + + rv = PAM_SUCCESS; +done: + pam_matrix_free(&pctx); + return rv; +} + +static void pam_matrix_stamp_destructor(pam_handle_t *pamh, + void *data, + int error_status) +{ + (void) pamh; /* unused */ + (void) error_status; /* unused */ + + free(data); +} + +PAM_EXTERN int +pam_sm_chauthtok(pam_handle_t *pamh, int flags, + int argc, const char *argv[]) +{ + struct pam_matrix_ctx pctx; + const char *old_pass; + int rv; + time_t *auth_stamp = NULL; + const time_t *auth_stamp_out = NULL; + + (void) flags; /* unused */ + + memset(&pctx, 0, sizeof(struct pam_matrix_ctx)); + + rv = pam_matrix_get(pamh, argc, argv, &pctx); + if (rv != PAM_SUCCESS) { + goto done; + } + + if (flags & PAM_PRELIM_CHECK) { + rv = pam_matrix_read_password( + pamh, pctx.flags, PAM_OLDAUTHTOK, + "Old password: ", NULL, + (const void **) &pctx.pli.password); + if (rv != PAM_SUCCESS) { + rv = PAM_AUTHINFO_UNAVAIL; + goto done; + } + + auth_stamp = malloc(sizeof(time_t)); + if (auth_stamp == NULL) { + rv = PAM_BUF_ERR; + goto done; + } + *auth_stamp = time(NULL); + + /* Not really useful, just test that between the two phases, + * data can be passed + */ + rv = pam_set_data(pamh, PAM_EXAMPLE_AUTH_DATA, + auth_stamp, pam_matrix_stamp_destructor); + if (rv != PAM_SUCCESS) { + goto done; + } + + rv = pam_matrix_auth(pamh, &pctx); + } else if (flags & PAM_UPDATE_AUTHTOK) { + rv = pam_get_item(pamh, + PAM_OLDAUTHTOK, + (const void **) &old_pass); + if (rv != PAM_SUCCESS || old_pass == NULL) { + rv = PAM_AUTHINFO_UNAVAIL; + goto done; + } + + + rv = pam_get_data(pamh, PAM_EXAMPLE_AUTH_DATA, + (const void **) &auth_stamp_out); + if (rv != PAM_SUCCESS) { + goto done; + } + + rv = pam_matrix_read_password(pamh, + pctx.flags, + PAM_AUTHTOK, + "New Password :", + "Verify New Password :", + (const void **) &pctx.pli.password); + if (rv != PAM_SUCCESS) { + rv = PAM_AUTHINFO_UNAVAIL; + goto done; + } + + /* Write the new password to the db */ + rv = pam_matrix_lib_items_put(pctx.passdb, &pctx.pli); + } else { + rv = PAM_SYSTEM_ERR; + } + +done: + pam_matrix_free(&pctx); + return rv; +} diff --git a/third_party/pam_wrapper/wscript b/third_party/pam_wrapper/wscript index 599072fe478..a60bd044071 100644 --- a/third_party/pam_wrapper/wscript +++ b/third_party/pam_wrapper/wscript @@ -19,6 +19,8 @@ def configure(conf): pam_set_items_so_path = find_library(['pam_set_items.so'], ['/usr/lib64/pam_wrapper', '/usr/lib/pam_wrapper']) + pam_matrix_so_path = find_library(['pam_matrix.so'], + ['/usr/lib64/pam_wrapper', '/usr/lib/pam_wrapper']) else: if conf.CONFIG_SET("HAVE___THREAD"): @@ -79,9 +81,11 @@ def configure(conf): blddir = os.path.realpath(conf.bldnode.abspath()) libpam_wrapper_so_path = blddir + '/default/third_party/pam_wrapper/libpam-wrapper.so' pam_set_items_so_path = blddir + '/default/third_party/pam_wrapper/libpam-set-items.so' + pam_matrix_so_path = blddir + '/default/third_party/pam_wrapper/libpam-matrix.so' conf.DEFINE('LIBPAM_WRAPPER_SO_PATH', libpam_wrapper_so_path) conf.DEFINE('PAM_SET_ITEMS_SO_PATH', pam_set_items_so_path) + conf.DEFINE('PAM_MATRIX_SO_PATH', pam_matrix_so_path) conf.DEFINE('PAM_WRAPPER', 1) def build(bld): @@ -106,6 +110,12 @@ def build(bld): install=False, force_unversioned=True, realname='pam_set_items.so') + bld.SAMBA_LIBRARY('pam_matrix', + source='modules/pam_matrix.c', + deps='pam', + install=False, + force_unversioned=True, + realname='pam_matrix.so') pypamtest_cflags = '' if bld.CONFIG_SET('HAVE_WNO_ERROR_DECLARATION_AFTER_STATEMENT'):