From caacbb07224bbeaf86b8dd279292a381218a939f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20Kou=C5=99il?= Date: Fri, 3 Oct 2008 09:21:19 +0000 Subject: [PATCH] consider also lifetime of the VOMS ACs when scheduling renewal - fixes #28167 --- org.glite.security.proxyrenewal/src/commands.c | 233 +++++++++++++++---------- 1 file changed, 142 insertions(+), 91 deletions(-) diff --git a/org.glite.security.proxyrenewal/src/commands.c b/org.glite.security.proxyrenewal/src/commands.c index a923da4..3701dd0 100644 --- a/org.glite.security.proxyrenewal/src/commands.c +++ b/org.glite.security.proxyrenewal/src/commands.c @@ -64,7 +64,8 @@ record_to_response(glite_renewal_core_context ctx, int status_code, proxy_record static int filename_to_response(glite_renewal_core_context ctx, char *filename, edg_wlpr_Response *response); - +static int +get_voms_cert(glite_renewal_core_context ctx, X509 *cert, STACK_OF(X509) *chain, struct vomsdata **vd); static char * @@ -139,7 +140,7 @@ copy_file_content(glite_renewal_core_context ctx, FILE *in, FILE *out) /* return the time interval, after which the renewal should be started */ static time_t -get_delta(glite_renewal_core_context ctx, time_t current_time, time_t start_time, time_t end_time) +get_delta(glite_renewal_core_context ctx, time_t current_time, time_t end_time) { time_t remaining_life; time_t life_to_lose; @@ -154,15 +155,9 @@ get_delta(glite_renewal_core_context ctx, time_t current_time, time_t start_time limit += RENEWAL_CLOCK_SKEW; - if (current_time + limit >= end_time) { - /* if the proxy is too short, renew it as soon as possible */ - - if (current_time + condor_limit > end_time ) { - edg_wlpr_Log(ctx, LOG_ERR, "Remaining proxy lifetime fell below the value of the Condor limit!"); - } - + /* if the proxy is too short, renew it as soon as possible */ + if (current_time + limit >= end_time) return 0; - } remaining_life = end_time - current_time; @@ -198,38 +193,79 @@ get_delta(glite_renewal_core_context ctx, time_t current_time, time_t start_time int get_times(glite_renewal_core_context ctx, char *proxy_file, proxy_record *record) { - FILE *fd; X509 *cert = NULL; - ASN1_UTCTIME *asn1_time = NULL; - int ret; - time_t current_time, start_time, end_time; - - assert(record != NULL); - assert(proxy_file != NULL); + STACK_OF(X509) *chain = NULL; + int ret, i; + time_t now, end_time, end_time_x509; + struct vomsdata *voms_data = NULL; + struct voms **voms_cert = NULL; + ASN1_UTCTIME *t; + time_t delta; + char *s, *c; - fd = fopen(proxy_file, "r"); - if (fd == NULL) { - edg_wlpr_Log(ctx, LOG_ERR, "Opening proxy file %s failed: %s", - proxy_file, strerror(errno)); - return errno; - } + ret = load_proxy(ctx, proxy_file, &cert, NULL, &chain, NULL); + if (ret) + return ret; - cert = PEM_read_X509(fd, NULL, NULL, NULL); - if (cert == NULL) { - edg_wlpr_Log(ctx, LOG_ERR, "Cannot read X.509 certificate from %s", - proxy_file); - ret = -1; /* XXX SSL_ERROR */ + ret = get_voms_cert(ctx, cert, chain, &voms_data); + if (ret) goto end; + + end_time = 0; + if (voms_data != NULL) { + for (voms_cert = voms_data->data; voms_cert && *voms_cert; voms_cert++) { + t = ASN1_UTCTIME_new(); + if (t == NULL) { + edg_wlpr_Log(ctx, LOG_ERR, "ASN1_UTCTIME_new() failed\n"); + ret = 1; + goto end; + } + + /* date2 contains a GENERALIZEDTIME format (YYYYMMDDHHSS[.fff]Z) + * value, which must be converted to the UTC (YYMMDDHHSSZ) format */ + s = strdup((*voms_cert)->date2 + 2); + if (s == NULL) { + edg_wlpr_Log(ctx, LOG_ERR, "Not enough memory\n"); + ret = ENOMEM; + goto end; + } + c = strchr(s, '.'); + if (c) { + *c++ = 'Z'; + *c = '\0'; + } + ret = ASN1_UTCTIME_set_string(t, s); + if (ret == 0) { + edg_wlpr_Log(ctx, LOG_ERR, "ASN1_UTCTIME_set_string() failed\n"); + ret = 1; + free(s); + goto end; + } + + if (end_time == 0 || ASN1_UTCTIME_cmp_time_t(t, end_time) < 0) + globus_gsi_cert_utils_make_time(t, &end_time); + + ASN1_UTCTIME_free(t); + free(s); + } + s = ctime(&end_time); + if ((c = strchr(s, '\n'))) + *c = '\0'; + edg_wlpr_Log(ctx, LOG_DEBUG, + "The shortest VOMS cert expires on %s", s); } - asn1_time = ASN1_UTCTIME_new(); - X509_gmtime_adj(asn1_time,0); - globus_gsi_cert_utils_make_time(X509_get_notAfter(cert), &end_time); - globus_gsi_cert_utils_make_time(X509_get_notBefore(cert), &start_time); - current_time = time(NULL); - ASN1_UTCTIME_free(asn1_time); - /* if (end_time - RENEWAL_CLOCK_SKEW < current_time) { Too short proxy } */ - if (end_time + RENEWAL_CLOCK_SKEW < current_time) { + globus_gsi_cert_utils_make_time(X509_get_notAfter(cert), &end_time_x509); + if (end_time_x509 < end_time || end_time == 0) + end_time = end_time_x509; + + s = ctime(&end_time_x509); + if ((c = strchr(s, '\n'))) + *c = '\0'; + edg_wlpr_Log(ctx, LOG_DEBUG, "X.509 proxy credential expires on %s", s); + + now = time(NULL); + if (end_time_x509 + RENEWAL_CLOCK_SKEW < now) { edg_wlpr_Log(ctx, LOG_ERR, "Expired proxy in %s", proxy_file); ret = EDG_WLPR_PROXY_EXPIRED; goto end; @@ -237,40 +273,35 @@ get_times(glite_renewal_core_context ctx, char *proxy_file, proxy_record *record /* Myproxy seems not to do check on expiration and return expired proxies if credentials in repository are expired */ - X509_free(cert); - cert = NULL; - while (1) { - time_t tmp_end; - /* see http://www.openssl.org/docs/crypto/pem.html section BUGS */ - cert = PEM_read_X509(fd, NULL, NULL, NULL); - if (cert == NULL) { - if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) { - /* End of file reached. no error */ - ERR_clear_error(); - break; - } - edg_wlpr_Log(ctx, LOG_ERR, "Cannot read additional certificates from %s", - proxy_file); - ret = -1; /* XXX SSL_ERROR */ - goto end; - } - globus_gsi_cert_utils_make_time(X509_get_notAfter(cert), &tmp_end); - if (tmp_end + RENEWAL_CLOCK_SKEW < current_time) { - edg_wlpr_Log(ctx, LOG_ERR, "Expired proxy in %s", proxy_file); - ret = EDG_WLPR_PROXY_EXPIRED; - goto end; + for (i = 0; i < sk_X509_num(chain); i++) { + t = X509_get_notAfter(sk_X509_value(chain, i)); + if (ASN1_UTCTIME_cmp_time_t(t, now - RENEWAL_CLOCK_SKEW) < 0) { + edg_wlpr_Log(ctx, LOG_ERR, "Expired proxy in %s", proxy_file); + ret = EDG_WLPR_PROXY_EXPIRED; + goto end; } - X509_free(cert); - cert = NULL; } - record->next_renewal = current_time + get_delta(ctx, current_time, start_time, - end_time); - record->end_time = end_time; + if (now + condor_limit > end_time_x509) { + edg_wlpr_Log(ctx, LOG_ERR, "Remaining proxy lifetime fell below the value of the Condor limit!"); + delta = 0; + } else + delta = get_delta(ctx, now, end_time); + + record->next_renewal = now + delta; + record->end_time = end_time_x509; ret = 0; + s = ctime(&record->next_renewal); + if ((c = strchr(s, '\n'))) + *c = '\0'; + edg_wlpr_Log(ctx, LOG_DEBUG, "Next renewal will be attempted on %s", s); + end: - fclose(fd); + if (voms_data) + VOMS_Destroy(voms_data); + if (chain) + sk_X509_pop_free(chain, X509_free); if (cert) X509_free(cert); @@ -852,50 +883,70 @@ find_proxyname(glite_renewal_core_context ctx, char *jobid, char **filename) return EDG_WLPR_PROXY_NOT_REGISTERED; } -#ifdef NOVOMS -int -find_voms_cert(glite_renewal_core_context ctx, char *file, int *present) +static int +get_voms_cert(glite_renewal_core_context ctx, X509 *cert, + STACK_OF(X509) *chain, struct vomsdata **vd) { - *present = 0; - return 0; + struct vomsdata *voms_info = NULL; + int voms_err, ret, voms_ret; + + voms_info = VOMS_Init(vomsdir, cadir); + if (voms_info == NULL) { + edg_wlpr_Log(ctx, LOG_ERR, "check_voms_cert(): Cannot initialize VOMS context (VOMS_Init() failed, probably voms dir was not specified)"); + return EDG_WLPR_ERROR_VOMS; + } + + ret = 0; + voms_ret = VOMS_Retrieve(cert, chain, RECURSE_CHAIN, voms_info, &voms_err); + if (voms_ret == 0) { + if (voms_err == VERR_NOEXT) { + voms_info = NULL; + ret = 0; + } else { + char *err_msg = VOMS_ErrorMessage(voms_info, voms_err, NULL, 0); + edg_wlpr_Log(ctx, LOG_ERR, "Failed to retrieve VOMS attributes: %s\n", + err_msg); + free(err_msg); + ret = -1; /* XXX */ + } + } + + if (ret == 0 && vd != NULL) + *vd = voms_info; + else + VOMS_Destroy(voms_info); + + return ret; } -#else int find_voms_cert(glite_renewal_core_context ctx, char *file, int *present) { struct vomsdata *voms_info = NULL; STACK_OF(X509) *chain = NULL; - EVP_PKEY *privkey = NULL; X509 *cert = NULL; - int ret, err; + int ret; *present = 0; - voms_info = VOMS_Init(vomsdir, cadir); - if (voms_info == NULL) { - edg_wlpr_Log(ctx, LOG_ERR, "check_voms_cert(): Cannot initialize VOMS context (VOMS_Init() failed, probably voms dir was not specified)"); - return EDG_WLPR_ERROR_VOMS; - } - - ret = load_proxy(ctx, file, &cert, &privkey, &chain, NULL); - if (ret) { - VOMS_Destroy(voms_info); + ret = load_proxy(ctx, file, &cert, NULL, &chain, NULL); + if (ret) return ret; - } - ret = VOMS_Retrieve(cert, chain, RECURSE_CHAIN, voms_info, &err); - if (ret == 1) { - *present = 1; - } + ret = get_voms_cert(ctx, cert, chain, &voms_info); + if (ret) + goto end; - VOMS_Destroy(voms_info); - X509_free(cert); - EVP_PKEY_free(privkey); + *present = (voms_info != NULL); + +end: + if (voms_info) + VOMS_Destroy(voms_info); sk_X509_pop_free(chain, X509_free); - return 0; + X509_free(cert); + + return ret; } -#endif void register_proxy(glite_renewal_core_context ctx, edg_wlpr_Request *request, edg_wlpr_Response *response) -- 1.8.2.3