static krb5_error_code make_preauth_list (krb5_context,
krb5_preauthtype *,
int, krb5_pa_data ***);
+
+/*
+ * This function performs 32 bit bounded addition so we can generate
+ * lifetimes without overflowing krb5_int32
+ */
+static krb5_int32 krb5int_addint32 (krb5_int32 x, krb5_int32 y)
+{
+ if ((x > 0) && (y > (KRB5_INT32_MAX - x))) {
+ /* sum will be be greater than KRB5_INT32_MAX */
+ return KRB5_INT32_MAX;
+ } else if ((x < 0) && (y < (KRB5_INT32_MIN - x))) {
+ /* sum will be less than KRB5_INT32_MIN */
+ return KRB5_INT32_MIN;
+ }
+
+ return x + y;
+}
+
/*
* This function sends a request to the KDC, and gets back a response;
* the response is parsed into ret_err_reply or ret_as_reply if the
krb5_pa_data **padata;
int tempint;
char *tempstr;
+ krb5_deltat tkt_life;
krb5_deltat renew_life;
int loopcount;
krb5_data salt;
if (tempint)
request.kdc_options |= KDC_OPT_PROXIABLE;
- /* renewable */
-
+ /* allow_postdate */
+
+ if (start_time > 0)
+ request.kdc_options |= (KDC_OPT_ALLOW_POSTDATE|KDC_OPT_POSTDATED);
+
+ /* ticket lifetime */
+
+ if ((ret = krb5_timeofday(context, &request.from)))
+ goto cleanup;
+ request.from = krb5int_addint32(request.from, start_time);
+
+ if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE)) {
+ tkt_life = options->tkt_life;
+ } else if ((ret = krb5_libdefault_string(context, &client->realm,
+ "ticket_lifetime", &tempstr))
+ == 0) {
+ if ((ret = krb5_string_to_deltat(tempstr, &tkt_life))) {
+ free(tempstr);
+ goto cleanup;
+ }
+ } else {
+ /* this used to be hardcoded in kinit.c */
+ tkt_life = 24*60*60;
+ }
+ request.till = krb5int_addint32(request.from, tkt_life);
+
+ /* renewable lifetime */
+
if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE)) {
renew_life = options->renew_life;
} else if ((ret = krb5_libdefault_string(context, &client->realm,
}
if (renew_life > 0)
request.kdc_options |= KDC_OPT_RENEWABLE;
-
- /* allow_postdate */
-
- if (start_time > 0)
- request.kdc_options |= (KDC_OPT_ALLOW_POSTDATE|KDC_OPT_POSTDATED);
-
+
+ if (renew_life > 0) {
+ request.rtime = krb5int_addint32(request.from, renew_life);
+ if (request.rtime < request.till) {
+ /* don't ask for a smaller renewable time than the lifetime */
+ request.rtime = request.till;
+ }
+ /* we are already asking for renewable tickets so strip this option */
+ request.kdc_options &= ~(KDC_OPT_RENEWABLE_OK);
+ } else {
+ request.rtime = 0;
+ }
+
/* client */
request.client = client;
+ /* service */
+
if (in_tkt_service) {
/* this is ugly, because so are the data structures involved. I'm
in the library, so I'm going to manipulate the data structures
goto cleanup;
}
- if ((ret = krb5_timeofday(context, &request.from)))
- goto cleanup;
- request.from += start_time;
-
- request.till = request.from;
- if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE))
- request.till += options->tkt_life;
- else
- request.till += 24*60*60; /* this used to be hardcoded in kinit.c */
-
- if (renew_life > 0) {
- request.rtime = request.from;
- request.rtime += renew_life;
- if (request.rtime >= request.till)
- request.kdc_options &= ~(KDC_OPT_RENEWABLE_OK);
- } else {
- request.rtime = 0;
- }
-
/* nonce is filled in by send_as_request */
if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST)) {