#include <krb5/krb5.h>
#include <krb5/kdb.h>
+#include <krb5/preauth.h>
#include <krb5/los-proto.h>
#include <krb5/asn1.h>
#include <krb5/osconf.h>
#ifdef KRB5_USE_INET
#include <sys/types.h>
#include <netinet/in.h>
+#ifndef hpux
#include <arpa/inet.h>
-#endif
+#endif /* hpux */
+#endif /* KRB5_USE_INET */
#include "kdc_util.h"
#include "policy.h"
static krb5_error_code prepare_error_as PROTOTYPE((krb5_kdc_req *,
int,
krb5_data **));
-
/*
- * Do all the processing required for a AS_REQ
+ * This routine is called to verify the preauthentication information
+ * for a V5 request. Client contains information about the principal
+ * from the database. Padata contains pre-auth info received from
+ * the network.
+ *
+ * Returns 0 if the pre-authentication is valid, non-zero to indicate
+ * an error code of some sort.
*/
-/* XXX needs lots of cleanup and modularizing */
+static krb5_error_code
+check_padata (client, src_addr, padata, pa_id, flags)
+ krb5_db_entry *client;
+ krb5_address **src_addr;
+ krb5_pa_data **padata;
+ int *pa_id; /* Unique id which can be used for replay
+ of padata. */
+ int *flags;
+{
+ krb5_encrypted_keyblock *enckey;
+ krb5_keyblock tmpkey;
+ krb5_error_code retval;
+
+ enckey = &(client->key);
+ /* Extract client key/alt_key from master key */
+
+ retval = KDB_CONVERT_KEY_OUTOF_DB(enckey,&tmpkey);
+ if (retval) {
+ syslog( LOG_ERR, "AS_REQ: Unable to Extract Client Key/alt_key\n");
+ return(0);
+ }
+ retval = krb5_verify_padata(*padata,client->principal,src_addr,
+ &tmpkey, pa_id, flags);
+ memset((char *)tmpkey.contents, 0, tmpkey.length);
+ xfree(tmpkey.contents);
+ if (retval && client->alt_key.length) {
+ /*
+ * If we failed, try again with the alternative key
+ */
+ enckey = &(client->alt_key);
+ /* Extract client key/alt_key from master key */
+ if (retval = KDB_CONVERT_KEY_OUTOF_DB(enckey,&tmpkey)){
+ syslog( LOG_ERR, "AS_REQ: Unable to Extract Client Key/alt_key\n");
+ return(0);
+ }
+ retval = krb5_verify_padata(*padata,client->principal,src_addr,
+ &tmpkey, pa_id, flags);
+ memset((char *)tmpkey.contents, 0, tmpkey.length);
+ xfree(tmpkey.contents);
+ }
+ return retval;
+}
/*ARGSUSED*/
krb5_error_code
krb5_ticket ticket_reply;
krb5_enc_tkt_part enc_tkt_reply;
krb5_error_code retval;
+ int errcode;
int nprincs;
+ char cpw_service[255];
+ int pwreq, pa_id, pa_flags;
krb5_boolean more;
- krb5_timestamp kdc_time;
+ krb5_timestamp kdc_time, authtime;
krb5_keyblock *session_key;
krb5_keyblock encrypting_key;
krb5_enctype useetype;
krb5_pa_data *padat_tmp[2], padat_local;
+ char *status;
register int i;
}
#ifdef KRB5_USE_INET
if (from->address->addrtype == ADDRTYPE_INET)
- fromstring = inet_ntoa(*(struct in_addr *)from->address->contents);
+ fromstring = (char *) inet_ntoa(*(struct in_addr *)from->address->contents);
#endif
if (!fromstring)
fromstring = "<unknown>";
- if (is_secondary)
- syslog(LOG_INFO, "AS_REQ; host %s, %s for %s", fromstring, cname,
- sname);
- else
- syslog(LOG_INFO, "AS_REQ: host %s, %s for %s", fromstring, cname,
- sname);
- free(cname);
- free(sname);
+ /*
+ * Special considerations are allowed when changing passwords. Is
+ * this request for changepw?
+ *
+ * XXX This logic should be moved someplace else, perhaps the
+ * site-specific policiy file....
+ */
+ pwreq = 0;
+ sprintf(cpw_service, "%s@%s", "changepw/kerberos",
+ krb5_princ_realm(request->server)->data);
+ if (strcmp(sname, cpw_service) == 0) pwreq++;
+
+#define cleanup() { free(cname); free(sname); }
nprincs = 1;
if (retval = krb5_db_get_principal(request->client, &client, &nprincs,
return(retval);
if (more) {
krb5_db_free_principal(&client, nprincs);
+ cleanup();
return(prepare_error_as(request, KDC_ERR_PRINCIPAL_NOT_UNIQUE, response));
} else if (nprincs != 1) {
krb5_db_free_principal(&client, nprincs);
+ cleanup();
+#ifdef KRBCONF_VAGUE_ERRORS
+ return(prepare_error_as(request, KRB_ERR_GENERIC, response));
+#else
return(prepare_error_as(request, KDC_ERR_C_PRINCIPAL_UNKNOWN, response));
- }
+#endif
+ }
+
+#undef cleanup
+#define cleanup() { krb5_db_free_principal(&client, 1); \
+ free(sname); free(cname);}
nprincs = 1;
if (retval = krb5_db_get_principal(request->server, &server, &nprincs,
&more))
return(retval);
if (more) {
- krb5_db_free_principal(&client, 1);
+ cleanup();
krb5_db_free_principal(&server, nprincs);
return(prepare_error_as(request, KDC_ERR_PRINCIPAL_NOT_UNIQUE, response));
} else if (nprincs != 1) {
- krb5_db_free_principal(&client, 1);
+ cleanup();
krb5_db_free_principal(&server, nprincs);
return(prepare_error_as(request, KDC_ERR_S_PRINCIPAL_UNKNOWN, response));
}
-#define cleanup() {krb5_db_free_principal(&client, 1); krb5_db_free_principal(&server, 1); }
+#undef cleanup
+#define cleanup() {krb5_db_free_principal(&client, 1); \
+ krb5_db_free_principal(&server, 1); \
+ free(cname); free(sname); \
+ }
- if (retval = check_kdb_flags_as(request, client, server)) {
- cleanup();
- return(prepare_error_as(request, retval, response));
- }
-
if (retval = krb5_timeofday(&kdc_time)) {
+ syslog(LOG_INFO, "AS_REQ: TIME_OF_DAY: host %s, %s for %s",
+ fromstring, cname, sname);
cleanup();
return(retval);
}
+ status = "UNKNOWN REASON";
+ if (retval = validate_as_request(request, client, server,
+ kdc_time, &status)) {
+ syslog(LOG_INFO, "AS_REQ: %s: host %s, %s for %s", status,
+ fromstring, cname, sname);
+ cleanup();
+ return(prepare_error_as(request, retval, response));
+ }
+
for (i = 0; i < request->netypes; i++)
if (valid_etype(request->etype[i]))
break;
if (i == request->netypes) {
/* unsupported etype */
-
+
+ syslog(LOG_INFO, "AS_REQ: BAD ENCRYPTION TYPE: host %s, %s for %s",
+ fromstring, cname, sname);
cleanup();
return(prepare_error_as(request, KDC_ERR_ETYPE_NOSUPP, response));
}
if (retval = (*(krb5_csarray[useetype]->system->random_key))(krb5_csarray[useetype]->random_sequence, &session_key)) {
/* random key failed */
+ syslog(LOG_INFO, "AS_REQ: RANDOM KEY FAILED: host %s, %s for %s",
+ fromstring, cname, sname);
cleanup();
return(retval);
}
#undef cleanup
#define cleanup() {krb5_db_free_principal(&client, 1); \
krb5_db_free_principal(&server, 1); \
+ free(cname); free(sname); \
krb5_free_keyblock(session_key); }
ticket_reply.server = request->server;
enc_tkt_reply.flags = 0;
setflag(enc_tkt_reply.flags, TKT_FLG_INITIAL);
- /* It should be noted that local policy may affect the */
+ /* It should be noted that local policy may affect the */
/* processing of any of these flags. For example, some */
/* realms may refuse to issue renewable tickets */
- if (against_flag_policy_as(request)) {
- cleanup();
- return(prepare_error_as(request, KDC_ERR_BADOPTION, response));
- }
-
if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE))
setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE))
- setflag(enc_tkt_reply.flags, TKT_FLG_PROXIABLE);
+ setflag(enc_tkt_reply.flags, TKT_FLG_PROXIABLE);
if (isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE))
- setflag(enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE);
-
+ setflag(enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE);
enc_tkt_reply.session = session_key;
enc_tkt_reply.client = request->client;
enc_tkt_reply.times.authtime = kdc_time;
if (isflagset(request->kdc_options, KDC_OPT_POSTDATED)) {
- if (against_postdate_policy(request->from)) {
- cleanup();
- return(prepare_error_as(request, KDC_ERR_POLICY, response));
- }
setflag(enc_tkt_reply.flags, TKT_FLG_INVALID);
enc_tkt_reply.times.starttime = request->from;
} else
min(enc_tkt_reply.times.starttime + server.max_life,
enc_tkt_reply.times.starttime + max_life_for_realm)));
- /* XXX why && request->till ? */
- if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
- request->till && (enc_tkt_reply.times.endtime < request->till)) {
+ if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) &&
+ !isflagset(client.attributes, KRB5_KDB_DISALLOW_RENEWABLE) &&
+ (enc_tkt_reply.times.endtime < request->till)) {
/* we set the RENEWABLE option for later processing */
}
rtime = (request->rtime == 0) ? kdc_infinity : request->rtime;
- /* should we squelch the output renew_till to be no earlier
- than the endtime of the ticket? XXX */
if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE)) {
+ /*
+ * XXX Should we squelch the output renew_till to be no
+ * earlier than the endtime of the ticket?
+ */
setflag(enc_tkt_reply.flags, TKT_FLG_RENEWABLE);
enc_tkt_reply.times.renew_till =
min(rtime, enc_tkt_reply.times.starttime +
enc_tkt_reply.times.starttime = 0;
enc_tkt_reply.caddrs = request->addresses;
- enc_tkt_reply.authorization_data = 0; /* XXX? */
+ enc_tkt_reply.authorization_data = 0;
+
+ /*
+ * Check the preauthentication if it is there.
+ */
+ if (request->padata) {
+ retval = check_padata(&client,request->addresses,
+ request->padata, &pa_id, &pa_flags);
+ if (retval) {
+#ifdef KRBCONF_KDC_MODIFIES_KDB
+ /*
+ * Note: this doesn't work if you're using slave servers!!!
+ * It also causes the database to be modified (and thus
+ * need to be locked) frequently.
+ */
+ if (client.fail_auth_count < KRB5_MAX_FAIL_COUNT) {
+ client.fail_auth_count = client.fail_auth_count + 1;
+ if (client.fail_auth_count == KRB5_MAX_FAIL_COUNT) {
+ client.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+ }
+ }
+ krb5_db_put_principal(&client, &one);
+#endif
+ syslog(LOG_INFO, "AS_REQ: PREAUTH FAILED: host %s, %s for %s (%s)",
+ fromstring, cname, sname, error_message(retval));
+ cleanup();
+#ifdef KRBCONF_VAGUE_ERRORS
+ return(prepare_error_as(request, KRB_ERR_GENERIC, response));
+#else
+ retval -= ERROR_TABLE_BASE_krb5;
+ if ((retval < 0) || (retval > 127))
+ retval = KDC_PREAUTH_FAILED;
+ return(prepare_error_as(request, retval, response));
+#endif
+ }
+
+ setflag(enc_tkt_reply.flags, TKT_FLG_PRE_AUTH);
+ /*
+ * If pa_type is one in which additional hardware authentication
+ * was performed set TKT_FLG_HW_AUTH too.
+ */
+ if (pa_flags & KRB5_PREAUTH_FLAGS_HARDWARE)
+ setflag(enc_tkt_reply.flags, TKT_FLG_HW_AUTH);
+ }
- ticket_reply.enc_part2 = &enc_tkt_reply;
+ /*
+ * Final check before handing out ticket: If the client requires
+ * Hardware authentication, verify ticket flag is set
+ */
+
+ if (isflagset(client.attributes, KRB5_KDB_REQUIRES_HW_AUTH) &&
+ !isflagset(enc_tkt_reply.flags, TKT_FLG_HW_AUTH)) {
+
+ /* Of course their are always exceptions, in this case if the
+ service requested is for changing of the key (password), then
+ if TKT_FLG_PRE_AUTH is set allow it. */
+
+ if (!pwreq || !(enc_tkt_reply.flags & TKT_FLG_PRE_AUTH)){
+ syslog(LOG_INFO, "AS_REQ: Needed HW preauth: host %s, %s for %s",
+ fromstring, cname, sname);
+ cleanup();
+ return(prepare_error_as(request, KRB_ERR_GENERIC, response));
+ }
+ }
+
+ticket_reply.enc_part2 = &enc_tkt_reply;
/* convert server.key into a real key (it may be encrypted
in the database) */
krb5_free_keyblock(session_key); \
memset(ticket_reply.enc_part.ciphertext.data, 0, \
ticket_reply.enc_part.ciphertext.length); \
+ free(cname); free(sname); \
free(ticket_reply.enc_part.ciphertext.data);}
/* Start assembling the response */
memset(ticket_reply.enc_part.ciphertext.data, 0, \
ticket_reply.enc_part.ciphertext.length); \
free(ticket_reply.enc_part.ciphertext.data); \
- if (client.salt_type == KRB5_KDB_SALTTYPE_NOREALM) xfree(padat_tmp[0]->contents);}
+ free(cname); free(sname); \
+ if (client.salt_type == KRB5_KDB_SALTTYPE_NOREALM) \
+ xfree(padat_tmp[0]->contents);}
reply.client = request->client;
/* XXX need separate etypes for ticket encryption and kdc_rep encryption */
/* copy the time fields EXCEPT for authtime; it's location
is used for ktime */
reply_encpart.times = enc_tkt_reply.times;
- reply_encpart.times.authtime = kdc_time;
+ reply_encpart.times.authtime = authtime = kdc_time;
reply_encpart.caddrs = enc_tkt_reply.caddrs;
memset(reply.enc_part.ciphertext.data, 0,
reply.enc_part.ciphertext.length);
free(reply.enc_part.ciphertext.data);
+
+ if (retval) {
+ syslog(LOG_INFO, "AS_REQ; ENCODE_KDC_REP: host %s, %s for %s",
+ fromstring, cname, sname);
+ } else {
+ if (is_secondary)
+ syslog(LOG_INFO, "AS_REQ; ISSUE: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
+ else
+ syslog(LOG_INFO, "AS_REQ: ISSUE: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
+ }
+
+ free(cname);
+ free(sname);
+
return retval;
}
#ifdef KRB5_USE_INET
#include <sys/types.h>
#include <netinet/in.h>
+#ifndef hpux
#include <arpa/inet.h>
#endif
+#endif
#include "kdc_util.h"
#include "policy.h"
krb5_error_code retval;
int nprincs;
krb5_boolean more;
- krb5_timestamp kdc_time;
+ krb5_timestamp kdc_time, authtime;
krb5_keyblock *session_key;
krb5_timestamp until, rtime;
krb5_keyblock encrypting_key;
krb5_last_req_entry *nolrarray[2], nolrentry;
/* krb5_address *noaddrarray[1]; */
krb5_enctype useetype;
+ int errcode;
register int i;
int firstpass = 1;
+ char *status;
#ifdef KRB5_USE_INET
if (from->address->addrtype == ADDRTYPE_INET)
- fromstring = inet_ntoa(*(struct in_addr *)from->address->contents);
+ fromstring =
+ (char *) inet_ntoa(*(struct in_addr *)from->address->contents);
#endif
if (!fromstring)
fromstring = "<unknown>";
krb5_free_tkt_authent(req_authdat);
header_ticket = 0;
}
- if (retval > ERROR_TABLE_BASE_krb5 &&
- retval < ERROR_TABLE_BASE_krb5 + 128) {
- /* protocol error */
- return(prepare_error_tgs(request,
- header_ticket,
- retval - ERROR_TABLE_BASE_krb5,
- fromstring,
- response));
- } else
+ errcode = retval - ERROR_TABLE_BASE_krb5;
+ if (errcode < 0 || errcode > 128) {
+ errcode = KRB_ERR_GENERIC;
+ prepare_error_tgs(request, header_ticket, errcode,
+ fromstring, response);
return retval;
+ } else {
+ /* protocol error */
+ return(prepare_error_tgs(request, header_ticket, errcode,
+ fromstring, response));
+ }
}
/* we've already dealt with the AP_REQ authentication, so
krb5_free_tkt_authent(req_authdat);
return(retval);
}
-
- if (is_secondary)
- syslog(LOG_INFO, "TGS_REQ; host %s, %s for %s", fromstring, cname,
- sname);
- else
- syslog(LOG_INFO, "TGS_REQ: host %s, %s for %s", fromstring, cname,
- sname);
- free(cname);
- free(sname);
+ authtime = header_ticket->enc_part2->times.authtime;
/* XXX make sure server here has the proper realm...taken from AP_REQ
header? */
nprincs = 1;
if (retval = krb5_db_get_principal(request->server, &server, &nprincs,
&more)) {
+ syslog(LOG_INFO,
+ "TGS_REQ: GET_PRINCIPAL: authtime %d, host %s, %s for %s (%s)",
+ authtime, fromstring, cname, sname, error_message(retval));
+ free(cname);
+ free(sname);
krb5_free_tkt_authent(req_authdat);
return(retval);
}
tgt_again:
if (more) {
+ syslog(LOG_INFO,
+ "TGS_REQ: NON_UNIQUE_PRINCIPAL: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
krb5_db_free_principal(&server, nprincs);
+ free(cname);
+ free(sname);
return(prepare_error_tgs(request,
header_ticket,
KDC_ERR_PRINCIPAL_NOT_UNIQUE,
goto tgt_again;
}
krb5_db_free_principal(&server, nprincs);
+ syslog(LOG_INFO,
+ "TGS_REQ: UNKNOWN PRINCIPAL: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
return(prepare_error_tgs(request,
header_ticket,
KDC_ERR_S_PRINCIPAL_UNKNOWN,
}
#define tkt_cleanup() {krb5_free_tkt_authent(req_authdat); }
-#define cleanup() { krb5_db_free_principal(&server, 1);}
+#define cleanup() { krb5_db_free_principal(&server, 1); free(cname); free(sname); }
- if (retval = check_kdb_flags_tgs(request, server)) {
+ status = "UNKNOWN_REASON";
+ if (retval = validate_tgs_request(request, server, header_ticket,
+ kdc_time, &status)) {
+ syslog(LOG_INFO, "TGS_REQ: %s: authtime %d, host %s, %s for %s",
+ status, authtime, fromstring, cname, sname);
cleanup();
return(prepare_error_tgs(request,
header_ticket,
}
if (retval = krb5_timeofday(&kdc_time)) {
+ syslog(LOG_INFO, "TGS_REQ: TIME_OF_DAY: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return(retval);
if (i == request->netypes) {
/* unsupported etype */
+ syslog(LOG_INFO, "TGS_REQ: BAD ENCRYPTION TYPE: authtime %d, host %s, %s for %s",
+ authtime, cname, sname);
cleanup();
return(prepare_error_tgs(request,
header_ticket,
if (retval = (*(krb5_csarray[useetype]->system->random_key))(krb5_csarray[useetype]->random_sequence, &session_key)) {
/* random key failed */
+ syslog(LOG_INFO, "TGS_REQ: RANDOM KEY FAILED: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return(retval);
#undef cleanup
#define cleanup() { krb5_db_free_principal(&server, 1); \
- krb5_free_keyblock(session_key);}
-
+ krb5_free_keyblock(session_key); \
+ free(cname); free(sname); }
+
ticket_reply.server = request->server; /* XXX careful for realm... */
ticket_reply.enc_part.etype = useetype;
ticket_reply.enc_part.kvno = server.kvno;
enc_tkt_reply.flags = 0;
enc_tkt_reply.times.starttime = 0;
+ /*
+ * Fix header_ticket's starttime; if it's zero, fill in the
+ * authtime's value.
+ */
+ if (!(header_ticket->enc_part2->times.starttime))
+ header_ticket->enc_part2->times.starttime =
+ header_ticket->enc_part2->times.authtime;
/* don't use new addresses unless forwarded, see below */
/* noaddrarray[0] = 0; */
reply_encpart.caddrs = 0; /* optional...don't put it in */
- /* It should be noted that local policy may affect the */
- /* processing of any of these flags. For example, some */
- /* realms may refuse to issue renewable tickets */
-
- /* the policy check MUST make sure there are no invalid option/flag
- combinations */
-
- if (against_flag_policy_tgs(request, header_ticket)) {
- cleanup();
- return(prepare_error_tgs(request, header_ticket,
- KDC_ERR_BADOPTION,
- fromstring, response));
- }
+ /* It should be noted that local policy may affect the */
+ /* processing of any of these flags. For example, some */
+ /* realms may refuse to issue renewable tickets */
if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE))
setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
if (isflagset(request->kdc_options, KDC_OPT_POSTDATED)) {
setflag(enc_tkt_reply.flags, TKT_FLG_POSTDATED);
setflag(enc_tkt_reply.flags, TKT_FLG_INVALID);
- if (against_postdate_policy(request->from)) {
- cleanup();
- return(prepare_error_tgs(request, header_ticket,
- KDC_ERR_BADOPTION,
- fromstring, response));
- }
enc_tkt_reply.times.starttime = request->from;
} else
enc_tkt_reply.times.starttime = kdc_time;
if (isflagset(request->kdc_options, KDC_OPT_VALIDATE)) {
- if (header_ticket->enc_part2->times.starttime > kdc_time) {
- cleanup();
- return(prepare_error_tgs(request, header_ticket,
- KRB_AP_ERR_TKT_NYV,
- fromstring, response));
- }
- /* XXX move this check out elsewhere? */
- if (check_hot_list(header_ticket)) {
- cleanup();
- return(prepare_error_tgs(request, header_ticket,
- KRB_AP_ERR_REPEAT,
- fromstring, response));
- }
/* BEWARE of allocation hanging off of ticket & enc_part2, it belongs
to the caller */
ticket_reply = *(header_ticket);
enc_tkt_reply = *(header_ticket->enc_part2);
clear(enc_tkt_reply.flags, TKT_FLG_INVALID);
}
- /*
- if (req.kdc_options.(any flag except ENC-TKT-IN-SKEY, RENEW,
- and those already processed) then
- return KRB_ERROR, code KDC_ERR_BADOPTION;
- endif
- */
- enc_tkt_reply.times.authtime = header_ticket->enc_part2->times.authtime;
if (isflagset(request->kdc_options, KDC_OPT_RENEW)) {
krb5_deltat old_life;
- /* Note that if the endtime has already passed, the ticket would */
- /* have been rejected in the initial authentication stage, so */
- /* there is no need to check again here */
-
- /* has it completely run out? */
- if (header_ticket->enc_part2->times.renew_till < kdc_time) {
- cleanup();
- return(prepare_error_tgs(request, header_ticket,
- KRB_AP_ERR_TKT_EXPIRED,
- fromstring, response));
- }
-
/* BEWARE of allocation hanging off of ticket & enc_part2, it belongs
to the caller */
ticket_reply = *(header_ticket);
min(server.max_renewable_life,
max_renewable_life_for_realm)));
} else {
- enc_tkt_reply.times.renew_till = 0; /* XXX */
+ enc_tkt_reply.times.renew_till = 0;
}
-
+
+ /*
+ * Set authtime to be the same as header_ticket's
+ */
+ enc_tkt_reply.times.authtime = header_ticket->enc_part2->times.authtime;
+
+ /*
+ * Propagate the preauthentication flags through to the returned ticket.
+ */
+ if (isflagset(header_ticket->enc_part2->flags, TKT_FLG_PRE_AUTH))
+ setflag(enc_tkt_reply.flags, TKT_FLG_PRE_AUTH);
+
+ if (isflagset(header_ticket->enc_part2->flags, TKT_FLG_HW_AUTH))
+ setflag(enc_tkt_reply.flags, TKT_FLG_HW_AUTH);
+
/* starttime is optional, and treated as authtime if not present.
so we can nuke it if it matches */
if (enc_tkt_reply.times.starttime == enc_tkt_reply.times.authtime)
/* decrypt the authdata in the request */
if (!valid_etype(request->authorization_data.etype)) {
+ syslog(LOG_INFO, "TGS_REQ: BAD_AUTH_ETYPE: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
cleanup();
return prepare_error_tgs(request, header_ticket,
KDC_ERR_ETYPE_NOSUPP,
scratch.length = request->authorization_data.ciphertext.length;
if (!(scratch.data =
malloc(request->authorization_data.ciphertext.length))) {
+ syslog(LOG_INFO, "TGS_REQ: AUTH_NOMEM: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return(ENOMEM);
/* do any necessary key pre-processing */
if (retval = krb5_process_key(&eblock,
header_ticket->enc_part2->session)) {
+ syslog(LOG_INFO, "TGS_REQ: AUTH_PROCESS_KEY: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
free(scratch.data);
tkt_cleanup();
cleanup();
if (retval = krb5_decrypt((krb5_pointer) request->authorization_data.ciphertext.data,
(krb5_pointer) scratch.data,
scratch.length, &eblock, 0)) {
+ syslog(LOG_INFO, "TGS_REQ: AUTH_ENCRYPT_FAIL: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
(void) krb5_finish_key(&eblock);
free(scratch.data);
tkt_cleanup();
return retval;
}
if (retval = krb5_finish_key(&eblock)) {
+ syslog(LOG_INFO, "TGS_REQ: FINISH_KEY: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
free(scratch.data);
tkt_cleanup();
cleanup();
retval = decode_krb5_authdata(&scratch, request->unenc_authdata);
free(scratch.data);
if (retval) {
+ syslog(LOG_INFO, "TGS_REQ: DECODE_AUTH: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return retval;
concat_authorization_data(request->unenc_authdata,
header_ticket->enc_part2->authorization_data,
&enc_tkt_reply.authorization_data)) {
+ syslog(LOG_INFO, "TGS_REQ: CONCAT_AUTH: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return retval;
/* assemble new transited field into allocated storage */
if (header_ticket->enc_part2->transited.tr_type !=
KRB5_DOMAIN_X500_COMPRESS) {
+ syslog(LOG_INFO, "TGS_REQ: BAD_TRTYPE: authtime %d, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return KRB5KDC_ERR_TRTYPE_NOSUPP;
header_ticket->server,
enc_tkt_reply.client,
request->server)) {
+ syslog(LOG_INFO, "TGS_REQ: ADD_TR_FAIL: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return retval;
#undef cleanup
#define cleanup() { krb5_db_free_principal(&server, 1); \
krb5_free_keyblock(session_key); \
- if (newtransited) free(enc_tkt_reply.transited.tr_contents.data);}
+ free(cname); free(sname); \
+ if (newtransited) free(enc_tkt_reply.transited.tr_contents.data); }
ticket_reply.enc_part2 = &enc_tkt_reply;
krb5_keyblock *st_sealing_key;
krb5_kvno st_srv_kvno;
- if (!request->second_ticket ||
- !request->second_ticket[st_idx]) {
- cleanup();
- return(prepare_error_tgs(request, header_ticket,
- KDC_ERR_BADOPTION,
- fromstring,
- response));
- }
if (retval = kdc_get_server_key(request->second_ticket[st_idx],
&st_sealing_key,
&st_srv_kvno)) {
+ syslog(LOG_INFO, "TGS_REQ: 2ND_TKT_SERVER: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return retval;
request->second_ticket[st_idx]);
krb5_free_keyblock(st_sealing_key);
if (retval) {
+ syslog(LOG_INFO, "TGS_REQ: 2ND_TKT_DECRYPT: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return retval;
if (retval = krb5_encrypt_tkt_part(request->second_ticket[st_idx]->enc_part2->session,
&ticket_reply)) {
+ syslog(LOG_INFO, "TGS_REQ: 2ND_TKT_ENCRYPT: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return retval;
/* convert server.key into a real key (it may be encrypted
in the database) */
if (retval = KDB_CONVERT_KEY_OUTOF_DB(&server.key, &encrypting_key)) {
+ syslog(LOG_INFO, "TGS_REQ: CONV_KEY: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return retval;
xfree(encrypting_key.contents);
if (retval) {
+ syslog(LOG_INFO, "TGS_REQ: TKT_ENCRYPT: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
tkt_cleanup();
cleanup();
return retval;
/* copy the time fields EXCEPT for authtime; its location
is used for ktime */
reply_encpart.times = enc_tkt_reply.times;
- reply_encpart.times.authtime = kdc_time;
+ reply_encpart.times.authtime = header_ticket->enc_part2->times.authtime;
+ /* starttime is optional, and treated as authtime if not present.
+ so we can nuke it if it matches */
+ if (enc_tkt_reply.times.starttime == enc_tkt_reply.times.authtime)
+ enc_tkt_reply.times.starttime = 0;
nolrentry.lr_type = KRB5_LRQ_NONE;
nolrentry.value = 0;
reply_encpart.key_exp = 0; /* ditto */
reply_encpart.flags = enc_tkt_reply.flags;
reply_encpart.server = ticket_reply.server;
-
+
/* use the session key in the ticket, unless there's a subsession key
in the AP_REQ */
req_authdat->authenticator->subkey :
header_ticket->enc_part2->session,
&reply, response);
+ if (retval) {
+ syslog(LOG_INFO, "TGS_REQ; ENCODE_KDC_REP: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
+ } else {
+ if (is_secondary)
+ syslog(LOG_INFO, "TGS_REQ; ISSUE: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
+ else
+ syslog(LOG_INFO, "TGS_REQ: ISSUE: authtime %d, host %s, %s for %s",
+ authtime, fromstring, cname, sname);
+ }
+ free(cname);
+ free(sname);
+
krb5_free_keyblock(session_key);
tkt_cleanup();
memset(ticket_reply.enc_part.ciphertext.data, 0,
authdat->ticket = apreq->ticket;
*ret_authdat = authdat;
- /* Verify that the server principal in authdat->ticket is
- the ticket granting service. */
- if (! krb5_principal_compare (authdat->ticket->server, tgs_server)) {
- cleanup_apreq();
- return KRB5KRB_AP_ERR_NOT_US;
- }
-
if (isflagset(apreq->ap_options, AP_OPTS_USE_SESSION_KEY) ||
isflagset(apreq->ap_options, AP_OPTS_MUTUAL_REQUIRED)) {
cleanup_apreq();
}
return 0;
}
+
+/*
+ * Routines that validate a AS request; checks a lot of things. :-)
+ *
+ * Returns a Kerberos protocol error number, which is _not_ the same
+ * as a com_err error number!
+ */
+#define AS_OPTIONS_HANDLED (KDC_OPT_FORWARDABLE | KDC_OPT_PROXIABLE | \
+ KDC_OPT_ALLOW_POSTDATE | KDC_OPT_POSTDATED | \
+ KDC_OPT_RENEWABLE | KDC_OPT_RENEWABLE_OK)
+int
+validate_as_request(request, client, server, kdc_time, status)
+register krb5_kdc_req *request;
+krb5_db_entry client;
+krb5_db_entry server;
+krb5_timestamp kdc_time;
+char **status;
+{
+ int errcode;
+
+ /*
+ * If an illegal option is set, complain.
+ */
+ if (request->kdc_options & ~(AS_OPTIONS_HANDLED)) {
+ *status = "INVALID AS OPTIONS";
+ return KDC_ERR_BADOPTION;
+ }
+
+ /* An AS request must include the addresses field */
+ if (request->addresses == 0) {
+ *status = "NO ADDRESS";
+ return KRB_AP_ERR_BADADDR;
+ }
+
+ /* The client's password must not be expired */
+ if (client.pw_expiration && client.pw_expiration < kdc_time) {
+ *status = "CLIENT KEY EXPIRED";
+#ifdef KRBCONF_VAGUE_ERRORS
+ return(KRB_ERR_GENERIC);
+#else
+ return(KDC_ERR_KEY_EXP);
+#endif
+ }
+
+ /* The client must not be expired */
+ if (client.expiration && client.expiration < kdc_time) {
+ *status = "CLIENT EXPIRED";
+#ifdef KRBCONF_VAGUE_ERRORS
+ return(KRB_ERR_GENERIC);
+#else
+ return(KDC_ERR_NAME_EXP);
+#endif
+ }
+
+ /* The server must not be expired */
+ if (server.expiration && server.expiration < kdc_time) {
+ *status = "SERVICE EXPIRED";
+ return(KDC_ERR_SERVICE_EXP);
+ }
+
+ /*
+ * If the client requires password changing, then only allow the
+ * pwchange service.
+ */
+ if (isflagset(client.attributes, KRB5_KDB_REQUIRES_PWCHANGE) &&
+ !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
+ *status = "REQUIRED PWCHANGE";
+ return(KDC_ERR_KEY_EXP);
+ }
+
+ /* Client and server must allow postdating tickets */
+ if ((isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) ||
+ isflagset(request->kdc_options, KDC_OPT_POSTDATED)) &&
+ (isflagset(client.attributes, KRB5_KDB_DISALLOW_POSTDATED) ||
+ isflagset(server.attributes, KRB5_KDB_DISALLOW_POSTDATED))) {
+ *status = "POSTDATE NOT ALLOWED";
+ return(KDC_ERR_CANNOT_POSTDATE);
+ }
+
+ /* Client and server must allow forwardable tickets */
+ if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE) &&
+ (isflagset(client.attributes, KRB5_KDB_DISALLOW_FORWARDABLE) ||
+ isflagset(server.attributes, KRB5_KDB_DISALLOW_FORWARDABLE))) {
+ *status = "FORWARDABLE NOT ALLOWED";
+ return(KDC_ERR_POLICY);
+ }
+
+ /* Client and server must allow renewable tickets */
+ if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE) &&
+ (isflagset(client.attributes, KRB5_KDB_DISALLOW_RENEWABLE) ||
+ isflagset(server.attributes, KRB5_KDB_DISALLOW_RENEWABLE))) {
+ *status = "RENEWABLE NOT ALLOWED";
+ return(KDC_ERR_POLICY);
+ }
+
+ /* Client and server must allow proxiable tickets */
+ if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE) &&
+ (isflagset(client.attributes, KRB5_KDB_DISALLOW_PROXIABLE) ||
+ isflagset(server.attributes, KRB5_KDB_DISALLOW_PROXIABLE))) {
+ *status = "PROXIABLE NOT ALLOWED";
+ return(KDC_ERR_POLICY);
+ }
+
+ /* Check to see if client is locked out */
+ if (isflagset(client.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
+ *status = "CLIENT LOCKED OUT";
+ return(KDC_ERR_C_PRINCIPAL_UNKNOWN);
+ }
+
+ /* Check to see if server is locked out */
+ if (isflagset(server.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
+ *status = "SERVICE LOCKED OUT";
+ return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
+ }
+
+ /* Check to see if server is allowed to be a service */
+ if (isflagset(server.attributes, KRB5_KDB_DISALLOW_SVR)) {
+ *status = "SERVICE NOT ALLOWED";
+ return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
+ }
+
+ /* Check to see if preauthentication is required */
+ if (isflagset(client.attributes, KRB5_KDB_REQUIRES_PRE_AUTH) &&
+ !request->padata) {
+ *status = "MISSING PRE_AUTH";
+#ifdef KRBCONF_VAGUE_ERRORS
+ return KRB_ERR_GENERIC;
+#else
+ return KDC_PREAUTH_FAILED;
+#endif
+ }
+
+ /*
+ * Check against local policy
+ */
+ errcode = against_local_policy_as(request, server, client,
+ kdc_time, status);
+ if (errcode)
+ return errcode;
+
+ return 0;
+}
+
+/*
+ * Routines that validate a TGS request; checks a lot of things. :-)
+ *
+ * Returns a Kerberos protocol error number, which is _not_ the same
+ * as a com_err error number!
+ */
+#define TGS_OPTIONS_HANDLED (KDC_OPT_FORWARDABLE | KDC_OPT_FORWARDED | \
+ KDC_OPT_PROXIABLE | KDC_OPT_PROXY | \
+ KDC_OPT_ALLOW_POSTDATE | KDC_OPT_POSTDATED | \
+ KDC_OPT_RENEWABLE | KDC_OPT_RENEWABLE_OK | \
+ KDC_OPT_ENC_TKT_IN_SKEY | KDC_OPT_RENEW | \
+ KDC_OPT_VALIDATE)
+
+#define TGS_SPECIAL_OPTS (KDC_OPT_FORWARDED | KDC_OPT_PROXY | \
+ KDC_OPT_RENEW | KDC_OPT_VALIDATE)
+
+int
+validate_tgs_request(request, server, ticket, kdc_time, status)
+register krb5_kdc_req *request;
+krb5_db_entry server;
+krb5_ticket *ticket;
+krb5_timestamp kdc_time;
+char **status;
+{
+ int errcode;
+ int st_idx = 0;
+
+ /*
+ * If an illegal option is set, complain.
+ */
+ if (request->kdc_options & ~(TGS_OPTIONS_HANDLED)) {
+ *status = "INVALID TGS OPTIONS";
+ return KDC_ERR_BADOPTION;
+ }
+
+ /* Check to see if server has expired */
+ if (server.expiration && server.expiration < kdc_time) {
+ *status = "SERVICE EXPIRED";
+ return(KDC_ERR_SERVICE_EXP);
+ }
+
+ /*
+ * Verify that the server principal in authdat->ticket is correct
+ * (either the ticket granting service or the service we're
+ * looking for)
+ */
+
+ if (request->kdc_options & TGS_SPECIAL_OPTS) {
+ /*
+ * This is one of the KDC options which allow a non-TGT ticket
+ * for the purposes of renewing, forwarding, proxying, or
+ * validating it.
+ *
+ * We just make sure the service in the ticket matches service
+ * the user is request.
+ */
+ if (!krb5_principal_compare(ticket->server,
+ request->server)) {
+ *status = "SERVER MISMATCH";
+ return KRB5KDC_SERVER_NOMATCH;
+ }
+ } else {
+ /*
+ * This is a normal TGS request; the ticket must belong to the
+ * TGS server
+ */
+ if (!krb5_principal_compare(ticket->server, tgs_server)) {
+ *status = "NOT TGS TICKET";
+ return KRB5KRB_AP_ERR_NOT_US;
+ }
+
+ /* Server must allow TGS based issuances */
+ if (isflagset(server.attributes, KRB5_KDB_DISALLOW_TGT_BASED)) {
+ *status = "TGT BASED NOT ALLOWED";
+ return(KDC_ERR_POLICY);
+ }
+ }
+
+ /* TGS must be forwardable to get forwarded or forwardable ticket */
+ if ((isflagset(request->kdc_options, KDC_OPT_FORWARDED) ||
+ isflagset(request->kdc_options, KDC_OPT_FORWARDABLE)) &&
+ !isflagset(ticket->enc_part2->flags, TKT_FLG_FORWARDABLE)) {
+ *status = "TGT NOT FORWARDABLE";
+
+ return KDC_ERR_BADOPTION;
+ }
+
+ /* TGS must be proxiable to get proxiable ticket */
+ if ((isflagset(request->kdc_options, KDC_OPT_PROXY) ||
+ isflagset(request->kdc_options, KDC_OPT_PROXIABLE)) &&
+ !isflagset(ticket->enc_part2->flags, TKT_FLG_PROXIABLE)) {
+ *status = "TGT NOT PROXIABLE";
+ return KDC_ERR_BADOPTION;
+ }
+
+ /* TGS must allow postdating to get postdated ticket */
+ if ((isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) ||
+ isflagset(request->kdc_options, KDC_OPT_POSTDATED)) &&
+ !isflagset(ticket->enc_part2->flags, TKT_FLG_MAY_POSTDATE)) {
+ *status = "TGT NOT POSTDATABLE";
+ return KDC_ERR_BADOPTION;
+ }
+
+ /* can only validate invalid tix */
+ if (isflagset(request->kdc_options, KDC_OPT_VALIDATE) &&
+ !isflagset(ticket->enc_part2->flags, TKT_FLG_INVALID)) {
+ *status = "VALIDATE VALID TICKET";
+ return KDC_ERR_BADOPTION;
+ }
+
+ /* can only renew renewable tix */
+ if ((isflagset(request->kdc_options, KDC_OPT_RENEW) ||
+ isflagset(request->kdc_options, KDC_OPT_RENEWABLE)) &&
+ !isflagset(ticket->enc_part2->flags, TKT_FLG_RENEWABLE)) {
+ *status = "TICKET NOT RENEWABLE";
+ return KDC_ERR_BADOPTION;
+ }
+
+ /* can not proxy ticket granting tickets */
+ if (isflagset(request->kdc_options, KDC_OPT_PROXY) &&
+ (!request->server->data ||
+ request->server->data[0].length != 6 ||
+ memcmp(request->server->data[0].data, "krbtgt", 6))) {
+ *status = "CAN'T PROXY TGT";
+ return KDC_ERR_BADOPTION;
+ }
+
+ /* Server must allow forwardable tickets */
+ if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE) &&
+ isflagset(server.attributes, KRB5_KDB_DISALLOW_FORWARDABLE)) {
+ *status = "NON-FORWARDABLE TICKET";
+ return(KDC_ERR_POLICY);
+ }
+
+ /* Server must allow renewable tickets */
+ if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE) &&
+ isflagset(server.attributes, KRB5_KDB_DISALLOW_RENEWABLE)) {
+ *status = "NON-RENEWABLE TICKET";
+ return(KDC_ERR_POLICY);
+ }
+
+ /* Server must allow proxiable tickets */
+ if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE) &&
+ isflagset(server.attributes, KRB5_KDB_DISALLOW_PROXIABLE)) {
+ *status = "NON-PROXIABLE TICKET";
+ return(KDC_ERR_POLICY);
+ }
+
+ /* Server must allow postdated tickets */
+ if (isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) &&
+ isflagset(server.attributes, KRB5_KDB_DISALLOW_POSTDATED)) {
+ *status = "NON-POSTDATABLE TICKET";
+ return(KDC_ERR_CANNOT_POSTDATE);
+ }
+
+ /* Server must allow DUP SKEY requests */
+ if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) &&
+ isflagset(server.attributes, KRB5_KDB_DISALLOW_DUP_SKEY)) {
+ *status = "DUP_SKEY DISALLOED";
+ return(KDC_ERR_POLICY);
+ }
+
+ /* Server must not be locked out */
+ if (isflagset(server.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
+ *status = "SERVER LOCKED OUT";
+ return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
+ }
+
+ /* Server must be allowed to be a service */
+ if (isflagset(server.attributes, KRB5_KDB_DISALLOW_SVR)) {
+ *status = "SERVER NOT ALLOWED";
+ return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
+ }
+
+ /* Check the hot list */
+ if (check_hot_list(ticket)) {
+ *status = "HOT_LIST";
+ return(KRB_AP_ERR_REPEAT);
+ }
+
+ /* Check the start time vs. the KDC time */
+ if (isflagset(request->kdc_options, KDC_OPT_VALIDATE)) {
+ if (ticket->enc_part2->times.starttime > kdc_time) {
+ *status = "NOT_YET_VALID";
+ return(KRB_AP_ERR_TKT_NYV);
+ }
+ }
+
+ /*
+ * Check the renew_till time. The endtime was already
+ * been checked in the initial authentication check.
+ */
+ if (isflagset(request->kdc_options, KDC_OPT_RENEW) &&
+ (ticket->enc_part2->times.renew_till < kdc_time)) {
+ *status = "TKT_EXPIRED";
+ return(KRB_AP_ERR_TKT_EXPIRED);
+ }
+
+ /* Make sure second ticket was provided for ENC_TKT_IN_SKEY */
+ if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) {
+ if (!request->second_ticket ||
+ !request->second_ticket[st_idx]) {
+ *status = "NO_2ND_TKT";
+ return(KDC_ERR_BADOPTION);
+ }
+ st_idx++;
+ }
+
+ /* Check for hardware preauthentication */
+ if (isflagset(server.attributes, KRB5_KDB_REQUIRES_HW_AUTH) &&
+ !isflagset(ticket->enc_part2->flags,TKT_FLG_HW_AUTH)) {
+ *status = "NO HW PREAUTH";
+ return KRB_ERR_GENERIC;
+ }
+
+ /* Check for any kind of preauthentication */
+ if (isflagset(server.attributes, KRB5_KDB_REQUIRES_PRE_AUTH) &&
+ !isflagset(ticket->enc_part2->flags, TKT_FLG_PRE_AUTH)) {
+ *status = "NO PREAUTH";
+ return KRB_ERR_GENERIC;
+ }
+
+ /*
+ * Check local policy
+ */
+ errcode = against_local_policy_tgs(request, server, ticket, status);
+ if (errcode)
+ return errcode;
+
+
+ return 0;
+}
#include "kdc_util.h"
-/*ARGSUSED*/
-krb5_boolean
-against_postdate_policy(fromtime)
-krb5_timestamp fromtime;
+int
+against_local_policy_as(request, client, server, kdc_time, status)
+register krb5_kdc_req *request;
+krb5_db_entry client;
+krb5_db_entry server;
+krb5_timestamp kdc_time;
+char **status;
{
- return FALSE;
+ return 0; /* not against policy */
}
-krb5_boolean
-against_flag_policy_as(request)
-const register krb5_kdc_req *request;
+/*
+ * This is where local policy restrictions for the TGS should placed.
+ */
+krb5_error_code
+against_local_policy_tgs(request, server, ticket, status)
+register krb5_kdc_req *request;
+krb5_db_entry server;
+krb5_ticket *ticket;
+char **status;
{
- if (isflagset(request->kdc_options, KDC_OPT_FORWARDED) ||
- isflagset(request->kdc_options, KDC_OPT_PROXY) ||
- isflagset(request->kdc_options, KDC_OPT_RENEW) ||
- isflagset(request->kdc_options, KDC_OPT_VALIDATE) ||
- isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY))
- return TRUE; /* against policy */
-
- return FALSE; /* not against policy */
+#ifdef 0
+ /*
+ * For example, if your site wants to disallow ticket forwarding,
+ * you might do something like this:
+ */
+
+ if (isflagset(request->kdc_options, KDC_OPT_FORWARDED)) {
+ *status = "FORWARD POLICY";
+ return KRB5KDC_ERR_POLICY;
+ }
+#endif
+
+ return 0; /* not against policy */
}
-krb5_boolean
-against_flag_policy_tgs(request, ticket)
-const register krb5_kdc_req *request;
-const register krb5_ticket *ticket;
-{
- if (((isflagset(request->kdc_options, KDC_OPT_FORWARDED) ||
- isflagset(request->kdc_options, KDC_OPT_FORWARDABLE)) &&
- !isflagset(ticket->enc_part2->flags,
- TKT_FLG_FORWARDABLE)) || /* TGS must be forwardable to get
- forwarded or forwardable ticket */
- ((isflagset(request->kdc_options, KDC_OPT_PROXY) ||
- isflagset(request->kdc_options, KDC_OPT_PROXIABLE)) &&
- !isflagset(ticket->enc_part2->flags,
- TKT_FLG_PROXIABLE)) || /* TGS must be proxiable to get
- proxiable ticket */
- ((isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) ||
- isflagset(request->kdc_options, KDC_OPT_POSTDATED)) &&
- !isflagset(ticket->enc_part2->flags,
- TKT_FLG_MAY_POSTDATE)) || /* TGS must allow postdating to get
- postdated ticket */
-
- (isflagset(request->kdc_options, KDC_OPT_VALIDATE) &&
- !isflagset(ticket->enc_part2->flags,
- TKT_FLG_INVALID)) || /* can only validate invalid tix */
- ((isflagset(request->kdc_options, KDC_OPT_RENEW) ||
- isflagset(request->kdc_options, KDC_OPT_RENEWABLE)) &&
- !isflagset(ticket->enc_part2->flags,
- TKT_FLG_RENEWABLE))) /* can only renew renewable tix */
- return TRUE; /* against policy */
- return FALSE; /* XXX not against policy */
-}