* PERFORMANCE OF THIS SOFTWARE.
*/
-#include "krb5.h"
+#include "k5-int.h" /* we need krb5_context::clockskew */
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <krb4-proto.h>
#include "krb524.h"
+/* rather than copying the cmu code, these values are derived from
+ a calculation based on the table and comments found there.
+ the expression (in elisp) is:
+ (defun cmu-to-secs2 (j)
+ (if (< j 128) (* j 5 60)
+ (round (* 38400 (expt 1.06914489 (- j 128))))))
+ and is low by one for 16 values but is exact for the others.
+ */
+
+static long cmu_seconds[] =
+{
+ 38400, 41055, 43894, 46929, 50174, 53643, 57352, 61318,
+ 65558, 70091, 74937, 80119, 85658, 91581, 97914, 104684,
+ 111922, 119661, 127935, 136781, 146239, 156350, 167161, 178720,
+ 191077, 204289, 218415, 233517, 249663, 266926, 285383, 305116,
+ 326213, 348769, 372885, 398668, 426233, 455705, 487215, 520903,
+ 556921, 595430, 636600, 680618, 727679, 777995, 831789, 889303,
+ 950794, 1016536, 1086825, 1161973, 1242317, 1328217, 1420057, 1518246,
+ 1623225, 1735463, 1855462, 1983757, 2120924, 2267575, 2424366, 2591999,
+ 0
+};
+
/*
* Convert a v5 ticket for server to a v4 ticket, using service key
* skey for both.
*/
-int krb524_convert_tkt_skey(context, v5tkt, v4tkt, skey)
+int krb524_convert_tkt_skey(context, v5tkt, v4tkt, v5_skey, v4_skey)
krb5_context context;
krb5_ticket *v5tkt;
KTEXT_ST *v4tkt;
- krb5_keyblock *skey;
+ krb5_keyblock *v5_skey, *v4_skey;
{
char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
char sname[ANAME_SZ], sinst[INST_SZ];
krb5_enc_tkt_part *v5etkt;
- int ret, lifetime;
+ int ret, lifetime, deltatime;
+ krb5_timestamp server_time;
v5tkt->enc_part2 = NULL;
- if ((ret = krb5_decrypt_tkt_part(context, skey, v5tkt))) {
+ if ((ret = krb5_decrypt_tkt_part(context, v5_skey, v5tkt))) {
krb5_free_ticket(context, v5tkt);
return ret;
}
return ret;
}
- if (v5etkt->session->keytype != KEYTYPE_DES ||
+ if (v5etkt->session->enctype != ENCTYPE_DES_CBC_CRC ||
v5etkt->session->length != sizeof(C_Block)) {
if (krb524_debug)
fprintf(stderr, "v5 session keyblock type %d length %d != C_Block size %d\n",
- v5etkt->session->keytype,
+ v5etkt->session->enctype,
v5etkt->session->length,
sizeof(C_Block));
krb5_free_enc_tkt_part(context, v5etkt);
/* V4 lifetime is 1 byte, in 5 minute increments */
if (v5etkt->times.starttime == 0)
v5etkt->times.starttime = v5etkt->times.authtime;
- lifetime = 0xff &
- ((v5etkt->times.endtime - v5etkt->times.authtime) / 300);
+ /* rather than apply fit an extended v5 lifetime into a v4 range,
+ give out a v4 ticket with as much of the v5 lifetime is available
+ "now" instead. */
+ if ((ret = krb5_timeofday(context, &server_time))) {
+ if (krb524_debug)
+ fprintf(stderr, "krb5_timeofday failed!\n");
+ krb5_free_enc_tkt_part(context, v5etkt);
+ v5tkt->enc_part2 = NULL;
+ return ret;
+ }
+ if ( (server_time+context->clockskew >= v5etkt->times.starttime)
+ && (server_time-context->clockskew <= v5etkt->times.endtime)) {
+ deltatime = v5etkt->times.endtime - (server_time-context->clockskew);
+ lifetime = deltatime / 300;
+ /* if (lifetime > 255) lifetime = 255; */
+ if (lifetime > 127) {
+ /* use the CMU algorithm instead: */
+ long *clist = cmu_seconds;
+ while(*clist && *clist < deltatime) clist++;
+ lifetime = 128 + (clist - cmu_seconds);
+ }
+ } else {
+ if (krb524_debug)
+ fprintf(stderr, "v5 ticket time out of bounds\n");
+ krb5_free_enc_tkt_part(context, v5etkt);
+ v5tkt->enc_part2 = NULL;
+ if (server_time+context->clockskew < v5etkt->times.starttime)
+ return KRB5KRB_AP_ERR_TKT_NYV;
+ else if (server_time-context->clockskew > v5etkt->times.endtime)
+ return KRB5KRB_AP_ERR_TKT_EXPIRED;
+ else /* shouldn't happen, but just in case... */
+ return KRB5KRB_AP_ERR_TKT_NYV;
+ }
/* XXX perhaps we should use the addr of the client host if */
/* v5creds contains more than one addr. Q: Does V4 support */
pinst,
prealm,
*((unsigned long *)v5etkt->caddrs[0]->contents),
- v5etkt->session->contents,
+ (char *) v5etkt->session->contents,
lifetime,
/* issue_data */
- v5etkt->times.starttime,
+ server_time,
sname,
sinst,
- skey->contents);
+ v4_skey->contents);
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;