diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/providers/ldap/ldap_child.c | 35 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 2 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async.h | 4 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_connection.c | 14 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_private.h | 3 | ||||
-rw-r--r-- | src/providers/ldap/sdap_child_helpers.c | 23 |
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; } |