summaryrefslogtreecommitdiffstats
path: root/sss_client
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2009-05-07 09:48:57 +0200
committerSimo Sorce <ssorce@redhat.com>2009-05-08 16:27:11 -0400
commit4d6f4ebe04b1c953cd31b8ed313eed193b29fc01 (patch)
tree04d8c4e52b6907bcd2fc3f0ae9b209adc5242305 /sss_client
parent0ef76122eda140452e2ee97aac18a59d3c686c94 (diff)
downloadsssd-4d6f4ebe04b1c953cd31b8ed313eed193b29fc01.tar.gz
sssd-4d6f4ebe04b1c953cd31b8ed313eed193b29fc01.tar.xz
sssd-4d6f4ebe04b1c953cd31b8ed313eed193b29fc01.zip
cleanup and fixes for pam_sss
- if PAM_USER==root return PAM_USER_UNKNOWN - pam_sss now can handle to following options: - use_first_pass: forces the module to use a previous stacked modules password and will never prompt the user - use_authtok: when password changing enforce the module to set the new password to the one provided by a previously stacked password module - forward_pass: store the passwords collected by the module as pam items for modules called later in the stack
Diffstat (limited to 'sss_client')
-rw-r--r--sss_client/pam_sss.c542
1 files changed, 352 insertions, 190 deletions
diff --git a/sss_client/pam_sss.c b/sss_client/pam_sss.c
index cacb19b0d..4cc4ba974 100644
--- a/sss_client/pam_sss.c
+++ b/sss_client/pam_sss.c
@@ -13,6 +13,10 @@
#include "sss_cli.h"
+#define FLAGS_USE_FIRST_PASS (1 << 0)
+#define FLAGS_FORWARD_PASS (1 << 1)
+#define FLAGS_USE_AUTHTOK (1 << 2)
+
struct pam_items {
const char* pam_service;
const char* pam_user;
@@ -23,27 +27,211 @@ struct pam_items {
const char* pam_newauthtok;
const char* pamstack_authtok;
const char* pamstack_oldauthtok;
- int pam_service_size;
- int pam_user_size;
- int pam_tty_size;
- int pam_ruser_size;
- int pam_rhost_size;
+ size_t pam_service_size;
+ size_t pam_user_size;
+ size_t pam_tty_size;
+ size_t pam_ruser_size;
+ size_t pam_rhost_size;
int pam_authtok_type;
- int pam_authtok_size;
+ size_t pam_authtok_size;
int pam_newauthtok_type;
- int pam_newauthtok_size;
+ size_t pam_newauthtok_size;
+};
+
+static int pack_message(struct pam_items *pi, size_t *size, uint8_t **buffer) {
+ int len;
+ uint8_t *buf;
+ int rp;
+
+ len = pi->pam_user_size +
+ pi->pam_service_size +
+ pi->pam_tty_size +
+ pi->pam_ruser_size +
+ pi->pam_rhost_size +
+ 2*sizeof(uint32_t) + pi->pam_authtok_size +
+ 2*sizeof(uint32_t) + pi->pam_newauthtok_size +
+ sizeof(uint32_t);
+
+ buf = malloc(len);
+ if (buf == NULL) {
+ D(("malloc failed."));
+ return PAM_BUF_ERR;
+ }
+
+ memcpy(buf, pi->pam_user, pi->pam_user_size);
+ rp = pi->pam_user_size;
+
+ memcpy(&buf[rp], pi->pam_service, pi->pam_service_size);
+ rp += pi->pam_service_size;
+
+ memcpy(&buf[rp], pi->pam_tty, pi->pam_tty_size);
+ rp += pi->pam_tty_size;
+
+ memcpy(&buf[rp], pi->pam_ruser, pi->pam_ruser_size);
+ rp += pi->pam_ruser_size;
+
+ memcpy(&buf[rp], pi->pam_rhost, pi->pam_rhost_size);
+ rp += pi->pam_rhost_size;
+
+ ((uint32_t *)(&buf[rp]))[0] = pi->pam_authtok_type;
+ rp += sizeof(uint32_t);
+ ((uint32_t *)(&buf[rp]))[0] = pi->pam_authtok_size;
+ rp += sizeof(uint32_t);
+ memcpy(&buf[rp], pi->pam_authtok, pi->pam_authtok_size);
+ rp += pi->pam_authtok_size;
+ _pam_overwrite((void *)pi->pam_authtok);
+ free((void *)pi->pam_authtok);
+ pi->pam_authtok = NULL;
+
+ ((uint32_t *)(&buf[rp]))[0] = pi->pam_newauthtok_type;
+ rp += sizeof(uint32_t);
+ ((uint32_t *)(&buf[rp]))[0] = pi->pam_newauthtok_size;
+ rp += sizeof(uint32_t);
+ memcpy(&buf[rp], pi->pam_newauthtok, pi->pam_newauthtok_size);
+ rp += pi->pam_newauthtok_size;
+ _pam_overwrite((void *)pi->pam_newauthtok);
+ 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 null_strcmp(const char *s1, const char *s2) {
+ if (s1 == NULL && s2 == NULL) return 0;
+ if (s1 == NULL && s2 != NULL) return -1;
+ if (s1 != NULL && s2 == NULL) return 1;
+ return strcmp(s1, s2);
+}
+
+enum {
+ PAM_CONV_DONE = 0,
+ PAM_CONV_STD,
+ PAM_CONV_REENTER,
};
-static int eval_response(pam_handle_t *pamh, int buflen, uint8_t *buf)
+static int do_pam_conversation(pam_handle_t *pamh, const int msg_style,
+ const char *msg,
+ const char *reenter_msg,
+ char **answer)
+{
+ int ret;
+ int state = PAM_CONV_STD;
+ struct pam_conv *conv;
+ struct pam_message *mesg[1];
+ struct pam_response *resp=NULL;
+
+ if ((msg_style == PAM_TEXT_INFO || msg_style == PAM_ERROR_MSG) &&
+ msg == NULL) return PAM_SYSTEM_ERR;
+
+ if ((msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON) &&
+ (msg == NULL || answer == NULL)) return PAM_SYSTEM_ERR;
+
+ ret=pam_get_item(pamh, PAM_CONV, (const void **) &conv);
+ if (ret != PAM_SUCCESS) return ret;
+
+ do {
+ mesg[0] = malloc(sizeof(struct pam_message));
+ if (mesg[0] == NULL) {
+ D(("Malloc failed."));
+ return PAM_SYSTEM_ERR;
+ }
+
+ mesg[0]->msg_style = msg_style;
+ if (state == PAM_CONV_REENTER) {
+ mesg[0]->msg = reenter_msg;
+ } else {
+ mesg[0]->msg = msg;
+ }
+
+ ret=conv->conv(1, (const struct pam_message **) mesg, &resp,
+ conv->appdata_ptr);
+ free(mesg[0]);
+ if (ret != PAM_SUCCESS) {
+ D(("Conversation failure: %s.", pam_strerror(pamh,ret)));
+ return ret;
+ }
+
+ if (msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON) {
+ if (resp == NULL) {
+ D(("response expected, but resp==NULL"));
+ return PAM_SYSTEM_ERR;
+ }
+
+ if (state == PAM_CONV_REENTER) {
+ if (null_strcmp(*answer, resp[0].resp) != 0) {
+ D(("Passwords do not match."));
+ _pam_overwrite((void *)resp[0].resp);
+ free(resp[0].resp);
+ if (*answer != NULL) {
+ _pam_overwrite((void *)*answer);
+ free(*answer);
+ *answer = NULL;
+ }
+ ret = do_pam_conversation(pamh, PAM_ERROR_MSG,
+ "Passwords do not match", NULL,
+ NULL);
+ if (ret != PAM_SUCCESS) {
+ D(("do_pam_conversation failed."));
+ return PAM_SYSTEM_ERR;
+ }
+ return PAM_CRED_ERR;
+ }
+ _pam_overwrite((void *)resp[0].resp);
+ free(resp[0].resp);
+ } else {
+ if (resp[0].resp == NULL) {
+ D(("Empty password"));
+ *answer = NULL;
+ } else {
+ *answer = strdup(resp[0].resp);
+ _pam_overwrite((void *)resp[0].resp);
+ free(resp[0].resp);
+ if(*answer == NULL) {
+ D(("strdup failed"));
+ return PAM_BUF_ERR;
+ }
+ }
+ }
+ free(resp);
+ resp = NULL;
+ }
+
+ if (reenter_msg != NULL && state == PAM_CONV_STD) {
+ state = PAM_CONV_REENTER;
+ } else {
+ state = PAM_CONV_DONE;
+ }
+ } while (state != PAM_CONV_DONE);
+
+ return PAM_SUCCESS;
+}
+
+static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf)
{
int ret;
- int p=0;
+ size_t p=0;
char *env_item;
int32_t *c;
int32_t *type;
int32_t *len;
int32_t *pam_status;
+ if (buflen < (2*sizeof(int32_t))) {
+ D(("response buffer is too small"));
+ return PAM_BUF_ERR;
+ }
+
pam_status = ((int32_t *)(buf+p));
p += sizeof(int32_t);
@@ -52,13 +240,34 @@ static int eval_response(pam_handle_t *pamh, int buflen, uint8_t *buf)
p += sizeof(int32_t);
while(*c>0) {
+ if (buflen < (p+2*sizeof(int32_t))) {
+ D(("response buffer is too small"));
+ return PAM_BUF_ERR;
+ }
+
type = ((int32_t *)(buf+p));
p += sizeof(int32_t);
+
len = ((int32_t *)(buf+p));
p += sizeof(int32_t);
+
+ if (buflen < (p + *len)) {
+ D(("response buffer is too small"));
+ return PAM_BUF_ERR;
+ }
+
switch(*type) {
case PAM_USER_INFO:
+ if (buf[p + (*len -1)] != '\0') {
+ D(("user info does not end with \\0."));
+ break;
+ }
D(("user info: [%s]", &buf[p]));
+ ret = do_pam_conversation(pamh, PAM_USER_INFO, (char *) &buf[p],
+ NULL, NULL);
+ if (ret != PAM_SUCCESS) {
+ D(("do_pam_conversation, canot display user info."));
+ }
break;
case PAM_DOMAIN_NAME:
D(("domain name: [%s]", &buf[p]));
@@ -67,7 +276,7 @@ static int eval_response(pam_handle_t *pamh, int buflen, uint8_t *buf)
case PAM_ENV_ITEM:
case ALL_ENV_ITEM:
if (buf[p + (*len -1)] != '\0') {
- D(("env item does not end with \\0.\n"));
+ D(("env item does not end with \\0."));
break;
}
@@ -75,7 +284,7 @@ static int eval_response(pam_handle_t *pamh, int buflen, uint8_t *buf)
if (*type == PAM_ENV_ITEM || *type == ALL_ENV_ITEM) {
ret = pam_putenv(pamh, (char *)&buf[p]);
if (ret != PAM_SUCCESS) {
- D(("pam_putenv failed.\n"));
+ D(("pam_putenv failed."));
break;
}
}
@@ -83,12 +292,12 @@ static int eval_response(pam_handle_t *pamh, int buflen, uint8_t *buf)
if (*type == ENV_ITEM || *type == ALL_ENV_ITEM) {
env_item = strdup((char *)&buf[p]);
if (env_item == NULL) {
- D(("strdup failed\n"));
+ D(("strdup failed"));
break;
}
ret = putenv(env_item);
if (ret == -1) {
- D(("putenv failed.\n"));
+ D(("putenv failed."));
break;
}
}
@@ -99,13 +308,20 @@ static int eval_response(pam_handle_t *pamh, int buflen, uint8_t *buf)
--(*c);
}
- return 0;
+ return PAM_SUCCESS;
}
static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi)
{
int ret;
+ pi->pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY;
+ pi->pam_authtok = NULL;
+ pi->pam_authtok_size = 0;
+ pi->pam_newauthtok_type = SSS_AUTHTOK_TYPE_EMPTY;
+ pi->pam_newauthtok = NULL;
+ pi->pam_newauthtok_size = 0;
+
ret = pam_get_item(pamh, PAM_SERVICE, (const void **) &(pi->pam_service));
if (ret != PAM_SUCCESS) return ret;
if (pi->pam_service == NULL) pi->pam_service="";
@@ -159,40 +375,36 @@ static void print_pam_items(struct pam_items pi)
}
}
-static int pam_sss(int task, pam_handle_t *pamh, int flags, int argc,
+static int pam_sss(int task, pam_handle_t *pamh, int pam_flags, int argc,
const char **argv)
{
int ret;
int errnop;
- int c;
struct pam_items pi;
struct sss_cli_req_data rd;
+ uint8_t *buf=NULL;
uint8_t *repbuf=NULL;
size_t replen;
- size_t rp;
- char *buf=NULL;
- struct pam_conv *conv;
- struct pam_message *mesg[1];
- struct pam_response *resp=NULL;
int pam_status;
- char *newpwd[2];
- int forward_pass = 0;
- int use_first_pass = 0;
+ uint32_t flags = 0;
+ char *answer;
D(("Hello pam_sssd: %d", task));
for (; argc-- > 0; ++argv) {
if (strcmp(*argv, "forward_pass") == 0) {
- forward_pass = 1;
+ flags |= FLAGS_FORWARD_PASS;
} else if (strcmp(*argv, "use_first_pass") == 0) {
- use_first_pass = 1;
+ flags |= FLAGS_USE_FIRST_PASS;
+ } else if (strcmp(*argv, "use_authtok") == 0) {
+ flags |= FLAGS_USE_AUTHTOK;
} else {
D(("unknown option: %s", *argv));
}
}
/* TODO: add useful prelim check */
- if (task == SSS_PAM_CHAUTHTOK && (flags & PAM_PRELIM_CHECK)) {
+ if (task == SSS_PAM_CHAUTHTOK && (pam_flags & PAM_PRELIM_CHECK)) {
D(("ignoring PAM_PRELIM_CHECK"));
return PAM_SUCCESS;
}
@@ -203,210 +415,160 @@ static int pam_sss(int task, pam_handle_t *pamh, int flags, int argc,
return ret;
}
- if (use_first_pass != 0 &&
- (*pi.pamstack_authtok != '\0' || *pi.pamstack_oldauthtok != '\0') &&
- (task == SSS_PAM_AUTHENTICATE || task == SSS_PAM_CHAUTHTOK)) {
- pi.pam_authtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
- pi.pam_authtok = strdup(pi.pamstack_authtok);
- pi.pam_authtok_size = strlen(pi.pamstack_authtok);
- pi.pam_newauthtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
- pi.pam_newauthtok = strdup(pi.pamstack_oldauthtok);
- pi.pam_newauthtok_size = strlen(pi.pamstack_oldauthtok);
-
- } else {
- pi.pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY;
- pi.pam_authtok = NULL;
- pi.pam_authtok_size = 0;
- pi.pam_newauthtok_type = SSS_AUTHTOK_TYPE_EMPTY;
- pi.pam_newauthtok = NULL;
- pi.pam_newauthtok_size = 0;
- /* according to pam_conv(3) only one message should be requested by
- * conv to keep compatibility to Solaris. Therefore we make separate
- * calls to request AUTHTOK and OLDAUTHTOK. */
- if ( task == SSS_PAM_AUTHENTICATE ||
- (task == SSS_PAM_CHAUTHTOK && getuid() != 0)) {
- ret=pam_get_item(pamh, PAM_CONV, (const void **) &conv);
- if (ret != PAM_SUCCESS) return ret;
-
- mesg[0] = malloc(sizeof(struct pam_message));
- if (mesg[0] == NULL) {
- D(("Malloc failed.\n"));
+ if (*pi.pam_user == '\0') {
+ D(("No user found, aborting."));
+ return PAM_BAD_ITEM;
+ }
+
+ if (strcmp(pi.pam_user, "root") == 0) {
+ D(("pam_sss will not handle root."));
+ return PAM_USER_UNKNOWN;
+ }
+
+ if (task == SSS_PAM_AUTHENTICATE ||
+ (task == SSS_PAM_CHAUTHTOK && getuid() != 0)) {
+ if (flags & FLAGS_USE_FIRST_PASS) {
+ pi.pam_authtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
+ if (task == SSS_PAM_AUTHENTICATE) {
+ pi.pam_authtok = strdup(pi.pamstack_authtok);
+ } else if (task == SSS_PAM_CHAUTHTOK) {
+ pi.pam_authtok = strdup(pi.pamstack_oldauthtok);
+ } else {
+ D(("internal logic error"));
return PAM_SYSTEM_ERR;
}
- mesg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
- mesg[0]->msg = strdup("Password: ");
-
- ret=conv->conv(1, (const struct pam_message **) mesg, &resp,
- conv->appdata_ptr);
- free((void *)mesg[0]->msg);
- free(mesg[0]);
+ if (pi.pam_authtok == NULL) {
+ pam_status = PAM_BUF_ERR;
+ goto done;
+ }
+ pi.pam_authtok_size = strlen(pi.pam_authtok);
+ } else {
+ ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, "Password: ",
+ NULL, &answer);
if (ret != PAM_SUCCESS) {
- D(("Conversation failure: %s.\n", pam_strerror(pamh,ret)));
+ D(("do_pam_conversation failed."));
pam_status = ret;
goto done;
}
- if (resp[0].resp == NULL) {
- D(("Empty password\n"));
+ if (answer == NULL) {
pi.pam_authtok = NULL;
pi.pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY;
+ pi.pam_authtok_size=0;
} else {
- pi.pam_authtok = strdup(resp[0].resp);
+ pi.pam_authtok = strdup(answer);
+ _pam_overwrite((void *)answer);
+ free(answer);
+ answer=NULL;
+ if (pi.pam_authtok == NULL) {
+ pam_status = PAM_BUF_ERR;
+ goto done;
+ }
pi.pam_authtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
+ pi.pam_authtok_size=strlen(pi.pam_authtok);
}
- pi.pam_authtok_size=strlen(pi.pam_authtok);
- if (forward_pass != 0) {
- ret = pam_set_item(pamh, PAM_AUTHTOK, resp[0].resp);
+ if (flags & FLAGS_FORWARD_PASS) {
+ if (task == SSS_PAM_AUTHENTICATE) {
+ ret = pam_set_item(pamh, PAM_AUTHTOK, pi.pam_authtok);
+ } else if (task == SSS_PAM_CHAUTHTOK) {
+ ret = pam_set_item(pamh, PAM_OLDAUTHTOK, pi.pam_authtok);
+ } else {
+ D(("internal logic error"));
+ return PAM_SYSTEM_ERR;
+ }
if (ret != PAM_SUCCESS) {
D(("Failed to set PAM_AUTHTOK, authtok may not be available for other modules"));
}
}
}
-
- if (task == SSS_PAM_CHAUTHTOK) {
- ret=pam_get_item(pamh, PAM_CONV, (const void **) &conv);
- if (ret != PAM_SUCCESS) return ret;
-
- mesg[0] = malloc(sizeof(struct pam_message));
- if (mesg[0] == NULL) {
- D(("Malloc failed.\n"));
- return PAM_SYSTEM_ERR;
+ }
+
+ if (task == SSS_PAM_CHAUTHTOK) {
+ if (flags & FLAGS_USE_AUTHTOK) {
+ pi.pam_newauthtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
+ pi.pam_newauthtok = strdup(pi.pamstack_authtok);
+ if (pi.pam_newauthtok == NULL) {
+ pam_status = PAM_BUF_ERR;
+ goto done;
}
- mesg[0]->msg_style = PAM_PROMPT_ECHO_OFF;
- mesg[0]->msg = strdup("New Password: ");
-
- c = 0;
- do {
- ret=conv->conv(1, (const struct pam_message **) mesg, &resp,
- conv->appdata_ptr);
- free((void *)mesg[0]->msg);
- if (ret != PAM_SUCCESS) {
- D(("Conversation failure: %s.\n", pam_strerror(pamh,ret)));
- pam_status = ret;
- goto done;
- }
-
- newpwd[c++] = strdup(resp[0].resp);
- _pam_overwrite((void *)resp[0].resp);
- free(resp[0].resp);
- free(resp);
- resp = NULL;
-
- mesg[0]->msg = strdup("Reenter new password: ");
- } while(c < 2);
- free(mesg[0]);
-
- if (strcmp(newpwd[0],newpwd[1]) != 0) {
- pam_status = PAM_AUTHTOK_ERR;
+ pi.pam_newauthtok_size = strlen(pi.pam_newauthtok);
+ } else {
+ ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF,
+ "New Password: ",
+ "Reenter new Password: ",
+ &answer);
+ if (ret != PAM_SUCCESS) {
+ D(("do_pam_conversation failed."));
+ pam_status = ret;
goto done;
}
-
- if (newpwd[0] == NULL) {
- D(("Empty password\n"));
+ if (answer == NULL) {
pi.pam_newauthtok = NULL;
pi.pam_newauthtok_type = SSS_AUTHTOK_TYPE_EMPTY;
+ pi.pam_newauthtok_size=0;
} else {
- pi.pam_newauthtok = strdup(newpwd[0]);
+ pi.pam_newauthtok = strdup(answer);
+ _pam_overwrite((void *)answer);
+ free(answer);
+ answer=NULL;
+ if (pi.pam_newauthtok == NULL) {
+ pam_status = PAM_BUF_ERR;
+ 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);
- _pam_overwrite((void *)newpwd[0]);
- free(newpwd[0]);
- _pam_overwrite((void *)newpwd[1]);
- free(newpwd[1]);
+ if (flags & FLAGS_FORWARD_PASS) {
+ ret = pam_set_item(pamh, PAM_AUTHTOK, pi.pam_newauthtok);
+ if (ret != PAM_SUCCESS) {
+ D(("Failed to set PAM_AUTHTOK, authtok may not be available for other modules"));
+ }
+ }
}
}
print_pam_items(pi);
- if (pi.pam_user) {
- rd.len = pi.pam_user_size +
- pi.pam_service_size +
- pi.pam_tty_size +
- pi.pam_ruser_size +
- pi.pam_rhost_size +
- 2*sizeof(uint32_t) + pi.pam_authtok_size +
- 2*sizeof(uint32_t) + pi.pam_newauthtok_size +
- sizeof(uint32_t);
- buf = malloc(rd.len);
-
- memcpy(buf, pi.pam_user, pi.pam_user_size);
- rp = pi.pam_user_size;
-
- memcpy(&buf[rp], pi.pam_service, pi.pam_service_size);
- rp += pi.pam_service_size;
-
- memcpy(&buf[rp], pi.pam_tty, pi.pam_tty_size);
- rp += pi.pam_tty_size;
-
- memcpy(&buf[rp], pi.pam_ruser, pi.pam_ruser_size);
- rp += pi.pam_ruser_size;
-
- memcpy(&buf[rp], pi.pam_rhost, pi.pam_rhost_size);
- rp += pi.pam_rhost_size;
-
- ((uint32_t *)(&buf[rp]))[0] = pi.pam_authtok_type;
- rp += sizeof(uint32_t);
- ((uint32_t *)(&buf[rp]))[0] = pi.pam_authtok_size;
- rp += sizeof(uint32_t);
- memcpy(&buf[rp], pi.pam_authtok, pi.pam_authtok_size);
- rp += pi.pam_authtok_size;
- _pam_overwrite((void *)pi.pam_authtok);
- free((void *)pi.pam_authtok);
-
- ((uint32_t *)(&buf[rp]))[0] = pi.pam_newauthtok_type;
- rp += sizeof(uint32_t);
- ((uint32_t *)(&buf[rp]))[0] = pi.pam_newauthtok_size;
- rp += sizeof(uint32_t);
- memcpy(&buf[rp], pi.pam_newauthtok, pi.pam_newauthtok_size);
- rp += pi.pam_newauthtok_size;
- _pam_overwrite((void *)pi.pam_newauthtok);
- free((void *)pi.pam_newauthtok);
-
- ((uint32_t *)(&buf[rp]))[0] = END_OF_PAM_REQUEST;
- rp += sizeof(uint32_t);
-
- if (rp != rd.len) {
- D(("error during packet creation."));
- pam_status = PAM_ABORT;
- goto done;
- }
- rd.data = buf;
+ ret = pack_message(&pi, &rd.len, &buf);
+ if (ret != 0) {
+ D(("pack_message failed."));
+ pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
+ rd.data = buf;
- ret = sss_pam_make_request(task, &rd, &repbuf, &replen, &errnop);
+ ret = sss_pam_make_request(task, &rd, &repbuf, &replen, &errnop);
- if (ret != NSS_STATUS_SUCCESS) {
- D(("sss_pam_make_request failed."));
- pam_status = ret;
- goto done;
- }
+ if (ret != NSS_STATUS_SUCCESS) {
+ D(("sss_pam_make_request failed."));
+ pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
/* FIXME: add an end signature */
- if (replen<sizeof(int)) {
- D(("response not in expected format."));
- pam_status=PAM_SYSTEM_ERR;
- goto done;
- }
+ if (replen < (2*sizeof(int32_t))) {
+ D(("response not in expected format."));
+ pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
- pam_status = ((int32_t *)repbuf)[0];
- eval_response(pamh, replen, repbuf);
- D(("received: %d (%s)", pam_status, pam_strerror(pamh,pam_status)));
- } else {
- D(("no user found, doing nothing"));
- return PAM_SUCCESS;
+ pam_status = ((int32_t *)repbuf)[0];
+ ret = eval_response(pamh, replen, repbuf);
+ if (ret != PAM_SUCCESS) {
+ D(("eval_response failed."));
+ pam_status = ret;
+ goto done;
}
+ D(("received: %d (%s)", pam_status, pam_strerror(pamh,pam_status)));
done:
- if ( resp != NULL ) {
- _pam_overwrite((void *)resp[0].resp);
- free(resp[0].resp);
- free(resp);
+ if (buf != NULL ) {
+ _pam_overwrite_n((void *)buf, rd.len);
+ free(buf);
}
- if ( buf != NULL && repbuf != NULL) _pam_overwrite_n(buf, rd.len);
- free(buf);
- free(repbuf);
+ if (repbuf != NULL) free(repbuf);
return pam_status;
}