-/* Helper function for kssl_validate_times().
-** We need context->clockskew, but krb5_context is an opaque struct.
-** So we try to sneek the clockskew out through the replay cache.
-** If that fails just return a likely default (300 seconds).
-*/
-static krb5_deltat get_rc_clockskew(krb5_context context)
- {
- krb5_rcache rc;
- krb5_deltat clockskew;
-
- if (krb5_rc_default(context, &rc)) return KSSL_CLOCKSKEW;
- if (krb5_rc_initialize(context, rc, 0)) return KSSL_CLOCKSKEW;
- if (krb5_rc_get_lifespan(context, rc, &clockskew)) {
- clockskew = KSSL_CLOCKSKEW;
- }
- (void) krb5_rc_destroy(context, rc);
- return clockskew;
- }
-
-
-/* kssl_validate_times() combines (and more importantly exposes)
-** the MIT KRB5 internal function krb5_validate_times() and the
-** in_clock_skew() macro. The authenticator client time is checked
-** to be within clockskew secs of the current time and the current
-** time is checked to be within the ticket start and expire times.
-** Either check may be omitted by supplying a NULL value.
-** Returns 0 for valid times, SSL_R_KRB5* error codes otherwise.
-** See Also: (Kerberos source)/krb5/lib/krb5/krb/valid_times.c
-** 20010420 VRS
-*/
-krb5_error_code kssl_validate_times( krb5_timestamp atime,
- krb5_ticket_times *ttimes)
- {
- krb5_deltat skew;
- krb5_timestamp start, now;
- krb5_error_code rc;
- krb5_context context;
-
- if ((rc = krb5_init_context(&context))) return SSL_R_KRB5_S_BAD_TICKET;
- skew = get_rc_clockskew(context);
- if ((rc = krb5_timeofday(context,&now))) return SSL_R_KRB5_S_BAD_TICKET;
- krb5_free_context(context);
-
- if (atime && labs(atime - now) >= skew) return SSL_R_KRB5_S_TKT_SKEW;
-
- if (! ttimes) return 0;
-
- start = (ttimes->starttime != 0)? ttimes->starttime: ttimes->authtime;
- if (start - now > skew) return SSL_R_KRB5_S_TKT_NYV;
- if ((now - ttimes->endtime) > skew) return SSL_R_KRB5_S_TKT_EXPIRED;
-
-#ifdef KSSL_DEBUG
- fprintf(stderr,"kssl_validate_times: %d |<- | %d - %d | < %d ->| %d\n",
- start, atime, now, skew, ttimes->endtime);
-#endif /* KSSL_DEBUG */
-
- return 0;
- }
-
-
-/* Decode and decrypt given DER-encoded authenticator, then pass
-** authenticator ctime back in *atimep (or 0 if time unavailable).
-** Returns krb5_error_code and kssl_err on error. A NULL
-** authenticator (authentp->length == 0) is not considered an error.
-** Note that kssl_check_authent() makes use of the KRB5 session key;
-** you must call kssl_sget_tkt() to get the key before calling this routine.
-*/
-krb5_error_code kssl_check_authent(
- /* IN */ KSSL_CTX *kssl_ctx,
- /* IN */ krb5_data *authentp,
- /* OUT */ krb5_timestamp *atimep,
- /* OUT */ KSSL_ERR *kssl_err )
- {
- krb5_error_code krb5rc = 0;
- KRB5_ENCDATA *dec_authent = NULL;
- KRB5_AUTHENTBODY *auth = NULL;
- krb5_enctype enctype;
- EVP_CIPHER_CTX ciph_ctx;
- const EVP_CIPHER *enc = NULL;
- unsigned char iv[EVP_MAX_IV_LENGTH];
- const unsigned char *p;
- unsigned char *unenc_authent;
- int outl, unencbufsize;
- struct tm tm_time, *tm_l, *tm_g;
- time_t now, tl, tg, tr, tz_offset;
-
- EVP_CIPHER_CTX_init(&ciph_ctx);
- *atimep = 0;
- kssl_err_set(kssl_err, 0, "");
-
-#ifndef KRB5CHECKAUTH
- authentp = NULL;
-#else
-#if KRB5CHECKAUTH == 0
- authentp = NULL;
-#endif
-#endif /* KRB5CHECKAUTH */
-
- if (authentp == NULL || authentp->length == 0) return 0;
-
-#ifdef KSSL_DEBUG
- {
- unsigned int ui;
- fprintf(stderr,"kssl_check_authent: authenticator[%d]:\n",authentp->length);
- p = authentp->data;
- for (ui=0; ui < authentp->length; ui++) fprintf(stderr,"%02x ",p[ui]);
- fprintf(stderr,"\n");
- }
-#endif /* KSSL_DEBUG */
-
- unencbufsize = 2 * authentp->length;
- if ((unenc_authent = calloc(1, unencbufsize)) == NULL)
- {
- kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
- "Unable to allocate authenticator buffer.\n");
- krb5rc = KRB5KRB_ERR_GENERIC;
- goto err;
- }
-
- p = (unsigned char *)authentp->data;
- if ((dec_authent = d2i_KRB5_ENCDATA(NULL, &p,
- (long) authentp->length)) == NULL)
- {
- kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
- "Error decoding authenticator.\n");
- krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
- goto err;
- }
-
- enctype = dec_authent->etype->data[0]; /* should = kssl_ctx->enctype */
-#if !defined(KRB5_MIT_OLD11)
- switch ( enctype ) {
- case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */
- case ENCTYPE_DES3_CBC_SHA:
- case ENCTYPE_DES3_CBC_RAW:
- krb5rc = 0; /* Skip, can't handle derived keys */
- goto err;
- }
-#endif
- enc = kssl_map_enc(enctype);
- memset(iv, 0, sizeof iv); /* per RFC 1510 */
-
- if (enc == NULL)
- {
- /* Disable kssl_check_authent for ENCTYPE_DES3_CBC_SHA1.
- ** This enctype indicates the authenticator was encrypted
- ** using key-usage derived keys which openssl cannot decrypt.
- */
- goto err;
- }
-
- if (!EVP_CipherInit(&ciph_ctx,enc,kssl_ctx->key,iv,0))
- {
- kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
- "EVP_CipherInit error decrypting authenticator.\n");
- krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
- goto err;
- }
- outl = dec_authent->cipher->length;
- if (!EVP_Cipher(&ciph_ctx,unenc_authent,dec_authent->cipher->data,outl))
- {
- kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
- "EVP_Cipher error decrypting authenticator.\n");
- krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
- goto err;
- }
- EVP_CIPHER_CTX_cleanup(&ciph_ctx);
-
-#ifdef KSSL_DEBUG
- {
- int padl;
- fprintf(stderr,"kssl_check_authent: decrypted authenticator[%d] =\n", outl);
- for (padl=0; padl < outl; padl++) fprintf(stderr,"%02x ",unenc_authent[padl]);
- fprintf(stderr,"\n");
- }
-#endif /* KSSL_DEBUG */
-
- if ((p = kssl_skip_confound(enctype, unenc_authent)) == NULL)
- {
- kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
- "confounded by authenticator.\n");
- krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
- goto err;
- }
- outl -= p - unenc_authent;
-
- if ((auth = (KRB5_AUTHENTBODY *) d2i_KRB5_AUTHENT(NULL, &p,
- (long) outl))==NULL)
- {
- kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
- "Error decoding authenticator body.\n");
- krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
- goto err;
- }
-
- memset(&tm_time,0,sizeof(struct tm));
- if (k_gmtime(auth->ctime, &tm_time) &&
- ((tr = mktime(&tm_time)) != (time_t)(-1)))
- {
- now = time(&now);
- tm_l = localtime(&now); tl = mktime(tm_l);
- tm_g = gmtime(&now); tg = mktime(tm_g);
- tz_offset = tg - tl;
-
- *atimep = (krb5_timestamp)(tr - tz_offset);
- }
-
-#ifdef KSSL_DEBUG
- fprintf(stderr,"kssl_check_authent: returns %d for client time ", *atimep);
- if (auth && auth->ctime && auth->ctime->length && auth->ctime->data)
- fprintf(stderr,"%.*s\n", auth->ctime->length, auth->ctime->data);
- else fprintf(stderr,"NULL\n");
-#endif /* KSSL_DEBUG */
+ if (!EVP_CipherInit(&ciph_ctx, enc, kssl_ctx->key, iv, 0)) {
+ kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+ "EVP_CipherInit error decrypting authenticator.\n");
+ krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto err;
+ }
+ outl = dec_authent->cipher->length;
+ if (!EVP_Cipher
+ (&ciph_ctx, unenc_authent, dec_authent->cipher->data, outl)) {
+ kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+ "EVP_Cipher error decrypting authenticator.\n");
+ krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto err;
+ }
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+# ifdef KSSL_DEBUG
+ {
+ int padl;
+ fprintf(stderr, "kssl_check_authent: decrypted authenticator[%d] =\n",
+ outl);
+ for (padl = 0; padl < outl; padl++)
+ fprintf(stderr, "%02x ", unenc_authent[padl]);
+ fprintf(stderr, "\n");
+ }
+# endif /* KSSL_DEBUG */
+
+ if ((p = kssl_skip_confound(enctype, unenc_authent)) == NULL) {
+ kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+ "confounded by authenticator.\n");
+ krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto err;
+ }
+ outl -= p - unenc_authent;
+
+ if ((auth = (KRB5_AUTHENTBODY *)d2i_KRB5_AUTHENT(NULL, &p,
+ (long)outl)) == NULL) {
+ kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
+ "Error decoding authenticator body.\n");
+ krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto err;
+ }
+
+ memset(&tm_time, 0, sizeof(struct tm));
+ if (k_gmtime(auth->ctime, &tm_time) &&
+ ((tr = mktime(&tm_time)) != (time_t)(-1))) {
+ now = time(&now);
+ tm_l = localtime(&now);
+ tl = mktime(tm_l);
+ tm_g = gmtime(&now);
+ tg = mktime(tm_g);
+ tz_offset = tg - tl;
+
+ *atimep = (krb5_timestamp)(tr - tz_offset);
+ }
+# ifdef KSSL_DEBUG
+ fprintf(stderr, "kssl_check_authent: returns %d for client time ",
+ *atimep);
+ if (auth && auth->ctime && auth->ctime->length && auth->ctime->data)
+ fprintf(stderr, "%.*s\n", auth->ctime->length, auth->ctime->data);
+ else
+ fprintf(stderr, "NULL\n");
+# endif /* KSSL_DEBUG */