summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2012-10-18 18:43:56 -0400
committerSimo Sorce <simo@redhat.com>2013-01-10 12:24:59 -0500
commit64af76e2bef2565caa9738f675c108a4b3789237 (patch)
treefa24e7f17f07136494a4c515c63b8795be7130e4 /src
parent918b2a5a91f1c551d48f4bffed2a28c36fdb4be1 (diff)
downloadsssd-64af76e2bef2565caa9738f675c108a4b3789237.tar.gz
sssd-64af76e2bef2565caa9738f675c108a4b3789237.tar.bz2
sssd-64af76e2bef2565caa9738f675c108a4b3789237.zip
Change pam data auth tokens.
Use the new authtok abstraction and interfaces throught the code.
Diffstat (limited to 'src')
-rw-r--r--src/db/sysdb_ops.c1
-rw-r--r--src/providers/data_provider.h9
-rw-r--r--src/providers/dp_auth_util.c76
-rw-r--r--src/providers/dp_pam_data_util.c117
-rw-r--r--src/providers/ipa/ipa_auth.c6
-rw-r--r--src/providers/krb5/krb5_auth.c58
-rw-r--r--src/providers/krb5/krb5_child.c148
-rw-r--r--src/providers/krb5/krb5_child_handler.c59
-rw-r--r--src/providers/krb5/krb5_delayed_online_authentication.c50
-rw-r--r--src/providers/krb5/krb5_renew_tgt.c18
-rw-r--r--src/providers/ldap/ldap_auth.c90
-rw-r--r--src/providers/ldap/sdap_async.c4
-rw-r--r--src/providers/ldap/sdap_async.h7
-rw-r--r--src/providers/ldap/sdap_async_connection.c88
-rw-r--r--src/providers/proxy/proxy.h7
-rw-r--r--src/providers/proxy/proxy_auth.c14
-rw-r--r--src/providers/proxy/proxy_child.c51
-rw-r--r--src/responder/pam/pam_LOCAL_domain.c54
-rw-r--r--src/responder/pam/pamsrv_cmd.c134
-rw-r--r--src/tests/krb5_child-test.c13
20 files changed, 531 insertions, 473 deletions
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index b9cecad5..9974beb0 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -2780,7 +2780,6 @@ int sysdb_cache_auth(struct sysdb_ctx *sysdb,
time_t expire_date = -1;
time_t delayed_until = -1;
int ret;
- int i;
if (name == NULL || *name == '\0') {
DEBUG(1, ("Missing user name.\n"));
diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
index f131e2c6..8e475d22 100644
--- a/src/providers/data_provider.h
+++ b/src/providers/data_provider.h
@@ -41,6 +41,7 @@
#include "sbus/sssd_dbus.h"
#include "sbus/sbus_client.h"
#include "sss_client/sss_cli.h"
+#include "util/authtok.h"
#define DATA_PROVIDER_VERSION 0x0001
#define DATA_PROVIDER_PIPE "private/sbus-dp"
@@ -169,18 +170,14 @@ struct response_data {
struct pam_data {
int cmd;
- uint32_t authtok_type;
- uint32_t authtok_size;
- uint32_t newauthtok_type;
- uint32_t newauthtok_size;
char *domain;
char *user;
char *service;
char *tty;
char *ruser;
char *rhost;
- uint8_t *authtok;
- uint8_t *newauthtok;
+ struct sss_auth_token authtok;
+ struct sss_auth_token newauthtok;
uint32_t cli_pid;
int pam_status;
diff --git a/src/providers/dp_auth_util.c b/src/providers/dp_auth_util.c
index 9a67564b..54f0ee8e 100644
--- a/src/providers/dp_auth_util.c
+++ b/src/providers/dp_auth_util.c
@@ -24,30 +24,43 @@
bool dp_pack_pam_request(DBusMessage *msg, struct pam_data *pd)
{
dbus_bool_t db_ret;
+ const char *service;
+ const char *tty;
+ const char *ruser;
+ const char *rhost;
+ uint32_t authtok_type;
+ uint32_t authtok_length;
+ uint8_t *authtok_data;
+ uint32_t new_authtok_type;
+ uint32_t new_authtok_length;
+ uint8_t *new_authtok_data;
if (pd->user == NULL) return false;
- if (pd->service == NULL) pd->service = talloc_strdup(pd, "");
- if (pd->tty == NULL) pd->tty = talloc_strdup(pd, "");
- if (pd->ruser == NULL) pd->ruser = talloc_strdup(pd, "");
- if (pd->rhost == NULL) pd->rhost = talloc_strdup(pd, "");
-
+ service = pd->service ? pd->service : "";
+ tty = pd->tty ? pd->tty : "";
+ ruser = pd->ruser ? pd->ruser : "";
+ rhost = pd->rhost ? pd->rhost : "";
+ authtok_type = (uint32_t)sss_authtok_get_type(&pd->authtok);
+ authtok_data = sss_authtok_get_data(&pd->authtok);
+ authtok_length = sss_authtok_get_size(&pd->authtok);
+ new_authtok_type = (uint32_t)sss_authtok_get_type(&pd->newauthtok);
+ new_authtok_data = sss_authtok_get_data(&pd->newauthtok);
+ new_authtok_length = sss_authtok_get_size(&pd->newauthtok);
db_ret = dbus_message_append_args(msg,
DBUS_TYPE_INT32, &(pd->cmd),
DBUS_TYPE_STRING, &(pd->user),
DBUS_TYPE_STRING, &(pd->domain),
- DBUS_TYPE_STRING, &(pd->service),
- DBUS_TYPE_STRING, &(pd->tty),
- DBUS_TYPE_STRING, &(pd->ruser),
- DBUS_TYPE_STRING, &(pd->rhost),
- DBUS_TYPE_UINT32, &(pd->authtok_type),
+ DBUS_TYPE_STRING, &service,
+ DBUS_TYPE_STRING, &tty,
+ DBUS_TYPE_STRING, &ruser,
+ DBUS_TYPE_STRING, &rhost,
+ DBUS_TYPE_UINT32, &authtok_type,
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &(pd->authtok),
- (pd->authtok_size),
- DBUS_TYPE_UINT32, &(pd->newauthtok_type),
+ &authtok_data, authtok_length,
+ DBUS_TYPE_UINT32, &new_authtok_type,
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &(pd->newauthtok),
- pd->newauthtok_size,
+ &new_authtok_data, new_authtok_length,
DBUS_TYPE_INT32, &(pd->priv),
DBUS_TYPE_UINT32, &(pd->cli_pid),
DBUS_TYPE_INVALID);
@@ -61,6 +74,12 @@ bool dp_unpack_pam_request(DBusMessage *msg, TALLOC_CTX *mem_ctx,
dbus_bool_t db_ret;
int ret;
struct pam_data pd;
+ uint32_t authtok_type;
+ uint32_t authtok_length;
+ uint8_t *authtok_data;
+ uint32_t new_authtok_type;
+ uint32_t new_authtok_length;
+ uint8_t *new_authtok_data;
memset(&pd, 0, sizeof(pd));
@@ -72,14 +91,12 @@ bool dp_unpack_pam_request(DBusMessage *msg, TALLOC_CTX *mem_ctx,
DBUS_TYPE_STRING, &(pd.tty),
DBUS_TYPE_STRING, &(pd.ruser),
DBUS_TYPE_STRING, &(pd.rhost),
- DBUS_TYPE_UINT32, &(pd.authtok_type),
+ DBUS_TYPE_UINT32, &authtok_type,
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &(pd.authtok),
- &(pd.authtok_size),
- DBUS_TYPE_UINT32, &(pd.newauthtok_type),
+ &authtok_data, &authtok_length,
+ DBUS_TYPE_UINT32, &new_authtok_type,
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &(pd.newauthtok),
- &(pd.newauthtok_size),
+ &new_authtok_data, &new_authtok_length,
DBUS_TYPE_INT32, &(pd.priv),
DBUS_TYPE_UINT32, &(pd.cli_pid),
DBUS_TYPE_INVALID);
@@ -95,14 +112,17 @@ bool dp_unpack_pam_request(DBusMessage *msg, TALLOC_CTX *mem_ctx,
return false;
}
- if (pd.authtok_size != 0 && pd.authtok != NULL) {
- memset(pd.authtok, 0, pd.authtok_size);
- pd.authtok_size = 0;
+ ret = sss_authtok_set(*new_pd, &((*new_pd)->authtok), authtok_type,
+ authtok_data, authtok_length);
+ if (ret) {
+ DEBUG(1, ("Failed to set auth token: %d [%s]\n", ret, strerror(ret)));
+ return false;
}
-
- if (pd.newauthtok_size != 0 && pd.newauthtok != NULL) {
- memset(pd.newauthtok, 0, pd.newauthtok_size);
- pd.newauthtok_size = 0;
+ ret = sss_authtok_set(*new_pd, &((*new_pd)->newauthtok), new_authtok_type,
+ new_authtok_data, new_authtok_length);
+ if (ret) {
+ DEBUG(1, ("Failed to set auth token: %d [%s]\n", ret, strerror(ret)));
+ return false;
}
return true;
diff --git a/src/providers/dp_pam_data_util.c b/src/providers/dp_pam_data_util.c
index 889c47f0..64f0d69b 100644
--- a/src/providers/dp_pam_data_util.c
+++ b/src/providers/dp_pam_data_util.c
@@ -25,26 +25,6 @@
#include "providers/data_provider.h"
-#define PD_STR_COPY(el) do { \
- if (old_pd->el != NULL) { \
- pd->el = talloc_strdup(pd, old_pd->el); \
- if (pd->el == NULL) { \
- DEBUG(1, ("talloc_strdup failed.\n")); \
- goto failed; \
- } \
- } \
-} while(0)
-
-#define PD_MEM_COPY(el, size) do { \
- if (old_pd->el != NULL) { \
- pd->el = talloc_memdup(pd, old_pd->el, (size)); \
- if (pd->el == NULL) { \
- DEBUG(1, ("talloc_memdup failed.\n")); \
- goto failed; \
- } \
- } \
-} while(0)
-
#define PAM_SAFE_ITEM(item) item ? item : "not set"
static const char *pamcmd2str(int cmd) {
@@ -72,17 +52,11 @@ int pam_data_destructor(void *ptr)
{
struct pam_data *pd = talloc_get_type(ptr, struct pam_data);
- if (pd->authtok_size != 0 && pd->authtok != NULL) {
- memset(pd->authtok, 0, pd->authtok_size);
- pd->authtok_size = 0;
- }
+ /* make sure to wipe any password from memory before freeing */
+ sss_authtok_wipe_password(&pd->authtok);
+ sss_authtok_wipe_password(&pd->newauthtok);
- if (pd->newauthtok_size != 0 && pd->newauthtok != NULL) {
- memset(pd->newauthtok, 0, pd->newauthtok_size);
- pd->newauthtok_size = 0;
- }
-
- return EOK;
+ return 0;
}
struct pam_data *create_pam_data(TALLOC_CTX *mem_ctx)
@@ -100,41 +74,72 @@ struct pam_data *create_pam_data(TALLOC_CTX *mem_ctx)
return pd;
}
-errno_t copy_pam_data(TALLOC_CTX *mem_ctx, struct pam_data *old_pd,
- struct pam_data **new_pd)
+errno_t copy_pam_data(TALLOC_CTX *mem_ctx, struct pam_data *src,
+ struct pam_data **dst)
{
struct pam_data *pd = NULL;
+ errno_t ret;
pd = create_pam_data(mem_ctx);
if (pd == NULL) {
- DEBUG(1, ("create_pam_data failed.\n"));
- return ENOMEM;
+ ret = ENOMEM;
+ goto failed;
+ }
+
+ pd->cmd = src->cmd;
+ pd->priv = src->priv;
+
+ pd->domain = talloc_strdup(pd, src->domain);
+ if (pd->domain == NULL && src->domain != NULL) {
+ ret = ENOMEM;
+ goto failed;
+ }
+ pd->user = talloc_strdup(pd, src->user);
+ if (pd->user == NULL && src->user != NULL) {
+ ret = ENOMEM;
+ goto failed;
+ }
+ pd->service = talloc_strdup(pd, src->service);
+ if (pd->service == NULL && src->service != NULL) {
+ ret = ENOMEM;
+ goto failed;
+ }
+ pd->tty = talloc_strdup(pd, src->tty);
+ if (pd->tty == NULL && src->tty != NULL) {
+ ret = ENOMEM;
+ goto failed;
+ }
+ pd->ruser = talloc_strdup(pd, src->ruser);
+ if (pd->ruser == NULL && src->ruser != NULL) {
+ ret = ENOMEM;
+ goto failed;
+ }
+ pd->rhost = talloc_strdup(pd, src->rhost);
+ if (pd->rhost == NULL && src->rhost != NULL) {
+ ret = ENOMEM;
+ goto failed;
+ }
+
+ pd->cli_pid = src->cli_pid;
+
+ ret = sss_authtok_copy(pd, &src->authtok, &pd->authtok);
+ if (ret) {
+ goto failed;
+ }
+
+ ret = sss_authtok_copy(pd, &src->newauthtok, &pd->newauthtok);
+ if (ret) {
+ goto failed;
}
- pd->cmd = old_pd->cmd;
- pd->authtok_type = old_pd->authtok_type;
- pd->authtok_size = old_pd->authtok_size;
- pd->newauthtok_type = old_pd->newauthtok_type;
- pd->newauthtok_size = old_pd->newauthtok_size;
- pd->priv = old_pd->priv;
-
- PD_STR_COPY(domain);
- PD_STR_COPY(user);
- PD_STR_COPY(service);
- PD_STR_COPY(tty);
- PD_STR_COPY(ruser);
- PD_STR_COPY(rhost);
- PD_MEM_COPY(authtok, old_pd->authtok_size);
- PD_MEM_COPY(newauthtok, old_pd->newauthtok_size);
- pd->cli_pid = old_pd->cli_pid;
-
- *new_pd = pd;
+ *dst = pd;
return EOK;
failed:
talloc_free(pd);
- return ENOMEM;
+ DEBUG(1, ("copy_pam_data failed: (%d) %s.\n", ret, strerror(ret)));
+ return ret;
}
void pam_print_data(int l, struct pam_data *pd)
@@ -146,10 +151,8 @@ void pam_print_data(int l, struct pam_data *pd)
DEBUG(l, ("tty: %s\n", PAM_SAFE_ITEM(pd->tty)));
DEBUG(l, ("ruser: %s\n", PAM_SAFE_ITEM(pd->ruser)));
DEBUG(l, ("rhost: %s\n", PAM_SAFE_ITEM(pd->rhost)));
- DEBUG(l, ("authtok type: %d\n", pd->authtok_type));
- DEBUG(l, ("authtok size: %d\n", pd->authtok_size));
- DEBUG(l, ("newauthtok type: %d\n", pd->newauthtok_type));
- DEBUG(l, ("newauthtok size: %d\n", pd->newauthtok_size));
+ DEBUG(l, ("authtok type: %d\n", sss_authtok_get_type(&pd->authtok)));
+ DEBUG(l, ("newauthtok type: %d\n", sss_authtok_get_type(&pd->newauthtok)));
DEBUG(l, ("priv: %d\n", pd->priv));
DEBUG(l, ("cli_pid: %d\n", pd->cli_pid));
}
diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c
index eb62f029..ee15afa5 100644
--- a/src/providers/ipa/ipa_auth.c
+++ b/src/providers/ipa/ipa_auth.c
@@ -332,7 +332,6 @@ static void ipa_migration_flag_connect_done(struct tevent_req *req)
const char **attrs;
struct ldb_message *user_msg;
const char *dn;
- struct dp_opt_blob password;
int dp_err = DP_ERR_FATAL;
int ret;
@@ -374,11 +373,8 @@ static void ipa_migration_flag_connect_done(struct tevent_req *req)
goto done;
}
- password.data = state->pd->authtok;
- password.length = state->pd->authtok_size;
-
req = sdap_auth_send(state, state->ev, state->sh, NULL, NULL, dn,
- "password", password);
+ &state->pd->authtok);
if (req == NULL) {
DEBUG(SSSDBG_OP_FAILURE, ("sdap_auth_send failed.\n"));
goto done;
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index bd014a49..398f06a8 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -278,12 +278,12 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx,
struct pam_data *pd, uid_t uid,
int *pam_status, int *dp_err)
{
- char *password = NULL;
+ const char *password = NULL;
errno_t ret;
- password = talloc_strndup(state, pd->authtok, pd->authtok_size);
- if (!password) {
- DEBUG(0, ("Out of memory copying password\n"));
+ ret = sss_authtok_get_password(&pd->authtok, &password, NULL);
+ if (ret != EOK) {
+ DEBUG(0, ("Failed to get password [%d] %s\n", ret, strerror(ret)));
*pam_status = PAM_SYSTEM_ERR;
*dp_err = DP_ERR_OK;
return;
@@ -294,7 +294,7 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx,
DEBUG(1, ("Offline authentication failed\n"));
*pam_status = cached_login_pam_status(ret);
*dp_err = DP_ERR_OK;
- goto done;
+ return;
}
ret = add_user_to_delayed_online_authentication(krb5_ctx, pd, uid);
@@ -304,12 +304,6 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx,
}
*pam_status = PAM_AUTHINFO_UNAVAIL;
*dp_err = DP_ERR_OFFLINE;
-
-done:
- if (password) {
- for (i = 0; password[i]; i++) password[i] = 0;
- talloc_zfree(password);
- }
}
static errno_t krb5_auth_prepare_ccache_file(struct krb5child_req *kr,
@@ -385,16 +379,9 @@ static errno_t krb5_auth_prepare_ccache_file(struct krb5child_req *kr,
static void krb5_auth_store_creds(struct sysdb_ctx *sysdb, struct pam_data *pd)
{
- TALLOC_CTX *tmp_ctx;
- char *password = NULL;
+ const char *password = NULL;
int ret = EOK;
- tmp_ctx = talloc_new(NULL);
- if (!tmp_ctx) {
- DEBUG(0, ("Out of memory when trying to store credentials\n"));
- return;
- }
-
switch(pd->cmd) {
case SSS_CMD_RENEW:
/* The authtok is set to the credential cache
@@ -404,42 +391,35 @@ static void krb5_auth_store_creds(struct sysdb_ctx *sysdb, struct pam_data *pd)
break;
case SSS_PAM_AUTHENTICATE:
case SSS_PAM_CHAUTHTOK_PRELIM:
- password = talloc_size(tmp_ctx, pd->authtok_size + 1);
- if (password != NULL) {
- memcpy(password, pd->authtok, pd->authtok_size);
- password[pd->authtok_size] = '\0';
- }
+ ret = sss_authtok_get_password(&pd->authtok, &password, NULL);
break;
case SSS_PAM_CHAUTHTOK:
- password = talloc_size(tmp_ctx, pd->newauthtok_size + 1);
- if (password != NULL) {
- memcpy(password, pd->newauthtok, pd->newauthtok_size);
- password[pd->newauthtok_size] = '\0';
- }
+ ret = sss_authtok_get_password(&pd->newauthtok, &password, NULL);
break;
default:
DEBUG(0, ("unsupported PAM command [%d].\n", pd->cmd));
}
+ if (ret != EOK) {
+ DEBUG(0, ("Failed to get password [%d] %s\n", ret, strerror(ret)));
+ /* password caching failures are not fatal errors */
+ return;
+ }
+
if (password == NULL) {
if (pd->cmd != SSS_CMD_RENEW) {
DEBUG(0, ("password not available, offline auth may not work.\n"));
/* password caching failures are not fatal errors */
}
- talloc_zfree(tmp_ctx);
return;
}
- talloc_set_destructor((TALLOC_CTX *)password, password_destructor);
-
ret = sysdb_cache_password(sysdb, pd->user, password);
if (ret) {
DEBUG(2, ("Failed to cache password, offline auth may not work."
" (%d)[%s]!?\n", ret, strerror(ret)));
/* password caching failures are not fatal errors */
}
-
- talloc_zfree(tmp_ctx);
}
/* krb5_auth request */
@@ -504,9 +484,17 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
case SSS_PAM_AUTHENTICATE:
case SSS_CMD_RENEW:
case SSS_PAM_CHAUTHTOK:
+ if (sss_authtok_get_type(&pd->authtok) != SSS_AUTHTOK_TYPE_PASSWORD) {
+ DEBUG(1, ("Missing authtok for user [%s].\n", pd->user));
+ state->pam_status = PAM_SYSTEM_ERR;
+ state->dp_err = DP_ERR_FATAL;
+ ret = EINVAL;
+ goto done;
+ }
break;
case SSS_PAM_CHAUTHTOK_PRELIM:
- if (pd->priv == 1 && pd->authtok_size == 0) {
+ if (pd->priv == 1 &&
+ sss_authtok_get_type(&pd->authtok) != SSS_AUTHTOK_TYPE_PASSWORD) {
DEBUG(4, ("Password reset by root is not supported.\n"));
state->pam_status = PAM_PERM_DENIED;
state->dp_err = DP_ERR_OK;
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 66e22f43..d1a42d56 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -950,7 +950,7 @@ done:
}
static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
- char *password)
+ const char *password)
{
krb5_error_code kerr = 0;
int ret;
@@ -971,7 +971,8 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
DEBUG(SSSDBG_TRACE_FUNC,
("Attempting kinit for realm [%s]\n",realm_name));
kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
- password, sss_krb5_prompter, kr, 0,
+ discard_const(password),
+ sss_krb5_prompter, kr, 0,
NULL, kr->options);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
@@ -1066,8 +1067,8 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
{
int ret;
krb5_error_code kerr = 0;
- char *pass_str = NULL;
- char *newpass_str = NULL;
+ const char *password = NULL;
+ const char *newpassword = NULL;
int pam_status = PAM_SYSTEM_ERR;
int result_code = -1;
krb5_data result_code_string;
@@ -1082,20 +1083,15 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
DEBUG(SSSDBG_TRACE_LIBS, ("Password change operation\n"));
- if (kr->pd->authtok_type != SSS_AUTHTOK_TYPE_PASSWORD) {
+ ret = sss_authtok_get_password(&kr->pd->authtok, &password, NULL);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to fetch current password [%d] %s.\n",
+ ret, strerror(ret)));
pam_status = PAM_CRED_INSUFFICIENT;
kerr = KRB5KRB_ERR_GENERIC;
goto sendresponse;
}
- pass_str = talloc_strndup(kr, (const char *) kr->pd->authtok,
- kr->pd->authtok_size);
- if (pass_str == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- kerr = KRB5KRB_ERR_GENERIC;
- goto sendresponse;
- }
-
if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
/* We do not need a password expiration warning here. */
prompter = NULL;
@@ -1112,7 +1108,8 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
DEBUG(SSSDBG_TRACE_FUNC,
("Attempting kinit for realm [%s]\n",realm_name));
kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
- pass_str, prompter, kr, 0,
+ discard_const(password),
+ prompter, kr, 0,
SSSD_KRB5_CHANGEPW_PRINCIPAL,
chagepw_options);
sss_krb5_get_init_creds_opt_free(kr->ctx, chagepw_options);
@@ -1121,9 +1118,7 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
goto sendresponse;
}
- memset(pass_str, 0, kr->pd->authtok_size);
- talloc_zfree(pass_str);
- memset(kr->pd->authtok, 0, kr->pd->authtok_size);
+ sss_authtok_set_empty(&kr->pd->authtok);
if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
DEBUG(SSSDBG_TRACE_LIBS,
@@ -1134,17 +1129,18 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
goto sendresponse;
}
- newpass_str = talloc_strndup(kr, (const char *) kr->pd->newauthtok,
- kr->pd->newauthtok_size);
- if (newpass_str == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
+ ret = sss_authtok_get_password(&kr->pd->newauthtok, &newpassword, NULL);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to fetch new password [%d] %s.\n",
+ ret, strerror(ret)));
kerr = KRB5KRB_ERR_GENERIC;
goto sendresponse;
}
memset(&result_code_string, 0, sizeof(krb5_data));
memset(&result_string, 0, sizeof(krb5_data));
- kerr = krb5_change_password(kr->ctx, kr->creds, newpass_str, &result_code,
+ kerr = krb5_change_password(kr->ctx, kr->creds,
+ discard_const(newpassword), &result_code,
&result_code_string, &result_string);
if (kerr == KRB5_KDC_UNREACH) {
@@ -1200,10 +1196,9 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
krb5_free_cred_contents(kr->ctx, kr->creds);
- kerr = get_and_save_tgt(kr, newpass_str);
- memset(newpass_str, 0, kr->pd->newauthtok_size);
- talloc_zfree(newpass_str);
- memset(kr->pd->newauthtok, 0, kr->pd->newauthtok_size);
+ kerr = get_and_save_tgt(kr, newpassword);
+
+ sss_authtok_set_empty(&kr->pd->newauthtok);
pam_status = kerr_to_status(kerr);
@@ -1220,28 +1215,21 @@ static errno_t tgt_req_child(int fd, struct krb5_req *kr)
{
int ret;
krb5_error_code kerr = 0;
- char *pass_str = NULL;
+ const char *password = NULL;
int pam_status = PAM_SYSTEM_ERR;
krb5_get_init_creds_opt *chagepw_options;
DEBUG(SSSDBG_TRACE_LIBS, ("Attempting to get a TGT\n"));
- if (kr->pd->authtok_type != SSS_AUTHTOK_TYPE_PASSWORD) {
+ ret = sss_authtok_get_password(&kr->pd->authtok, &password, NULL);
+ if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("Unknown authtok type\n"));
pam_status = PAM_CRED_INSUFFICIENT;
kerr = KRB5KRB_ERR_GENERIC;
goto sendresponse;
}
- pass_str = talloc_strndup(kr, (const char *) kr->pd->authtok,
- kr->pd->authtok_size);
- if (pass_str == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- kerr = KRB5KRB_ERR_GENERIC;
- goto sendresponse;
- }
-
- kerr = get_and_save_tgt(kr, pass_str);
+ kerr = get_and_save_tgt(kr, password);
/* If the password is expired the KDC will always return
KRB5KDC_ERR_KEY_EXP regardless if the supplied password is correct or
@@ -1264,7 +1252,8 @@ static errno_t tgt_req_child(int fd, struct krb5_req *kr)
}
kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
- pass_str, sss_krb5_prompter, kr, 0,
+ discard_const(password),
+ sss_krb5_prompter, kr, 0,
SSSD_KRB5_CHANGEPW_PRINCIPAL,
chagepw_options);
@@ -1276,9 +1265,7 @@ static errno_t tgt_req_child(int fd, struct krb5_req *kr)
}
}
- memset(pass_str, 0, kr->pd->authtok_size);
- talloc_zfree(pass_str);
- memset(kr->pd->authtok, 0, kr->pd->authtok_size);
+ sss_authtok_set_empty(&kr->pd->authtok);
pam_status = kerr_to_status(kerr);
@@ -1333,25 +1320,20 @@ static errno_t renew_tgt_child(int fd, struct krb5_req *kr)
int ret;
int status = PAM_AUTHTOK_ERR;
int kerr;
- char *ccname;
+ const char *ccname;
krb5_ccache ccache = NULL;
DEBUG(SSSDBG_TRACE_LIBS, ("Renewing a ticket\n"));
- if (kr->pd->authtok_type != SSS_AUTHTOK_TYPE_CCFILE) {
- DEBUG(1, ("Unsupported authtok type for TGT renewal [%d].\n",
- kr->pd->authtok_type));
+ ret = sss_authtok_get_ccfile(&kr->pd->authtok, &ccname, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Unsupported authtok type for TGT renewal [%d].\n",
+ sss_authtok_get_type(&kr->pd->authtok)));
kerr = EINVAL;
goto done;
}
- ccname = talloc_strndup(kr, (char *) kr->pd->authtok, kr->pd->authtok_size);
- if (ccname == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- kerr = ENOMEM;
- goto done;
- }
-
kerr = krb5_cc_resolve(kr->ctx, ccname, &ccache);
if (kerr != 0) {
KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
@@ -1444,6 +1426,38 @@ static errno_t create_empty_ccache(int fd, struct krb5_req *kr)
return ret;
}
+static errno_t unpack_authtok(TALLOC_CTX *mem_ctx, struct sss_auth_token *tok,
+ uint8_t *buf, size_t size, size_t *p)
+{
+ uint32_t auth_token_type;
+ uint32_t auth_token_length;
+ errno_t ret = EOK;
+
+ SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, buf + *p, size, p);
+ SAFEALIGN_COPY_UINT32_CHECK(&auth_token_length, buf + *p, size, p);
+ if ((*p + auth_token_length) > size) {
+ return EINVAL;
+ }
+ switch (auth_token_type) {
+ case SSS_AUTHTOK_TYPE_EMPTY:
+ sss_authtok_set_empty(tok);
+ break;
+ case SSS_AUTHTOK_TYPE_PASSWORD:
+ ret = sss_authtok_set_password(mem_ctx, tok, (char *)(buf + *p), 0);
+ break;
+ case SSS_AUTHTOK_TYPE_CCFILE:
+ ret = sss_authtok_set_ccfile(mem_ctx, tok, (char *)(buf + *p), 0);
+ break;
+ default:
+ return EINVAL;
+ }
+
+ if (ret == EOK) {
+ *p += auth_token_length;
+ }
+ return ret;
+}
+
static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd,
struct krb5_req *kr, uint32_t *offline)
{
@@ -1451,6 +1465,7 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd,
uint32_t len;
uint32_t validate;
uint32_t different_realm;
+ errno_t ret;
DEBUG(SSSDBG_TRACE_LIBS, ("total buffer size: [%d]\n", size));
@@ -1491,35 +1506,26 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd,
if (kr->keytab == NULL) return ENOMEM;
p += len;
- SAFEALIGN_COPY_UINT32_CHECK(&pd->authtok_type, buf + p, size, &p);
- SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
- if ((p + len) > size) return EINVAL;
- pd->authtok = (uint8_t *)talloc_strndup(pd, (char *)(buf + p), len);
- if (pd->authtok == NULL) return ENOMEM;
- pd->authtok_size = len + 1;
- p += len;
+ ret = unpack_authtok(pd, &pd->authtok, buf, size, &p);
+ if (ret) {
+ return ret;
+ }
DEBUG(SSSDBG_CONF_SETTINGS, ("ccname: [%s] keytab: [%s]\n",
kr->ccname, kr->keytab));
} else {
kr->ccname = NULL;
kr->keytab = NULL;
- pd->authtok = NULL;
- pd->authtok_size = 0;
+ sss_authtok_set_empty(&pd->authtok);
}
if (pd->cmd == SSS_PAM_CHAUTHTOK) {
- SAFEALIGN_COPY_UINT32_CHECK(&pd->newauthtok_type, buf + p, size, &p);
- SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
-
- if ((p + len) > size) return EINVAL;
- pd->newauthtok = (uint8_t *)talloc_strndup(pd, (char *)(buf + p), len);
- if (pd->newauthtok == NULL) return ENOMEM;
- pd->newauthtok_size = len + 1;
- p += len;
+ ret = unpack_authtok(pd, &pd->newauthtok, buf, size, &p);
+ if (ret) {
+ return ret;
+ }
} else {
- pd->newauthtok = NULL;
- pd->newauthtok_size = 0;
+ sss_authtok_set_empty(&pd->newauthtok);
}
if (pd->cmd == SSS_PAM_ACCT_MGMT) {
diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
index e792db3f..5adbcf70 100644
--- a/src/providers/krb5/krb5_child_handler.c
+++ b/src/providers/krb5/krb5_child_handler.c
@@ -85,6 +85,43 @@ static int child_io_destructor(void *ptr)
return EOK;
}
+static errno_t pack_authtok(struct io_buffer *buf, size_t *rp,
+ struct sss_auth_token *tok)
+{
+ uint32_t auth_token_type;
+ uint32_t auth_token_length;
+ const char *data;
+ size_t len;
+ errno_t ret = EOK;
+
+ auth_token_type = sss_authtok_get_type(tok);
+
+ switch (auth_token_type) {
+ case SSS_AUTHTOK_TYPE_EMPTY:
+ auth_token_length = 0;
+ data = "";
+ break;
+ case SSS_AUTHTOK_TYPE_PASSWORD:
+ ret = sss_authtok_get_password(tok, &data, &len);
+ auth_token_length = len + 1;
+ break;
+ case SSS_AUTHTOK_TYPE_CCFILE:
+ ret = sss_authtok_get_password(tok, &data, &len);
+ auth_token_length = len + 1;
+ break;
+ default:
+ ret = EINVAL;
+ }
+
+ if (ret == EOK) {
+ SAFEALIGN_COPY_UINT32(&buf->data[*rp], &auth_token_type, rp);
+ SAFEALIGN_COPY_UINT32(&buf->data[*rp], &auth_token_length, rp);
+ safealign_memcpy(&buf->data[*rp], data, auth_token_length, rp);
+ }
+
+ return ret;
+}
+
static errno_t create_send_buffer(struct krb5child_req *kr,
struct io_buffer **io_buf)
{
@@ -94,6 +131,7 @@ static errno_t create_send_buffer(struct krb5child_req *kr,
uint32_t validate;
uint32_t different_realm;
size_t username_len = 0;
+ errno_t ret;
keytab = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_KEYTAB);
if (keytab == NULL) {
@@ -117,11 +155,12 @@ static errno_t create_send_buffer(struct krb5child_req *kr,
kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM ||
kr->pd->cmd == SSS_PAM_CHAUTHTOK) {
buf->size += 4*sizeof(uint32_t) + strlen(kr->ccname) + strlen(keytab) +
- kr->pd->authtok_size;
+ sss_authtok_get_size(&kr->pd->authtok);
}
if (kr->pd->cmd == SSS_PAM_CHAUTHTOK) {
- buf->size += 2*sizeof(uint32_t) + kr->pd->newauthtok_size;
+ buf->size += 2*sizeof(uint32_t) +
+ sss_authtok_get_size(&kr->pd->newauthtok);
}
if (kr->pd->cmd == SSS_PAM_ACCT_MGMT) {
@@ -157,17 +196,17 @@ static errno_t create_send_buffer(struct krb5child_req *kr,
SAFEALIGN_SET_UINT32(&buf->data[rp], strlen(keytab), &rp);
safealign_memcpy(&buf->data[rp], keytab, strlen(keytab), &rp);
- SAFEALIGN_COPY_UINT32(&buf->data[rp], &kr->pd->authtok_type, &rp);
- SAFEALIGN_COPY_UINT32(&buf->data[rp], &kr->pd->authtok_size, &rp);
- safealign_memcpy(&buf->data[rp], kr->pd->authtok,
- kr->pd->authtok_size, &rp);
+ ret = pack_authtok(buf, &rp, &kr->pd->authtok);
+ if (ret) {
+ return ret;
+ }
}
if (kr->pd->cmd == SSS_PAM_CHAUTHTOK) {
- SAFEALIGN_COPY_UINT32(&buf->data[rp], &kr->pd->newauthtok_type, &rp);
- SAFEALIGN_COPY_UINT32(&buf->data[rp], &kr->pd->newauthtok_size, &rp);
- safealign_memcpy(&buf->data[rp], kr->pd->newauthtok,
- kr->pd->newauthtok_size, &rp);
+ ret = pack_authtok(buf, &rp, &kr->pd->newauthtok);
+ if (ret) {
+ return ret;
+ }
}
if (kr->pd->cmd == SSS_PAM_ACCT_MGMT) {
diff --git a/src/providers/krb5/krb5_delayed_online_authentication.c b/src/providers/krb5/krb5_delayed_online_authentication.c
index d5dea3bb..f95fa634 100644
--- a/src/providers/krb5/krb5_delayed_online_authentication.c
+++ b/src/providers/krb5/krb5_delayed_online_authentication.c
@@ -71,27 +71,29 @@ static void authenticate_user(struct tevent_context *ev,
DEBUG_PAM_DATA(9, pd);
- if (pd->authtok == NULL || pd->authtok_size == 0) {
- DEBUG(1, ("Missing authtok for user [%s].\n", pd->user));
- return;
- }
-
#ifdef USE_KEYRING
+ char *password;
long keysize;
long keyrevoke;
- int ret;
- keysize = keyctl_read(pd->key_serial, (char *) pd->authtok,
- pd->authtok_size);
- keyrevoke = keyctl_revoke(pd->key_serial);
+ errno_t ret;
+
+ keysize = keyctl_read_alloc(pd->key_serial, (void **)&password);
if (keysize == -1) {
ret = errno;
DEBUG(1, ("keyctl_read failed [%d][%s].\n", ret, strerror(ret)));
return;
- } else if (keysize != pd->authtok_size) {
- DEBUG(1, ("keyctl_read returned key with wrong size, "
- "expect [%d] got [%d].\n", pd->authtok_size, keysize));
+ }
+
+ ret = sss_authtok_set_password(pd, &pd->authtok, password, keysize);
+ safezero(password, keysize);
+ free(password);
+ if (ret) {
+ DEBUG(1, ("failed to set password in auth token [%d][%s].\n",
+ ret, strerror(ret)));
return;
}
+
+ keyrevoke = keyctl_revoke(pd->key_serial);
if (keyrevoke == -1) {
ret = errno;
DEBUG(1, ("keyctl_revoke failed [%d][%s].\n", ret, strerror(ret)));
@@ -244,8 +246,8 @@ errno_t add_user_to_delayed_online_authentication(struct krb5_ctx *krb5_ctx,
return EINVAL;
}
- if (pd->authtok_size == 0 || pd->authtok == NULL) {
- DEBUG(1, ("Missing authtok for user [%s].\n", pd->user));
+ if (sss_authtok_get_type(&pd->authtok) != SSS_AUTHTOK_TYPE_PASSWORD) {
+ DEBUG(1, ("Invalid authtok for user [%s].\n", pd->user));
return EINVAL;
}
@@ -257,17 +259,29 @@ errno_t add_user_to_delayed_online_authentication(struct krb5_ctx *krb5_ctx,
#ifdef USE_KEYRING
- new_pd->key_serial = add_key("user", new_pd->user, new_pd->authtok,
- new_pd->authtok_size, KEY_SPEC_SESSION_KEYRING);
+ const char *password;
+ size_t len;
+
+ ret = sss_authtok_get_password(&new_pd->authtok, &password, &len);
+ if (ret) {
+ DEBUG(1, ("Failed to get password [%d][%s].\n", ret, strerror(ret)));
+ sss_authtok_set_empty(&new_pd->authtok);
+ talloc_free(new_pd);
+ return ret;
+ }
+
+ new_pd->key_serial = add_key("user", new_pd->user, password, len,
+ KEY_SPEC_SESSION_KEYRING);
if (new_pd->key_serial == -1) {
ret = errno;
- DEBUG(1, ("add_key fialed [%d][%s].\n", ret, strerror(ret)));
+ DEBUG(1, ("add_key failed [%d][%s].\n", ret, strerror(ret)));
+ sss_authtok_set_empty(&new_pd->authtok);
talloc_free(new_pd);
return ret;
}
DEBUG(9, ("Saved authtok of user [%s] with serial [%ld].\n",
new_pd->user, new_pd->key_serial));
- memset(new_pd->authtok, 0, new_pd->authtok_size);
+ sss_authtok_set_empty(&new_pd->authtok);
#endif
key.type = HASH_KEY_ULONG;
diff --git a/src/providers/krb5/krb5_renew_tgt.c b/src/providers/krb5/krb5_renew_tgt.c
index b5eee697..85315425 100644
--- a/src/providers/krb5/krb5_renew_tgt.c
+++ b/src/providers/krb5/krb5_renew_tgt.c
@@ -593,22 +593,14 @@ errno_t add_tgt_to_renew_table(struct krb5_ctx *krb5_ctx, const char *ccfile,
goto done;
}
- if (renew_data->pd->newauthtok_type != SSS_AUTHTOK_TYPE_EMPTY) {
- talloc_zfree(renew_data->pd->newauthtok);
- renew_data->pd->newauthtok_size = 0;
- renew_data->pd->newauthtok_type = SSS_AUTHTOK_TYPE_EMPTY;
- }
+ sss_authtok_set_empty(&renew_data->pd->newauthtok);
- talloc_zfree(renew_data->pd->authtok);
- renew_data->pd->authtok = (uint8_t *) talloc_strdup(renew_data->pd,
- renew_data->ccfile);
- if (renew_data->pd->authtok == NULL) {
- DEBUG(1, ("talloc_strdup failed.\n"));
- ret = ENOMEM;
+ ret = sss_authtok_set_ccfile(renew_data->pd, &renew_data->pd->authtok,
+ renew_data->ccfile, 0);
+ if (ret) {
+ DEBUG(1, ("Failed to store ccfile in auth token.\n"));
goto done;
}
- renew_data->pd->authtok_size = strlen((char *) renew_data->pd->authtok) + 1;
- renew_data->pd->authtok_type = SSS_AUTHTOK_TYPE_CCFILE;
renew_data->pd->cmd = SSS_CMD_RENEW;
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index b0dd30ce..3dcb0b2d 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -463,7 +463,7 @@ struct auth_state {
struct tevent_context *ev;
struct sdap_auth_ctx *ctx;
const char *username;
- struct dp_opt_blob password;
+ struct sss_auth_token *authtok;
struct sdap_service *sdap_service;
struct sdap_handle *sh;
@@ -485,7 +485,7 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_auth_ctx *ctx,
const char *username,
- struct dp_opt_blob password,
+ struct sss_auth_token *authtok,
bool try_chpass_service)
{
struct tevent_req *req;
@@ -494,8 +494,8 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx,
req = tevent_req_create(memctx, &state, struct auth_state);
if (!req) return NULL;
- /* Treat a zero-length password as a failure */
- if (password.length == 0) {
+ /* The token must be a password token */
+ if (sss_authtok_get_type(authtok) != SSS_AUTHTOK_TYPE_PASSWORD) {
state->result = SDAP_AUTH_FAILED;
tevent_req_done(req);
return tevent_req_post(req, ev);
@@ -504,7 +504,7 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ctx = ctx;
state->username = username;
- state->password = password;
+ state->authtok = authtok;
state->srv = NULL;
if (try_chpass_service && ctx->chpass_service != NULL &&
ctx->chpass_service->name != NULL) {
@@ -629,7 +629,7 @@ static void auth_connect_done(struct tevent_req *subreq)
subreq = sdap_auth_send(state, state->ev, state->sh,
NULL, NULL, state->dn,
- "password", state->password);
+ state->authtok);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
@@ -721,8 +721,6 @@ struct sdap_pam_chpass_state {
struct pam_data *pd;
const char *username;
char *dn;
- char *password;
- char *new_password;
struct sdap_handle *sh;
struct sdap_auth_ctx *ctx;
@@ -738,7 +736,6 @@ void sdap_pam_chpass_handler(struct be_req *breq)
struct sdap_auth_ctx *ctx;
struct tevent_req *subreq;
struct pam_data *pd;
- struct dp_opt_blob authtok;
int dp_err = DP_ERR_FATAL;
ctx = talloc_get_type(breq->be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
@@ -752,8 +749,8 @@ void sdap_pam_chpass_handler(struct be_req *breq)
goto done;
}
- if (pd->priv == 1 && pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM &&
- pd->authtok_size == 0) {
+ if ((pd->priv == 1) && (pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) &&
+ (sss_authtok_get_type(&pd->authtok) != SSS_AUTHTOK_TYPE_PASSWORD)) {
DEBUG(4, ("Password reset by root is not supported.\n"));
pd->pam_status = PAM_PERM_DENIED;
dp_err = DP_ERR_OK;
@@ -776,25 +773,9 @@ void sdap_pam_chpass_handler(struct be_req *breq)
state->pd = pd;
state->username = pd->user;
state->ctx = ctx;
- state->password = talloc_strndup(state,
- (char *)pd->authtok, pd->authtok_size);
- if (!state->password) goto done;
- talloc_set_destructor((TALLOC_CTX *)state->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);
- subreq = auth_send(breq, breq->be_ctx->ev,
- ctx, state->username, authtok, true);
+ subreq = auth_send(breq, breq->be_ctx->ev, ctx,
+ state->username, &pd->authtok, true);
if (!subreq) goto done;
tevent_req_set_callback(subreq, sdap_auth4chpass_done, state);
@@ -881,18 +862,30 @@ static void sdap_auth4chpass_done(struct tevent_req *req)
state->pd->pam_status = PAM_MODULE_UNKNOWN;
goto done;
} else {
+ const char *password;
+ const char *new_password;
+
+ ret = sss_authtok_get_password(&state->pd->authtok,
+ &password, NULL);
+ if (ret) {
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
+ ret = sss_authtok_get_password(&state->pd->newauthtok,
+ &new_password, NULL);
+ if (ret) {
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
+
subreq = sdap_exop_modify_passwd_send(state,
state->breq->be_ctx->ev,
- state->sh,
- state->dn,
- state->password,
- state->new_password);
-
+ state->sh, state->dn,
+ password, new_password);
if (!subreq) {
DEBUG(2, ("Failed to change password for %s\n", state->username));
goto done;
}
-
tevent_req_set_callback(subreq, sdap_pam_chpass_done, state);
return;
}
@@ -1007,8 +1000,6 @@ done:
struct sdap_pam_auth_state {
struct be_req *breq;
struct pam_data *pd;
- const char *username;
- struct dp_opt_blob password;
};
static void sdap_pam_auth_done(struct tevent_req *req);
@@ -1043,12 +1034,9 @@ void sdap_pam_auth_handler(struct be_req *breq)
state->breq = breq;
state->pd = pd;
- state->username = pd->user;
- state->password.data = pd->authtok;
- state->password.length = pd->authtok_size;
subreq = auth_send(breq, breq->be_ctx->ev, ctx,
- state->username, state->password,
+ pd->user, &pd->authtok,
pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM ? true : false);
if (!subreq) goto done;
@@ -1082,6 +1070,7 @@ static void sdap_pam_auth_done(struct tevent_req *req)
enum pwexpire pw_expire_type;
struct be_ctx *be_ctx = state->breq->be_ctx;
void *pw_expire_data;
+ const char *password;
int dp_err = DP_ERR_OK;
int ret;
@@ -1164,26 +1153,19 @@ static void sdap_pam_auth_done(struct tevent_req *req)
if (result == SDAP_AUTH_SUCCESS &&
state->breq->be_ctx->domain->cache_credentials) {
- char *password = talloc_strndup(state, (char *)
- state->password.data,
- state->password.length);
- /* password caching failures are not fatal errors */
- if (!password) {
- DEBUG(2, ("Failed to cache password for %s\n", state->username));
- goto done;
+ ret = sss_authtok_get_password(&state->pd->authtok, &password, NULL);
+ if (ret == EOK) {
+ ret = sysdb_cache_password(state->breq->be_ctx->sysdb,
+ state->pd->user, password);
}
- talloc_set_destructor((TALLOC_CTX *)password, password_destructor);
-
- ret = sysdb_cache_password(state->breq->be_ctx->sysdb,
- state->username, password);
/* password caching failures are not fatal errors */
if (ret != EOK) {
DEBUG(2, ("Failed to cache password for %s\n",
- state->username));
+ state->pd->user));
} else {
DEBUG(4, ("Password successfully cached for %s\n",
- state->username));
+ state->pd->user));
}
goto done;
}
diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
index e0440625..84497b75 100644
--- a/src/providers/ldap/sdap_async.c
+++ b/src/providers/ldap/sdap_async.c
@@ -502,8 +502,8 @@ struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_handle *sh,
char *user_dn,
- char *password,
- char *new_password)
+ const char *password,
+ const char *new_password)
{
struct tevent_req *req = NULL;
struct sdap_exop_modify_passwd_state *state;
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 8c16d94e..c5dc1703 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -108,8 +108,7 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
const char *sasl_mech,
const char *sasl_user,
const char *user_dn,
- const char *authtok_type,
- struct dp_opt_blob authtok);
+ struct sss_auth_token *authtok);
int sdap_auth_recv(struct tevent_req *req,
TALLOC_CTX *memctx,
@@ -128,8 +127,8 @@ struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_handle *sh,
char *user_dn,
- char *password,
- char *new_password);
+ const char *password,
+ const char *new_password);
int sdap_exop_modify_passwd_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
enum sdap_result *result,
char **user_error_msg);
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index ff992484..da50f4ad 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -493,7 +493,7 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
DEBUG(4, ("Executing simple bind as: %s\n", state->user_dn));
ret = ldap_sasl_bind(state->sh->ldap, state->user_dn, LDAP_SASL_SIMPLE,
- state->pw, request_controls, NULL, &msgid);
+ pw, request_controls, NULL, &msgid);
if (ctrls[0]) ldap_control_free(ctrls[0]);
if (ret == -1 || msgid == -1) {
ret = ldap_get_option(state->sh->ldap,
@@ -1082,18 +1082,12 @@ int sdap_kinit_recv(struct tevent_req *req,
/* ==Authenticaticate-User-by-DN========================================== */
struct sdap_auth_state {
- const char *user_dn;
- struct berval pw;
struct sdap_ppolicy_data *ppolicy;
-
- int result;
bool is_sasl;
+ int result;
};
static void sdap_auth_done(struct tevent_req *subreq);
-static int sdap_auth_get_authtok(const char *authtok_type,
- struct dp_opt_blob authtok,
- struct berval *pw);
/* TODO: handle sasl_cred */
struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
@@ -1102,31 +1096,14 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
const char *sasl_mech,
const char *sasl_user,
const char *user_dn,
- const char *authtok_type,
- struct dp_opt_blob authtok)
+ struct sss_auth_token *authtok)
{
struct tevent_req *req, *subreq;
struct sdap_auth_state *state;
- int ret;
req = tevent_req_create(memctx, &state, struct sdap_auth_state);
if (!req) return NULL;
- state->user_dn = user_dn;
-
- ret = sdap_auth_get_authtok(authtok_type, authtok, &state->pw);
- if (ret != EOK) {
- if (ret == ENOSYS) {
- DEBUG(1, ("Getting authtok is not supported with the "
- "crypto library compiled with, authentication "
- "might fail!\n"));
- } else {
- DEBUG(1, ("Cannot parse authtok.\n"));
- tevent_req_error(req, ret);
- return tevent_req_post(req, ev);
- }
- }
-
if (sasl_mech) {
state->is_sasl = true;
subreq = sasl_bind_send(state, ev, sh, sasl_mech, sasl_user, NULL);
@@ -1135,8 +1112,27 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
return tevent_req_post(req, ev);
}
} else {
+ const char *password = NULL;
+ struct berval pw;
+ size_t pwlen;
+ errno_t ret;
+
+ ret = sss_authtok_get_password(authtok, &password, &pwlen);
+ if (ret != EOK) {
+ DEBUG(1, ("Cannot parse authtok.\n"));
+ tevent_req_error(req, ret);
+ return tevent_req_post(req, ev);
+ }
+ /* Treat a zero-length password as a failure */
+ if (*password == '\0') {
+ tevent_req_error(req, ENOENT);
+ return tevent_req_post(req, ev);
+ }
+ pw.bv_val = discard_const(password);
+ pw.bv_len = pwlen - 1;
+
state->is_sasl = false;
- subreq = simple_bind_send(state, ev, sh, user_dn, &state->pw);
+ subreq = simple_bind_send(state, ev, sh, user_dn, &pw);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return tevent_req_post(req, ev);
@@ -1598,6 +1594,10 @@ static void sdap_cli_auth_step(struct tevent_req *req)
SDAP_SASL_MECH);
const char *user_dn = dp_opt_get_string(state->opts->basic,
SDAP_DEFAULT_BIND_DN);
+ const char *authtok_type;
+ struct dp_opt_blob authtok_blob;
+ struct sss_auth_token authtok = { 0 };
+ errno_t ret;
/* Set the LDAP expiration time
* If SASL has already set it, use the sooner of the two
@@ -1620,17 +1620,31 @@ static void sdap_cli_auth_step(struct tevent_req *req)
return;
}
- subreq = sdap_auth_send(state,
- state->ev,
- state->sh,
- sasl_mech,
- dp_opt_get_string(state->opts->basic,
- SDAP_SASL_AUTHID),
- user_dn,
+ authtok_type = dp_opt_get_string(state->opts->basic,
+ SDAP_DEFAULT_AUTHTOK_TYPE);
+ if (authtok_type != NULL) {
+ if (strcasecmp(authtok_type, "password") != 0) {
+ DEBUG(SSSDBG_TRACE_LIBS, ("Invalid authtoken type\n"));
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+ authtok_blob = dp_opt_get_blob(state->opts->basic,
+ SDAP_DEFAULT_AUTHTOK);
+
+ ret = sss_authtok_set_password(state, &authtok,
+ (const char *)authtok_blob.data,
+ authtok_blob.length);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+ }
+
+ subreq = sdap_auth_send(state, state->ev,
+ state->sh, sasl_mech,
dp_opt_get_string(state->opts->basic,
- SDAP_DEFAULT_AUTHTOK_TYPE),
- dp_opt_get_blob(state->opts->basic,
- SDAP_DEFAULT_AUTHTOK));
+ SDAP_SASL_AUTHID),
+ user_dn, &authtok);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
diff --git a/src/providers/proxy/proxy.h b/src/providers/proxy/proxy.h
index cea03382..962cb28f 100644
--- a/src/providers/proxy/proxy.h
+++ b/src/providers/proxy/proxy.h
@@ -89,11 +89,8 @@ struct proxy_nss_ops {
};
struct authtok_conv {
- uint32_t authtok_size;
- uint8_t *authtok;
-
- uint32_t newauthtok_size;
- uint8_t *newauthtok;
+ struct sss_auth_token authtok;
+ struct sss_auth_token newauthtok;
bool sent_old;
};
diff --git a/src/providers/proxy/proxy_auth.c b/src/providers/proxy/proxy_auth.c
index 8088283f..3430f38b 100644
--- a/src/providers/proxy/proxy_auth.c
+++ b/src/providers/proxy/proxy_auth.c
@@ -712,7 +712,7 @@ static void proxy_child_done(struct tevent_req *req)
struct proxy_client_ctx *client_ctx =
tevent_req_callback_data(req, struct proxy_client_ctx);
struct pam_data *pd = NULL;
- char *password;
+ const char *password;
int ret;
struct tevent_immediate *imm;
@@ -747,17 +747,15 @@ static void proxy_child_done(struct tevent_req *req)
/* Check if we need to save the cached credentials */
if ((pd->cmd == SSS_PAM_AUTHENTICATE || pd->cmd == SSS_PAM_CHAUTHTOK) &&
- pd->pam_status == PAM_SUCCESS &&
- client_ctx->be_req->be_ctx->domain->cache_credentials) {
- password = talloc_strndup(client_ctx->be_req,
- (char *) pd->authtok,
- pd->authtok_size);
- if (!password) {
+ (pd->pam_status == PAM_SUCCESS) &&
+ client_ctx->be_req->be_ctx->domain->cache_credentials) {
+
+ ret = sss_authtok_get_password(&pd->authtok, &password, NULL);
+ if (ret) {
/* password caching failures are not fatal errors */
DEBUG(2, ("Failed to cache password\n"));
goto done;
}
- talloc_set_destructor((TALLOC_CTX *)password, password_destructor);
ret = sysdb_cache_password(client_ctx->be_req->be_ctx->sysdb,
pd->user, password);
diff --git a/src/providers/proxy/proxy_child.c b/src/providers/proxy/proxy_child.c
index c575948a..556dbf9b 100644
--- a/src/providers/proxy/proxy_child.c
+++ b/src/providers/proxy/proxy_child.c
@@ -80,6 +80,9 @@ static int proxy_internal_conv(int num_msg, const struct pam_message **msgm,
int i;
struct pam_response *reply;
struct authtok_conv *auth_data;
+ const char *password;
+ size_t pwlen;
+ errno_t ret;
auth_data = talloc_get_type(appdata_ptr, struct authtok_conv);
@@ -94,11 +97,13 @@ static int proxy_internal_conv(int num_msg, const struct pam_message **msgm,
case PAM_PROMPT_ECHO_OFF:
DEBUG(4, ("Conversation message: [%s]\n", msgm[i]->msg));
reply[i].resp_retcode = 0;
- reply[i].resp = calloc(auth_data->authtok_size + 1,
- sizeof(char));
+
+ ret = sss_authtok_get_password(&auth_data->authtok,
+ &password, &pwlen);
+ if (ret) goto failed;
+ reply[i].resp = calloc(pwlen + 1, sizeof(char));
if (reply[i].resp == NULL) goto failed;
- memcpy(reply[i].resp, auth_data->authtok,
- auth_data->authtok_size);
+ memcpy(reply[i].resp, password, pwlen + 1);
break;
default:
@@ -124,6 +129,9 @@ static int proxy_chauthtok_conv(int num_msg, const struct pam_message **msgm,
int i;
struct pam_response *reply;
struct authtok_conv *auth_data;
+ const char *password;
+ size_t pwlen;
+ errno_t ret;
auth_data = talloc_get_type(appdata_ptr, struct authtok_conv);
@@ -141,20 +149,23 @@ static int proxy_chauthtok_conv(int num_msg, const struct pam_message **msgm,
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));
+ ret = sss_authtok_get_password(&auth_data->authtok,
+ &password, &pwlen);
+ if (ret) goto failed;
+ reply[i].resp = calloc(pwlen + 1, sizeof(char));
if (reply[i].resp == NULL) goto failed;
- memcpy(reply[i].resp, auth_data->authtok,
- auth_data->authtok_size);
+ memcpy(reply[i].resp, password, pwlen + 1);
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));
+ ret = sss_authtok_get_password(&auth_data->newauthtok,
+ &password, &pwlen);
+ if (ret) goto failed;
+ reply[i].resp = calloc(pwlen + 1, sizeof(char));
if (reply[i].resp == NULL) goto failed;
- memcpy(reply[i].resp, auth_data->newauthtok,
- auth_data->newauthtok_size);
+ memcpy(reply[i].resp, password, pwlen + 1);
+ auth_data->sent_old = true;
}
break;
@@ -213,8 +224,8 @@ static errno_t call_pam_stack(const char *pam_target, struct pam_data *pd)
}
switch (pd->cmd) {
case SSS_PAM_AUTHENTICATE:
- auth_data->authtok_size = pd->authtok_size;
- auth_data->authtok = pd->authtok;
+ sss_authtok_copy(auth_data, &pd->authtok,
+ &auth_data->authtok);
pam_status = pam_authenticate(pamh, 0);
break;
case SSS_PAM_SETCRED:
@@ -230,21 +241,21 @@ 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;
+ sss_authtok_copy(auth_data, &pd->authtok,
+ &auth_data->authtok);
if (pd->priv != 1) {
pam_status = pam_authenticate(pamh, 0);
auth_data->sent_old = false;
if (pam_status != PAM_SUCCESS) break;
}
- auth_data->newauthtok_size = pd->newauthtok_size;
- auth_data->newauthtok = pd->newauthtok;
+ sss_authtok_copy(auth_data, &pd->newauthtok,
+ &auth_data->newauthtok);
pam_status = pam_chauthtok(pamh, 0);
break;
case SSS_PAM_CHAUTHTOK_PRELIM:
if (pd->priv != 1) {
- auth_data->authtok_size = pd->authtok_size;
- auth_data->authtok = pd->authtok;
+ sss_authtok_copy(auth_data, &pd->authtok,
+ &auth_data->authtok);
pam_status = pam_authenticate(pamh, 0);
} else {
pam_status = PAM_SUCCESS;
diff --git a/src/responder/pam/pam_LOCAL_domain.c b/src/responder/pam/pam_LOCAL_domain.c
index 71446b4f..23eb7a2a 100644
--- a/src/responder/pam/pam_LOCAL_domain.c
+++ b/src/responder/pam/pam_LOCAL_domain.c
@@ -154,22 +154,19 @@ static void do_pam_acct_mgmt(struct LOCAL_request *lreq)
static void do_pam_chauthtok(struct LOCAL_request *lreq)
{
int ret;
- char *newauthtok;
+ const char *password;
char *salt;
char *new_hash;
struct pam_data *pd;
pd = lreq->preq->pd;
- newauthtok = talloc_strndup(lreq, (char *) pd->newauthtok,
- pd->newauthtok_size);
- NULL_CHECK_OR_JUMP(newauthtok, ("talloc_strndup failed.\n"), lreq->error,
- ENOMEM, done);
- memset(pd->newauthtok, 0, pd->newauthtok_size);
-
- if (strlen(newauthtok) == 0) {
+ ret = sss_authtok_get_password(&pd->newauthtok, &password, NULL);
+ if (ret) {
/* TODO: should we allow null passwords via a config option ? */
- DEBUG(1, ("Empty passwords are not allowed!\n"));
+ if (ret == ENOENT) {
+ DEBUG(1, ("Empty passwords are not allowed!\n"));
+ }
lreq->error = EINVAL;
goto done;
}
@@ -179,11 +176,10 @@ static void do_pam_chauthtok(struct LOCAL_request *lreq)
lreq->error, ret, done);
DEBUG(4, ("Using salt [%s]\n", salt));
- ret = s3crypt_sha512(lreq, newauthtok, salt, &new_hash);
+ ret = s3crypt_sha512(lreq, password, salt, &new_hash);
NEQ_CHECK_OR_JUMP(ret, EOK, ("Hash generation failed.\n"),
lreq->error, ret, done);
DEBUG(4, ("New hash [%s]\n", new_hash));
- memset(newauthtok, 0, pd->newauthtok_size);
lreq->mod_attrs = sysdb_new_attrs(lreq);
NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
@@ -204,7 +200,7 @@ static void do_pam_chauthtok(struct LOCAL_request *lreq)
lreq->error, ret, done);
done:
- return;
+ sss_authtok_set_empty(&pd->newauthtok);
}
int LOCAL_pam_handler(struct pam_auth_req *preq)
@@ -223,9 +219,9 @@ int LOCAL_pam_handler(struct pam_auth_req *preq)
NULL};
struct ldb_result *res;
const char *username = NULL;
- const char *password = NULL;
+ const char *pwdhash = NULL;
char *new_hash = NULL;
- char *authtok = NULL;
+ const char *password;
struct pam_data *pd = preq->pd;
int ret;
@@ -287,25 +283,22 @@ int LOCAL_pam_handler(struct pam_auth_req *preq)
DEBUG(4, ("allowing root to reset a password.\n"));
break;
}
- authtok = talloc_strndup(lreq, (char *) pd->authtok,
- pd->authtok_size);
- NULL_CHECK_OR_JUMP(authtok, ("talloc_strndup failed.\n"),
- lreq->error, ENOMEM, done);
- memset(pd->authtok, 0, pd->authtok_size);
-
- password = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_PWD, NULL);
- NULL_CHECK_OR_JUMP(password, ("No password stored.\n"),
+ ret = sss_authtok_get_password(&pd->authtok, &password, NULL);
+ NEQ_CHECK_OR_JUMP(ret, EOK, ("Failed to get password.\n"),
+ lreq->error, ret, done);
+
+ pwdhash = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_PWD, NULL);
+ NULL_CHECK_OR_JUMP(pwdhash, ("No password stored.\n"),
lreq->error, LDB_ERR_NO_SUCH_ATTRIBUTE, done);
- DEBUG(4, ("user: [%s], password hash: [%s]\n", username, password));
+ DEBUG(4, ("user: [%s], password hash: [%s]\n", username, pwdhash));
- ret = s3crypt_sha512(lreq, authtok, password, &new_hash);
- memset(authtok, 0, pd->authtok_size);
+ ret = s3crypt_sha512(lreq, password, pwdhash, &new_hash);
NEQ_CHECK_OR_JUMP(ret, EOK, ("nss_sha512_crypt failed.\n"),
lreq->error, ret, done);
DEBUG(4, ("user: [%s], new hash: [%s]\n", username, new_hash));
- if (strcmp(new_hash, password) != 0) {
+ if (strcmp(new_hash, pwdhash) != 0) {
DEBUG(1, ("Passwords do not match.\n"));
do_failed_login(lreq);
goto done;
@@ -338,13 +331,8 @@ int LOCAL_pam_handler(struct pam_auth_req *preq)
}
done:
- if (pd->authtok != NULL)
- memset(pd->authtok, 0, pd->authtok_size);
- if (authtok != NULL)
- memset(authtok, 0, pd->authtok_size);
- if (pd->newauthtok != NULL)
- memset(pd->newauthtok, 0, pd->newauthtok_size);
-
+ sss_authtok_set_empty(&pd->newauthtok);
+ sss_authtok_set_empty(&pd->authtok);
prepare_reply(lreq);
return EOK;
}
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index ed7438f8..813894d3 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -49,21 +49,38 @@ enum pam_verbosity {
static void pam_reply(struct pam_auth_req *preq);
-static int extract_authtok(uint32_t *type, uint32_t *size, uint8_t **tok,
- size_t data_size, uint8_t *body, size_t blen,
- size_t *c) {
+static int extract_authtok_v2(TALLOC_CTX *mem_ctx, struct sss_auth_token *tok,
+ size_t data_size, uint8_t *body, size_t blen,
+ size_t *c)
+{
+ uint32_t auth_token_type;
+ uint32_t auth_token_length;
+ uint8_t *auth_token_data;
+ int ret = EOK;
if (data_size < sizeof(uint32_t) || *c+data_size > blen ||
SIZE_T_OVERFLOW(*c, data_size)) return EINVAL;
- *size = data_size - sizeof(uint32_t);
- SAFEALIGN_COPY_UINT32_CHECK(type, &body[*c], blen, c);
+ SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
+ auth_token_length = data_size - sizeof(uint32_t);
+ auth_token_data = body+(*c);
- *tok = body+(*c);
+ switch (auth_token_type) {
+ case SSS_AUTHTOK_TYPE_EMPTY:
+ sss_authtok_set_empty(tok);
+ break;
+ case SSS_AUTHTOK_TYPE_PASSWORD:
+ ret = sss_authtok_set_password(mem_ctx, tok,
+ (const char *)auth_token_data,
+ auth_token_length);
+ break;
+ default:
+ return EINVAL;
+ }
- *c += (*size);
+ *c += auth_token_length;
- return EOK;
+ return ret;
}
static int extract_string(char **var, size_t size, uint8_t *body, size_t blen,
@@ -185,14 +202,13 @@ static int pam_parse_in_data_v2(struct sss_domain_info *domains,
if (ret != EOK) return ret;
break;
case SSS_PAM_ITEM_AUTHTOK:
- ret = extract_authtok(&pd->authtok_type, &pd->authtok_size,
- &pd->authtok, size, body, blen, &c);
+ ret = extract_authtok_v2(pd, &pd->authtok,
+ size, body, blen, &c);
if (ret != EOK) return ret;
break;
case SSS_PAM_ITEM_NEWAUTHTOK:
- ret = extract_authtok(&pd->newauthtok_type,
- &pd->newauthtok_size,
- &pd->newauthtok, size, body, blen, &c);
+ ret = extract_authtok_v2(pd, &pd->newauthtok,
+ size, body, blen, &c);
if (ret != EOK) return ret;
break;
default:
@@ -232,14 +248,44 @@ static int pam_parse_in_data_v3(struct sss_domain_info *domains,
return EOK;
}
+static int extract_authtok_v1(TALLOC_CTX *mem_ctx, struct sss_auth_token *tok,
+ uint8_t *body, size_t blen, size_t *c)
+{
+ uint32_t auth_token_type;
+ uint32_t auth_token_length;
+ uint8_t *auth_token_data;
+ int ret = EOK;
+
+ SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c);
+ SAFEALIGN_COPY_UINT32_CHECK(&auth_token_length, &body[*c], blen, c);
+ auth_token_data = body+(*c);
+
+ switch (auth_token_type) {
+ case SSS_AUTHTOK_TYPE_EMPTY:
+ sss_authtok_set_empty(tok);
+ break;
+ case SSS_AUTHTOK_TYPE_PASSWORD:
+ ret = sss_authtok_set_password(mem_ctx, tok,
+ (const char *)auth_token_data,
+ auth_token_length);
+ break;
+ default:
+ return EINVAL;
+ }
+
+ *c += auth_token_length;
+
+ return ret;
+}
+
static int pam_parse_in_data(struct sss_domain_info *domains,
const char *default_domain,
struct pam_data *pd,
uint8_t *body, size_t blen)
{
- int start;
- int end;
- int last;
+ size_t start;
+ size_t end;
+ size_t last;
int ret;
last = blen - 1;
@@ -269,45 +315,15 @@ static int pam_parse_in_data(struct sss_domain_info *domains,
if (body[end++] != '\0') return EINVAL;
pd->rhost = (char *) &body[start];
- start = end;
- pd->authtok_type = (int) body[start];
-
- start += sizeof(uint32_t);
- pd->authtok_size = (int) body[start];
- if (pd->authtok_size >= blen) return EINVAL;
-
- start += sizeof(uint32_t);
- end = start + pd->authtok_size;
- if (pd->authtok_size == 0) {
- pd->authtok = NULL;
- } else {
- if (end <= blen) {
- pd->authtok = (uint8_t *) &body[start];
- } else {
- DEBUG(1, ("Invalid authtok size: %d\n", pd->authtok_size));
- return EINVAL;
- }
+ ret = extract_authtok_v1(pd, &pd->authtok, body, blen, &end);
+ if (ret) {
+ DEBUG(1, ("Invalid auth token\n"));
+ return ret;
}
-
- start = end;
- pd->newauthtok_type = (int) body[start];
-
- start += sizeof(uint32_t);
- pd->newauthtok_size = (int) body[start];
- if (pd->newauthtok_size >= blen) return EINVAL;
-
- start += sizeof(uint32_t);
- end = start + pd->newauthtok_size;
-
- if (pd->newauthtok_size == 0) {
- pd->newauthtok = NULL;
- } else {
- if (end <= blen) {
- pd->newauthtok = (uint8_t *) &body[start];
- } else {
- DEBUG(1, ("Invalid newauthtok size: %d\n", pd->newauthtok_size));
- return EINVAL;
- }
+ ret = extract_authtok_v1(pd, &pd->newauthtok, body, blen, &end);
+ if (ret) {
+ DEBUG(1, ("Invalid new auth token\n"));
+ return ret;
}
DEBUG_PAM_DATA(4, pd);
@@ -763,9 +779,9 @@ static void pam_reply(struct pam_auth_req *preq)
goto done;
}
- password = talloc_strndup(preq, pd->authtok, pd->authtok_size);
- if (!password) {
- DEBUG(0, ("Fatal: Out of memory copying password\n"));
+ ret = sss_authtok_get_password(&pd->authtok, &password, NULL);
+ if (ret) {
+ DEBUG(0, ("Failed to get password.\n"));
goto done;
}
@@ -775,10 +791,6 @@ static void pam_reply(struct pam_auth_req *preq)
&exp_date, &delay_until);
pam_handle_cached_login(preq, ret, exp_date, delay_until);
- if (password) {
- for (i = 0; password[i]; i++) password[i] = 0;
- talloc_zfree(password);
- }
return;
}
break;
diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
index 34d025b7..a72a3519 100644
--- a/src/tests/krb5_child-test.c
+++ b/src/tests/krb5_child-test.c
@@ -167,6 +167,9 @@ create_dummy_pam_data(TALLOC_CTX *mem_ctx, const char *user,
const char *password)
{
struct pam_data *pd;
+ const char *authtok;
+ size_t authtok_len;
+ errno_t ret;
pd = talloc_zero(mem_ctx, struct pam_data);
if (!pd) goto fail;
@@ -175,12 +178,12 @@ create_dummy_pam_data(TALLOC_CTX *mem_ctx, const char *user,
pd->user = talloc_strdup(pd, user);
if (!pd->user) goto fail;
- pd->authtok = discard_const(talloc_strdup(pd, password));
- if (!pd->authtok) goto fail;
- pd->authtok_size = strlen(password);
- pd->authtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
+ ret = sss_authtok_set_password(pd, &pd->authtok, password, 0);
+ if (ret) goto fail;
+
+ (void)sss_authtok_get_password(&pd->authtok, &authtok, &authtok_len);
DEBUG(SSSDBG_FUNC_DATA, ("Authtok [%s] len [%d]\n",
- pd->authtok, pd->authtok_size));
+ authtok, (int)authtok_len));
return pd;