summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-04-11 00:31:50 -0400
committerSimo Sorce <ssorce@redhat.com>2009-04-13 09:07:10 -0400
commit943df8483b9f8a43df72121883ca67f17571d214 (patch)
treea9301004163a7033b4a342057c355da1ea49454b /server
parentf16705ecade500f77b525d1a3df0109196c98ee0 (diff)
downloadsssd-943df8483b9f8a43df72121883ca67f17571d214.tar.gz
sssd-943df8483b9f8a43df72121883ca67f17571d214.tar.bz2
sssd-943df8483b9f8a43df72121883ca67f17571d214.zip
Implement credentials caching in pam responder.
Implement credentials caching in pam responder. Currently works only for the proxy backend. Also cleanup pam responder code and mode common code in data provider. (the data provider should never include responder private headers)
Diffstat (limited to 'server')
-rw-r--r--server/examples/sssdproxylocal6
-rw-r--r--server/examples/sssdproxytest8
-rw-r--r--server/providers/data_provider.c1
-rw-r--r--server/providers/data_provider.h47
-rw-r--r--server/providers/dp_auth_util.c (renamed from server/responder/pam/pamsrv_util.c)24
-rw-r--r--server/providers/dp_backend.h1
-rw-r--r--server/responder/pam/pam_LOCAL_domain.c153
-rw-r--r--server/responder/pam/pam_LOCAL_domain.h9
-rw-r--r--server/responder/pam/pamsrv.c3
-rw-r--r--server/responder/pam/pamsrv.h53
-rw-r--r--server/responder/pam/pamsrv_cache.c275
-rw-r--r--server/responder/pam/pamsrv_cmd.c123
-rw-r--r--server/responder/pam/pamsrv_dp.c63
-rw-r--r--server/server.mk19
14 files changed, 576 insertions, 209 deletions
diff --git a/server/examples/sssdproxylocal b/server/examples/sssdproxylocal
index 1bc47f89..063dbff3 100644
--- a/server/examples/sssdproxylocal
+++ b/server/examples/sssdproxylocal
@@ -1,9 +1,5 @@
#%PAM-1.0
-auth sufficient pam_unix.so
-auth requisite pam_succeed_if.so uid >= 500 quiet
-auth required pam_deny.so
+auth required pam_unix.so
account required pam_unix.so
-account sufficient pam_succeed_if.so uid < 500 quiet
-account required pam_permit.so
diff --git a/server/examples/sssdproxytest b/server/examples/sssdproxytest
index 9c5cb4ad..14217969 100644
--- a/server/examples/sssdproxytest
+++ b/server/examples/sssdproxytest
@@ -1,9 +1,5 @@
#%PAM-1.0
-auth sufficient pam_ldap.so debug
-auth requisite pam_succeed_if.so uid >= 1000 quiet
-auth required pam_deny.so
+auth irequired pam_ldap.so
-account required pam_ldap.so debug
-account sufficient pam_succeed_if.so uid < 1000 quiet
-account required pam_permit.so
+account required pam_ldap.so
diff --git a/server/providers/data_provider.c b/server/providers/data_provider.c
index 4614250c..e8f190ea 100644
--- a/server/providers/data_provider.c
+++ b/server/providers/data_provider.c
@@ -41,7 +41,6 @@
#include "dp_interfaces.h"
#include "monitor/monitor_sbus.h"
#include "monitor/monitor_interfaces.h"
-#include "responder/pam/pamsrv.h"
#define DP_CONF_ENTRY "config/services/dp"
diff --git a/server/providers/data_provider.h b/server/providers/data_provider.h
index 4b68a0bd..2c828fab 100644
--- a/server/providers/data_provider.h
+++ b/server/providers/data_provider.h
@@ -34,6 +34,7 @@
#include "sbus/sssd_dbus.h"
#include "sbus/sbus_client.h"
#include "providers/dp_interfaces.h"
+#include "../sss_client/sss_cli.h"
#define DATA_PROVIDER_VERSION 0x0001
#define DATA_PROVIDER_SERVICE_NAME "dp"
@@ -80,4 +81,50 @@
#define BE_REQ_GROUP 2
#define BE_REQ_INITGROUPS 3
+/* AUTH related common data and functions */
+
+#define DEBUG_PAM_DATA(level, pd) do { \
+ if (level <= debug_level) pam_print_data(level, pd); \
+} while(0);
+
+
+struct response_data {
+ int32_t type;
+ int32_t len;
+ uint8_t *data;
+ struct response_data *next;
+};
+
+struct pam_data {
+ int cmd;
+ uint32_t authtok_type;
+ uint32_t authtok_size;
+ uint32_t newauthtok_type;
+ uint32_t newauthtok_size;
+ char *domain;
+ char *user;
+ char *service;
+ char *tty;
+ char *ruser;
+ char *rhost;
+ uint8_t *authtok;
+ uint8_t *newauthtok;
+
+ int pam_status;
+ int response_delay;
+ struct response_data *resp_list;
+
+ bool offline_auth;
+};
+
+void pam_print_data(int l, struct pam_data *pd);
+
+int pam_add_response(struct pam_data *pd, enum response_type type,
+ int len, const uint8_t *data);
+
+bool dp_pack_pam_request(DBusMessage *msg, struct pam_data *pd);
+bool dp_unpack_pam_request(DBusMessage *msg, struct pam_data *pd, DBusError *dbus_error);
+bool dp_pack_pam_response(DBusMessage *msg, struct pam_data *pd);
+bool dp_unpack_pam_response(DBusMessage *msg, struct pam_data *pd, DBusError *dbus_error);
+
#endif /* __DATA_PROVIDER_ */
diff --git a/server/responder/pam/pamsrv_util.c b/server/providers/dp_auth_util.c
index ab9b733e..99e57e2e 100644
--- a/server/responder/pam/pamsrv_util.c
+++ b/server/providers/dp_auth_util.c
@@ -1,5 +1,25 @@
-#include "util/util.h"
-#include "responder/pam/pamsrv.h"
+/*
+ SSSD
+
+ Data Provider, auth utils
+
+ Copyright (C) Sumit Bose <sbose@redhat.com> 2009
+
+ 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 "data_provider.h"
void pam_print_data(int l, struct pam_data *pd)
{
diff --git a/server/providers/dp_backend.h b/server/providers/dp_backend.h
index da71e753..27f79eb7 100644
--- a/server/providers/dp_backend.h
+++ b/server/providers/dp_backend.h
@@ -24,7 +24,6 @@
#include "providers/data_provider.h"
#include "db/sysdb.h"
-#include "responder/pam/pamsrv.h"
struct be_ctx;
struct be_id_ops;
diff --git a/server/responder/pam/pam_LOCAL_domain.c b/server/responder/pam/pam_LOCAL_domain.c
index 7ee84eb6..df2803e5 100644
--- a/server/responder/pam/pam_LOCAL_domain.c
+++ b/server/responder/pam/pam_LOCAL_domain.c
@@ -1,11 +1,32 @@
+/*
+ SSSD
+
+ PAM e credentials
+
+ Copyright (C) Sumit Bose <sbose@redhat.com> 2009
+
+ 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 <time.h>
#include <security/pam_modules.h>
-#include <ldb.h>
#include "util/util.h"
-#include "responder/pam/pamsrv.h"
#include "db/sysdb.h"
#include "util/nss_sha512crypt.h"
+#include "providers/data_provider.h"
+#include "responder/pam/pamsrv.h"
#define NULL_CHECK_OR_JUMP(var, msg, ret, err, label) do { \
@@ -26,15 +47,14 @@
struct LOCAL_request {
- struct cli_ctx *cctx;
- struct pam_data *pd;
- pam_dp_callback_t callback;
struct sysdb_ctx *dbctx;
- struct sss_domain_info *domain_info;
struct sysdb_attrs *mod_attrs;
struct sysdb_req *sysdb_req;
+
struct ldb_result *res;
int error;
+
+ struct pam_auth_req *preq;
};
static int authtok2str(const void *mem_ctx, uint8_t *src, const int src_size, char **dest)
@@ -45,7 +65,7 @@ static int authtok2str(const void *mem_ctx, uint8_t *src, const int src_size, ch
}
*dest = talloc_size(mem_ctx, src_size + 1);
- if (dest == NULL) {
+ if (*dest == NULL) {
return ENOMEM;
}
memcpy(*dest, src, src_size);
@@ -56,12 +76,14 @@ static int authtok2str(const void *mem_ctx, uint8_t *src, const int src_size, ch
static void prepare_reply(struct LOCAL_request *lreq)
{
- if (lreq->error != EOK && lreq->pd->pam_status == PAM_SUCCESS)
- lreq->pd->pam_status = PAM_SYSTEM_ERR;
+ struct pam_data *pd;
+
+ pd = lreq->preq->pd;
- lreq->callback(lreq->pd);
+ if (lreq->error != EOK && pd->pam_status == PAM_SUCCESS)
+ pd->pam_status = PAM_SYSTEM_ERR;
- talloc_free(lreq);
+ lreq->preq->callback(lreq->preq);
}
static void set_user_attr_callback(void *pvt, int ldb_status, struct ldb_result *res)
@@ -93,8 +115,8 @@ static void set_user_attr_req(struct sysdb_req *req, void *pvt)
lreq->sysdb_req = req;
- ret = sysdb_set_user_attr(req, lreq->dbctx, lreq->domain_info,
- lreq->pd->user, lreq->mod_attrs,
+ ret = sysdb_set_user_attr(req, lreq->dbctx, lreq->preq->domain,
+ lreq->preq->pd->user, lreq->mod_attrs,
set_user_attr_callback, lreq);
if (ret != EOK)
sysdb_transaction_done(lreq->sysdb_req, ret);
@@ -139,10 +161,12 @@ static void do_failed_login(struct LOCAL_request *lreq)
{
int ret;
int failedLoginAttempts;
+ struct pam_data *pd;
- lreq->pd->pam_status = PAM_AUTH_ERR;
+ pd = lreq->preq->pd;
+ pd->pam_status = PAM_AUTH_ERR;
/* TODO: maybe add more inteligent delay calculation */
- lreq->pd->response_delay = 3;
+ pd->response_delay = 3;
lreq->mod_attrs = sysdb_new_attrs(lreq);
NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
@@ -175,14 +199,17 @@ done:
static void do_pam_acct_mgmt(struct LOCAL_request *lreq)
{
- const char *disabled=NULL;
+ const char *disabled;
+ struct pam_data *pd;
+
+ pd = lreq->preq->pd;
disabled = ldb_msg_find_attr_as_string(lreq->res->msgs[0],
SYSDB_DISABLED, NULL);
- if (disabled != NULL &&
- strncasecmp(disabled, "false",5)!=0 &&
- strncasecmp(disabled, "no",2)!=0 ) {
- lreq->pd->pam_status = PAM_PERM_DENIED;
+ if ((disabled != NULL) &&
+ (strncasecmp(disabled, "false",5) != 0) &&
+ (strncasecmp(disabled, "no",2) != 0) ) {
+ pd->pam_status = PAM_PERM_DENIED;
}
prepare_reply(lreq);
@@ -194,12 +221,14 @@ static void do_pam_chauthtok(struct LOCAL_request *lreq)
char *newauthtok;
char *salt;
char *new_hash;
+ struct pam_data *pd;
+
+ pd = lreq->preq->pd;
- ret = authtok2str(lreq, lreq->pd->newauthtok, lreq->pd->newauthtok_size,
- &newauthtok);
+ ret = authtok2str(lreq, pd->newauthtok, pd->newauthtok_size, &newauthtok);
NEQ_CHECK_OR_JUMP(ret, EOK, ("authtok2str failed.\n"),
lreq->error, ret, done);
- memset(lreq->pd->newauthtok, 0, lreq->pd->newauthtok_size);
+ memset(pd->newauthtok, 0, pd->newauthtok_size);
salt = gen_salt();
NULL_CHECK_OR_JUMP(salt, ("Salt generation failed.\n"),
@@ -210,7 +239,7 @@ static void do_pam_chauthtok(struct LOCAL_request *lreq)
NULL_CHECK_OR_JUMP(new_hash, ("Hash generation failed.\n"),
lreq->error, EFAULT, done);
DEBUG(4, ("New hash [%s]\n", new_hash));
- memset(newauthtok, 0, lreq->pd->newauthtok_size);
+ memset(newauthtok, 0, pd->newauthtok_size);
lreq->mod_attrs = sysdb_new_attrs(lreq);
NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
@@ -234,8 +263,8 @@ done:
prepare_reply(lreq);
}
-static void pam_handler_callback(void *pvt, int ldb_status,
- struct ldb_result *res)
+static void local_handler_callback(void *pvt, int ldb_status,
+ struct ldb_result *res)
{
struct LOCAL_request *lreq;
const char *username = NULL;
@@ -243,9 +272,11 @@ static void pam_handler_callback(void *pvt, int ldb_status,
char *newauthtok = NULL;
char *new_hash = NULL;
char *authtok = NULL;
+ struct pam_data *pd;
int ret;
lreq = talloc_get_type(pvt, struct LOCAL_request);
+ pd = lreq->preq->pd;
DEBUG(4, ("pam_handler_callback called with ldb_status [%d].\n",
ldb_status));
@@ -256,8 +287,8 @@ static void pam_handler_callback(void *pvt, int ldb_status,
if (res->count < 1) {
DEBUG(4, ("No user found with filter ["SYSDB_PWNAM_FILTER"]\n",
- lreq->pd->user));
- lreq->pd->pam_status = PAM_USER_UNKNOWN;
+ pd->user));
+ pd->pam_status = PAM_USER_UNKNOWN;
goto done;
} else if (res->count > 1) {
DEBUG(4, ("More than one object found with filter ["SYSDB_PWNAM_FILTER"]\n"));
@@ -266,27 +297,26 @@ static void pam_handler_callback(void *pvt, int ldb_status,
}
username = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
- if (strcmp(username, lreq->pd->user) != 0) {
- DEBUG(1, ("Expected username [%s] get [%s].\n", lreq->pd->user, username));
+ if (strcmp(username, pd->user) != 0) {
+ DEBUG(1, ("Expected username [%s] get [%s].\n", pd->user, username));
lreq->error = EINVAL;
goto done;
}
lreq->res = res;
- switch (lreq->pd->cmd) {
+ switch (pd->cmd) {
case SSS_PAM_AUTHENTICATE:
case SSS_PAM_CHAUTHTOK:
- if (lreq->pd->cmd == SSS_PAM_CHAUTHTOK && lreq->cctx->priv == 1) {
+ if (pd->cmd == SSS_PAM_CHAUTHTOK && lreq->preq->cctx->priv == 1) {
/* TODO: maybe this is a candiate for an explicit audit message. */
DEBUG(4, ("allowing root to reset a password.\n"));
break;
}
- ret = authtok2str(lreq, lreq->pd->authtok,
- lreq->pd->authtok_size, &authtok);
+ ret = authtok2str(lreq, pd->authtok, pd->authtok_size, &authtok);
NEQ_CHECK_OR_JUMP(ret, EOK, ("authtok2str failed.\n"),
lreq->error, ret, done);
- memset(lreq->pd->authtok, 0, lreq->pd->authtok_size);
+ memset(pd->authtok, 0, pd->authtok_size);
password = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_PWD, NULL);
NULL_CHECK_OR_JUMP(password, ("No password stored.\n"),
@@ -294,7 +324,7 @@ static void pam_handler_callback(void *pvt, int ldb_status,
DEBUG(4, ("user: [%s], password hash: [%s]\n", username, password));
new_hash = nss_sha512_crypt(authtok, password);
- memset(authtok, 0, lreq->pd->authtok_size);
+ memset(authtok, 0, pd->authtok_size);
NULL_CHECK_OR_JUMP(new_hash, ("nss_sha512_crypt failed.\n"),
lreq->error, EFAULT, done);
@@ -309,7 +339,7 @@ static void pam_handler_callback(void *pvt, int ldb_status,
break;
}
- switch (lreq->pd->cmd) {
+ switch (pd->cmd) {
case SSS_PAM_AUTHENTICATE:
do_successful_login(lreq);
return;
@@ -334,23 +364,22 @@ static void pam_handler_callback(void *pvt, int ldb_status,
}
done:
- if (lreq->pd->authtok != NULL)
- memset(lreq->pd->authtok, 0, lreq->pd->authtok_size);
+ if (pd->authtok != NULL)
+ memset(pd->authtok, 0, pd->authtok_size);
if (authtok != NULL)
- memset(authtok, 0, lreq->pd->authtok_size);
- if (lreq->pd->newauthtok != NULL)
- memset(lreq->pd->newauthtok, 0, lreq->pd->newauthtok_size);
+ memset(authtok, 0, pd->authtok_size);
+ if (pd->newauthtok != NULL)
+ memset(pd->newauthtok, 0, pd->newauthtok_size);
if (newauthtok != NULL)
- memset(newauthtok, 0, lreq->pd->newauthtok_size);
+ memset(newauthtok, 0, pd->newauthtok_size);
prepare_reply(lreq);
}
-int LOCAL_pam_handler(struct cli_ctx *cctx, pam_dp_callback_t callback,
- struct sss_domain_info *dom, struct pam_data *pd)
+int LOCAL_pam_handler(struct pam_auth_req *preq)
{
int ret;
- struct LOCAL_request *lreq=NULL;
+ struct LOCAL_request *lreq;
static const char *attrs[] = {SYSDB_NAME,
SYSDB_PWD,
@@ -364,37 +393,27 @@ int LOCAL_pam_handler(struct cli_ctx *cctx, pam_dp_callback_t callback,
"lastFailedLogin",
NULL};
- lreq = talloc_zero(cctx, struct LOCAL_request);
+ DEBUG(4, ("LOCAL pam handler.\n"));
+
+ lreq = talloc_zero(preq, struct LOCAL_request);
if (!lreq) {
return ENOMEM;
}
- lreq->cctx = cctx;
- lreq->pd = pd;
- lreq->callback = callback;
- lreq->pd->pam_status = PAM_SUCCESS;
- lreq->error = EOK;
-
-
- DEBUG(4, ("LOCAL pam handler.\n"));
- lreq->domain_info = dom;
- NULL_CHECK_OR_JUMP(lreq->domain_info, ("Domain info not found.\n"),
- ret, EINVAL, done);
+ lreq->dbctx = preq->cctx->rctx->sysdb;
+ lreq->preq = preq;
- lreq->dbctx = lreq->cctx->rctx->sysdb;
+ preq->pd->pam_status = PAM_SUCCESS;
ret = sysdb_get_user_attr(lreq, lreq->dbctx,
- lreq->domain_info, lreq->pd->user, attrs,
- pam_handler_callback, lreq);
+ preq->domain, preq->pd->user, attrs,
+ local_handler_callback, preq);
- if(ret != EOK) {
+ if (ret != EOK) {
DEBUG(1, ("sysdb_get_user_attr failed.\n"));
- goto done;
+ talloc_free(lreq);
+ return ret;
}
return EOK;
-
-done:
- talloc_free(lreq);
- return ret;
}
diff --git a/server/responder/pam/pam_LOCAL_domain.h b/server/responder/pam/pam_LOCAL_domain.h
deleted file mode 100644
index bc2064db..00000000
--- a/server/responder/pam/pam_LOCAL_domain.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __PAM_LOCAL_DOMAIN_H__
-#define __PAM_LOCAL_DOMAIN_H__
-
-#include "responder/pam/pamsrv.h"
-
-int LOCAL_pam_handler(struct cli_ctx *cctx, pam_dp_callback_t callback,
- struct sss_domain_info *dom, struct pam_data *pd);
-
-#endif /* __PAM_LOCAL_DOMAIN_H__ */
diff --git a/server/responder/pam/pamsrv.c b/server/responder/pam/pamsrv.c
index 2f74a4ac..1adbb14c 100644
--- a/server/responder/pam/pamsrv.c
+++ b/server/responder/pam/pamsrv.c
@@ -3,7 +3,8 @@
PAM Responder
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
+ Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
+ Copyright (C) Sumit Bose <sbose@redhat.com> 2009
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
diff --git a/server/responder/pam/pamsrv.h b/server/responder/pam/pamsrv.h
index 077b495d..c751ceed 100644
--- a/server/responder/pam/pamsrv.h
+++ b/server/responder/pam/pamsrv.h
@@ -1,59 +1,34 @@
#ifndef __PAMSRV_H__
#define __PAMSRV_H__
-
+#include <security/pam_appl.h>
#include "util/util.h"
#include "sbus/sssd_dbus.h"
#include "responder/common/responder.h"
#define PAM_DP_TIMEOUT 5000
-#define DEBUG_PAM_DATA(level, pd) do { \
- if (level <= debug_level) pam_print_data(level, pd); \
-} while(0);
+struct pam_auth_req;
-struct response_data {
- int32_t type;
- int32_t len;
- uint8_t *data;
- struct response_data *next;
-};
+typedef void (pam_dp_callback_t)(struct pam_auth_req *preq);
-struct pam_data {
- int cmd;
- uint32_t authtok_type;
- uint32_t authtok_size;
- uint32_t newauthtok_type;
- uint32_t newauthtok_size;
- char *domain;
- char *user;
- char *service;
- char *tty;
- char *ruser;
- char *rhost;
- uint8_t *authtok;
- uint8_t *newauthtok;
-
- int pam_status;
- int response_delay;
- struct response_data *resp_list;
+struct pam_auth_req {
struct cli_ctx *cctx;
-};
+ struct sss_domain_info *domain;
-int pam_add_response(struct pam_data *pd, enum response_type type,
- int len, const uint8_t *data);
-void pam_print_data(int l, struct pam_data *pd);
+ struct pam_data *pd;
-typedef void (*pam_dp_callback_t)(struct pam_data *pd);
+ pam_dp_callback_t *callback;
+};
struct sbus_method *register_pam_dp_methods(void);
struct sss_cmd_table *register_sss_cmds(void);
-int pam_dp_send_req(struct cli_ctx *cctx, pam_dp_callback_t callback,
- int timeout, struct pam_data *pd);
+int pam_dp_send_req(struct pam_auth_req *preq, int timeout);
+
+int pam_cache_credentials(struct pam_auth_req *preq);
+int pam_cache_auth(struct pam_auth_req *preq);
+
+int LOCAL_pam_handler(struct pam_auth_req *preq);
-bool dp_pack_pam_request(DBusMessage *msg, struct pam_data *pd);
-bool dp_unpack_pam_request(DBusMessage *msg, struct pam_data *pd, DBusError *dbus_error);
-bool dp_pack_pam_response(DBusMessage *msg, struct pam_data *pd);
-bool dp_unpack_pam_response(DBusMessage *msg, struct pam_data *pd, DBusError *dbus_error);
#endif /* __PAMSRV_H__ */
diff --git a/server/responder/pam/pamsrv_cache.c b/server/responder/pam/pamsrv_cache.c
new file mode 100644
index 00000000..10f41996
--- /dev/null
+++ b/server/responder/pam/pamsrv_cache.c
@@ -0,0 +1,275 @@
+/*
+ SSSD
+
+ PAM cache credentials
+
+ Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
+ Copyright (C) Sumit Bose <sbose@redhat.com> 2009
+
+ 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 <security/pam_modules.h>
+#include <time.h>
+#include "util/util.h"
+#include "db/sysdb.h"
+#include "util/nss_sha512crypt.h"
+#include "providers/data_provider.h"
+#include "responder/pam/pamsrv.h"
+
+static int authtok2str(const void *mem_ctx,
+ uint8_t *src, const int src_size,
+ char **_dest)
+{
+ char *dest;
+
+ if ((src == NULL && src_size != 0) ||
+ (src != NULL && *src != '\0' && src_size == 0)) {
+ return EINVAL;
+ }
+
+ dest = talloc_size(mem_ctx, src_size + 1);
+ if (dest == NULL) {
+ return ENOMEM;
+ }
+
+ memcpy(dest, src, src_size);
+ dest[src_size]='\0';
+
+ *_dest = dest;
+ return EOK;
+}
+
+struct set_attrs_ctx {
+ struct pam_auth_req *preq;
+ struct sysdb_attrs *attrs;
+ struct sysdb_req *sysreq;
+};
+
+static void pc_set_user_attr_callback(void *pvt,
+ int ldb_status,
+ struct ldb_result *res)
+{
+ struct set_attrs_ctx *ctx;
+ int error;
+
+ ctx = talloc_get_type(pvt, struct set_attrs_ctx);
+ error = sysdb_error_to_errno(ldb_status);
+
+ sysdb_transaction_done(ctx->sysreq, error);
+
+ if (ldb_status != LDB_SUCCESS) {
+ DEBUG(2, ("Failed to cache credentials for user [%s] (%d)!\n",
+ ctx->preq->pd->user, error, strerror(error)));
+ }
+
+ ctx->preq->callback(ctx->preq);
+}
+
+static void pc_set_user_attr_req(struct sysdb_req *req, void *pvt)
+{
+ struct set_attrs_ctx *ctx;
+ int ret;
+
+ DEBUG(4, ("entering pc_set_user_attr_req\n"));
+
+ ctx = talloc_get_type(pvt, struct set_attrs_ctx);
+
+ ctx->sysreq = req;
+
+ ret = sysdb_set_user_attr(req, ctx->preq->cctx->rctx->sysdb,
+ ctx->preq->domain,
+ ctx->preq->pd->user,
+ ctx->attrs,
+ pc_set_user_attr_callback, ctx);
+ if (ret != EOK) {
+ sysdb_transaction_done(ctx->sysreq, ret);
+ }
+
+ if (ret != EOK) {
+ DEBUG(2, ("Failed to cache credentials for user [%s] (%d)!\n",
+ ctx->preq->pd->user, ret, strerror(ret)));
+ ctx->preq->callback(ctx->preq);
+ }
+}
+
+int pam_cache_credentials(struct pam_auth_req *preq)
+{
+ struct set_attrs_ctx *ctx;
+ struct pam_data *pd;
+ char *password = NULL;
+ char *comphash = NULL;
+ char *salt;
+ int i, ret;
+
+ pd = preq->pd;
+
+ ret = authtok2str(preq, pd->authtok, pd->authtok_size, &password);
+ if (ret) {
+ DEBUG(4, ("Invalid auth token.\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ salt = gen_salt();
+ if (!salt) {
+ DEBUG(4, ("Failed to generate random salt.\n"));
+ ret = EFAULT;
+ goto done;
+ }
+
+ comphash = nss_sha512_crypt(password, salt);
+ if (!comphash) {
+ DEBUG(4, ("Failed to create password hash.\n"));
+ ret = EFAULT;
+ goto done;
+ }
+
+ ctx = talloc_zero(preq, struct set_attrs_ctx);
+ if (!ctx) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ctx->preq = preq;
+
+ ctx->attrs = sysdb_new_attrs(ctx);
+ if (!ctx->attrs) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_attrs_add_string(ctx->attrs, SYSDB_PWD, comphash);
+ if (ret) goto done;
+
+ /* FIXME: should we use a different attribute for chache passwords ?? */
+ ret = sysdb_attrs_add_long(ctx->attrs, "lastPasswordChange",
+ (long)time(NULL));
+ if (ret) goto done;
+
+ ret = sysdb_transaction(ctx, preq->cctx->rctx->sysdb,
+ pc_set_user_attr_req, ctx);
+
+done:
+ if (password) for (i = 0; password[i]; i++) password[i] = 0;
+ if (ret != EOK) {
+ DEBUG(2, ("Failed to cache credentials for user [%s] (%d)!\n",
+ pd->user, ret, strerror(ret)));
+ }
+ return ret;
+}
+
+static void pam_cache_auth_return(struct pam_auth_req *preq, int error)
+{
+ preq->pd->pam_status = error;
+ preq->callback(preq);
+}
+
+static void pam_cache_auth_callback(void *pvt, int ldb_status,
+ struct ldb_result *res)
+{
+ struct pam_auth_req *preq;
+ struct pam_data *pd;
+ const char *userhash;
+ const char *comphash;
+ char *password = NULL;
+ int i, ret;
+
+ preq = talloc_get_type(pvt, struct pam_auth_req);
+ pd = preq->pd;
+
+ if (ldb_status != LDB_SUCCESS) {
+ DEBUG(4, ("User info retireval failed! (%d [%s])\n",
+ ldb_status, sysdb_error_to_errno(ldb_status)));
+
+ ret = PAM_SYSTEM_ERR;
+ goto done;
+ }
+
+ if (res->count == 0) {
+ DEBUG(4, ("User [%s@%s] not found.\n",
+ pd->user, preq->domain->name));
+ ret = PAM_USER_UNKNOWN;
+ goto done;
+ }
+
+ if (res->count != 1) {
+ DEBUG(4, ("Too manyt results for user [%s@%s].\n",
+ pd->user, preq->domain->name));
+ ret = PAM_SYSTEM_ERR;
+ goto done;
+ }
+
+ /* TODO: verify user account (failed logins, disabled, expired ...) */
+
+ ret = authtok2str(preq, pd->authtok, pd->authtok_size, &password);
+ if (ret) {
+ DEBUG(4, ("Invalid auth token.\n"));
+ ret = PAM_AUTH_ERR;
+ goto done;
+ }
+
+ userhash = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_PWD, NULL);
+ if (userhash == NULL || *userhash == '\0') {
+ DEBUG(4, ("Cached credentials not available.\n"));
+ ret = PAM_AUTHINFO_UNAVAIL;
+ goto done;
+ }
+
+ comphash = nss_sha512_crypt(password, userhash);
+ if (!comphash) {
+ DEBUG(4, ("Failed to create password hash.\n"));
+ ret = PAM_SYSTEM_ERR;
+ goto done;
+ }
+
+ if (strcmp(userhash, comphash) == 0) {
+ /* TODO: probable good point for audit logging */
+ DEBUG(4, ("Hashes do match!\n"));
+ ret = PAM_SUCCESS;
+ goto done;
+ }
+
+ DEBUG(4, ("Authentication failed.\n"));
+ ret = PAM_AUTH_ERR;
+
+done:
+ if (password) for (i = 0; password[i]; i++) password[i] = 0;
+ pam_cache_auth_return(preq, ret);
+}
+
+int pam_cache_auth(struct pam_auth_req *preq)
+{
+ int ret;
+
+ static const char *attrs[] = {SYSDB_NAME,
+ SYSDB_PWD,
+ SYSDB_DISABLED,
+ SYSDB_LAST_LOGIN,
+ "lastPasswordChange",
+ "accountExpires",
+ "failedLoginAttempts",
+ "lastFailedLogin",
+ NULL};
+
+ ret = sysdb_get_user_attr(preq, preq->cctx->rctx->sysdb,
+ preq->domain, preq->pd->user, attrs,
+ pam_cache_auth_callback, preq);
+
+ if (ret != EOK) {
+ DEBUG(2, ("sysdb_get_user_attr failed.\n"));
+ }
+
+ return ret;
+}
+
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
index db5f064f..2190b566 100644
--- a/server/responder/pam/pamsrv_cmd.c
+++ b/server/responder/pam/pamsrv_cmd.c
@@ -1,10 +1,32 @@
+/*
+ SSSD
+
+ PAM Responder
+
+ Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
+ Copyright (C) Sumit Bose <sbose@redhat.com> 2009
+
+ 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 <errno.h>
#include <talloc.h>
#include "util/util.h"
#include "confdb/confdb.h"
#include "responder/common/responder_packet.h"
-#include "responder/pam/pam_LOCAL_domain.h"
+#include "providers/data_provider.h"
#include "responder/pam/pamsrv.h"
static int pam_parse_in_data(struct sss_names_ctx *snctx,
@@ -86,19 +108,20 @@ static int pam_parse_in_data(struct sss_names_ctx *snctx,
return EOK;
}
-static void pam_reply(struct pam_data *pd);
+static void pam_reply(struct pam_auth_req *preq);
static void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
struct timeval tv, void *pvt)
{
- struct pam_data *pd;
+ struct pam_auth_req *preq;
+
DEBUG(4, ("pam_reply_delay get called.\n"));
- pd = talloc_get_type(pvt, struct pam_data);
+ preq = talloc_get_type(pvt, struct pam_auth_req);
- pam_reply(pd);
+ pam_reply(preq);
}
-static void pam_reply(struct pam_data *pd)
+static void pam_reply(struct pam_auth_req *preq)
{
struct cli_ctx *cctx;
uint8_t *body;
@@ -111,13 +134,48 @@ static void pam_reply(struct pam_data *pd)
int p;
struct timeval tv;
struct tevent_timer *te;
+ struct pam_data *pd;
+
+ pd = preq->pd;
DEBUG(4, ("pam_reply get called.\n"));
+ if ((pd->cmd == SSS_PAM_AUTHENTICATE) &&
+ (preq->domain->cache_credentials == true) &&
+ (pd->offline_auth == false)) {
+
+ if (pd->pam_status == PAM_SUCCESS) {
+ pd->offline_auth = true;
+ preq->callback = pam_reply;
+ ret = pam_cache_credentials(preq);
+ if (ret == EOK) {
+ return;
+ }
+ else {
+ DEBUG(0, ("Failed to cache credentials"));
+ /* this error is not fatal, continue */
+ }
+ }
+
+ if (pd->pam_status == PAM_AUTHINFO_UNAVAIL) {
+ /* do auth with offline credentials */
+ pd->offline_auth = true;
+ preq->callback = pam_reply;
+ ret = pam_cache_auth(preq);
+ if (ret == EOK) {
+ return;
+ }
+ else {
+ DEBUG(1, ("Failed to setup offline auth"));
+ /* this error is not fatal, continue */
+ }
+ }
+ }
+
if (pd->response_delay > 0) {
ret = gettimeofday(&tv, NULL);
if (ret != EOK) {
- DEBUG(0, ("gettimeofday failed [%d][%s].\n",
+ DEBUG(1, ("gettimeofday failed [%d][%s].\n",
errno, strerror(errno)));
err = ret;
goto done;
@@ -126,9 +184,9 @@ static void pam_reply(struct pam_data *pd)
tv.tv_usec = 0;
pd->response_delay = 0;
- te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, pd);
+ te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, preq);
if (te == NULL) {
- DEBUG(0, ("Failed to add event pam_reply_delay.\n"));
+ DEBUG(1, ("Failed to add event pam_reply_delay.\n"));
err = ENOMEM;
goto done;
}
@@ -136,7 +194,7 @@ static void pam_reply(struct pam_data *pd)
return;
}
- cctx = pd->cctx;
+ cctx = preq->cctx;
ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
@@ -191,8 +249,7 @@ static void pam_reply(struct pam_data *pd)
}
done:
- talloc_free(pd);
- sss_cmd_done(cctx, NULL);
+ sss_cmd_done(cctx, preq);
}
static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
@@ -201,50 +258,60 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
uint8_t *body;
size_t blen;
int ret;
+ struct pam_auth_req *preq;
struct pam_data *pd;
- pd = talloc(cctx, struct pam_data);
- if (pd == NULL) return ENOMEM;
+ preq = talloc_zero(cctx, struct pam_auth_req);
+ if (!preq) {
+ return ENOMEM;
+ }
+ preq->cctx = cctx;
+
+ preq->pd = talloc_zero(preq, struct pam_data);
+ if (!preq->pd) {
+ talloc_free(preq);
+ return ENOMEM;
+ }
+ pd = preq->pd;
sss_packet_get_body(cctx->creq->in, &body, &blen);
if (blen >= sizeof(uint32_t) &&
((uint32_t *)(&body[blen - sizeof(uint32_t)]))[0] != END_OF_PAM_REQUEST) {
DEBUG(1, ("Received data not terminated.\n"));
- talloc_free(pd);
+ talloc_free(preq);
return EINVAL;
}
pd->cmd = pam_cmd;
- pd->cctx = cctx;
- ret=pam_parse_in_data(cctx->rctx->names, pd, body, blen);
- if( ret != 0 ) {
- talloc_free(pd);
+ ret = pam_parse_in_data(cctx->rctx->names, pd, body, blen);
+ if (ret != 0) {
+ talloc_free(preq);
return EINVAL;
}
- pd->response_delay = 0;
- pd->resp_list = NULL;
-
if (pd->domain) {
for (dom = cctx->rctx->domains; dom; dom = dom->next) {
if (strcasecmp(dom->name, pd->domain) == 0) break;
}
if (!dom) {
- talloc_free(pd);
+ talloc_free(preq);
return EINVAL;
}
+ preq->domain = dom;
}
else {
DEBUG(4, ("Domain not provided, using default.\n"));
- dom = cctx->rctx->domains;
- pd->domain = dom->name;
+ preq->domain = cctx->rctx->domains;
+ pd->domain = preq->domain->name;
}
- if (!dom->provider) {
- return LOCAL_pam_handler(cctx, pam_reply, dom, pd);
+ if (!preq->domain->provider) {
+ preq->callback = pam_reply;
+ return LOCAL_pam_handler(preq);
};
- ret = pam_dp_send_req(cctx, pam_reply, PAM_DP_TIMEOUT, pd);
+ preq->callback = pam_reply;
+ ret = pam_dp_send_req(preq, PAM_DP_TIMEOUT);
DEBUG(4, ("pam_dp_send_req returned %d\n", ret));
return ret;
diff --git a/server/responder/pam/pamsrv_dp.c b/server/responder/pam/pamsrv_dp.c
index 3555c20e..f352b270 100644
--- a/server/responder/pam/pamsrv_dp.c
+++ b/server/responder/pam/pamsrv_dp.c
@@ -32,21 +32,15 @@
#include "providers/dp_sbus.h"
#include "responder/pam/pamsrv.h"
-struct pam_reply_ctx {
- struct cli_ctx *cctx;
- struct pam_data *pd;
- pam_dp_callback_t callback;
-};
-
-static void pam_process_dp_reply(DBusPendingCall *pending, void *ptr)
+static void pam_dp_process_reply(DBusPendingCall *pending, void *ptr)
{
DBusError dbus_error;
DBusMessage* msg;
int ret;
int type;
- struct pam_reply_ctx *rctx;
+ struct pam_auth_req *preq;
- rctx = talloc_get_type(ptr, struct pam_reply_ctx);
+ preq = talloc_get_type(ptr, struct pam_auth_req);
dbus_error_init(&dbus_error);
@@ -54,7 +48,7 @@ static void pam_process_dp_reply(DBusPendingCall *pending, void *ptr)
msg = dbus_pending_call_steal_reply(pending);
if (msg == NULL) {
DEBUG(0, ("Severe error. A reply callback was called but no reply was received and no timeout occurred\n"));
- rctx->pd->pam_status = PAM_SYSTEM_ERR;
+ preq->pd->pam_status = PAM_SYSTEM_ERR;
goto done;
}
@@ -62,57 +56,44 @@ static void pam_process_dp_reply(DBusPendingCall *pending, void *ptr)
type = dbus_message_get_type(msg);
switch (type) {
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
- ret = dp_unpack_pam_response(msg, rctx->pd, &dbus_error);
+ ret = dp_unpack_pam_response(msg, preq->pd, &dbus_error);
if (!ret) {
DEBUG(0, ("Failed to parse reply.\n"));
- rctx->pd->pam_status = PAM_SYSTEM_ERR;
+ preq->pd->pam_status = PAM_SYSTEM_ERR;
goto done;
}
- DEBUG(4, ("received: [%d][%s]\n", rctx->pd->pam_status, rctx->pd->domain));
+ DEBUG(4, ("received: [%d][%s]\n", preq->pd->pam_status, preq->pd->domain));
break;
case DBUS_MESSAGE_TYPE_ERROR:
DEBUG(0, ("Reply error.\n"));
- rctx->pd->pam_status = PAM_SYSTEM_ERR;
+ preq->pd->pam_status = PAM_SYSTEM_ERR;
break;
default:
DEBUG(0, ("Default... what now?.\n"));
- rctx->pd->pam_status = PAM_SYSTEM_ERR;
+ preq->pd->pam_status = PAM_SYSTEM_ERR;
}
done:
dbus_pending_call_unref(pending);
dbus_message_unref(msg);
- rctx->callback(rctx->pd);
-
- talloc_free(rctx);
+ preq->callback(preq);
}
-int pam_dp_send_req(struct cli_ctx *cctx,
- pam_dp_callback_t callback,
- int timeout, struct pam_data *pd)
+int pam_dp_send_req(struct pam_auth_req *preq, int timeout)
{
+ struct pam_data *pd = preq->pd;
DBusMessage *msg;
DBusPendingCall *pending_reply;
DBusConnection *conn;
dbus_bool_t ret;
- struct pam_reply_ctx *rctx;
- rctx = talloc(cctx, struct pam_reply_ctx);
- if (rctx == NULL) {
- DEBUG(0,("Out of memory?!\n"));
- return ENOMEM;
- }
- rctx->cctx = cctx;
- rctx->callback = callback;
- rctx->pd = pd;
-
- if (pd->domain==NULL ||
- pd->user==NULL ||
- pd->service==NULL ||
- pd->tty==NULL ||
- pd->ruser==NULL ||
- pd->rhost==NULL ) {
+ if ((pd->domain == NULL) ||
+ (pd->user == NULL) ||
+ (pd->service == NULL) ||
+ (pd->tty == NULL) ||
+ (pd->ruser == NULL) ||
+ (pd->rhost == NULL) ) {
return EINVAL;
}
@@ -120,12 +101,12 @@ int pam_dp_send_req(struct cli_ctx *cctx,
* in some pathological cases it may happen that nss starts up before
* dp connection code is actually able to establish a connection.
*/
- if (!cctx->rctx->dp_ctx) {
+ if (!preq->cctx->rctx->dp_ctx) {
DEBUG(1, ("The Data Provider connection is not available yet!"
" This maybe a bug, it shouldn't happen!\n"));
return EIO;
}
- conn = sbus_get_connection(cctx->rctx->dp_ctx->scon_ctx);
+ conn = sbus_get_connection(preq->cctx->rctx->dp_ctx->scon_ctx);
msg = dbus_message_new_method_call(NULL,
DP_CLI_PATH,
@@ -158,8 +139,8 @@ int pam_dp_send_req(struct cli_ctx *cctx,
return EIO;
}
- dbus_pending_call_set_notify(pending_reply, pam_process_dp_reply, rctx,
- NULL);
+ dbus_pending_call_set_notify(pending_reply,
+ pam_dp_process_reply, preq, NULL);
dbus_message_unref(msg);
return EOK;
diff --git a/server/server.mk b/server/server.mk
index 9785f636..07848939 100644
--- a/server/server.mk
+++ b/server/server.mk
@@ -7,6 +7,7 @@ UTIL_OBJ = \
util/usertools.o \
monitor/monitor_sbus.o \
providers/dp_sbus.o \
+ providers/dp_auth_util.o \
sbus/sssd_dbus_common.o \
sbus/sssd_dbus_connection.o \
sbus/sssd_dbus_server.o \
@@ -30,7 +31,7 @@ DP_OBJ = \
providers/data_provider.o
DP_BE_OBJ = \
- providers/data_provider_be.o \
+ providers/data_provider_be.o
PROXY_BE_OBJ = \
providers/proxy.o
@@ -62,16 +63,16 @@ SYSDB_TEST_OBJ = \
INFP_TEST_OBJ = \
tests/infopipe-tests.o
-CRYPT_OBJ = util/nss_sha512crypt.o
+CRYPT_OBJ = \
+ util/nss_sha512crypt.o
PAMSRV_OBJ = \
responder/pam/pamsrv.o \
responder/pam/pamsrv_cmd.o \
+ responder/pam/pamsrv_cache.o \
responder/pam/pam_LOCAL_domain.o \
responder/pam/pamsrv_dp.o
-PAMSRV_UTIL_OBJ = responder/pam/pamsrv_util.o
-
$(LDAP_BE_OBJ): CFLAGS += $(LDAP_CFLAGS)
$(CRYPT_OBJ): CFLAGS += $(NSS_CFLAGS)
@@ -103,14 +104,14 @@ sbin/sssd: $(SERVER_OBJ) $(UTIL_OBJ)
sbin/sssd_nss: $(NSSSRV_OBJ) $(UTIL_OBJ) $(RESPONDER_UTIL_OBJ)
$(CC) -o sbin/sssd_nss $(NSSSRV_OBJ) $(UTIL_OBJ) $(RESPONDER_UTIL_OBJ) $(LDFLAGS) $(LIBS)
-sbin/sssd_pam: $(PAMSRV_OBJ) $(UTIL_OBJ) $(RESPONDER_UTIL_OBJ) $(PAMSRV_UTIL_OBJ) $(CRYPT_OBJ)
- $(CC) -o sbin/sssd_pam $(PAMSRV_OBJ) $(UTIL_OBJ) $(PAMSRV_UTIL_OBJ) $(RESPONDER_UTIL_OBJ) $(CRYPT_OBJ) $(LDFLAGS) $(LIBS) $(NSS_LIBS)
+sbin/sssd_pam: $(PAMSRV_OBJ) $(UTIL_OBJ) $(RESPONDER_UTIL_OBJ) $(CRYPT_OBJ)
+ $(CC) -o sbin/sssd_pam $(PAMSRV_OBJ) $(UTIL_OBJ) $(RESPONDER_UTIL_OBJ) $(CRYPT_OBJ) $(LDFLAGS) $(LIBS) $(NSS_LIBS)
-sbin/sssd_dp: $(DP_OBJ) $(UTIL_OBJ) $(PAMSRV_UTIL_OBJ)
- $(CC) -o sbin/sssd_dp $(DP_OBJ) $(UTIL_OBJ) $(PAMSRV_UTIL_OBJ) $(LDFLAGS) $(LIBS)
+sbin/sssd_dp: $(DP_OBJ) $(UTIL_OBJ)
+ $(CC) -o sbin/sssd_dp $(DP_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS)
sbin/sssd_be: $(DP_BE_OBJ) $(UTIL_OBJ)
- $(CC) -Wl,-E -o sbin/sssd_be $(DP_BE_OBJ) $(UTIL_OBJ) $(PAMSRV_UTIL_OBJ) $(LDFLAGS) $(LIBS) $(PAM_LIBS)
+ $(CC) -Wl,-E -o sbin/sssd_be $(DP_BE_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS) $(PAM_LIBS)
sbin/sssd_info: $(INFOPIPE_OBJ) $(UTIL_OBJ)
$(CC) -o sbin/sssd_info $(INFOPIPE_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS)