summaryrefslogtreecommitdiffstats
path: root/src/providers
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2010-05-24 11:43:45 -0400
committerStephen Gallagher <sgallagh@redhat.com>2010-05-27 14:44:13 -0400
commit35c70c767d366fc82a50f6f29793ab7f1477f79d (patch)
treeace3061bf0cb93a60b17ddcbd2054005ec368635 /src/providers
parent10afbe39cb81a1810dba486c4b8e46578bb300bb (diff)
downloadsssd-35c70c767d366fc82a50f6f29793ab7f1477f79d.tar.gz
sssd-35c70c767d366fc82a50f6f29793ab7f1477f79d.tar.xz
sssd-35c70c767d366fc82a50f6f29793ab7f1477f79d.zip
Support password changes in chpass_provider = proxy
We were not passing the old authtok to the pam_chauthtok() function, causing it to return PAM_AUTH_ERR.
Diffstat (limited to 'src/providers')
-rw-r--r--src/providers/proxy/proxy_child.c78
1 files changed, 73 insertions, 5 deletions
diff --git a/src/providers/proxy/proxy_child.c b/src/providers/proxy/proxy_child.c
index c8f1eeb50..4d853efbd 100644
--- a/src/providers/proxy/proxy_child.c
+++ b/src/providers/proxy/proxy_child.c
@@ -77,6 +77,11 @@ struct pc_ctx {
struct authtok_conv {
uint32_t authtok_size;
uint8_t *authtok;
+
+ uint32_t newauthtok_size;
+ uint8_t *newauthtok;
+
+ bool sent_old;
};
static int proxy_internal_conv(int num_msg, const struct pam_message **msgm,
@@ -123,6 +128,63 @@ failed:
return PAM_CONV_ERR;
}
+static int proxy_chauthtok_conv(int num_msg, const struct pam_message **msgm,
+ struct pam_response **response,
+ void *appdata_ptr) {
+ int i;
+ struct pam_response *reply;
+ struct authtok_conv *auth_data;
+
+ auth_data = talloc_get_type(appdata_ptr, struct authtok_conv);
+
+ if (num_msg <= 0) return PAM_CONV_ERR;
+
+ reply = (struct pam_response *) calloc(num_msg,
+ sizeof(struct pam_response));
+ if (reply == NULL) return PAM_CONV_ERR;
+
+ for (i=0; i < num_msg; i++) {
+ switch( msgm[i]->msg_style ) {
+ case PAM_PROMPT_ECHO_OFF:
+ DEBUG(4, ("Conversation message: [%s]\n", msgm[i]->msg));
+
+ reply[i].resp_retcode = 0;
+ if (!auth_data->sent_old) {
+ /* The first prompt will be asking for the old authtok */
+ reply[i].resp = calloc(auth_data->authtok_size + 1,
+ sizeof(char));
+ if (reply[i].resp == NULL) goto failed;
+ memcpy(reply[i].resp, auth_data->authtok,
+ auth_data->authtok_size);
+ auth_data->sent_old = true;
+ }
+ else {
+ /* Subsequent prompts are looking for the new authtok */
+ reply[i].resp = calloc(auth_data->newauthtok_size + 1,
+ sizeof(char));
+ if (reply[i].resp == NULL) goto failed;
+ memcpy(reply[i].resp, auth_data->newauthtok,
+ auth_data->newauthtok_size);
+ }
+
+ break;
+ default:
+ DEBUG(1, ("Conversation style %d not supported.\n",
+ msgm[i]->msg_style));
+ goto failed;
+ }
+ }
+
+ *response = reply;
+ reply = NULL;
+
+ return PAM_SUCCESS;
+
+failed:
+ free(reply);
+ return PAM_CONV_ERR;
+}
+
static errno_t call_pam_stack(const char *pam_target, struct pam_data *pd)
{
int ret;
@@ -131,7 +193,12 @@ static errno_t call_pam_stack(const char *pam_target, struct pam_data *pd)
struct authtok_conv *auth_data;
struct pam_conv conv;
- conv.conv=proxy_internal_conv;
+ if (pd->cmd == SSS_PAM_CHAUTHTOK) {
+ conv.conv=proxy_chauthtok_conv;
+ }
+ else {
+ conv.conv=proxy_internal_conv;
+ }
auth_data = talloc_zero(pd, struct authtok_conv);
conv.appdata_ptr=auth_data;
@@ -173,14 +240,15 @@ static errno_t call_pam_stack(const char *pam_target, struct pam_data *pd)
pam_status=pam_close_session(pamh, 0);
break;
case SSS_PAM_CHAUTHTOK:
+ auth_data->authtok_size = pd->authtok_size;
+ auth_data->authtok = pd->authtok;
if (pd->priv != 1) {
- auth_data->authtok_size = pd->authtok_size;
- auth_data->authtok = pd->authtok;
pam_status = pam_authenticate(pamh, 0);
+ auth_data->sent_old = false;
if (pam_status != PAM_SUCCESS) break;
}
- auth_data->authtok_size = pd->newauthtok_size;
- auth_data->authtok = pd->newauthtok;
+ auth_data->newauthtok_size = pd->newauthtok_size;
+ auth_data->newauthtok = pd->newauthtok;
pam_status = pam_chauthtok(pamh, 0);
break;
case SSS_PAM_CHAUTHTOK_PRELIM: