1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-21 18:04:06 +03:00

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 <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
Stefan Metzmacher 2024-07-15 18:43:37 +02:00
parent 9afe7b7a0f
commit 97f0408f77
4 changed files with 855 additions and 2 deletions

View File

@ -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'"),

View File

@ -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',
]

View File

@ -0,0 +1,842 @@
/*
* Copyright (c) 2015 Andreas Schneider <asn@samba.org>
* Copyright (c) 2015 Jakub Hrozek <jakub.hrozek@posteo.se>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <stdint.h>
#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 <security/pam_appl.h>
#endif
#ifdef HAVE_SECURITY_PAM_MODULES_H
#include <security/pam_modules.h>
#endif
#ifdef HAVE_SECURITY_PAM_EXT_H
#include <security/pam_ext.h>
#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;
}

View File

@ -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'):