summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2009-05-14 12:42:05 +0200
committerSimo Sorce <ssorce@redhat.com>2009-05-15 19:09:45 -0400
commit67ce05ee0351a4d014a726e7a2e6757e13e2a201 (patch)
treeced9ca464aa9d746b71fff811cecfce8157b6384
parentab691765dc8d727d01f061d846e7c765e89fb299 (diff)
downloadsssd-67ce05ee0351a4d014a726e7a2e6757e13e2a201.tar.gz
sssd-67ce05ee0351a4d014a726e7a2e6757e13e2a201.tar.xz
sssd-67ce05ee0351a4d014a726e7a2e6757e13e2a201.zip
added new pam client protocol
-rw-r--r--server/responder/pam/pamsrv_cmd.c133
-rw-r--r--sss_client/pam_sss.c138
-rw-r--r--sss_client/sss_cli.h15
3 files changed, 282 insertions, 4 deletions
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
index 02b52138e..00765d47c 100644
--- a/server/responder/pam/pamsrv_cmd.c
+++ b/server/responder/pam/pamsrv_cmd.c
@@ -29,6 +29,124 @@
#include "responder/pam/pamsrv.h"
#include "db/sysdb.h"
+static int extract_authtok(uint32_t *type, uint32_t *size, uint8_t **tok, uint8_t *body, size_t blen, size_t *c) {
+ size_t data_size;
+
+ if (blen-(*c) < 2*sizeof(uint32_t)) return EINVAL;
+
+ data_size = ((uint32_t *)&body[*c])[0];
+ *c += sizeof(uint32_t);
+ if (data_size < sizeof(uint32_t) || (*c)+(data_size) > blen) return EINVAL;
+ *size = data_size - sizeof(uint32_t);
+
+ *type = ((uint32_t *)&body[*c])[0];
+ *c += sizeof(uint32_t);
+
+ *tok = body+(*c);
+
+ *c += (*size);
+
+ return EOK;
+}
+
+static int extract_string(char **var, uint8_t *body, size_t blen, size_t *c) {
+ uint32_t size;
+ uint8_t *str;
+
+ if (blen-(*c) < sizeof(uint32_t)+1) return EINVAL;
+
+ size = ((uint32_t *)&body[*c])[0];
+ *c += sizeof(uint32_t);
+ if (*c+size > blen) return EINVAL;
+
+ str = body+(*c);
+
+ if (str[size-1]!='\0') return EINVAL;
+
+ *c += size;
+
+ *var = (char *) str;
+
+ return EOK;
+}
+
+static int pam_parse_in_data_v2(struct sss_names_ctx *snctx,
+ struct pam_data *pd,
+ uint8_t *body, size_t blen)
+{
+ size_t c;
+ uint32_t type;
+ uint32_t size;
+ char *pam_user;
+ int ret;
+
+ if (blen < 4*sizeof(uint32_t)+2 ||
+ ((uint32_t *)body)[0] != START_OF_PAM_REQUEST ||
+ ((uint32_t *)(&body[blen - sizeof(uint32_t)]))[0] != END_OF_PAM_REQUEST) {
+ DEBUG(1, ("Received data is invalid.\n"));
+ return EINVAL;
+ }
+
+ c = sizeof(uint32_t);
+ do {
+ type = ((uint32_t *)&body[c])[0];
+ c += sizeof(uint32_t);
+ if (c > blen) return EINVAL;
+
+ switch(type) {
+ case PAM_ITEM_USER:
+ ret = extract_string(&pam_user, body, blen, &c);
+ if (ret != EOK) return ret;
+
+ ret = sss_parse_name(pd, snctx, pam_user,
+ &pd->domain, &pd->user);
+ if (ret != EOK) return ret;
+ break;
+ case PAM_ITEM_SERVICE:
+ ret = extract_string(&pd->service, body, blen, &c);
+ if (ret != EOK) return ret;
+ break;
+ case PAM_ITEM_TTY:
+ ret = extract_string(&pd->tty, body, blen, &c);
+ if (ret != EOK) return ret;
+ break;
+ case PAM_ITEM_RUSER:
+ ret = extract_string(&pd->ruser, body, blen, &c);
+ if (ret != EOK) return ret;
+ break;
+ case PAM_ITEM_RHOST:
+ ret = extract_string(&pd->rhost, body, blen, &c);
+ if (ret != EOK) return ret;
+ break;
+ case PAM_ITEM_AUTHTOK:
+ ret = extract_authtok(&pd->authtok_type, &pd->authtok_size,
+ &pd->authtok, body, blen, &c);
+ if (ret != EOK) return ret;
+ break;
+ case PAM_ITEM_NEWAUTHTOK:
+ ret = extract_authtok(&pd->newauthtok_type,
+ &pd->newauthtok_size,
+ &pd->newauthtok, body, blen, &c);
+ if (ret != EOK) return ret;
+ break;
+ case END_OF_PAM_REQUEST:
+ if (c != blen) return EINVAL;
+ break;
+ default:
+ DEBUG(1,("Ignoring unknown data type [%d].\n", type));
+ size = ((uint32_t *)&body[c])[0];
+ c += size+sizeof(uint32_t);
+ }
+ } while(c < blen);
+
+ if (pd->user == NULL || *pd->user == '\0') return EINVAL;
+
+ DEBUG_PAM_DATA(4, pd);
+
+ return EOK;
+
+}
+
static int pam_parse_in_data(struct sss_names_ctx *snctx,
struct pam_data *pd,
uint8_t *body, size_t blen)
@@ -307,7 +425,19 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
pd->cmd = pam_cmd;
pd->priv = cctx->priv;
- ret = pam_parse_in_data(cctx->rctx->names, pd, body, blen);
+
+ switch (cctx->cli_protocol_version->version) {
+ case 1:
+ ret = pam_parse_in_data(cctx->rctx->names, pd, body, blen);
+ break;
+ case 2:
+ ret = pam_parse_in_data_v2(cctx->rctx->names, pd, body, blen);
+ break;
+ default:
+ DEBUG(1, ("Illegal protocol version [%d].\n",
+ cctx->cli_protocol_version->version));
+ ret = EINVAL;
+ }
if (ret != EOK) {
talloc_free(preq);
ret = EINVAL;
@@ -660,6 +790,7 @@ struct cli_protocol_version *register_cli_protocol_version(void)
{
static struct cli_protocol_version pam_cli_protocol_version[] = {
{1, "2008-09-05", "initial version, \\0 terminated strings"},
+ {2, "2009-05-12", "new format <type><size><data>"},
{0, NULL, NULL}
};
diff --git a/sss_client/pam_sss.c b/sss_client/pam_sss.c
index 3ed642a7a..2b676f078 100644
--- a/sss_client/pam_sss.c
+++ b/sss_client/pam_sss.c
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <syslog.h>
+#include <locale.h>
#include <security/pam_modules.h>
#include <security/pam_misc.h>
@@ -39,6 +40,8 @@ struct pam_items {
size_t pam_authtok_size;
int pam_newauthtok_type;
size_t pam_newauthtok_size;
+ char *pam_cli_locale;
+ size_t pam_cli_locale_size;
};
#define DEBUG_MGS_LEN 1024
@@ -71,6 +74,126 @@ static void logger(pam_handle_t *pamh, int level, const char *fmt, ...) {
va_end(ap);
}
+
+static size_t add_authtok_item(enum pam_item_type type,
+ enum sss_authtok_type authtok_type,
+ const char *tok, const size_t size,
+ uint8_t *buf) {
+ size_t rp=0;
+
+ if (tok == NULL) return 0;
+
+ ((uint32_t *)(&buf[rp]))[0] = type;
+ rp += sizeof(uint32_t);
+
+ ((uint32_t *)(&buf[rp]))[0] = size + sizeof(uint32_t);
+ rp += sizeof(uint32_t);
+
+ ((uint32_t *)(&buf[rp]))[0] = authtok_type;
+ rp += sizeof(uint32_t);
+
+ memcpy(&buf[rp], tok, size);
+ rp += size;
+
+ return rp;
+}
+
+static size_t add_string_item(enum pam_item_type type, const char *str,
+ const size_t size, uint8_t *buf) {
+ size_t rp=0;
+
+ if (*str == '\0') return 0;
+
+ ((uint32_t *)(&buf[rp]))[0] = type;
+ rp += sizeof(uint32_t);
+
+ ((uint32_t *)(&buf[rp]))[0] = size;
+ rp += sizeof(uint32_t);
+
+ memcpy(&buf[rp], str, size);
+ rp += size;
+
+ return rp;
+}
+
+static int pack_message_v2(struct pam_items *pi, size_t *size, uint8_t **buffer) {
+ int len;
+ uint8_t *buf;
+ int rp;
+
+ len = sizeof(uint32_t) +
+ 2*sizeof(uint32_t) + pi->pam_user_size +
+ sizeof(uint32_t);
+ len += *pi->pam_service != '\0' ?
+ 2*sizeof(uint32_t) + pi->pam_service_size : 0;
+ len += *pi->pam_tty != '\0' ?
+ 2*sizeof(uint32_t) + pi->pam_tty_size : 0;
+ len += *pi->pam_ruser != '\0' ?
+ 2*sizeof(uint32_t) + pi->pam_ruser_size : 0;
+ len += *pi->pam_rhost != '\0' ?
+ 2*sizeof(uint32_t) + pi->pam_rhost_size : 0;
+ len += *pi->pam_cli_locale != '\0' ?
+ 2*sizeof(uint32_t) + pi->pam_cli_locale_size : 0;
+ len += pi->pam_authtok != NULL ?
+ 3*sizeof(uint32_t) + pi->pam_authtok_size : 0;
+ len += pi->pam_newauthtok != NULL ?
+ 3*sizeof(uint32_t) + pi->pam_newauthtok_size : 0;
+
+ buf = malloc(len);
+ if (buf == NULL) {
+ D(("malloc failed."));
+ return PAM_BUF_ERR;
+ }
+
+ rp = 0;
+ ((uint32_t *)(&buf[rp]))[0] = START_OF_PAM_REQUEST;
+ rp += sizeof(uint32_t);
+
+ rp += add_string_item(PAM_ITEM_USER, pi->pam_user, pi->pam_user_size,
+ &buf[rp]);
+
+ rp += add_string_item(PAM_ITEM_SERVICE, pi->pam_service,
+ pi->pam_service_size, &buf[rp]);
+
+ rp += add_string_item(PAM_ITEM_TTY, pi->pam_tty, pi->pam_tty_size,
+ &buf[rp]);
+
+ rp += add_string_item(PAM_ITEM_RUSER, pi->pam_ruser, pi->pam_ruser_size,
+ &buf[rp]);
+
+ rp += add_string_item(PAM_ITEM_RHOST, pi->pam_rhost, pi->pam_rhost_size,
+ &buf[rp]);
+
+ rp += add_string_item(PAM_CLI_LOCALE, pi->pam_cli_locale,
+ pi->pam_cli_locale_size, &buf[rp]);
+
+ rp += add_authtok_item(PAM_ITEM_AUTHTOK, pi->pam_authtok_type,
+ pi->pam_authtok, pi->pam_authtok_size, &buf[rp]);
+ _pam_overwrite_n((void *)pi->pam_authtok, pi->pam_authtok_size);
+ free((void *)pi->pam_authtok);
+ pi->pam_authtok = NULL;
+
+ rp += add_authtok_item(PAM_ITEM_NEWAUTHTOK, pi->pam_newauthtok_type,
+ pi->pam_newauthtok, pi->pam_newauthtok_size,
+ &buf[rp]);
+ _pam_overwrite_n((void *)pi->pam_newauthtok, pi->pam_newauthtok_size);
+ free((void *)pi->pam_newauthtok);
+ pi->pam_newauthtok = NULL;
+
+ ((uint32_t *)(&buf[rp]))[0] = END_OF_PAM_REQUEST;
+ rp += sizeof(uint32_t);
+
+ if (rp != len) {
+ D(("error during packet creation."));
+ return PAM_BUF_ERR;
+ }
+
+ *size = len;
+ *buffer = buf;
+
+ return 0;
+}
+
static int pack_message(struct pam_items *pi, size_t *size, uint8_t **buffer) {
int len;
uint8_t *buf;
@@ -347,6 +470,7 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf)
static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi)
{
int ret;
+ char *cli_locale;
pi->pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY;
pi->pam_authtok = NULL;
@@ -388,6 +512,15 @@ static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi)
if (ret != PAM_SUCCESS) return ret;
if (pi->pamstack_oldauthtok == NULL) pi->pamstack_oldauthtok="";
+ cli_locale = setlocale(LC_ALL, NULL);
+ if (cli_locale == NULL) {
+ pi->pam_cli_locale = "";
+ } else {
+ pi->pam_cli_locale = strdup(cli_locale);
+ if (pi->pam_cli_locale == NULL) return PAM_BUF_ERR;
+ }
+ pi->pam_cli_locale_size = strlen(pi->pam_cli_locale)+1;
+
return PAM_SUCCESS;
}
@@ -406,6 +539,7 @@ static void print_pam_items(struct pam_items pi)
if (pi.pam_newauthtok != NULL) {
D(("Newauthtok: %s", *pi.pam_newauthtok!='\0' ? pi.pam_newauthtok : "(not available)"));
}
+ D(("Locale: %s", *pi.pam_cli_locale!='\0' ? pi.pam_cli_locale : "(not available)"));
}
static int pam_sss(int task, pam_handle_t *pamh, int pam_flags, int argc,
@@ -550,7 +684,7 @@ static int pam_sss(int task, pam_handle_t *pamh, int pam_flags, int argc,
goto done;
}
pi.pam_newauthtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
- pi.pam_newauthtok_size=strlen(pi.pam_authtok);
+ pi.pam_newauthtok_size=strlen(pi.pam_newauthtok);
}
if (flags & FLAGS_FORWARD_PASS) {
@@ -564,7 +698,7 @@ static int pam_sss(int task, pam_handle_t *pamh, int pam_flags, int argc,
print_pam_items(pi);
- ret = pack_message(&pi, &rd.len, &buf);
+ ret = pack_message_v2(&pi, &rd.len, &buf);
if (ret != 0) {
D(("pack_message failed."));
pam_status = PAM_SYSTEM_ERR;
diff --git a/sss_client/sss_cli.h b/sss_client/sss_cli.h
index ba412fd07..63daf7bca 100644
--- a/sss_client/sss_cli.h
+++ b/sss_client/sss_cli.h
@@ -22,7 +22,7 @@
#define SSS_PAM_PRIV_SOCKET_NAME "/var/lib/sss/pipes/private/pam"
#define SSS_NSS_PROTOCOL_VERSION 1
-#define SSS_PAM_PROTOCOL_VERSION 1
+#define SSS_PAM_PROTOCOL_VERSION 2
enum sss_cli_command {
/* null */
@@ -138,8 +138,21 @@ enum sss_authtok_type {
SSS_AUTHTOK_TYPE_PASSWORD = 0x0001,
};
+#define START_OF_PAM_REQUEST 0x4d415049
#define END_OF_PAM_REQUEST 0x4950414d
+enum pam_item_type {
+ PAM_ITEM_EMPTY = 0x0000,
+ PAM_ITEM_USER,
+ PAM_ITEM_SERVICE,
+ PAM_ITEM_TTY,
+ PAM_ITEM_RUSER,
+ PAM_ITEM_RHOST,
+ PAM_ITEM_AUTHTOK,
+ PAM_ITEM_NEWAUTHTOK,
+ PAM_CLI_LOCALE,
+};
+
#define SSS_NSS_MAX_ENTRIES 256
#define SSS_NSS_HEADER_SIZE (sizeof(uint32_t) * 4)
struct sss_cli_req_data {