summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/providers/data_provider_be.c1
-rw-r--r--server/providers/krb5/krb5_auth.c14
-rw-r--r--server/providers/krb5/krb5_child.c36
-rw-r--r--server/providers/ldap/ldap_auth.c26
-rw-r--r--server/providers/proxy.c13
-rw-r--r--server/responder/pam/pamsrv_cmd.c6
-rw-r--r--sss_client/pam_sss.c2
-rw-r--r--sss_client/sss_cli.h2
8 files changed, 77 insertions, 23 deletions
diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c
index 02d5a0d12..05f3eaffa 100644
--- a/server/providers/data_provider_be.c
+++ b/server/providers/data_provider_be.c
@@ -565,6 +565,7 @@ static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn)
target = BET_ACCESS;
break;
case SSS_PAM_CHAUTHTOK:
+ case SSS_PAM_CHAUTHTOK_PRELIM:
target = BET_CHPASS;
break;
default:
diff --git a/server/providers/krb5/krb5_auth.c b/server/providers/krb5/krb5_auth.c
index 4581278de..73018413c 100644
--- a/server/providers/krb5/krb5_auth.c
+++ b/server/providers/krb5/krb5_auth.c
@@ -398,6 +398,7 @@ static struct krb5_ctx *get_krb5_ctx(struct be_req *be_req)
struct krb5_ctx);
break;
case SSS_PAM_CHAUTHTOK:
+ case SSS_PAM_CHAUTHTOK_PRELIM:
return talloc_get_type(be_req->be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
struct krb5_ctx);
break;
@@ -685,14 +686,16 @@ void krb5_pam_handler(struct be_req *be_req)
pd = talloc_get_type(be_req->req_data, struct pam_data);
- if (pd->cmd != SSS_PAM_AUTHENTICATE && pd->cmd != SSS_PAM_CHAUTHTOK) {
+ if (pd->cmd != SSS_PAM_AUTHENTICATE && pd->cmd != SSS_PAM_CHAUTHTOK &&
+ pd->cmd != SSS_PAM_CHAUTHTOK_PRELIM) {
DEBUG(4, ("krb5 does not handles pam task %d.\n", pd->cmd));
pam_status = PAM_SUCCESS;
dp_err = DP_ERR_OK;
goto done;
}
- if (be_is_offline(be_req->be_ctx) && pd->cmd == SSS_PAM_CHAUTHTOK) {
+ if (be_is_offline(be_req->be_ctx) &&
+ (pd->cmd == SSS_PAM_CHAUTHTOK || pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM)) {
DEBUG(9, ("Password changes are not possible while offline.\n"));
pam_status = PAM_AUTHINFO_UNAVAIL;
dp_err = DP_ERR_OFFLINE;
@@ -958,6 +961,12 @@ static void krb5_child_done(struct tevent_req *req)
pd->pam_status = *msg_status;
}
+ if (*msg_status == PAM_SUCCESS && pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
+ pam_status = PAM_SUCCESS;
+ dp_err = DP_ERR_OK;
+ goto done;
+ }
+
pref_len = strlen(CCACHE_ENV_NAME)+1;
if (*msg_len > pref_len &&
strncmp((const char *) &buf[p], CCACHE_ENV_NAME"=", pref_len) == 0) {
@@ -1047,6 +1056,7 @@ static void krb5_save_ccname_done(struct tevent_req *req)
switch(pd->cmd) {
case SSS_PAM_AUTHENTICATE:
+ case SSS_PAM_CHAUTHTOK_PRELIM:
password = talloc_size(be_req, pd->authtok_size + 1);
if (password != NULL) {
memcpy(password, pd->authtok, pd->authtok_size);
diff --git a/server/providers/krb5/krb5_child.c b/server/providers/krb5/krb5_child.c
index 2f4857432..6eb420bce 100644
--- a/server/providers/krb5/krb5_child.c
+++ b/server/providers/krb5/krb5_child.c
@@ -299,19 +299,24 @@ static struct response *prepare_response_message(struct krb5_req *kr,
}
if (kerr == 0) {
- if (kr->ccname == NULL) {
- DEBUG(1, ("Error obtaining ccname.\n"));
- return NULL;
- }
+ if(kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
+ ret = pack_response_packet(resp, PAM_SUCCESS, PAM_USER_INFO,
+ "success");
+ } else {
+ if (kr->ccname == NULL) {
+ DEBUG(1, ("Error obtaining ccname.\n"));
+ return NULL;
+ }
- msg = talloc_asprintf(kr, "%s=%s",CCACHE_ENV_NAME, kr->ccname);
- if (msg == NULL) {
- DEBUG(1, ("talloc_asprintf failed.\n"));
- return NULL;
- }
+ msg = talloc_asprintf(kr, "%s=%s",CCACHE_ENV_NAME, kr->ccname);
+ if (msg == NULL) {
+ DEBUG(1, ("talloc_asprintf failed.\n"));
+ return NULL;
+ }
- ret = pack_response_packet(resp, PAM_SUCCESS, PAM_ENV_ITEM, msg);
- talloc_zfree(msg);
+ ret = pack_response_packet(resp, PAM_SUCCESS, PAM_ENV_ITEM, msg);
+ talloc_zfree(msg);
+ }
} else {
krb5_msg = sss_krb5_get_error_message(krb5_error_ctx, kerr);
if (krb5_msg == NULL) {
@@ -528,6 +533,14 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
talloc_zfree(pass_str);
memset(kr->pd->authtok, 0, kr->pd->authtok_size);
+ if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
+ DEBUG(9, ("Initial authentication for change password operation "
+ "successfull.\n"));
+ krb5_free_cred_contents(kr->ctx, kr->creds);
+ pam_status = PAM_SUCCESS;
+ goto sendresponse;
+ }
+
newpass_str = talloc_strndup(kr, (const char *) kr->pd->newauthtok,
kr->pd->newauthtok_size);
if (newpass_str == NULL) {
@@ -824,6 +837,7 @@ static int krb5_setup(struct pam_data *pd, const char *user_princ_str,
}
break;
case SSS_PAM_CHAUTHTOK:
+ case SSS_PAM_CHAUTHTOK_PRELIM:
kr->child_req = changepw_child;
break;
default:
diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c
index 88e637b09..28b3240b3 100644
--- a/server/providers/ldap/ldap_auth.c
+++ b/server/providers/ldap/ldap_auth.c
@@ -661,7 +661,7 @@ void sdap_pam_chpass_handler(struct be_req *breq)
pd->pam_status = PAM_SYSTEM_ERR;
- if (pd->cmd != SSS_PAM_CHAUTHTOK) {
+ if (pd->cmd != SSS_PAM_CHAUTHTOK && pd->cmd != SSS_PAM_CHAUTHTOK_PRELIM) {
DEBUG(2, ("chpass target was called by wrong pam command.\n"));
goto done;
}
@@ -677,12 +677,15 @@ void sdap_pam_chpass_handler(struct be_req *breq)
if (!state->password) goto done;
talloc_set_destructor((TALLOC_CTX *)state->password,
password_destructor);
- state->new_password = talloc_strndup(state,
- (char *)pd->newauthtok,
- pd->newauthtok_size);
- if (!state->new_password) goto done;
- talloc_set_destructor((TALLOC_CTX *)state->new_password,
- password_destructor);
+
+ if (pd->cmd == SSS_PAM_CHAUTHTOK) {
+ state->new_password = talloc_strndup(state,
+ (char *)pd->newauthtok,
+ pd->newauthtok_size);
+ if (!state->new_password) goto done;
+ talloc_set_destructor((TALLOC_CTX *)state->new_password,
+ password_destructor);
+ }
authtok.data = (uint8_t *)state->password;
authtok.length = strlen(state->password);
@@ -717,6 +720,14 @@ static void sdap_auth4chpass_done(struct tevent_req *req)
goto done;
}
+ if (result == SDAP_AUTH_SUCCESS &&
+ state->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
+ DEBUG(9, ("Initial authentication for change password operation "
+ "successful.\n"));
+ state->pd->pam_status = PAM_SUCCESS;
+ goto done;
+ }
+
if (result == SDAP_AUTH_SUCCESS) {
switch (pw_expire_type) {
case PWEXPIRE_SHADOW:
@@ -851,6 +862,7 @@ void sdap_pam_auth_handler(struct be_req *breq)
switch (pd->cmd) {
case SSS_PAM_AUTHENTICATE:
+ case SSS_PAM_CHAUTHTOK_PRELIM:
state = talloc_zero(breq, struct sdap_pam_auth_state);
if (!state) goto done;
diff --git a/server/providers/proxy.c b/server/providers/proxy.c
index ef52ae91e..080479c4c 100644
--- a/server/providers/proxy.c
+++ b/server/providers/proxy.c
@@ -137,6 +137,7 @@ static void proxy_pam_handler(struct be_req *req) {
struct proxy_auth_ctx);
break;
case SSS_PAM_CHAUTHTOK:
+ case SSS_PAM_CHAUTHTOK_PRELIM:
ctx = talloc_get_type(req->be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
struct proxy_auth_ctx);
break;
@@ -207,12 +208,22 @@ static void proxy_pam_handler(struct be_req *req) {
cache_auth_data = true;
}
break;
+ case SSS_PAM_CHAUTHTOK_PRELIM:
+ if (pd->priv != 1) {
+ auth_data->authtok_size = pd->authtok_size;
+ auth_data->authtok = pd->authtok;
+ pam_status = pam_authenticate(pamh, 0);
+ } else {
+ pam_status = PAM_SUCCESS;
+ }
+ break;
default:
DEBUG(1, ("unknown PAM call"));
pam_status=PAM_ABORT;
}
- DEBUG(4, ("Pam result: [%d][%s]\n", pam_status, pam_strerror(pamh, pam_status)));
+ DEBUG(4, ("Pam result: [%d][%s]\n", pam_status,
+ pam_strerror(pamh, pam_status)));
if (pam_status == PAM_AUTHINFO_UNAVAIL) {
be_mark_offline(req->be_ctx);
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
index 447992664..69cbf55d8 100644
--- a/server/responder/pam/pamsrv_cmd.c
+++ b/server/responder/pam/pamsrv_cmd.c
@@ -1051,6 +1051,11 @@ static int pam_cmd_chauthtok(struct cli_ctx *cctx) {
return pam_forwarder(cctx, SSS_PAM_CHAUTHTOK);
}
+static int pam_cmd_chauthtok_prelim(struct cli_ctx *cctx) {
+ DEBUG(4, ("entering pam_cmd_chauthtok_prelim\n"));
+ return pam_forwarder(cctx, SSS_PAM_CHAUTHTOK_PRELIM);
+}
+
struct cli_protocol_version *register_cli_protocol_version(void)
{
static struct cli_protocol_version pam_cli_protocol_version[] = {
@@ -1073,6 +1078,7 @@ struct sss_cmd_table *get_pam_cmds(void)
{SSS_PAM_OPEN_SESSION, pam_cmd_open_session},
{SSS_PAM_CLOSE_SESSION, pam_cmd_close_session},
{SSS_PAM_CHAUTHTOK, pam_cmd_chauthtok},
+ {SSS_PAM_CHAUTHTOK_PRELIM, pam_cmd_chauthtok_prelim},
{SSS_CLI_NULL, NULL}
};
diff --git a/sss_client/pam_sss.c b/sss_client/pam_sss.c
index 1c4aed04e..951a1dcef 100644
--- a/sss_client/pam_sss.c
+++ b/sss_client/pam_sss.c
@@ -814,7 +814,7 @@ static int pam_sss(enum sss_cli_command task, pam_handle_t *pamh,
return ret;
}
if (pam_flags & PAM_PRELIM_CHECK) {
- return ret;
+ task = SSS_PAM_CHAUTHTOK_PRELIM;
}
break;
case SSS_PAM_ACCT_MGMT:
diff --git a/sss_client/sss_cli.h b/sss_client/sss_cli.h
index b036aec31..7c18e1cf8 100644
--- a/sss_client/sss_cli.h
+++ b/sss_client/sss_cli.h
@@ -128,7 +128,7 @@ enum sss_cli_command {
SSS_PAM_OPEN_SESSION = 0x00F4,
SSS_PAM_CLOSE_SESSION = 0x00F5,
SSS_PAM_CHAUTHTOK = 0x00F6,
- SSS_PAM_CHAUTHTOK_PRELIM = 0x00F6,
+ SSS_PAM_CHAUTHTOK_PRELIM = 0x00F7,
};