summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/providers/ldap/ldap_child.c35
-rw-r--r--src/providers/ldap/sdap.h2
-rw-r--r--src/providers/ldap/sdap_async.h4
-rw-r--r--src/providers/ldap/sdap_async_connection.c14
-rw-r--r--src/providers/ldap/sdap_async_private.h3
-rw-r--r--src/providers/ldap/sdap_child_helpers.c23
6 files changed, 64 insertions, 17 deletions
diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
index 3369d7098..19162e92a 100644
--- a/src/providers/ldap/ldap_child.c
+++ b/src/providers/ldap/ldap_child.c
@@ -94,13 +94,13 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size,
return EOK;
}
-static int pack_buffer(struct response *r, int result, const char *msg)
+static int pack_buffer(struct response *r, int result, const char *msg, time_t expire_time)
{
int len;
size_t p = 0;
len = strlen(msg);
- r->size = 2 * sizeof(uint32_t) + len;
+ r->size = 2 * sizeof(uint32_t) + len + sizeof(time_t);
r->buf = talloc_array(r, uint8_t, r->size);
if(!r->buf) {
@@ -116,6 +116,9 @@ static int pack_buffer(struct response *r, int result, const char *msg)
/* message itself */
safealign_memcpy(&r->buf[p], msg, len, &p);
+ /* ticket expiration time */
+ safealign_memcpy(&r->buf[p], &expire_time, sizeof(expire_time), &p);
+
return EOK;
}
@@ -124,7 +127,8 @@ static int ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
const char *princ_str,
const char *keytab_name,
const krb5_deltat lifetime,
- const char **ccname_out)
+ const char **ccname_out,
+ time_t *expire_time_out)
{
char *ccname;
char *realm_name = NULL;
@@ -136,6 +140,8 @@ static int ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
krb5_creds my_creds;
krb5_get_init_creds_opt options;
krb5_error_code krberr;
+ krb5_timestamp kdc_time_offset;
+ int kdc_time_offset_usec;
int ret;
krberr = krb5_init_context(&context);
@@ -254,8 +260,20 @@ static int ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
goto done;
}
+ krberr = krb5_get_time_offsets(context, &kdc_time_offset, &kdc_time_offset_usec);
+ if (krberr) {
+ DEBUG(2, ("Failed to get KDC time offset: %s\n",
+ sss_krb5_get_error_message(context, krberr)));
+ kdc_time_offset = 0;
+ } else {
+ if (kdc_time_offset_usec > 0) {
+ kdc_time_offset++;
+ }
+ }
+
ret = EOK;
*ccname_out = ccname;
+ *expire_time_out = my_creds.times.endtime - kdc_time_offset;
done:
if (keytab) krb5_kt_close(context, keytab);
@@ -265,6 +283,7 @@ done:
static int prepare_response(TALLOC_CTX *mem_ctx,
const char *ccname,
+ time_t expire_time,
krb5_error_code kerr,
struct response **rsp)
{
@@ -279,7 +298,7 @@ static int prepare_response(TALLOC_CTX *mem_ctx,
r->size = 0;
if (kerr == 0) {
- ret = pack_buffer(r, EOK, ccname);
+ ret = pack_buffer(r, EOK, ccname, expire_time);
} else {
krb5_msg = sss_krb5_get_error_message(krb5_error_ctx, kerr);
if (krb5_msg == NULL) {
@@ -287,7 +306,7 @@ static int prepare_response(TALLOC_CTX *mem_ctx,
return ENOMEM;
}
- ret = pack_buffer(r, EFAULT, krb5_msg);
+ ret = pack_buffer(r, EFAULT, krb5_msg, 0);
sss_krb5_free_error_message(krb5_error_ctx, krb5_msg);
}
@@ -311,6 +330,7 @@ int main(int argc, const char *argv[])
uint8_t *buf = NULL;
ssize_t len = 0;
const char *ccname = NULL;
+ time_t expire_time = 0;
struct input_buffer *ibuf = NULL;
struct response *resp = NULL;
size_t written;
@@ -397,13 +417,14 @@ int main(int argc, const char *argv[])
kerr = ldap_child_get_tgt_sync(main_ctx,
ibuf->realm_str, ibuf->princ_str,
- ibuf->keytab_name, ibuf->lifetime, &ccname);
+ ibuf->keytab_name, ibuf->lifetime,
+ &ccname, &expire_time);
if (kerr != EOK) {
DEBUG(1, ("ldap_child_get_tgt_sync failed.\n"));
/* Do not return, must report failure */
}
- ret = prepare_response(main_ctx, ccname, kerr, &resp);
+ ret = prepare_response(main_ctx, ccname, expire_time, kerr, &resp);
if (ret != EOK) {
DEBUG(1, ("prepare_response failed. [%d][%s].\n", ret, strerror(ret)));
return ENOMEM;
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index ef22cda06..91d91b859 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -80,6 +80,8 @@ struct ldap_cb_data {
struct sdap_handle {
LDAP *ldap;
bool connected;
+ /* Authentication ticket expiration time (if any) */
+ time_t expire_time;
struct sdap_fd_events *sdap_fd_events;
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 1e52c480a..99cf064dc 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -67,7 +67,9 @@ struct tevent_req *sdap_kinit_send(TALLOC_CTX *memctx,
const char *principal,
const char *realm,
int lifetime);
-int sdap_kinit_recv(struct tevent_req *req, enum sdap_result *result);
+int sdap_kinit_recv(struct tevent_req *req,
+ enum sdap_result *result,
+ time_t *expire_time);
struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index fd1cc8c72..193971c23 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -626,6 +626,7 @@ static int sasl_bind_recv(struct tevent_req *req, int *ldaperr)
struct sdap_kinit_state {
int result;
+ time_t expire_time;
};
static void sdap_kinit_done(struct tevent_req *subreq);
@@ -686,8 +687,9 @@ static void sdap_kinit_done(struct tevent_req *subreq)
int ret;
int result;
char *ccname = NULL;
+ time_t expire_time;
- ret = sdap_get_tgt_recv(subreq, state, &result, &ccname);
+ ret = sdap_get_tgt_recv(subreq, state, &result, &ccname, &expire_time);
talloc_zfree(subreq);
if (ret != EOK) {
state->result = SDAP_AUTH_FAILED;
@@ -704,6 +706,7 @@ static void sdap_kinit_done(struct tevent_req *subreq)
tevent_req_error(req, EFAULT);
}
+ state->expire_time = expire_time;
state->result = SDAP_AUTH_SUCCESS;
tevent_req_done(req);
return;
@@ -714,7 +717,9 @@ static void sdap_kinit_done(struct tevent_req *subreq)
tevent_req_error(req, EIO);
}
-int sdap_kinit_recv(struct tevent_req *req, enum sdap_result *result)
+int sdap_kinit_recv(struct tevent_req *req,
+ enum sdap_result *result,
+ time_t *expire_time)
{
struct sdap_kinit_state *state = tevent_req_data(req,
struct sdap_kinit_state);
@@ -729,6 +734,7 @@ int sdap_kinit_recv(struct tevent_req *req, enum sdap_result *result)
}
*result = state->result;
+ *expire_time = state->expire_time;
return EOK;
}
@@ -1121,9 +1127,10 @@ static void sdap_cli_kinit_done(struct tevent_req *subreq)
struct sdap_cli_connect_state *state = tevent_req_data(req,
struct sdap_cli_connect_state);
enum sdap_result result;
+ time_t expire_time;
int ret;
- ret = sdap_kinit_recv(subreq, &result);
+ ret = sdap_kinit_recv(subreq, &result, &expire_time);
talloc_zfree(subreq);
if (ret) {
if (ret == ETIMEDOUT) { /* child timed out, retry another server */
@@ -1142,6 +1149,7 @@ static void sdap_cli_kinit_done(struct tevent_req *subreq)
tevent_req_error(req, EACCES);
return;
}
+ state->sh->expire_time = expire_time;
sdap_cli_auth_step(req);
}
diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h
index ac91a0105..bc897fd96 100644
--- a/src/providers/ldap/sdap_async_private.h
+++ b/src/providers/ldap/sdap_async_private.h
@@ -65,6 +65,7 @@ struct tevent_req *sdap_get_tgt_send(TALLOC_CTX *mem_ctx,
int sdap_get_tgt_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
int *result,
- char **ccname);
+ char **ccname,
+ time_t *expire_time);
#endif /* _SDAP_ASYNC_PRIVATE_H_ */
diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c
index 724de28da..58b757efd 100644
--- a/src/providers/ldap/sdap_child_helpers.c
+++ b/src/providers/ldap/sdap_child_helpers.c
@@ -30,6 +30,7 @@
#include "util/util.h"
#include "providers/ldap/ldap_common.h"
+#include "providers/ldap/sdap_async_private.h"
#include "providers/child_common.h"
#ifndef SSSD_LIBEXEC_PATH
@@ -204,12 +205,14 @@ static errno_t create_tgt_req_send_buffer(TALLOC_CTX *mem_ctx,
static int parse_child_response(TALLOC_CTX *mem_ctx,
uint8_t *buf, ssize_t size,
- int *result, char **ccache)
+ int *result, char **ccache,
+ time_t *expire_time_out)
{
size_t p = 0;
uint32_t len;
uint32_t res;
char *ccn;
+ time_t expire_time;
/* operation result code */
SAFEALIGN_COPY_UINT32_CHECK(&res, buf + p, size, &p);
@@ -224,11 +227,18 @@ static int parse_child_response(TALLOC_CTX *mem_ctx,
DEBUG(1, ("talloc_size failed.\n"));
return ENOMEM;
}
- memcpy(ccn, buf+p, sizeof(char) * (len + 1));
+ safealign_memcpy(ccn, buf+p, sizeof(char) * len, &p);
ccn[len] = '\0';
+ if (p + sizeof(time_t) > size) {
+ talloc_free(ccn);
+ return EINVAL;
+ }
+ safealign_memcpy(&expire_time, buf+p, sizeof(time_t), &p);
+
*result = res;
*ccache = ccn;
+ *expire_time_out = expire_time;
return EOK;
}
@@ -363,25 +373,28 @@ static void sdap_get_tgt_done(struct tevent_req *subreq)
int sdap_get_tgt_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
int *result,
- char **ccname)
+ char **ccname,
+ time_t *expire_time_out)
{
struct sdap_get_tgt_state *state = tevent_req_data(req,
struct sdap_get_tgt_state);
char *ccn;
+ time_t expire_time;
int res;
int ret;
TEVENT_REQ_RETURN_ON_ERROR(req);
- ret = parse_child_response(mem_ctx, state->buf, state->len, &res, &ccn);
+ ret = parse_child_response(mem_ctx, state->buf, state->len, &res, &ccn, &expire_time);
if (ret != EOK) {
DEBUG(1, ("Cannot parse child response: [%d][%s]\n", ret, strerror(ret)));
return ret;
}
- DEBUG(6, ("Child responded: %d [%s]\n", res, ccn));
+ DEBUG(6, ("Child responded: %d [%s], expired on [%ld]\n", res, ccn, (long)expire_time));
*result = res;
*ccname = ccn;
+ *expire_time_out = expire_time;
return EOK;
}