krb5 commit: Refactor process_tgs_req() service princ search
Tom Yu
tlyu at MIT.EDU
Mon Oct 15 20:27:44 EDT 2012
https://github.com/krb5/krb5/commit/3b8b18d6a87f5d2b4f255ee2e7d34ae6b48b4bf6
commit 3b8b18d6a87f5d2b4f255ee2e7d34ae6b48b4bf6
Author: Tom Yu <tlyu at mit.edu>
Date: Fri Sep 21 15:32:20 2012 -0400
Refactor process_tgs_req() service princ search
The service principal database entry search logic in process_tgs_req()
was excessively complex, containing questionable uses of "goto", along
with deeply nested control flow. Refactor it into smaller functions.
src/kdc/do_tgs_req.c | 192 ++++++++++++++++++++++++--------------------------
1 files changed, 91 insertions(+), 101 deletions(-)
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index c45fe87..52d456e 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -69,16 +69,23 @@
#include <ctype.h>
static krb5_error_code
-find_alternate_tgs(struct kdc_request_state *, krb5_kdc_req *,
- krb5_db_entry **);
+find_alternate_tgs(kdc_realm_t *, krb5_principal, krb5_db_entry **,
+ const char**);
static krb5_error_code
prepare_error_tgs(struct kdc_request_state *, krb5_kdc_req *,krb5_ticket *,int,
krb5_principal,krb5_data **,const char *, krb5_pa_data **);
static krb5_int32
-prep_reprocess_req(struct kdc_request_state *, krb5_kdc_req *,
- krb5_principal *);
+prep_reprocess_req(kdc_realm_t *, krb5_kdc_req *, krb5_principal *);
+
+static krb5_error_code
+db_get_svc_princ(krb5_context, krb5_principal, krb5_flags,
+ krb5_db_entry **, const char **);
+
+static krb5_error_code
+search_sprinc(kdc_realm_t *, krb5_kdc_req *, krb5_flags,
+ krb5_db_entry **, const char **);
/*ARGSUSED*/
krb5_error_code
@@ -108,7 +115,6 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
krb5_enctype useenctype;
int errcode, errcode2;
register int i;
- int firstpass = 1;
const char *status = 0;
krb5_enc_tkt_part *header_enc_tkt = NULL; /* TGT */
krb5_enc_tkt_part *subject_tkt = NULL; /* TGT or evidence ticket */
@@ -117,10 +123,8 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
krb5_authdata **kdc_issued_auth_data = NULL; /* auth data issued by KDC */
unsigned int c_flags = 0, s_flags = 0; /* client/server KDB flags */
char *s4u_name = NULL;
- krb5_boolean is_referral, db_ref_done = FALSE;
+ krb5_boolean is_referral;
const char *emsg = NULL;
- krb5_data *tgs_1 =NULL, *server_1 = NULL;
- krb5_principal krbtgt_princ;
krb5_kvno ticket_kvno = 0;
struct kdc_request_state *state = NULL;
krb5_pa_data *pa_tgs_req; /*points into request*/
@@ -210,70 +214,25 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE);
}
- db_ref_done = FALSE;
-ref_tgt_again:
- if ((errcode = krb5_unparse_name(kdc_context, request->server, &sname))) {
- status = "UNPARSING SERVER";
+ errcode = search_sprinc(kdc_active_realm, request, s_flags, &server,
+ &status);
+ if (errcode != 0)
goto cleanup;
- }
- limit_string(sname);
-
- errcode = krb5_db_get_principal(kdc_context, request->server,
- s_flags, &server);
- if (errcode == KRB5_KDB_CANTLOCK_DB)
- errcode = KRB5KDC_ERR_SVC_UNAVAILABLE;
- if (errcode && errcode != KRB5_KDB_NOENTRY) {
- status = "LOOKING_UP_SERVER";
+ /* XXX until nothing depends on request being mutated */
+ krb5_free_principal(kdc_context, request->server);
+ request->server = NULL;
+ errcode = krb5_copy_principal(kdc_context, server->princ,
+ &request->server);
+ if (errcode != 0) {
+ status = "COPYING RESOLVED SERVER";
goto cleanup;
}
-tgt_again:
- if (errcode == KRB5_KDB_NOENTRY) {
- /*
- * might be a request for a TGT for some other realm; we
- * should do our best to find such a TGS in this db
- */
- if (firstpass ) {
-
- if ( krb5_is_tgs_principal(request->server) == TRUE) {
- /* Principal is a name of krb ticket service */
- if (krb5_princ_size(kdc_context, request->server) == 2) {
-
- server_1 = krb5_princ_component(kdc_context,
- request->server, 1);
- tgs_1 = krb5_princ_component(kdc_context, tgs_server, 1);
-
- if (!tgs_1 || !data_eq(*server_1, *tgs_1)) {
- errcode = find_alternate_tgs(state, request, &server);
- firstpass = 0;
- if (errcode == 0)
- goto tgt_again;
- }
- }
- status = "UNKNOWN_SERVER";
- errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
- goto cleanup;
-
- } else if ( db_ref_done == FALSE) {
- retval = prep_reprocess_req(state, request, &krbtgt_princ);
- if (!retval) {
- krb5_free_principal(kdc_context, request->server);
- request->server = NULL;
- retval = krb5_copy_principal(kdc_context, krbtgt_princ,
- &(request->server));
- if (!retval) {
- db_ref_done = TRUE;
- if (sname != NULL)
- free(sname);
- goto ref_tgt_again;
- }
- }
- }
- }
- status = "UNKNOWN_SERVER";
- errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+ if ((errcode = krb5_unparse_name(kdc_context, server->princ, &sname))) {
+ status = "UNPARSING SERVER";
goto cleanup;
}
+ limit_string(sname);
if ((errcode = krb5_timeofday(kdc_context, &kdc_time))) {
status = "TIME_OF_DAY";
@@ -1060,29 +1019,22 @@ prepare_error_tgs (struct kdc_request_state *state,
* some intermediate realm.
*/
static krb5_error_code
-find_alternate_tgs(struct kdc_request_state *state,
- krb5_kdc_req *request, krb5_db_entry **server_ptr)
+find_alternate_tgs(kdc_realm_t *kdc_active_realm, krb5_principal princ,
+ krb5_db_entry **server_ptr, const char **status)
{
krb5_error_code retval;
- krb5_principal *plist = NULL, *pl2, tmpprinc;
+ krb5_principal *plist = NULL, *pl2;
krb5_data tmp;
krb5_db_entry *server = NULL;
- kdc_realm_t *kdc_active_realm = state->realm_data;
*server_ptr = NULL;
-
- /*
- * Call to krb5_princ_component is normally not safe but is so
- * here only because find_alternate_tgs() is only called from
- * somewhere that has already checked the number of components in
- * the principal.
- */
+ assert(is_cross_tgs_principal(princ));
if ((retval = krb5_walk_realm_tree(kdc_context,
- krb5_princ_realm(kdc_context, request->server),
- krb5_princ_component(kdc_context, request->server, 1),
- &plist, KRB5_REALM_BRANCH_CHAR)))
- return retval;
-
+ krb5_princ_realm(kdc_context, princ),
+ krb5_princ_component(kdc_context, princ, 1),
+ &plist, KRB5_REALM_BRANCH_CHAR))) {
+ goto cleanup;
+ }
/* move to the end */
for (pl2 = plist; *pl2; pl2++);
@@ -1092,48 +1044,35 @@ find_alternate_tgs(struct kdc_request_state *state,
tmp = *krb5_princ_realm(kdc_context, *pl2);
krb5_princ_set_realm(kdc_context, *pl2,
krb5_princ_realm(kdc_context, tgs_server));
- retval = krb5_db_get_principal(kdc_context, *pl2, 0, &server);
- if (retval == KRB5_KDB_CANTLOCK_DB)
- retval = KRB5KDC_ERR_SVC_UNAVAILABLE;
+ retval = db_get_svc_princ(kdc_context, *pl2, 0, &server, status);
krb5_princ_set_realm(kdc_context, *pl2, &tmp);
if (retval == KRB5_KDB_NOENTRY)
continue;
else if (retval)
goto cleanup;
- /* Found it. */
- tmp = *krb5_princ_realm(kdc_context, *pl2);
- krb5_princ_set_realm(kdc_context, *pl2,
- krb5_princ_realm(kdc_context, tgs_server));
- retval = krb5_copy_principal(kdc_context, *pl2, &tmpprinc);
- if (retval)
- goto cleanup;
- krb5_princ_set_realm(kdc_context, *pl2, &tmp);
-
- krb5_free_principal(kdc_context, request->server);
- request->server = tmpprinc;
- log_tgs_alt_tgt(kdc_context, request->server);
+ log_tgs_alt_tgt(kdc_context, server->princ);
*server_ptr = server;
server = NULL;
goto cleanup;
}
- retval = KRB5_KDB_NOENTRY;
-
cleanup:
+ if (retval != 0)
+ *status = "UNKNOWN_SERVER";
+
krb5_free_realm_tree(kdc_context, plist);
krb5_db_free_principal(kdc_context, server);
return retval;
}
static krb5_int32
-prep_reprocess_req(struct kdc_request_state *state, krb5_kdc_req *request,
+prep_reprocess_req(kdc_realm_t *kdc_active_realm, krb5_kdc_req *request,
krb5_principal *krbtgt_princ)
{
krb5_error_code retval = KRB5KRB_AP_ERR_BADMATCH;
char **realms, **cpp, *temp_buf=NULL;
krb5_data *comp1 = NULL, *comp2 = NULL;
char *comp1_str = NULL;
- kdc_realm_t *kdc_active_realm = state->realm_data;
/* By now we know that server principal name is unknown.
* If CANONICALIZE flag is set in the request
@@ -1217,3 +1156,54 @@ cleanup:
return retval;
}
+
+static krb5_error_code
+db_get_svc_princ(krb5_context ctx, krb5_principal princ,
+ krb5_flags flags, krb5_db_entry **server,
+ const char **status)
+{
+ krb5_error_code ret;
+
+ ret = krb5_db_get_principal(ctx, princ, flags, server);
+ if (ret == KRB5_KDB_CANTLOCK_DB)
+ ret = KRB5KDC_ERR_SVC_UNAVAILABLE;
+ if (ret != 0) {
+ *status = "LOOKING_UP_SERVER";
+ }
+ return ret;
+}
+
+static krb5_error_code
+search_sprinc(kdc_realm_t *kdc_active_realm, krb5_kdc_req *req,
+ krb5_flags flags, krb5_db_entry **server, const char **status)
+{
+ krb5_error_code ret;
+ krb5_principal princ = req->server;
+ krb5_principal reftgs = NULL;
+
+ ret = db_get_svc_princ(kdc_context, princ, flags, server, status);
+ if (ret == 0 || ret != KRB5_KDB_NOENTRY)
+ goto cleanup;
+
+ if (!is_cross_tgs_principal(req->server)) {
+ /* domain->realm referral */
+ ret = prep_reprocess_req(kdc_active_realm, req, &reftgs);
+ if (ret != 0)
+ goto cleanup;
+ ret = db_get_svc_princ(kdc_context, reftgs, flags, server, status);
+ if (ret == 0 || ret != KRB5_KDB_NOENTRY)
+ goto cleanup;
+
+ princ = reftgs;
+ }
+ ret = find_alternate_tgs(kdc_active_realm, princ, server, status);
+
+cleanup:
+ if (ret != 0 && ret != KRB5KDC_ERR_SVC_UNAVAILABLE) {
+ ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+ if (*status == NULL)
+ *status = "LOOKING_UP_SERVER";
+ }
+ krb5_free_principal(kdc_context, reftgs);
+ return ret;
+}
More information about the cvs-krb5
mailing list