summaryrefslogtreecommitdiffstats
path: root/server/providers
diff options
context:
space:
mode:
Diffstat (limited to 'server/providers')
-rw-r--r--server/providers/krb5/krb5_child.c78
-rw-r--r--server/providers/ldap/ldap_auth.c19
-rw-r--r--server/providers/ldap/sdap_async.c17
-rw-r--r--server/providers/ldap/sdap_async.h5
4 files changed, 96 insertions, 23 deletions
diff --git a/server/providers/krb5/krb5_child.c b/server/providers/krb5/krb5_child.c
index d8f733b70..645274b36 100644
--- a/server/providers/krb5/krb5_child.c
+++ b/server/providers/krb5/krb5_child.c
@@ -30,6 +30,7 @@
#include <security/pam_modules.h>
#include "util/util.h"
+#include "util/user_info_msg.h"
#include "providers/child_common.h"
#include "providers/dp_backend.h"
#include "providers/krb5/krb5_auth.h"
@@ -256,13 +257,12 @@ static struct response *init_response(TALLOC_CTX *mem_ctx) {
return r;
}
-static errno_t pack_response_packet(struct response *resp, int status, int type, const char *data)
+static errno_t pack_response_packet(struct response *resp, int status, int type,
+ size_t len, const uint8_t *data)
{
- int len;
int p=0;
int32_t c;
- len = strlen(data)+1;
if ((3*sizeof(int32_t) + len +1) > resp->max_size) {
DEBUG(1, ("response message too big.\n"));
return ENOMEM;
@@ -289,12 +289,16 @@ static errno_t pack_response_packet(struct response *resp, int status, int type,
}
static struct response *prepare_response_message(struct krb5_req *kr,
- krb5_error_code kerr, int pam_status)
+ krb5_error_code kerr,
+ char *user_error_message,
+ int pam_status)
{
char *msg = NULL;
const char *krb5_msg = NULL;
int ret;
struct response *resp;
+ size_t user_resp_len;
+ uint8_t *user_resp;
resp = init_response(kr);
if (resp == NULL) {
@@ -305,7 +309,8 @@ static struct response *prepare_response_message(struct krb5_req *kr,
if (kerr == 0) {
if(kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
ret = pack_response_packet(resp, PAM_SUCCESS, SSS_PAM_SYSTEM_INFO,
- "success");
+ strlen("success") + 1,
+ (const uint8_t *) "success");
} else {
if (kr->ccname == NULL) {
DEBUG(1, ("Error obtaining ccname.\n"));
@@ -318,19 +323,43 @@ static struct response *prepare_response_message(struct krb5_req *kr,
return NULL;
}
- ret = pack_response_packet(resp, PAM_SUCCESS, SSS_PAM_ENV_ITEM, msg);
+ ret = pack_response_packet(resp, PAM_SUCCESS, SSS_PAM_ENV_ITEM,
+ strlen(msg) + 1, (uint8_t *) msg);
talloc_zfree(msg);
}
} else {
- krb5_msg = sss_krb5_get_error_message(krb5_error_ctx, kerr);
- if (krb5_msg == NULL) {
- DEBUG(1, ("sss_krb5_get_error_message failed.\n"));
- return NULL;
+
+ if (user_error_message != NULL) {
+ ret = pack_user_info_chpass_error(kr, user_error_message,
+ &user_resp_len, &user_resp);
+ if (ret != EOK) {
+ DEBUG(1, ("pack_user_info_chpass_error failed.\n"));
+ talloc_zfree(user_error_message);
+ } else {
+ ret = pack_response_packet(resp, pam_status, SSS_PAM_USER_INFO,
+ user_resp_len, user_resp);
+ if (ret != EOK) {
+ DEBUG(1, ("pack_response_packet failed.\n"));
+ talloc_zfree(user_error_message);
+ }
+ }
+ }
+
+ if (user_error_message == NULL) {
+ krb5_msg = sss_krb5_get_error_message(krb5_error_ctx, kerr);
+ if (krb5_msg == NULL) {
+ DEBUG(1, ("sss_krb5_get_error_message failed.\n"));
+ return NULL;
+ }
+
+ ret = pack_response_packet(resp, pam_status, SSS_PAM_SYSTEM_INFO,
+ strlen(krb5_msg) + 1,
+ (const uint8_t *) krb5_msg);
+ sss_krb5_free_error_message(krb5_error_ctx, krb5_msg);
+ } else {
+
}
- ret = pack_response_packet(resp, pam_status, SSS_PAM_SYSTEM_INFO,
- krb5_msg);
- sss_krb5_free_error_message(krb5_error_ctx, krb5_msg);
}
if (ret != EOK) {
@@ -341,14 +370,15 @@ static struct response *prepare_response_message(struct krb5_req *kr,
return resp;
}
-static errno_t sendresponse(int fd, krb5_error_code kerr, int pam_status,
+static errno_t sendresponse(int fd, krb5_error_code kerr,
+ char *user_error_message, int pam_status,
struct krb5_req *kr)
{
struct response *resp;
size_t written;
int ret;
- resp = prepare_response_message(kr, kerr, pam_status);
+ resp = prepare_response_message(kr, kerr, user_error_message, pam_status);
if (resp == NULL) {
DEBUG(1, ("prepare_response_message failed.\n"));
return ENOMEM;
@@ -522,6 +552,7 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
int result_code = -1;
krb5_data result_code_string;
krb5_data result_string;
+ char *user_error_message = NULL;
pass_str = talloc_strndup(kr, (const char *) kr->pd->authtok,
kr->pd->authtok_size);
@@ -576,11 +607,22 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
if (result_code_string.length > 0) {
DEBUG(1, ("krb5_change_password failed [%d][%.*s].\n", result_code,
result_code_string.length, result_code_string.data));
+ user_error_message = talloc_strndup(kr->pd, result_code_string.data,
+ result_code_string.length);
+ if (user_error_message == NULL) {
+ DEBUG(1, ("talloc_strndup failed.\n"));
+ }
}
if (result_string.length > 0) {
DEBUG(1, ("krb5_change_password failed [%d][%.*s].\n", result_code,
result_string.length, result_string.data));
+ talloc_free(user_error_message);
+ user_error_message = talloc_strndup(kr->pd, result_string.data,
+ result_string.length);
+ if (user_error_message == NULL) {
+ DEBUG(1, ("talloc_strndup failed.\n"));
+ }
}
pam_status = PAM_AUTHTOK_ERR;
@@ -602,7 +644,7 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
}
sendresponse:
- ret = sendresponse(fd, kerr, pam_status, kr);
+ ret = sendresponse(fd, kerr, user_error_message, pam_status, kr);
if (ret != EOK) {
DEBUG(1, ("sendresponse failed.\n"));
}
@@ -664,7 +706,7 @@ static errno_t tgt_req_child(int fd, struct krb5_req *kr)
}
sendresponse:
- ret = sendresponse(fd, kerr, pam_status, kr);
+ ret = sendresponse(fd, kerr, NULL, pam_status, kr);
if (ret != EOK) {
DEBUG(1, ("sendresponse failed.\n"));
}
@@ -683,7 +725,7 @@ static errno_t create_empty_ccache(int fd, struct krb5_req *kr)
pam_status = PAM_SYSTEM_ERR;
}
- ret = sendresponse(fd, ret, pam_status, kr);
+ ret = sendresponse(fd, ret, NULL, pam_status, kr);
if (ret != EOK) {
DEBUG(1, ("sendresponse failed.\n"));
}
diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c
index 1d1346c07..cfe8adb97 100644
--- a/server/providers/ldap/ldap_auth.c
+++ b/server/providers/ldap/ldap_auth.c
@@ -40,6 +40,7 @@
#include <security/pam_modules.h>
#include "util/util.h"
+#include "util/user_info_msg.h"
#include "db/sysdb.h"
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap_async.h"
@@ -809,8 +810,11 @@ static void sdap_pam_chpass_done(struct tevent_req *req)
enum sdap_result result;
int dp_err = DP_ERR_FATAL;
int ret;
+ char *user_error_message = NULL;
+ size_t msg_len;
+ uint8_t *msg;
- ret = sdap_exop_modify_passwd_recv(req, &result);
+ ret = sdap_exop_modify_passwd_recv(req, state, &result, &user_error_message);
talloc_zfree(req);
if (ret) {
state->pd->pam_status = PAM_SYSTEM_ERR;
@@ -824,6 +828,19 @@ static void sdap_pam_chpass_done(struct tevent_req *req)
break;
default:
state->pd->pam_status = PAM_AUTHTOK_ERR;
+ if (user_error_message != NULL) {
+ ret = pack_user_info_chpass_error(state->pd, user_error_message,
+ &msg_len, &msg);
+ if (ret != EOK) {
+ DEBUG(1, ("pack_user_info_chpass_error failed.\n"));
+ } else {
+ ret = pam_add_response(state->pd, SSS_PAM_USER_INFO, msg_len,
+ msg);
+ if (ret != EOK) {
+ DEBUG(1, ("pam_add_response failed.\n"));
+ }
+ }
+ }
}
done:
diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c
index 88f1c4be6..959c08a65 100644
--- a/server/providers/ldap/sdap_async.c
+++ b/server/providers/ldap/sdap_async.c
@@ -530,6 +530,7 @@ struct sdap_exop_modify_passwd_state {
struct sdap_op *op;
int result;
+ char *user_error_message;
};
static void sdap_exop_modify_passwd_done(struct sdap_op *op,
@@ -556,6 +557,7 @@ struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
if (!req) return NULL;
state->sh = sh;
+ state->user_error_message = NULL;
ber = ber_alloc_t( LBER_USE_DER );
if (ber == NULL) {
@@ -626,7 +628,7 @@ static void sdap_exop_modify_passwd_done(struct sdap_op *op,
struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
struct sdap_exop_modify_passwd_state *state = tevent_req_data(req,
struct sdap_exop_modify_passwd_state);
- char *errmsg;
+ char *errmsg = NULL;
int ret;
LDAPControl **response_controls = NULL;
int c;
@@ -673,12 +675,20 @@ static void sdap_exop_modify_passwd_done(struct sdap_op *op,
}
}
+ if (state->result != LDAP_SUCCESS) {
+ state->user_error_message = talloc_strdup(state, errmsg);
+ if (state->user_error_message == NULL) {
+ DEBUG(1, ("talloc_strdup failed.\n"));
+ }
+ }
+
DEBUG(3, ("ldap_extended_operation result: %s(%d), %s\n",
ldap_err2string(state->result), state->result, errmsg));
ret = LDAP_SUCCESS;
done:
ldap_controls_free(response_controls);
+ ldap_memfree(errmsg);
if (ret == LDAP_SUCCESS) {
tevent_req_done(req);
@@ -688,12 +698,15 @@ done:
}
int sdap_exop_modify_passwd_recv(struct tevent_req *req,
- enum sdap_result *result)
+ TALLOC_CTX * mem_ctx,
+ enum sdap_result *result,
+ char **user_error_message)
{
struct sdap_exop_modify_passwd_state *state = tevent_req_data(req,
struct sdap_exop_modify_passwd_state);
*result = SDAP_ERROR;
+ *user_error_message = talloc_steal(mem_ctx, state->user_error_message);
TEVENT_REQ_RETURN_ON_ERROR(req);
diff --git a/server/providers/ldap/sdap_async.h b/server/providers/ldap/sdap_async.h
index e18fb69a2..3c52d236b 100644
--- a/server/providers/ldap/sdap_async.h
+++ b/server/providers/ldap/sdap_async.h
@@ -94,8 +94,9 @@ struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
char *user_dn,
char *password,
char *new_password);
-int sdap_exop_modify_passwd_recv(struct tevent_req *req,
- enum sdap_result *result);
+int sdap_exop_modify_passwd_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ enum sdap_result *result,
+ char **user_error_msg);
struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx,
struct tevent_context *ev,