summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Gollub <dgollub at brocade.com>2014-09-27 12:06:44 +0100
committerJakub Hrozek <jhrozek@redhat.com>2014-09-29 18:27:16 +0200
commit663fd9bcdcc6b299785ba3434532cd7e6c462bff (patch)
tree6ade5b5e821fce75a1c58b63b882aa133b96c755
parent830ded27453015080a54d6ba85fd4999ee7e9af1 (diff)
downloadsssd-663fd9bcdcc6b299785ba3434532cd7e6c462bff.tar.gz
sssd-663fd9bcdcc6b299785ba3434532cd7e6c462bff.tar.xz
sssd-663fd9bcdcc6b299785ba3434532cd7e6c462bff.zip
PAM: Add domains= option to pam_sss
Design document: https://fedorahosted.org/sssd/wiki/DesignDocs/RestrictDomainsInPAM Fixes: https://fedorahosted.org/sssd/ticket/1021 Signed-off-by: Pavel Reichl <preichl@redhat.com> Reviewed-by: Sven-Thorsten Dietrich <sven@brocade.com> Reviewed-by: Jakub Hrozek <jhrozek@redhat.com> Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
-rw-r--r--src/providers/data_provider.h1
-rw-r--r--src/responder/pam/pamsrv_cmd.c51
-rw-r--r--src/sss_client/pam_sss.c29
-rw-r--r--src/sss_client/sss_cli.h1
4 files changed, 79 insertions, 3 deletions
diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
index b1279852e..ec5b79d83 100644
--- a/src/providers/data_provider.h
+++ b/src/providers/data_provider.h
@@ -172,6 +172,7 @@ struct pam_data {
char *tty;
char *ruser;
char *rhost;
+ char **requested_domains;
struct sss_auth_token *authtok;
struct sss_auth_token *newauthtok;
uint32_t cli_pid;
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index eb6953a74..c135e3c49 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -44,6 +44,28 @@ enum pam_verbosity {
static void pam_reply(struct pam_auth_req *preq);
+static bool is_domain_requested(struct pam_data *pd, const char *domain_name)
+{
+ int i;
+
+ /* If none specific domains got requested via pam, all domains are allowed.
+ * Which mimics the default/original behaviour.
+ */
+ if (!pd->requested_domains) {
+ return true;
+ }
+
+ for (i = 0; pd->requested_domains[i]; i++) {
+ if (strcmp(domain_name, pd->requested_domains[i])) {
+ continue;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
static int extract_authtok_v2(struct sss_auth_token *tok,
size_t data_size, uint8_t *body, size_t blen,
size_t *c)
@@ -143,6 +165,7 @@ static int pam_parse_in_data_v2(struct pam_data *pd,
int ret;
uint32_t start;
uint32_t terminator;
+ char *requested_domains;
if (blen < 4*sizeof(uint32_t)+2) {
DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n");
@@ -194,6 +217,20 @@ static int pam_parse_in_data_v2(struct pam_data *pd,
ret = extract_string(&pd->rhost, size, body, blen, &c);
if (ret != EOK) return ret;
break;
+ case SSS_PAM_ITEM_REQUESTED_DOMAINS:
+ ret = extract_string(&requested_domains, size, body, blen,
+ &c);
+ if (ret != EOK) return ret;
+
+ ret = split_on_separator(pd, requested_domains, ',', true,
+ true, &pd->requested_domains,
+ NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Failed to parse requested_domains list!\n");
+ return ret;
+ }
+ break;
case SSS_PAM_ITEM_CLI_PID:
ret = extract_uint32_t(&pd->cli_pid, size,
body, blen, &c);
@@ -879,6 +916,12 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
ret = ENOENT;
goto done;
}
+
+ /* skip this domain if not requested */
+ if (!is_domain_requested(pd, pd->domain)) {
+ ret = ENOENT;
+ goto done;
+ }
} else {
for (dom = preq->cctx->rctx->domains;
dom;
@@ -896,6 +939,11 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
continue;
}
+ /* skip this domain if not requested */
+ if (!is_domain_requested(pd, dom->name)) {
+ continue;
+ }
+
ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout,
dom, pd->user);
if (ncret == ENOENT) {
@@ -910,7 +958,8 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
"User [%s@%s] filtered out (negative cache). "
"Trying next domain.\n", pd->user, dom->name);
}
- if (!dom) {
+
+ if (!dom || !is_domain_requested(pd, dom->name)) {
ret = ENOENT;
goto done;
}
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index d2502d13d..abe9b0547 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -58,6 +58,7 @@
#define PW_RESET_MSG_MAX_SIZE 4096
#define OPT_RETRY_KEY "retry="
+#define OPT_DOMAINS_KEY "domains="
struct pam_items {
const char* pam_service;
@@ -81,6 +82,8 @@ struct pam_items {
pid_t cli_pid;
const char *login_name;
char *domain_name;
+ const char *requested_domains;
+ size_t requested_domains_size;
};
#define DEBUG_MGS_LEN 1024
@@ -246,6 +249,9 @@ static int pack_message_v3(struct pam_items *pi, size_t *size,
len += pi->pam_newauthtok != NULL ?
3*sizeof(uint32_t) + pi->pam_newauthtok_size : 0;
len += 3*sizeof(uint32_t); /* cli_pid */
+ len += *pi->requested_domains != '\0' ?
+ 2*sizeof(uint32_t) + pi->requested_domains_size : 0;
+
buf = malloc(len);
if (buf == NULL) {
@@ -271,6 +277,9 @@ static int pack_message_v3(struct pam_items *pi, size_t *size,
rp += add_string_item(SSS_PAM_ITEM_RHOST, pi->pam_rhost, pi->pam_rhost_size,
&buf[rp]);
+ rp += add_string_item(SSS_PAM_ITEM_REQUESTED_DOMAINS, pi->requested_domains, pi->requested_domains_size,
+ &buf[rp]);
+
rp += add_uint32_t_item(SSS_PAM_ITEM_CLI_PID, (uint32_t) pi->cli_pid,
&buf[rp]);
@@ -1061,6 +1070,9 @@ static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi)
pi->domain_name = NULL;
+ if (pi->requested_domains == NULL) pi->requested_domains = "";
+ pi->requested_domains_size = strlen(pi->requested_domains) + 1;
+
return PAM_SUCCESS;
}
@@ -1080,6 +1092,7 @@ static void print_pam_items(struct pam_items *pi)
D(("Authtok: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_authtok)));
D(("Newauthtok: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_newauthtok)));
D(("Cli_PID: %d", pi->cli_pid));
+ D(("Requested domains: %s", pi->requested_domains));
}
static int send_and_receive(pam_handle_t *pamh, struct pam_items *pi,
@@ -1271,7 +1284,8 @@ static int prompt_new_password(pam_handle_t *pamh, struct pam_items *pi)
}
static void eval_argv(pam_handle_t *pamh, int argc, const char **argv,
- uint32_t *flags, int *retries, bool *quiet_mode)
+ uint32_t *flags, int *retries, bool *quiet_mode,
+ const char **domains)
{
char *ep;
@@ -1284,6 +1298,14 @@ static void eval_argv(pam_handle_t *pamh, int argc, const char **argv,
*flags |= FLAGS_USE_FIRST_PASS;
} else if (strcmp(*argv, "use_authtok") == 0) {
*flags |= FLAGS_USE_AUTHTOK;
+ } else if (strncmp(*argv, OPT_DOMAINS_KEY, strlen(OPT_DOMAINS_KEY)) == 0) {
+ if (*(*argv+strlen(OPT_DOMAINS_KEY)) == '\0') {
+ logger(pamh, LOG_ERR, "Missing argument to option domains.");
+ *domains = "";
+ } else {
+ *domains = *argv+strlen(OPT_DOMAINS_KEY);
+ }
+
} else if (strncmp(*argv, OPT_RETRY_KEY, strlen(OPT_RETRY_KEY)) == 0) {
if (*(*argv+6) == '\0') {
logger(pamh, LOG_ERR, "Missing argument to option retry.");
@@ -1443,12 +1465,15 @@ static int pam_sss(enum sss_cli_command task, pam_handle_t *pamh,
bool retry = false;
bool quiet_mode = false;
int retries = 0;
+ const char *domains = NULL;
bindtextdomain(PACKAGE, LOCALEDIR);
D(("Hello pam_sssd: %d", task));
- eval_argv(pamh, argc, argv, &flags, &retries, &quiet_mode);
+ eval_argv(pamh, argc, argv, &flags, &retries, &quiet_mode, &domains);
+
+ pi.requested_domains = domains;
ret = get_pam_items(pamh, &pi);
if (ret != PAM_SUCCESS) {
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
index a0c635f72..edb520c8e 100644
--- a/src/sss_client/sss_cli.h
+++ b/src/sss_client/sss_cli.h
@@ -314,6 +314,7 @@ enum pam_item_type {
SSS_PAM_ITEM_NEWAUTHTOK,
SSS_PAM_ITEM_CLI_LOCALE,
SSS_PAM_ITEM_CLI_PID,
+ SSS_PAM_ITEM_REQUESTED_DOMAINS,
};
#define SSS_NSS_MAX_ENTRIES 256