diff options
author | Tom Yu <tlyu@mit.edu> | 2009-10-31 00:48:38 +0000 |
---|---|---|
committer | Tom Yu <tlyu@mit.edu> | 2009-10-31 00:48:38 +0000 |
commit | 02d6bcbc98a214e7aeaaa9f45f0db8784a7b743b (patch) | |
tree | 61b9147863cd8be3eff63903dc36cae168254bd5 /src/kdc | |
parent | 162ab371748cba0cc6f172419bd6e71fa04bb878 (diff) | |
download | krb5-02d6bcbc98a214e7aeaaa9f45f0db8784a7b743b.zip krb5-02d6bcbc98a214e7aeaaa9f45f0db8784a7b743b.tar.gz krb5-02d6bcbc98a214e7aeaaa9f45f0db8784a7b743b.tar.bz2 |
make mark-cstyle
make reindent
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23100 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/kdc')
-rw-r--r-- | src/kdc/dispatch.c | 89 | ||||
-rw-r--r-- | src/kdc/do_as_req.c | 557 | ||||
-rw-r--r-- | src/kdc/do_tgs_req.c | 297 | ||||
-rw-r--r-- | src/kdc/extern.c | 19 | ||||
-rw-r--r-- | src/kdc/extern.h | 85 | ||||
-rw-r--r-- | src/kdc/fast_util.c | 455 | ||||
-rw-r--r-- | src/kdc/kdc_authdata.c | 628 | ||||
-rw-r--r-- | src/kdc/kdc_preauth.c | 3547 | ||||
-rw-r--r-- | src/kdc/kdc_util.c | 2508 | ||||
-rw-r--r-- | src/kdc/kdc_util.h | 357 | ||||
-rw-r--r-- | src/kdc/main.c | 715 | ||||
-rw-r--r-- | src/kdc/network.c | 1507 | ||||
-rw-r--r-- | src/kdc/pkinit_apple_server.c | 187 | ||||
-rw-r--r-- | src/kdc/pkinit_server.h | 81 | ||||
-rw-r--r-- | src/kdc/policy.c | 88 | ||||
-rw-r--r-- | src/kdc/policy.h | 7 | ||||
-rw-r--r-- | src/kdc/replay.c | 119 | ||||
-rw-r--r-- | src/kdc/rtest.c | 117 |
18 files changed, 5687 insertions, 5676 deletions
diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c index 3678645..3885b4e 100644 --- a/src/kdc/dispatch.c +++ b/src/kdc/dispatch.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/dispatch.c * @@ -7,7 +8,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -21,7 +22,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * Dispatch an incoming packet. */ @@ -44,68 +45,68 @@ dispatch(krb5_data *pkt, const krb5_fulladdr *from, krb5_data **response) krb5_error_code retval; krb5_kdc_req *as_req; krb5_int32 now, now_usec; - + /* decode incoming packet, and dispatch */ #ifndef NOCACHE /* try the replay lookaside buffer */ if (kdc_check_lookaside(pkt, response)) { - /* a hit! */ - const char *name = 0; - char buf[46]; + /* a hit! */ + const char *name = 0; + char buf[46]; - name = inet_ntop (ADDRTYPE2FAMILY (from->address->addrtype), - from->address->contents, buf, sizeof (buf)); - if (name == 0) - name = "[unknown address type]"; - krb5_klog_syslog(LOG_INFO, - "DISPATCH: repeated (retransmitted?) request from %s, resending previous response", - name); - return 0; + name = inet_ntop (ADDRTYPE2FAMILY (from->address->addrtype), + from->address->contents, buf, sizeof (buf)); + if (name == 0) + name = "[unknown address type]"; + krb5_klog_syslog(LOG_INFO, + "DISPATCH: repeated (retransmitted?) request from %s, resending previous response", + name); + return 0; } #endif retval = krb5_crypto_us_timeofday(&now, &now_usec); if (retval == 0) { - krb5_int32 usec_difference = now_usec-last_usec; - krb5_data data; - if(last_os_random == 0) - last_os_random = now; - /* Grab random data from OS every hour*/ - if(now-last_os_random >= 60*60) { - krb5_c_random_os_entropy(kdc_context, 0, NULL); - last_os_random = now; - } - - data.length = sizeof(krb5_int32); - data.data = (void *) &usec_difference; - - krb5_c_random_add_entropy(kdc_context, - KRB5_C_RANDSOURCE_TIMING, &data); - last_usec = now_usec; + krb5_int32 usec_difference = now_usec-last_usec; + krb5_data data; + if(last_os_random == 0) + last_os_random = now; + /* Grab random data from OS every hour*/ + if(now-last_os_random >= 60*60) { + krb5_c_random_os_entropy(kdc_context, 0, NULL); + last_os_random = now; + } + + data.length = sizeof(krb5_int32); + data.data = (void *) &usec_difference; + + krb5_c_random_add_entropy(kdc_context, + KRB5_C_RANDSOURCE_TIMING, &data); + last_usec = now_usec; } /* try TGS_REQ first; they are more common! */ if (krb5_is_tgs_req(pkt)) { - retval = process_tgs_req(pkt, from, response); + retval = process_tgs_req(pkt, from, response); } else if (krb5_is_as_req(pkt)) { - if (!(retval = decode_krb5_as_req(pkt, &as_req))) { - /* - * setup_server_realm() sets up the global realm-specific data - * pointer. - * process_as_req frees the request if it is called - */ - if (!(retval = setup_server_realm(as_req->server))) { - retval = process_as_req(as_req, pkt, from, response); - } - else krb5_free_kdc_req(kdc_context, as_req); - } + if (!(retval = decode_krb5_as_req(pkt, &as_req))) { + /* + * setup_server_realm() sets up the global realm-specific data + * pointer. + * process_as_req frees the request if it is called + */ + if (!(retval = setup_server_realm(as_req->server))) { + retval = process_as_req(as_req, pkt, from, response); + } + else krb5_free_kdc_req(kdc_context, as_req); + } } else - retval = KRB5KRB_AP_ERR_MSG_TYPE; + retval = KRB5KRB_AP_ERR_MSG_TYPE; #ifndef NOCACHE /* put the response into the lookaside buffer */ if (!retval && *response != NULL) - kdc_insert_lookaside(pkt, *response); + kdc_insert_lookaside(pkt, *response); #endif return retval; diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index 1feb468..5067ff8 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/do_as_req.c * @@ -9,7 +10,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -23,7 +24,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * KDC Routines to deal with AS_REQ's */ @@ -64,7 +65,7 @@ #include <netinet/in.h> #ifndef hpux #include <arpa/inet.h> -#endif /* hpux */ +#endif /* hpux */ #endif /* HAVE_NETINET_IN_H */ #include "kdc_util.h" @@ -75,21 +76,21 @@ #if APPLE_PKINIT #define AS_REQ_DEBUG 0 -#if AS_REQ_DEBUG +#if AS_REQ_DEBUG #define asReqDebug(args...) printf(args) #else #define asReqDebug(args...) #endif #endif /* APPLE_PKINIT */ -static krb5_error_code prepare_error_as (struct kdc_request_state *, krb5_kdc_req *, int, krb5_data *, - krb5_principal, krb5_data **, - const char *); +static krb5_error_code prepare_error_as (struct kdc_request_state *, krb5_kdc_req *, int, krb5_data *, + krb5_principal, krb5_data **, + const char *); /*ARGSUSED*/ krb5_error_code process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, - const krb5_fulladdr *from, krb5_data **response) + const krb5_fulladdr *from, krb5_data **response) { krb5_db_entry client, server; krb5_kdc_rep reply; @@ -119,11 +120,11 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, struct kdc_request_state *state = NULL; krb5_data encoded_req_body; krb5_keyblock *as_encrypting_key = NULL; - + #if APPLE_PKINIT - asReqDebug("process_as_req top realm %s name %s\n", - request->client->realm.data, request->client->data->data); + asReqDebug("process_as_req top realm %s name %s\n", + request->client->realm.data, request->client->data->data); #endif /* APPLE_PKINIT */ ticket_reply.enc_part.ciphertext.data = 0; @@ -138,42 +139,42 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, errcode = kdc_make_rstate(&state); if (errcode != 0) { - status = "constructing state"; - goto errout; + status = "constructing state"; + goto errout; } if (fetch_asn1_field((unsigned char *) req_pkt->data, - 1, 4, &encoded_req_body) != 0) { + 1, 4, &encoded_req_body) != 0) { errcode = ASN1_BAD_ID; status = "Finding req_body"; - goto errout; + goto errout; } errcode = kdc_find_fast(&request, &encoded_req_body, NULL /*TGS key*/, NULL, state); if (errcode) { - status = "error decoding FAST"; - goto errout; + status = "error decoding FAST"; + goto errout; } request->kdc_state = state; if (!request->client) { - status = "NULL_CLIENT"; - errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - goto errout; + status = "NULL_CLIENT"; + errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + goto errout; } if ((errcode = krb5_unparse_name(kdc_context, request->client, &cname))) { - status = "UNPARSING_CLIENT"; - goto errout; + status = "UNPARSING_CLIENT"; + goto errout; } limit_string(cname); if (!request->server) { - status = "NULL_SERVER"; - errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; - goto errout; + status = "NULL_SERVER"; + errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto errout; } if ((errcode = krb5_unparse_name(kdc_context, request->server, &sname))) { - status = "UNPARSING_SERVER"; - goto errout; + status = "UNPARSING_SERVER"; + goto errout; } limit_string(sname); - + /* * We set KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY as a hint * to the backend to return naming information in lieu @@ -185,109 +186,109 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, * always canonicalize enterprise principal names. */ if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) || - krb5_princ_type(kdc_context, - request->client) == KRB5_NT_ENTERPRISE_PRINCIPAL) { - setflag(c_flags, KRB5_KDB_FLAG_CANONICALIZE); + krb5_princ_type(kdc_context, + request->client) == KRB5_NT_ENTERPRISE_PRINCIPAL) { + setflag(c_flags, KRB5_KDB_FLAG_CANONICALIZE); } if (include_pac_p(kdc_context, request)) { - setflag(c_flags, KRB5_KDB_FLAG_INCLUDE_PAC); + setflag(c_flags, KRB5_KDB_FLAG_INCLUDE_PAC); } c_nprincs = 1; if ((errcode = krb5_db_get_principal_ext(kdc_context, request->client, - c_flags, &client, &c_nprincs, - &more))) { - status = "LOOKING_UP_CLIENT"; - c_nprincs = 0; - goto errout; + c_flags, &client, &c_nprincs, + &more))) { + status = "LOOKING_UP_CLIENT"; + c_nprincs = 0; + goto errout; } if (more) { - status = "NON-UNIQUE_CLIENT"; - errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; - goto errout; + status = "NON-UNIQUE_CLIENT"; + errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; + goto errout; } else if (c_nprincs != 1) { - status = "CLIENT_NOT_FOUND"; - if (vague_errors) - errcode = KRB5KRB_ERR_GENERIC; - else - errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - goto errout; - } - + status = "CLIENT_NOT_FOUND"; + if (vague_errors) + errcode = KRB5KRB_ERR_GENERIC; + else + errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + goto errout; + } + /* * If the backend returned a principal that is not in the local * realm, then we need to refer the client to that realm. */ if (!is_local_principal(client.princ)) { - /* Entry is a referral to another realm */ - status = "REFERRAL"; - errcode = KRB5KDC_ERR_WRONG_REALM; - goto errout; + /* Entry is a referral to another realm */ + status = "REFERRAL"; + errcode = KRB5KDC_ERR_WRONG_REALM; + goto errout; } -#if 0 +#if 0 /* * Turn off canonicalization if client is marked DES only * (unless enterprise principal name was requested) */ if (isflagset(client.attributes, KRB5_KDB_NON_MS_PRINCIPAL) && - krb5_princ_type(kdc_context, - request->client) != KRB5_NT_ENTERPRISE_PRINCIPAL) { - clear(c_flags, KRB5_KDB_FLAG_CANONICALIZE); + krb5_princ_type(kdc_context, + request->client) != KRB5_NT_ENTERPRISE_PRINCIPAL) { + clear(c_flags, KRB5_KDB_FLAG_CANONICALIZE); } #endif - + s_flags = 0; if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE)) { - setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE); + setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE); } s_nprincs = 1; if ((errcode = krb5_db_get_principal_ext(kdc_context, request->server, - s_flags, &server, - &s_nprincs, &more))) { - status = "LOOKING_UP_SERVER"; - goto errout; + s_flags, &server, + &s_nprincs, &more))) { + status = "LOOKING_UP_SERVER"; + goto errout; } if (more) { - status = "NON-UNIQUE_SERVER"; - errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; - goto errout; + status = "NON-UNIQUE_SERVER"; + errcode = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; + goto errout; } else if (s_nprincs != 1) { - status = "SERVER_NOT_FOUND"; - errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; - goto errout; + status = "SERVER_NOT_FOUND"; + errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto errout; } if ((errcode = krb5_timeofday(kdc_context, &kdc_time))) { - status = "TIMEOFDAY"; - goto errout; + status = "TIMEOFDAY"; + goto errout; } authtime = kdc_time; /* for audit_as_request() */ if ((errcode = validate_as_request(request, client, server, - kdc_time, &status, &e_data))) { - if (!status) - status = "UNKNOWN_REASON"; - errcode += ERROR_TABLE_BASE_krb5; - goto errout; + kdc_time, &status, &e_data))) { + if (!status) + status = "UNKNOWN_REASON"; + errcode += ERROR_TABLE_BASE_krb5; + goto errout; } - + /* * Select the keytype for the ticket session key. */ if ((useenctype = select_session_keytype(kdc_context, &server, - request->nktypes, - request->ktype)) == 0) { - /* unsupported ktype */ - status = "BAD_ENCRYPTION_TYPE"; - errcode = KRB5KDC_ERR_ETYPE_NOSUPP; - goto errout; + request->nktypes, + request->ktype)) == 0) { + /* unsupported ktype */ + status = "BAD_ENCRYPTION_TYPE"; + errcode = KRB5KDC_ERR_ETYPE_NOSUPP; + goto errout; } if ((errcode = krb5_c_make_random_key(kdc_context, useenctype, - &session_key))) { - status = "RANDOM_KEY_FAILED"; - goto errout; + &session_key))) { + status = "RANDOM_KEY_FAILED"; + goto errout; } /* @@ -296,11 +297,11 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, * aliases, nothing more). */ if (isflagset(s_flags, KRB5_KDB_FLAG_CANONICALIZE) && - krb5_is_tgs_principal(request->server) && - krb5_is_tgs_principal(server.princ)) { - ticket_reply.server = server.princ; + krb5_is_tgs_principal(request->server) && + krb5_is_tgs_principal(server.princ)) { + ticket_reply.server = server.princ; } else { - ticket_reply.server = request->server; + ticket_reply.server = request->server; } enc_tkt_reply.flags = 0; @@ -308,94 +309,94 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, setflag(enc_tkt_reply.flags, TKT_FLG_INITIAL); - /* 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 */ + /* 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); + 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; if (isflagset(c_flags, KRB5_KDB_FLAG_CANONICALIZE)) { - client_princ = *(client.princ); + client_princ = *(client.princ); } else { - client_princ = *(request->client); - /* The realm is always canonicalized */ - client_princ.realm = *(krb5_princ_realm(context, client.princ)); + client_princ = *(request->client); + /* The realm is always canonicalized */ + client_princ.realm = *(krb5_princ_realm(context, client.princ)); } enc_tkt_reply.client = &client_princ; enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; enc_tkt_reply.transited.tr_contents = empty_string; /* equivalent of "" */ if (isflagset(request->kdc_options, KDC_OPT_POSTDATED)) { - setflag(enc_tkt_reply.flags, TKT_FLG_POSTDATED); - setflag(enc_tkt_reply.flags, TKT_FLG_INVALID); - enc_tkt_reply.times.starttime = request->from; + setflag(enc_tkt_reply.flags, TKT_FLG_POSTDATED); + setflag(enc_tkt_reply.flags, TKT_FLG_INVALID); + enc_tkt_reply.times.starttime = request->from; } else - enc_tkt_reply.times.starttime = kdc_time; + enc_tkt_reply.times.starttime = kdc_time; kdc_get_ticket_endtime(kdc_context, - enc_tkt_reply.times.starttime, - kdc_infinity, - request->till, - &client, - &server, - &enc_tkt_reply.times.endtime); + enc_tkt_reply.times.starttime, + kdc_infinity, + request->till, + &client, + &server, + &enc_tkt_reply.times.endtime); if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) && - !isflagset(client.attributes, KRB5_KDB_DISALLOW_RENEWABLE) && - (enc_tkt_reply.times.endtime < request->till)) { + !isflagset(client.attributes, KRB5_KDB_DISALLOW_RENEWABLE) && + (enc_tkt_reply.times.endtime < request->till)) { - /* we set the RENEWABLE option for later processing */ + /* we set the RENEWABLE option for later processing */ - setflag(request->kdc_options, KDC_OPT_RENEWABLE); - request->rtime = request->till; + setflag(request->kdc_options, KDC_OPT_RENEWABLE); + request->rtime = request->till; } rtime = (request->rtime == 0) ? kdc_infinity : request->rtime; 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 + - min(client.max_renewable_life, - min(server.max_renewable_life, - max_renewable_life_for_realm))); + /* + * 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 + + min(client.max_renewable_life, + 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; /* XXX */ /* 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; + enc_tkt_reply.times.starttime = 0; enc_tkt_reply.caddrs = request->addresses; enc_tkt_reply.authorization_data = 0; - /* + /* * Check the preauthentication if it is there. */ if (request->padata) { - errcode = check_padata(kdc_context, &client, req_pkt, request, - &enc_tkt_reply, &pa_context, &e_data); - if (errcode) { - if (errcode == KRB5KDC_ERR_PREAUTH_FAILED) - get_preauth_hint_list(request, &client, &server, &e_data); - - status = "PREAUTH_FAILED"; - if (vague_errors) - errcode = KRB5KRB_ERR_GENERIC; - goto errout; - } + errcode = check_padata(kdc_context, &client, req_pkt, request, + &enc_tkt_reply, &pa_context, &e_data); + if (errcode) { + if (errcode == KRB5KDC_ERR_PREAUTH_FAILED) + get_preauth_hint_list(request, &client, &server, &e_data); + + status = "PREAUTH_FAILED"; + if (vague_errors) + errcode = KRB5KRB_ERR_GENERIC; + goto errout; + } } /* @@ -405,15 +406,15 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, */ status = missing_required_preauth(&client, &server, &enc_tkt_reply); if (status) { - errcode = KRB5KDC_ERR_PREAUTH_REQUIRED; - get_preauth_hint_list(request, &client, &server, &e_data); - goto errout; + errcode = KRB5KDC_ERR_PREAUTH_REQUIRED; + get_preauth_hint_list(request, &client, &server, &e_data); + goto errout; } if ((errcode = validate_forwardable(request, client, server, - kdc_time, &status))) { - errcode += ERROR_TABLE_BASE_krb5; - goto errout; + kdc_time, &status))) { + errcode += ERROR_TABLE_BASE_krb5; + goto errout; } ticket_reply.enc_part2 = &enc_tkt_reply; @@ -422,12 +423,12 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, * Find the server key */ if ((errcode = krb5_dbe_find_enctype(kdc_context, &server, - -1, /* ignore keytype */ - -1, /* Ignore salttype */ - 0, /* Get highest kvno */ - &server_key))) { - status = "FINDING_SERVER_KEY"; - goto errout; + -1, /* ignore keytype */ + -1, /* Ignore salttype */ + 0, /* Get highest kvno */ + &server_key))) { + status = "FINDING_SERVER_KEY"; + goto errout; } if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, &server, @@ -451,33 +452,33 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, /* convert server.key into a real key (it may be encrypted in the database) */ - if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, mkey_ptr, - /* server_keyblock is later used to generate auth data signatures */ - server_key, &server_keyblock, - NULL))) { - status = "DECRYPT_SERVER_KEY"; - goto errout; - } - + if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, mkey_ptr, + /* server_keyblock is later used to generate auth data signatures */ + server_key, &server_keyblock, + NULL))) { + status = "DECRYPT_SERVER_KEY"; + goto errout; + } + /* * Find the appropriate client key. We search in the order specified * by request keytype list. */ client_key = (krb5_key_data *) NULL; for (i = 0; i < request->nktypes; i++) { - useenctype = request->ktype[i]; - if (!krb5_c_valid_enctype(useenctype)) - continue; + useenctype = request->ktype[i]; + if (!krb5_c_valid_enctype(useenctype)) + continue; - if (!krb5_dbe_find_enctype(kdc_context, &client, useenctype, -1, - 0, &client_key)) - break; + if (!krb5_dbe_find_enctype(kdc_context, &client, useenctype, -1, + 0, &client_key)) + break; } if (!(client_key)) { - /* Cannot find an appropriate key */ - status = "CANT_FIND_CLIENT_KEY"; - errcode = KRB5KDC_ERR_ETYPE_NOSUPP; - goto errout; + /* Cannot find an appropriate key */ + status = "CANT_FIND_CLIENT_KEY"; + errcode = KRB5KDC_ERR_ETYPE_NOSUPP; + goto errout; } if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, &client, @@ -500,11 +501,11 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, } /* convert client.key_data into a real key */ - if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, mkey_ptr, - client_key, &client_keyblock, - NULL))) { - status = "DECRYPT_CLIENT_KEY"; - goto errout; + if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, mkey_ptr, + client_key, &client_keyblock, + NULL))) { + status = "DECRYPT_CLIENT_KEY"; + goto errout; } client_keyblock.enctype = useenctype; @@ -514,8 +515,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, reply.ticket = &ticket_reply; reply_encpart.session = &session_key; if ((errcode = fetch_last_req_info(&client, &reply_encpart.last_req))) { - status = "FETCH_LAST_REQ"; - goto errout; + status = "FETCH_LAST_REQ"; + goto errout; } reply_encpart.nonce = request->nonce; reply_encpart.key_exp = client.expiration; @@ -533,54 +534,54 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, /* Fetch the padata info to be returned (do this before authdata to handle possible replacement of reply key */ errcode = return_padata(kdc_context, &client, req_pkt, request, - &reply, client_key, &client_keyblock, &pa_context); + &reply, client_key, &client_keyblock, &pa_context); if (errcode) { - status = "KDC_RETURN_PADATA"; - goto errout; + status = "KDC_RETURN_PADATA"; + goto errout; } #if APPLE_PKINIT - asReqDebug("process_as_req reply realm %s name %s\n", - reply.client->realm.data, reply.client->data->data); + asReqDebug("process_as_req reply realm %s name %s\n", + reply.client->realm.data, reply.client->data->data); #endif /* APPLE_PKINIT */ errcode = return_svr_referral_data(kdc_context, - &server, &reply_encpart); + &server, &reply_encpart); if (errcode) { - status = "KDC_RETURN_ENC_PADATA"; - goto errout; + status = "KDC_RETURN_ENC_PADATA"; + goto errout; } - + errcode = handle_authdata(kdc_context, - c_flags, - &client, - &server, - &server, - &client_keyblock, - &server_keyblock, - &server_keyblock, - req_pkt, - request, - NULL, /* for_user_princ */ - NULL, /* enc_tkt_request */ - &enc_tkt_reply); + c_flags, + &client, + &server, + &server, + &client_keyblock, + &server_keyblock, + &server_keyblock, + req_pkt, + request, + NULL, /* for_user_princ */ + NULL, /* enc_tkt_request */ + &enc_tkt_reply); if (errcode) { - krb5_klog_syslog(LOG_INFO, "AS_REQ : handle_authdata (%d)", errcode); - status = "HANDLE_AUTHDATA"; - goto errout; + krb5_klog_syslog(LOG_INFO, "AS_REQ : handle_authdata (%d)", errcode); + status = "HANDLE_AUTHDATA"; + goto errout; } errcode = krb5_encrypt_tkt_part(kdc_context, &server_keyblock, &ticket_reply); if (errcode) { - status = "ENCRYPTING_TICKET"; - goto errout; + status = "ENCRYPTING_TICKET"; + goto errout; } ticket_reply.enc_part.kvno = server_key->key_data_kvno; errcode = kdc_fast_response_handle_padata(state, request, &reply, client_keyblock.enctype); if (errcode) { - status = "fast response handling"; - goto errout; + status = "fast response handling"; + goto errout; } /* now encode/encrypt the response */ @@ -589,24 +590,24 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, errcode = kdc_fast_handle_reply_key(state, &client_keyblock, &as_encrypting_key); if (errcode) { - status = "generating reply key"; - goto errout; + status = "generating reply key"; + goto errout; } - errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart, - 0, as_encrypting_key, &reply, response); + errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart, + 0, as_encrypting_key, &reply, response); reply.enc_part.kvno = client_key->key_data_kvno; if (errcode) { - status = "ENCODE_KDC_REP"; - goto errout; + status = "ENCODE_KDC_REP"; + goto errout; } - + /* these parts are left on as a courtesy from krb5_encode_kdc_rep so we can use them in raw form if needed. But, we don't... */ memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length); free(reply.enc_part.ciphertext.data); log_as_req(from, request, &reply, &client, cname, &server, sname, - authtime, 0, 0, 0); + authtime, 0, 0, 0); did_log = 1; goto egress; @@ -617,56 +618,56 @@ errout: egress: if (pa_context) - free_padata_context(kdc_context, &pa_context); + free_padata_context(kdc_context, &pa_context); if (as_encrypting_key) - krb5_free_keyblock(kdc_context, as_encrypting_key); + krb5_free_keyblock(kdc_context, as_encrypting_key); if (errcode) - emsg = krb5_get_error_message(kdc_context, errcode); + emsg = krb5_get_error_message(kdc_context, errcode); if (status) { - log_as_req(from, request, &reply, &client, cname, &server, sname, - authtime, status, errcode, emsg); - did_log = 1; + log_as_req(from, request, &reply, &client, cname, &server, sname, + authtime, status, errcode, emsg); + did_log = 1; } if (errcode) { - if (status == 0) { - status = emsg; - } - errcode -= ERROR_TABLE_BASE_krb5; - if (errcode < 0 || errcode > 128) - errcode = KRB_ERR_GENERIC; - - errcode = prepare_error_as(state, request, errcode, &e_data, - c_nprincs ? client.princ : NULL, - response, status); - status = 0; + if (status == 0) { + status = emsg; + } + errcode -= ERROR_TABLE_BASE_krb5; + if (errcode < 0 || errcode > 128) + errcode = KRB_ERR_GENERIC; + + errcode = prepare_error_as(state, request, errcode, &e_data, + c_nprincs ? client.princ : NULL, + response, status); + status = 0; } if (emsg) - krb5_free_error_message(kdc_context, emsg); + krb5_free_error_message(kdc_context, emsg); if (enc_tkt_reply.authorization_data != NULL) - krb5_free_authdata(kdc_context, enc_tkt_reply.authorization_data); + krb5_free_authdata(kdc_context, enc_tkt_reply.authorization_data); if (server_keyblock.contents != NULL) - krb5_free_keyblock_contents(kdc_context, &server_keyblock); + krb5_free_keyblock_contents(kdc_context, &server_keyblock); if (client_keyblock.contents != NULL) - krb5_free_keyblock_contents(kdc_context, &client_keyblock); + krb5_free_keyblock_contents(kdc_context, &client_keyblock); if (reply.padata != NULL) - krb5_free_pa_data(kdc_context, reply.padata); + krb5_free_pa_data(kdc_context, reply.padata); if (cname != NULL) - free(cname); + free(cname); if (sname != NULL) - free(sname); + free(sname); if (c_nprincs) - krb5_db_free_principal(kdc_context, &client, c_nprincs); + krb5_db_free_principal(kdc_context, &client, c_nprincs); if (s_nprincs) - krb5_db_free_principal(kdc_context, &server, s_nprincs); + krb5_db_free_principal(kdc_context, &server, s_nprincs); if (session_key.contents != NULL) - krb5_free_keyblock_contents(kdc_context, &session_key); + krb5_free_keyblock_contents(kdc_context, &session_key); if (ticket_reply.enc_part.ciphertext.data != NULL) { - memset(ticket_reply.enc_part.ciphertext.data , 0, - ticket_reply.enc_part.ciphertext.length); - free(ticket_reply.enc_part.ciphertext.data); + memset(ticket_reply.enc_part.ciphertext.data , 0, + ticket_reply.enc_part.ciphertext.length); + free(ticket_reply.enc_part.ciphertext.data); } krb5_free_data_contents(kdc_context, &e_data); @@ -679,8 +680,8 @@ egress: static krb5_error_code prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request, int error, krb5_data *e_data, - krb5_principal canon_client, krb5_data **response, - const char *status) + krb5_principal canon_client, krb5_data **response, + const char *status) { krb5_error errpkt; krb5_error_code retval; @@ -688,66 +689,66 @@ prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request, int e krb5_pa_data **pa = NULL; krb5_typed_data **td = NULL; size_t size; - + errpkt.ctime = request->nonce; errpkt.cusec = 0; if ((retval = krb5_us_timeofday(kdc_context, &errpkt.stime, - &errpkt.susec))) - return(retval); + &errpkt.susec))) + return(retval); errpkt.error = error; errpkt.server = request->server; if (error == KRB5KDC_ERR_WRONG_REALM) - errpkt.client = canon_client; + errpkt.client = canon_client; else - errpkt.client = request->client; + errpkt.client = request->client; errpkt.text.length = strlen(status) + 1; if (!(errpkt.text.data = strdup(status))) - return ENOMEM; + return ENOMEM; if (!(scratch = (krb5_data *)malloc(sizeof(*scratch)))) { - free(errpkt.text.data); - return ENOMEM; + free(errpkt.text.data); + return ENOMEM; } if (e_data != NULL&& e_data->data != NULL) { - errpkt.e_data = *e_data; + errpkt.e_data = *e_data; } else { - errpkt.e_data.length = 0; - errpkt.e_data.data = NULL; + errpkt.e_data.length = 0; + errpkt.e_data.data = NULL; } /*We need to try and produce a padata sequence for FAST*/ retval = decode_krb5_padata_sequence(e_data, &pa); if (retval != 0) { - retval = decode_krb5_typed_data(e_data, &td); - if (retval == 0) { - for (size =0; td[size]; size++); - pa = calloc(size+1, sizeof(*pa)); - if (pa == NULL) - retval = ENOMEM; - else for (size = 0; td[size]; size++) { - krb5_pa_data *pad = malloc(sizeof(krb5_pa_data )); - if (pad == NULL) { - retval = ENOMEM; - break; - } - pad->pa_type = td[size]->type; - pad->contents = td[size]->data; - pad->length = td[size]->length; - pa[size] = pad; - } - krb5_free_typed_data(kdc_context, td); - } + retval = decode_krb5_typed_data(e_data, &td); + if (retval == 0) { + for (size =0; td[size]; size++); + pa = calloc(size+1, sizeof(*pa)); + if (pa == NULL) + retval = ENOMEM; + else for (size = 0; td[size]; size++) { + krb5_pa_data *pad = malloc(sizeof(krb5_pa_data )); + if (pad == NULL) { + retval = ENOMEM; + break; + } + pad->pa_type = td[size]->type; + pad->contents = td[size]->data; + pad->length = td[size]->length; + pa[size] = pad; + } + krb5_free_typed_data(kdc_context, td); + } } retval = kdc_fast_handle_error(kdc_context, rstate, - request, pa, &errpkt); + request, pa, &errpkt); if (retval == 0) - retval = krb5_mk_error(kdc_context, &errpkt, scratch); + retval = krb5_mk_error(kdc_context, &errpkt, scratch); free(errpkt.text.data); if (retval) - free(scratch); - else - *response = scratch; + free(scratch); + else + *response = scratch; krb5_free_pa_data(kdc_context, pa); return retval; } diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 103a29f..24e32df 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/do_tgs_req.c * @@ -8,7 +9,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -22,7 +23,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * KDC Routines to deal with TGS_REQ's */ @@ -71,11 +72,11 @@ #include "adm_proto.h" #include <ctype.h> -static void +static void find_alternate_tgs(krb5_kdc_req *,krb5_db_entry *, krb5_boolean *,int *); -static krb5_error_code +static krb5_error_code prepare_error_tgs(struct kdc_request_state *, krb5_kdc_req *,krb5_ticket *,int, krb5_principal,krb5_data **,const char *, krb5_data *); @@ -152,7 +153,7 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, &krbtgt, &k_nprincs, &tgskey, &subkey, &pa_tgs_req); if (header_ticket && header_ticket->enc_part2 && - (errcode2 = krb5_unparse_name(kdc_context, + (errcode2 = krb5_unparse_name(kdc_context, header_ticket->enc_part2->client, &cname))) { status = "UNPARSING CLIENT"; @@ -160,7 +161,7 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, goto cleanup; } limit_string(cname); - + if (errcode) { status = "PROCESS_TGS"; goto cleanup; @@ -173,18 +174,18 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, } errcode = kdc_make_rstate(&state); if (errcode !=0) { - status = "making state"; - goto cleanup; + status = "making state"; + goto cleanup; } scratch.length = pa_tgs_req->length; scratch.data = (char *) pa_tgs_req->contents; errcode = kdc_find_fast(&request, &scratch, subkey, header_ticket->enc_part2->session, state); if (errcode !=0) { - status = "kdc_find_fast"; - goto cleanup; + status = "kdc_find_fast"; + goto cleanup; } - - + + /* * Pointer to the encrypted part of the header ticket, which may be * replaced to point to the encrypted part of the evidence ticket @@ -192,7 +193,7 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, * special cases for constrained delegation. */ header_enc_tkt = header_ticket->enc_part2; - + /* * We've already dealt with the AP_REQ authentication, so we can * use header_ticket freely. The encrypted part (if any) has been @@ -240,8 +241,8 @@ tgt_again: 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) { - + 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); @@ -251,7 +252,7 @@ tgt_again: firstpass = 0; goto tgt_again; } - } + } krb5_db_free_principal(kdc_context, &server, nprincs); status = "UNKNOWN_SERVER"; errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; @@ -264,7 +265,7 @@ tgt_again: retval = krb5_copy_principal(kdc_context, krbtgt_princ, &(request->server)); if (!retval) { db_ref_done = TRUE; - if (sname != NULL) + if (sname != NULL) free(sname); goto ref_tgt_again; } @@ -282,11 +283,11 @@ tgt_again: status = "TIME_OF_DAY"; goto cleanup; } - + if ((retval = validate_tgs_request(request, server, header_ticket, kdc_time, &status, &e_data))) { - if (!status) - status = "UNKNOWN_REASON"; + if (!status) + status = "UNKNOWN_REASON"; errcode = retval + ERROR_TABLE_BASE_krb5; goto cleanup; } @@ -299,16 +300,16 @@ tgt_again: /* Check for protocol transition */ errcode = kdc_process_s4u2self_req(kdc_context, - request, - header_enc_tkt->client, + request, + header_enc_tkt->client, &server, - subkey, - header_enc_tkt->session, - kdc_time, + subkey, + header_enc_tkt->session, + kdc_time, &s4u_x509_user, - &client, - &c_nprincs, - &status); + &client, + &c_nprincs, + &status); if (errcode) goto cleanup; if (s4u_x509_user != NULL) @@ -316,7 +317,7 @@ tgt_again: /* * We pick the session keytype here.... - * + * * Some special care needs to be taken in the user-to-user * case, since we don't know what keytypes the application server * which is doing user-to-user authentication can support. We @@ -327,7 +328,7 @@ tgt_again: */ useenctype = 0; if (isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY | - KDC_OPT_CNAME_IN_ADDL_TKT)) { + KDC_OPT_CNAME_IN_ADDL_TKT)) { krb5_keyblock * st_sealing_key; krb5_kvno st_srv_kvno; krb5_enctype etype; @@ -348,14 +349,14 @@ tgt_again: goto cleanup; } errcode = krb5_decrypt_tkt_part(kdc_context, st_sealing_key, - request->second_ticket[st_idx]); + request->second_ticket[st_idx]); krb5_free_keyblock(kdc_context, st_sealing_key); if (errcode) { status = "2ND_TKT_DECRYPT"; krb5_db_free_principal(kdc_context, &st_client, st_nprincs); goto cleanup; } - + etype = request->second_ticket[st_idx]->enc_part2->session->enctype; if (!krb5_c_valid_enctype(etype)) { status = "BAD_ETYPE_IN_2ND_TKT"; @@ -363,7 +364,7 @@ tgt_again: krb5_db_free_principal(kdc_context, &st_client, st_nprincs); goto cleanup; } - + for (i = 0; i < request->nktypes; i++) { if (request->ktype[i] == etype) { useenctype = etype; @@ -386,7 +387,7 @@ tgt_again: setflag(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION); assert(krb5_is_tgs_principal(header_ticket->server)); - + /* From now on, use evidence ticket as header ticket */ header_enc_tkt = request->second_ticket[st_idx]->enc_part2; @@ -405,14 +406,14 @@ tgt_again: */ if ((useenctype == 0) && (useenctype = select_session_keytype(kdc_context, &server, - request->nktypes, - request->ktype)) == 0) { + request->nktypes, + request->ktype)) == 0) { /* unsupported ktype */ status = "BAD_ENCRYPTION_TYPE"; errcode = KRB5KDC_ERR_ETYPE_NOSUPP; goto cleanup; } - + errcode = krb5_c_make_random_key(kdc_context, useenctype, &session_key); if (errcode) { @@ -478,7 +479,7 @@ tgt_again: * S4U2Self in order for forwardable tickets to be returned. */ else if (!is_referral && - !isflagset(server.attributes, KRB5_KDB_OK_TO_AUTH_AS_DELEGATE)) + !isflagset(server.attributes, KRB5_KDB_OK_TO_AUTH_AS_DELEGATE)) clear(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE); } } @@ -490,7 +491,7 @@ tgt_again: enc_tkt_reply.caddrs = request->addresses; reply_encpart.caddrs = request->addresses; - } + } if (isflagset(header_enc_tkt->flags, TKT_FLG_FORWARDED)) setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDED); @@ -544,13 +545,13 @@ tgt_again: /* not a renew request */ enc_tkt_reply.times.starttime = kdc_time; - kdc_get_ticket_endtime(kdc_context, - enc_tkt_reply.times.starttime, - header_enc_tkt->times.endtime, - request->till, - &client, - &server, - &enc_tkt_reply.times.endtime); + kdc_get_ticket_endtime(kdc_context, + enc_tkt_reply.times.starttime, + header_enc_tkt->times.endtime, + request->till, + &client, + &server, + &enc_tkt_reply.times.endtime); if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) && (enc_tkt_reply.times.endtime < request->till) && @@ -558,7 +559,7 @@ tgt_again: setflag(request->kdc_options, KDC_OPT_RENEWABLE); request->rtime = min(request->till, header_enc_tkt->times.renew_till); - } + } } rtime = (request->rtime == 0) ? kdc_infinity : request->rtime; @@ -567,20 +568,20 @@ tgt_again: renewable ticket using a non-renewable ticket */ setflag(enc_tkt_reply.flags, TKT_FLG_RENEWABLE); enc_tkt_reply.times.renew_till = - min(rtime, - min(header_enc_tkt->times.renew_till, - enc_tkt_reply.times.starttime + - min(server.max_renewable_life, - max_renewable_life_for_realm))); + min(rtime, + min(header_enc_tkt->times.renew_till, + enc_tkt_reply.times.starttime + + min(server.max_renewable_life, + max_renewable_life_for_realm))); } else { enc_tkt_reply.times.renew_till = 0; } - + /* * Set authtime to be the same as header_ticket's */ enc_tkt_reply.times.authtime = header_enc_tkt->times.authtime; - + /* * Propagate the preauthentication flags through to the returned ticket. */ @@ -589,7 +590,7 @@ tgt_again: if (isflagset(header_enc_tkt->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) @@ -615,7 +616,7 @@ tgt_again: * Find the server key */ if ((errcode = krb5_dbe_find_enctype(kdc_context, &server, - -1, /* ignore keytype */ + -1, /* ignore keytype */ -1, /* Ignore salttype */ 0,/* Get highest kvno */ &server_key))) { @@ -646,7 +647,7 @@ tgt_again: /* convert server.key into a real key (it may be encrypted * in the database) */ if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, - mkey_ptr, + mkey_ptr, server_key, &encrypting_key, NULL))) { status = "DECRYPT_SERVER_KEY"; @@ -727,7 +728,7 @@ tgt_again: pkt, request, s4u_x509_user ? - s4u_x509_user->user_id.user : NULL, + s4u_x509_user->user_id.user : NULL, header_enc_tkt, &enc_tkt_reply); if (errcode) { @@ -746,7 +747,7 @@ tgt_again: } /* - * Only add the realm of the presented tgt to the transited list if + * Only add the realm of the presented tgt to the transited list if * it is different than the local realm (cross-realm) and it is different * than the realm of the client (since the realm of the client is already * implicitly part of the transited list and should not be explicitly @@ -774,20 +775,20 @@ tgt_again: enc_tkt_transited.tr_contents.length = 0; enc_tkt_reply.transited = enc_tkt_transited; if ((errcode = - add_to_transited(&header_enc_tkt->transited.tr_contents, - &enc_tkt_reply.transited.tr_contents, - header_ticket->server, - enc_tkt_reply.client, - request->server))) { - status = "ADD_TR_FAIL"; - goto cleanup; + add_to_transited(&header_enc_tkt->transited.tr_contents, + &enc_tkt_reply.transited.tr_contents, + header_ticket->server, + enc_tkt_reply.client, + request->server))) { + status = "ADD_TR_FAIL"; + goto cleanup; } newtransited = 1; } if (isflagset(c_flags, KRB5_KDB_FLAG_CROSS_REALM)) { errcode = validate_transit_path(kdc_context, header_enc_tkt->client, - &server, - (k_nprincs != 0) ? &krbtgt : NULL); + &server, + (k_nprincs != 0) ? &krbtgt : NULL); if (errcode) { status = "NON_TRANSITIVE"; goto cleanup; @@ -863,7 +864,7 @@ tgt_again: status = "2ND_TKT_MISMATCH"; goto cleanup; } - + ticket_kvno = 0; ticket_reply.enc_part.enctype = t2enc->session->enctype; st_idx++; @@ -872,7 +873,7 @@ tgt_again: } errcode = krb5_encrypt_tkt_part(kdc_context, &encrypting_key, - &ticket_reply); + &ticket_reply); if (!isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY)) krb5_free_keyblock_contents(kdc_context, &encrypting_key); if (errcode) { @@ -921,27 +922,27 @@ tgt_again: 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 */ reply.enc_part.enctype = subkey ? subkey->enctype : - header_ticket->enc_part2->session->enctype; + header_ticket->enc_part2->session->enctype; errcode = kdc_fast_response_handle_padata(state, request, &reply, - subkey?subkey->enctype:header_ticket->enc_part2->session->enctype); + subkey?subkey->enctype:header_ticket->enc_part2->session->enctype); if (errcode !=0 ) { - status = "Preparing FAST padata"; - goto cleanup; + status = "Preparing FAST padata"; + goto cleanup; } errcode =kdc_fast_handle_reply_key(state, subkey?subkey:header_ticket->enc_part2->session, &reply_key); if (errcode) { - status = "generating reply key"; - goto cleanup; + status = "generating reply key"; + goto cleanup; } - errcode = krb5_encode_kdc_rep(kdc_context, KRB5_TGS_REP, &reply_encpart, - subkey ? 1 : 0, - reply_key, - &reply, response); + errcode = krb5_encode_kdc_rep(kdc_context, KRB5_TGS_REP, &reply_encpart, + subkey ? 1 : 0, + reply_key, + &reply, response); if (errcode) { status = "ENCODE_KDC_REP"; } else { @@ -956,12 +957,12 @@ tgt_again: memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length); free(reply.enc_part.ciphertext.data); - + cleanup: assert(status != NULL); if (reply_key) - krb5_free_keyblock(kdc_context, reply_key); - if (errcode) + krb5_free_keyblock(kdc_context, reply_key); + if (errcode) emsg = krb5_get_error_message (kdc_context, errcode); log_tgs_req(from, request, &reply, cname, sname, altcname, authtime, c_flags, s4u_name, status, errcode, emsg); @@ -979,22 +980,22 @@ cleanup: errcode -= ERROR_TABLE_BASE_krb5; if (errcode < 0 || errcode > 128) errcode = KRB_ERR_GENERIC; - + retval = prepare_error_tgs(state, request, header_ticket, errcode, - nprincs ? server.princ : NULL, - response, status, &e_data); + nprincs ? server.princ : NULL, + response, status, &e_data); if (got_err) { krb5_free_error_message (kdc_context, status); status = 0; } } - + if (header_ticket != NULL) krb5_free_ticket(kdc_context, header_ticket); if (request != NULL) krb5_free_kdc_req(kdc_context, request); if (state) - kdc_free_rstate(state); + kdc_free_rstate(state); if (cname != NULL) free(cname); if (sname != NULL) @@ -1030,10 +1031,10 @@ cleanup: static krb5_error_code prepare_error_tgs (struct kdc_request_state *state, - krb5_kdc_req *request, krb5_ticket *ticket, int error, + krb5_kdc_req *request, krb5_ticket *ticket, int error, krb5_principal canon_server, krb5_data **response, const char *status, - krb5_data *e_data) + krb5_data *e_data) { krb5_error errpkt; krb5_error_code retval = 0; @@ -1043,7 +1044,7 @@ prepare_error_tgs (struct kdc_request_state *state, errpkt.cusec = 0; if ((retval = krb5_us_timeofday(kdc_context, &errpkt.stime, - &errpkt.susec))) + &errpkt.susec))) return(retval); errpkt.error = error; errpkt.server = request->server; @@ -1054,18 +1055,18 @@ prepare_error_tgs (struct kdc_request_state *state, errpkt.text.length = strlen(status) + 1; if (!(errpkt.text.data = strdup(status))) return ENOMEM; - + if (!(scratch = (krb5_data *)malloc(sizeof(*scratch)))) { free(errpkt.text.data); return ENOMEM; } errpkt.e_data = *e_data; if (state) - retval = kdc_fast_handle_error(kdc_context, state, request, NULL, &errpkt); + retval = kdc_fast_handle_error(kdc_context, state, request, NULL, &errpkt); if (retval) { - free(scratch); - free(errpkt.text.data); - return retval; + free(scratch); + free(errpkt.text.data); + return retval; } retval = krb5_mk_error(kdc_context, &errpkt, scratch); free(errpkt.text.data); @@ -1099,10 +1100,10 @@ find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server, * somewhere that has already checked the number of components in * the principal. */ - 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))) + 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; /* move to the end */ @@ -1113,8 +1114,8 @@ find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server, while (--pl2 > plist) { *nprincs = 1; tmp = *krb5_princ_realm(kdc_context, *pl2); - krb5_princ_set_realm(kdc_context, *pl2, - krb5_princ_realm(kdc_context, tgs_server)); + krb5_princ_set_realm(kdc_context, *pl2, + krb5_princ_realm(kdc_context, tgs_server)); retval = get_principal(kdc_context, *pl2, server, nprincs, more); krb5_princ_set_realm(kdc_context, *pl2, &tmp); if (retval) { @@ -1131,12 +1132,12 @@ find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server, krb5_principal tmpprinc; tmp = *krb5_princ_realm(kdc_context, *pl2); - krb5_princ_set_realm(kdc_context, *pl2, - krb5_princ_realm(kdc_context, tgs_server)); + krb5_princ_set_realm(kdc_context, *pl2, + krb5_princ_realm(kdc_context, tgs_server)); if ((retval = krb5_copy_principal(kdc_context, *pl2, &tmpprinc))) { - krb5_db_free_principal(kdc_context, server, *nprincs); - krb5_princ_set_realm(kdc_context, *pl2, &tmp); - continue; + krb5_db_free_principal(kdc_context, server, *nprincs); + krb5_princ_set_realm(kdc_context, *pl2, &tmp); + continue; } krb5_princ_set_realm(kdc_context, *pl2, &tmp); @@ -1157,54 +1158,54 @@ find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server, } static krb5_int32 -prep_reprocess_req(krb5_kdc_req *request, krb5_principal *krbtgt_princ) +prep_reprocess_req(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; + krb5_data *comp1 = NULL, *comp2 = NULL; + char *comp1_str = NULL; /* By now we know that server principal name is unknown. - * If CANONICALIZE flag is set in the request - * If req is not U2U authn. req - * the requested server princ. has exactly two components - * either - * the name type is NT-SRV-HST - * or name type is NT-UNKNOWN and - * the 1st component is listed in conf file under host_based_services - * the 1st component is not in a list in conf under "no_host_referral" - * the 2d component looks like fully-qualified domain name (FQDN) - * If all of these conditions are satisfied - try mapping the FQDN and + * If CANONICALIZE flag is set in the request + * If req is not U2U authn. req + * the requested server princ. has exactly two components + * either + * the name type is NT-SRV-HST + * or name type is NT-UNKNOWN and + * the 1st component is listed in conf file under host_based_services + * the 1st component is not in a list in conf under "no_host_referral" + * the 2d component looks like fully-qualified domain name (FQDN) + * If all of these conditions are satisfied - try mapping the FQDN and * re-process the request as if client had asked for cross-realm TGT. */ - if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) && - !isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) && - krb5_princ_size(kdc_context, request->server) == 2) { + if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) && + !isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) && + krb5_princ_size(kdc_context, request->server) == 2) { comp1 = krb5_princ_component(kdc_context, request->server, 0); comp2 = krb5_princ_component(kdc_context, request->server, 1); comp1_str = calloc(1,comp1->length+1); if (!comp1_str) { - retval = ENOMEM; - goto cleanup; - } + retval = ENOMEM; + goto cleanup; + } strlcpy(comp1_str,comp1->data,comp1->length+1); - if ((krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_HST || - (krb5_princ_type(kdc_context, request->server) == KRB5_NT_UNKNOWN && - kdc_active_realm->realm_host_based_services != NULL && - (krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, comp1_str) == TRUE || - krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, KRB5_CONF_ASTERISK) == TRUE))) && - (kdc_active_realm->realm_no_host_referral == NULL || - (krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, KRB5_CONF_ASTERISK) == FALSE && - krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, comp1_str) == FALSE))) { - - if (memchr(comp2->data, '.', comp2->length) == NULL) - goto cleanup; + if ((krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_HST || + (krb5_princ_type(kdc_context, request->server) == KRB5_NT_UNKNOWN && + kdc_active_realm->realm_host_based_services != NULL && + (krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, comp1_str) == TRUE || + krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, KRB5_CONF_ASTERISK) == TRUE))) && + (kdc_active_realm->realm_no_host_referral == NULL || + (krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, KRB5_CONF_ASTERISK) == FALSE && + krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, comp1_str) == FALSE))) { + + if (memchr(comp2->data, '.', comp2->length) == NULL) + goto cleanup; temp_buf = calloc(1, comp2->length+1); if (!temp_buf){ - retval = ENOMEM; + retval = ENOMEM; goto cleanup; } strlcpy(temp_buf, comp2->data,comp2->length+1); @@ -1224,21 +1225,19 @@ prep_reprocess_req(krb5_kdc_req *request, krb5_principal *krbtgt_princ) retval = KRB5KRB_AP_ERR_BADMATCH; goto cleanup; } - /* Modify request. - * Construct cross-realm tgt : krbtgt/REMOTE_REALM@LOCAL_REALM - * and use it as a principal in this req. + /* Modify request. + * Construct cross-realm tgt : krbtgt/REMOTE_REALM@LOCAL_REALM + * and use it as a principal in this req. */ - retval = krb5_build_principal(kdc_context, krbtgt_princ, - (*request->server).realm.length, - (*request->server).realm.data, + retval = krb5_build_principal(kdc_context, krbtgt_princ, + (*request->server).realm.length, + (*request->server).realm.data, "krbtgt", realms[0], (char *)0); - for (cpp = realms; *cpp; cpp++) - free(*cpp); + for (cpp = realms; *cpp; cpp++) + free(*cpp); } } cleanup: free(comp1_str); return retval; } - - diff --git a/src/kdc/extern.c b/src/kdc/extern.c index 7ebc7bb..763adf5 100644 --- a/src/kdc/extern.c +++ b/src/kdc/extern.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/extern.c * @@ -7,7 +8,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -21,7 +22,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * allocations of extern stuff */ @@ -31,14 +32,14 @@ #include "extern.h" /* real declarations of KDC's externs */ -kdc_realm_t **kdc_realmlist = (kdc_realm_t **) NULL; -int kdc_numrealms = 0; -kdc_realm_t *kdc_active_realm = (kdc_realm_t *) NULL; +kdc_realm_t **kdc_realmlist = (kdc_realm_t **) NULL; +int kdc_numrealms = 0; +kdc_realm_t *kdc_active_realm = (kdc_realm_t *) NULL; krb5_data empty_string = {0, 0, ""}; krb5_timestamp kdc_infinity = KRB5_INT32_MAX; /* XXX */ -krb5_rcache kdc_rcache = (krb5_rcache) NULL; -krb5_keyblock psr_key; -krb5_int32 max_dgram_reply_size = MAX_DGRAM_SIZE; +krb5_rcache kdc_rcache = (krb5_rcache) NULL; +krb5_keyblock psr_key; +krb5_int32 max_dgram_reply_size = MAX_DGRAM_SIZE; -volatile int signal_requests_exit = 0; /* gets set when signal hits */ +volatile int signal_requests_exit = 0; /* gets set when signal hits */ volatile int signal_requests_hup = 0; /* ditto */ diff --git a/src/kdc/extern.h b/src/kdc/extern.h index 079f0e4..af5b308 100644 --- a/src/kdc/extern.h +++ b/src/kdc/extern.h @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/extern.h * @@ -7,7 +8,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -21,7 +22,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * <<< Description >>> */ @@ -33,52 +34,52 @@ typedef struct __kdc_realm_data { /* * General Kerberos per-realm data. */ - char * realm_name; /* Realm name */ -/* XXX the real context should go away once the db_context is done. - * The db_context is then associated with the realm keytab using - * krb5_ktkdb_resolv(). There should be nothing in the context which + char * realm_name; /* Realm name */ +/* XXX the real context should go away once the db_context is done. + * The db_context is then associated with the realm keytab using + * krb5_ktkdb_resolv(). There should be nothing in the context which * cannot span multiple realms -- proven */ - krb5_context realm_context; /* Context to be used for realm */ - krb5_keytab realm_keytab; /* keytab to be used for this realm */ - char * realm_profile; /* Profile file for this realm */ - char * realm_host_based_services; /* do referral processing for these services + krb5_context realm_context; /* Context to be used for realm */ + krb5_keytab realm_keytab; /* keytab to be used for this realm */ + char * realm_profile; /* Profile file for this realm */ + char * realm_host_based_services; /* do referral processing for these services * If '*' - allow all referrals */ char * realm_no_host_referral; /* no referral for these services. - * If '*' - disallow all referrals and + * If '*' - disallow all referrals and * ignore realm_host_based_services */ /* * Database per-realm data. */ - char * realm_dbname; /* Database name for realm */ - char * realm_stash; /* Stash file name for realm */ - char * realm_mpname; /* Master principal name for realm */ - krb5_principal realm_mprinc; /* Master principal for realm */ + char * realm_dbname; /* Database name for realm */ + char * realm_stash; /* Stash file name for realm */ + char * realm_mpname; /* Master principal name for realm */ + krb5_principal realm_mprinc; /* Master principal for realm */ /* * Note realm_mkey is mkey read from stash or keyboard and may not be the * latest. The mkey_list will have all the mkeys in use. */ - krb5_keyblock realm_mkey; /* Master key for this realm */ - krb5_keylist_node * mkey_list; /* list of mkeys in use for this realm */ + krb5_keyblock realm_mkey; /* Master key for this realm */ + krb5_keylist_node * mkey_list; /* list of mkeys in use for this realm */ /* * TGS per-realm data. */ - krb5_principal realm_tgsprinc; /* TGS principal for this realm */ + krb5_principal realm_tgsprinc; /* TGS principal for this realm */ /* * Other per-realm data. */ - char *realm_ports; /* Per-realm KDC UDP port */ - char *realm_tcp_ports; /* Per-realm KDC TCP port */ + char *realm_ports; /* Per-realm KDC UDP port */ + char *realm_tcp_ports; /* Per-realm KDC TCP port */ /* * Per-realm parameters. */ - krb5_deltat realm_maxlife; /* Maximum ticket life for realm */ - krb5_deltat realm_maxrlife; /* Maximum renewable life for realm */ - krb5_boolean realm_reject_bad_transit; /* Accept unverifiable transited_realm ? */ + krb5_deltat realm_maxlife; /* Maximum ticket life for realm */ + krb5_deltat realm_maxrlife; /* Maximum renewable life for realm */ + krb5_boolean realm_reject_bad_transit; /* Accept unverifiable transited_realm ? */ } kdc_realm_t; -extern kdc_realm_t **kdc_realmlist; -extern int kdc_numrealms; -extern kdc_realm_t *kdc_active_realm; +extern kdc_realm_t **kdc_realmlist; +extern int kdc_numrealms; +extern kdc_realm_t *kdc_active_realm; kdc_realm_t *find_realm_data (char *, krb5_ui_4); @@ -87,25 +88,25 @@ kdc_realm_t *find_realm_data (char *, krb5_ui_4); * realm data. This allows us to support multiple realms with minimal logic * changes. */ -#define kdc_context kdc_active_realm->realm_context -#define max_life_for_realm kdc_active_realm->realm_maxlife -#define max_renewable_life_for_realm kdc_active_realm->realm_maxrlife -#define master_keyblock kdc_active_realm->realm_mkey -#define master_keylist kdc_active_realm->mkey_list -#define master_princ kdc_active_realm->realm_mprinc -#define tgs_server kdc_active_realm->realm_tgsprinc -#define reject_bad_transit kdc_active_realm->realm_reject_bad_transit +#define kdc_context kdc_active_realm->realm_context +#define max_life_for_realm kdc_active_realm->realm_maxlife +#define max_renewable_life_for_realm kdc_active_realm->realm_maxrlife +#define master_keyblock kdc_active_realm->realm_mkey +#define master_keylist kdc_active_realm->mkey_list +#define master_princ kdc_active_realm->realm_mprinc +#define tgs_server kdc_active_realm->realm_tgsprinc +#define reject_bad_transit kdc_active_realm->realm_reject_bad_transit /* various externs for KDC */ -extern krb5_data empty_string; /* an empty string */ -extern krb5_timestamp kdc_infinity; /* greater than all other timestamps */ -extern krb5_rcache kdc_rcache; /* replay cache */ -extern krb5_keyblock psr_key; /* key for predicted sam response */ -extern const int kdc_modifies_kdb; -extern char **db_args; -extern krb5_int32 max_dgram_reply_size; /* maximum datagram size */ +extern krb5_data empty_string; /* an empty string */ +extern krb5_timestamp kdc_infinity; /* greater than all other timestamps */ +extern krb5_rcache kdc_rcache; /* replay cache */ +extern krb5_keyblock psr_key; /* key for predicted sam response */ +extern const int kdc_modifies_kdb; +extern char **db_args; +extern krb5_int32 max_dgram_reply_size; /* maximum datagram size */ -extern const int vague_errors; +extern const int vague_errors; extern volatile int signal_requests_exit; extern volatile int signal_requests_hup; diff --git a/src/kdc/fast_util.c b/src/kdc/fast_util.c index f02410b..f7a1ac4 100644 --- a/src/kdc/fast_util.c +++ b/src/kdc/fast_util.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/fast_util.c * @@ -8,7 +9,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -22,8 +23,8 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * - * + * + * * */ @@ -49,49 +50,49 @@ static krb5_error_code armor_ap_request krb5_auth_context authcontext = NULL; krb5_ticket *ticket = NULL; krb5_keyblock *subkey = NULL; - + assert(armor->armor_type == KRB5_FAST_ARMOR_AP_REQUEST); krb5_clear_error_message(kdc_context); retval = krb5_auth_con_init(kdc_context, &authcontext); if (retval == 0) - retval = krb5_auth_con_setflags(kdc_context, authcontext, 0); /*disable replay cache*/ + retval = krb5_auth_con_setflags(kdc_context, authcontext, 0); /*disable replay cache*/ retval = krb5_rd_req(kdc_context, &authcontext, - &armor->armor_value, NULL /*server*/, - kdc_active_realm->realm_keytab, NULL, &ticket); + &armor->armor_value, NULL /*server*/, + kdc_active_realm->realm_keytab, NULL, &ticket); if (retval !=0) { - const char * errmsg = krb5_get_error_message(kdc_context, retval); - krb5_set_error_message(kdc_context, retval, - "%s while handling ap-request armor", errmsg); - krb5_free_error_message(kdc_context, errmsg); + const char * errmsg = krb5_get_error_message(kdc_context, retval); + krb5_set_error_message(kdc_context, retval, + "%s while handling ap-request armor", errmsg); + krb5_free_error_message(kdc_context, errmsg); } if (retval == 0) { - if (!krb5_principal_compare_any_realm(kdc_context, - tgs_server, - ticket->server)) { - krb5_set_error_message(kdc_context, KRB5KDC_ERR_SERVER_NOMATCH, - "ap-request armor for something other than the local TGS"); - retval = KRB5KDC_ERR_SERVER_NOMATCH; - } + if (!krb5_principal_compare_any_realm(kdc_context, + tgs_server, + ticket->server)) { + krb5_set_error_message(kdc_context, KRB5KDC_ERR_SERVER_NOMATCH, + "ap-request armor for something other than the local TGS"); + retval = KRB5KDC_ERR_SERVER_NOMATCH; + } } if (retval ==0) { - retval = krb5_auth_con_getrecvsubkey(kdc_context, authcontext, &subkey); - if (retval !=0 || subkey == NULL) { - krb5_set_error_message(kdc_context, KRB5KDC_ERR_POLICY, - "ap-request armor without subkey"); - retval = KRB5KDC_ERR_POLICY; - } + retval = krb5_auth_con_getrecvsubkey(kdc_context, authcontext, &subkey); + if (retval !=0 || subkey == NULL) { + krb5_set_error_message(kdc_context, KRB5KDC_ERR_POLICY, + "ap-request armor without subkey"); + retval = KRB5KDC_ERR_POLICY; + } } - if (retval==0) - retval = krb5_c_fx_cf2_simple(kdc_context, - subkey, "subkeyarmor", - ticket->enc_part2->session, "ticketarmor", - &state->armor_key); + if (retval==0) + retval = krb5_c_fx_cf2_simple(kdc_context, + subkey, "subkeyarmor", + ticket->enc_part2->session, "ticketarmor", + &state->armor_key); if (ticket) - krb5_free_ticket(kdc_context, ticket); + krb5_free_ticket(kdc_context, ticket); if (subkey) - krb5_free_keyblock(kdc_context, subkey); + krb5_free_keyblock(kdc_context, subkey); if (authcontext) - krb5_auth_con_free(kdc_context, authcontext); + krb5_auth_con_free(kdc_context, authcontext); return retval; } @@ -104,22 +105,22 @@ static krb5_error_code encrypt_fast_reply krb5_data *encoded_response = NULL; assert(state->armor_key); retval = encode_krb5_fast_response(response, &encoded_response); - if (retval== 0) - retval = krb5_encrypt_helper(kdc_context, state->armor_key, - KRB5_KEYUSAGE_FAST_REP, - encoded_response, &encrypted_reply); + if (retval== 0) + retval = krb5_encrypt_helper(kdc_context, state->armor_key, + KRB5_KEYUSAGE_FAST_REP, + encoded_response, &encrypted_reply); if (encoded_response) - krb5_free_data(kdc_context, encoded_response); + krb5_free_data(kdc_context, encoded_response); encoded_response = NULL; if (retval == 0) { - retval = encode_krb5_pa_fx_fast_reply(&encrypted_reply, - fx_fast_reply); - krb5_free_data_contents(kdc_context, &encrypted_reply.ciphertext); + retval = encode_krb5_pa_fx_fast_reply(&encrypted_reply, + fx_fast_reply); + krb5_free_data_contents(kdc_context, &encrypted_reply.ciphertext); } return retval; } - + krb5_error_code kdc_find_fast (krb5_kdc_req **requestptr, krb5_data *checksummed_data, krb5_keyblock *tgs_subkey, @@ -139,115 +140,115 @@ krb5_error_code kdc_find_fast krb5_clear_error_message(kdc_context); memset(&empty_keyblock, 0, sizeof(krb5_keyblock)); fast_padata = find_pa_data(request->padata, - KRB5_PADATA_FX_FAST); + KRB5_PADATA_FX_FAST); if (fast_padata != NULL){ - scratch.length = fast_padata->length; - scratch.data = (char *) fast_padata->contents; - retval = decode_krb5_pa_fx_fast_request(&scratch, &fast_armored_req); - if (retval == 0 &&fast_armored_req->armor) { - switch (fast_armored_req->armor->armor_type) { - case KRB5_FAST_ARMOR_AP_REQUEST: - retval = armor_ap_request(state, fast_armored_req->armor); - break; - default: - krb5_set_error_message(kdc_context, KRB5KDC_ERR_PREAUTH_FAILED, - "Unknow FAST armor type %d", - fast_armored_req->armor->armor_type); - retval = KRB5KDC_ERR_PREAUTH_FAILED; - } - } - if (retval == 0 && !state->armor_key) { - if (tgs_subkey) - retval = krb5_c_fx_cf2_simple(kdc_context, - tgs_subkey, "subkeyarmor", - tgs_session, "ticketarmor", - &state->armor_key); - else { - krb5_set_error_message(kdc_context, KRB5KDC_ERR_PREAUTH_FAILED, - "No armor key but FAST armored request present"); - retval = KRB5KDC_ERR_PREAUTH_FAILED; - } - } - if (retval == 0) { - krb5_data plaintext; - plaintext.length = fast_armored_req->enc_part.ciphertext.length; - plaintext.data = malloc(plaintext.length); - if (plaintext.data == NULL) - retval = ENOMEM; - retval = krb5_c_decrypt(kdc_context, - state->armor_key, - KRB5_KEYUSAGE_FAST_ENC, NULL, - &fast_armored_req->enc_part, - &plaintext); - if (retval == 0) - retval = decode_krb5_fast_req(&plaintext, &fast_req); - if (plaintext.data) - free(plaintext.data); - } - if (retval == 0) - retval = krb5_c_verify_checksum(kdc_context, state->armor_key, - KRB5_KEYUSAGE_FAST_REQ_CHKSUM, - checksummed_data, &fast_armored_req->req_checksum, - &cksum_valid); - if (retval == 0 && !cksum_valid) { - retval = KRB5KRB_AP_ERR_MODIFIED; - krb5_set_error_message(kdc_context, KRB5KRB_AP_ERR_MODIFIED, - "FAST req_checksum invalid; request modified"); - } - if (retval == 0) { - krb5_error_code ret; - /* We need to confirm that a keyed checksum is used for the - * fast_req checksum. In April 2009, the best way to do this is - * to try verifying the checksum with a keyblock with an zero - * length; if it succeeds, then an unkeyed checksum is used.*/ - ret = krb5_c_verify_checksum(kdc_context, &empty_keyblock, - KRB5_KEYUSAGE_FAST_REQ_CHKSUM, - checksummed_data, &fast_armored_req->req_checksum, - &cksum_valid); - if (ret == 0) { - retval = KRB5KDC_ERR_POLICY; - krb5_set_error_message(kdc_context, KRB5KDC_ERR_POLICY, - "Unkeyed checksum used in fast_req"); - } - } - if (retval == 0) { - if ((fast_req->fast_options & UNSUPPORTED_CRITICAL_FAST_OPTIONS) !=0) - retval = KRB5KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTION; - } - if (retval == 0) - cookie_padata = find_pa_data(fast_req->req_body->padata, KRB5_PADATA_FX_COOKIE); - if (retval == 0) { - state->fast_options = fast_req->fast_options; - if (request->kdc_state == state) - request->kdc_state = NULL; - krb5_free_kdc_req( kdc_context, request); - *requestptr = fast_req->req_body; - fast_req->req_body = NULL; - - } + scratch.length = fast_padata->length; + scratch.data = (char *) fast_padata->contents; + retval = decode_krb5_pa_fx_fast_request(&scratch, &fast_armored_req); + if (retval == 0 &&fast_armored_req->armor) { + switch (fast_armored_req->armor->armor_type) { + case KRB5_FAST_ARMOR_AP_REQUEST: + retval = armor_ap_request(state, fast_armored_req->armor); + break; + default: + krb5_set_error_message(kdc_context, KRB5KDC_ERR_PREAUTH_FAILED, + "Unknow FAST armor type %d", + fast_armored_req->armor->armor_type); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + } + } + if (retval == 0 && !state->armor_key) { + if (tgs_subkey) + retval = krb5_c_fx_cf2_simple(kdc_context, + tgs_subkey, "subkeyarmor", + tgs_session, "ticketarmor", + &state->armor_key); + else { + krb5_set_error_message(kdc_context, KRB5KDC_ERR_PREAUTH_FAILED, + "No armor key but FAST armored request present"); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + } + } + if (retval == 0) { + krb5_data plaintext; + plaintext.length = fast_armored_req->enc_part.ciphertext.length; + plaintext.data = malloc(plaintext.length); + if (plaintext.data == NULL) + retval = ENOMEM; + retval = krb5_c_decrypt(kdc_context, + state->armor_key, + KRB5_KEYUSAGE_FAST_ENC, NULL, + &fast_armored_req->enc_part, + &plaintext); + if (retval == 0) + retval = decode_krb5_fast_req(&plaintext, &fast_req); + if (plaintext.data) + free(plaintext.data); + } + if (retval == 0) + retval = krb5_c_verify_checksum(kdc_context, state->armor_key, + KRB5_KEYUSAGE_FAST_REQ_CHKSUM, + checksummed_data, &fast_armored_req->req_checksum, + &cksum_valid); + if (retval == 0 && !cksum_valid) { + retval = KRB5KRB_AP_ERR_MODIFIED; + krb5_set_error_message(kdc_context, KRB5KRB_AP_ERR_MODIFIED, + "FAST req_checksum invalid; request modified"); + } + if (retval == 0) { + krb5_error_code ret; + /* We need to confirm that a keyed checksum is used for the + * fast_req checksum. In April 2009, the best way to do this is + * to try verifying the checksum with a keyblock with an zero + * length; if it succeeds, then an unkeyed checksum is used.*/ + ret = krb5_c_verify_checksum(kdc_context, &empty_keyblock, + KRB5_KEYUSAGE_FAST_REQ_CHKSUM, + checksummed_data, &fast_armored_req->req_checksum, + &cksum_valid); + if (ret == 0) { + retval = KRB5KDC_ERR_POLICY; + krb5_set_error_message(kdc_context, KRB5KDC_ERR_POLICY, + "Unkeyed checksum used in fast_req"); + } + } + if (retval == 0) { + if ((fast_req->fast_options & UNSUPPORTED_CRITICAL_FAST_OPTIONS) !=0) + retval = KRB5KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTION; + } + if (retval == 0) + cookie_padata = find_pa_data(fast_req->req_body->padata, KRB5_PADATA_FX_COOKIE); + if (retval == 0) { + state->fast_options = fast_req->fast_options; + if (request->kdc_state == state) + request->kdc_state = NULL; + krb5_free_kdc_req( kdc_context, request); + *requestptr = fast_req->req_body; + fast_req->req_body = NULL; + + } } else cookie_padata = find_pa_data(request->padata, KRB5_PADATA_FX_COOKIE); - if (retval == 0 && cookie_padata != NULL) { - krb5_pa_data *new_padata = malloc(sizeof (krb5_pa_data)); - if (new_padata == NULL) { - retval = ENOMEM; - } else { - new_padata->pa_type = KRB5_PADATA_FX_COOKIE; - new_padata->length = cookie_padata->length; - new_padata->contents = malloc(new_padata->length); - if (new_padata->contents == NULL) { - retval = ENOMEM; - free(new_padata); - } else { - memcpy(new_padata->contents, cookie_padata->contents, new_padata->length); - state->cookie = new_padata; - } - } + if (retval == 0 && cookie_padata != NULL) { + krb5_pa_data *new_padata = malloc(sizeof (krb5_pa_data)); + if (new_padata == NULL) { + retval = ENOMEM; + } else { + new_padata->pa_type = KRB5_PADATA_FX_COOKIE; + new_padata->length = cookie_padata->length; + new_padata->contents = malloc(new_padata->length); + if (new_padata->contents == NULL) { + retval = ENOMEM; + free(new_padata); + } else { + memcpy(new_padata->contents, cookie_padata->contents, new_padata->length); + state->cookie = new_padata; + } + } } - if (fast_req) - krb5_free_fast_req( kdc_context, fast_req); + if (fast_req) + krb5_free_fast_req( kdc_context, fast_req); if (fast_armored_req) - krb5_free_fast_armored_req(kdc_context, fast_armored_req); + krb5_free_fast_armored_req(kdc_context, fast_armored_req); return retval; } @@ -256,7 +257,7 @@ krb5_error_code kdc_make_rstate(struct kdc_request_state **out) { struct kdc_request_state *state = malloc( sizeof(struct kdc_request_state)); if (state == NULL) - return ENOMEM; + return ENOMEM; memset( state, 0, sizeof(struct kdc_request_state)); *out = state; return 0; @@ -265,15 +266,15 @@ krb5_error_code kdc_make_rstate(struct kdc_request_state **out) void kdc_free_rstate (struct kdc_request_state *s) { - if (s == NULL) - return; + if (s == NULL) + return; if (s->armor_key) - krb5_free_keyblock(kdc_context, s->armor_key); + krb5_free_keyblock(kdc_context, s->armor_key); if (s->strengthen_key) - krb5_free_keyblock(kdc_context, s->strengthen_key); + krb5_free_keyblock(kdc_context, s->strengthen_key); if (s->cookie) { - free(s->cookie->contents); - free(s->cookie); + free(s->cookie->contents); + free(s->cookie); } free(s); } @@ -292,70 +293,70 @@ krb5_error_code kdc_fast_response_handle_padata krb5_cksumtype cksumtype = CKSUMTYPE_RSA_MD5; krb5_pa_data *empty_padata[] = {NULL}; krb5_keyblock *strengthen_key = NULL; - + if (!state->armor_key) - return 0; + return 0; memset(&finish, 0, sizeof(finish)); retval = krb5_init_keyblock(kdc_context, enctype, 0, &strengthen_key); if (retval == 0) - retval = krb5_c_make_random_key(kdc_context, enctype, strengthen_key); + retval = krb5_c_make_random_key(kdc_context, enctype, strengthen_key); if (retval == 0) { - state->strengthen_key = strengthen_key; - strengthen_key = NULL; + state->strengthen_key = strengthen_key; + strengthen_key = NULL; } - + fast_response.padata = rep->padata; if (fast_response.padata == NULL) - fast_response.padata = &empty_padata[0]; - fast_response.strengthen_key = state->strengthen_key; + fast_response.padata = &empty_padata[0]; + fast_response.strengthen_key = state->strengthen_key; fast_response.nonce = request->nonce; fast_response.finished = &finish; finish.client = rep->client; pa_array = calloc(3, sizeof(*pa_array)); if (pa_array == NULL) - retval = ENOMEM; + retval = ENOMEM; pa = calloc(1, sizeof(krb5_pa_data)); if (retval == 0 && pa == NULL) - retval = ENOMEM; + retval = ENOMEM; if (retval == 0) - retval = krb5_us_timeofday(kdc_context, &finish.timestamp, &finish.usec); + retval = krb5_us_timeofday(kdc_context, &finish.timestamp, &finish.usec); if (retval == 0) - retval = encode_krb5_ticket(rep->ticket, &encoded_ticket); + retval = encode_krb5_ticket(rep->ticket, &encoded_ticket); if (retval == 0) - retval = krb5int_c_mandatory_cksumtype(kdc_context, state->armor_key->enctype, &cksumtype); + retval = krb5int_c_mandatory_cksumtype(kdc_context, state->armor_key->enctype, &cksumtype); if (retval == 0) - retval = krb5_c_make_checksum(kdc_context, cksumtype, - state->armor_key, KRB5_KEYUSAGE_FAST_FINISHED, - encoded_ticket, &finish.ticket_checksum); + retval = krb5_c_make_checksum(kdc_context, cksumtype, + state->armor_key, KRB5_KEYUSAGE_FAST_FINISHED, + encoded_ticket, &finish.ticket_checksum); if (retval == 0) - retval = encrypt_fast_reply(state, &fast_response, &encrypted_reply); + retval = encrypt_fast_reply(state, &fast_response, &encrypted_reply); if (retval == 0) { - pa[0].pa_type = KRB5_PADATA_FX_FAST; - pa[0].length = encrypted_reply->length; - pa[0].contents = (unsigned char *) encrypted_reply->data; - pa_array[0] = &pa[0]; - rep->padata = pa_array; - pa_array = NULL; - free(encrypted_reply); - encrypted_reply = NULL; - pa = NULL; + pa[0].pa_type = KRB5_PADATA_FX_FAST; + pa[0].length = encrypted_reply->length; + pa[0].contents = (unsigned char *) encrypted_reply->data; + pa_array[0] = &pa[0]; + rep->padata = pa_array; + pa_array = NULL; + free(encrypted_reply); + encrypted_reply = NULL; + pa = NULL; } if (pa) - free(pa); + free(pa); if (pa_array) - free(pa_array); + free(pa_array); if (encrypted_reply) - krb5_free_data(kdc_context, encrypted_reply); + krb5_free_data(kdc_context, encrypted_reply); if (encoded_ticket) - krb5_free_data(kdc_context, encoded_ticket); + krb5_free_data(kdc_context, encoded_ticket); if (strengthen_key != NULL) - krb5_free_keyblock(kdc_context, strengthen_key); + krb5_free_keyblock(kdc_context, strengthen_key); if (finish.ticket_checksum.contents) - krb5_free_checksum_contents(kdc_context, &finish.ticket_checksum); + krb5_free_checksum_contents(kdc_context, &finish.ticket_checksum); return retval; } - + /* * We assume the caller is responsible for passing us an in_padata * sufficient to include in a FAST error. In the FAST case we will @@ -379,7 +380,7 @@ krb5_error_code kdc_fast_handle_error memset(outer_pa, 0, sizeof(outer_pa)); if (!state->armor_key) - return 0; + return 0; fx_error = *err; fx_error.e_data.data = NULL; fx_error.e_data.length = 0; @@ -387,76 +388,76 @@ krb5_error_code kdc_fast_handle_error size +=3; inner_pa = calloc(size, sizeof(krb5_pa_data *)); if (inner_pa == NULL) - retval = ENOMEM; + retval = ENOMEM; if (retval == 0) - for (size=0; in_padata&&in_padata[size]; size++) - inner_pa[size] = in_padata[size]; + for (size=0; in_padata&&in_padata[size]; size++) + inner_pa[size] = in_padata[size]; if (retval == 0) - retval = encode_krb5_error(&fx_error, &encoded_fx_error); + retval = encode_krb5_error(&fx_error, &encoded_fx_error); if (retval == 0) { - pa[0].pa_type = KRB5_PADATA_FX_ERROR; - pa[0].length = encoded_fx_error->length; - pa[0].contents = (unsigned char *) encoded_fx_error->data; - inner_pa[size++] = &pa[0]; - if (find_pa_data(inner_pa, KRB5_PADATA_FX_COOKIE) == NULL) - retval = kdc_preauth_get_cookie(state, &cookie); + pa[0].pa_type = KRB5_PADATA_FX_ERROR; + pa[0].length = encoded_fx_error->length; + pa[0].contents = (unsigned char *) encoded_fx_error->data; + inner_pa[size++] = &pa[0]; + if (find_pa_data(inner_pa, KRB5_PADATA_FX_COOKIE) == NULL) + retval = kdc_preauth_get_cookie(state, &cookie); } if (cookie != NULL) - inner_pa[size++] = cookie; + inner_pa[size++] = cookie; if (retval == 0) { - resp.padata = inner_pa; - resp.nonce = request->nonce; - resp.strengthen_key = NULL; - resp.finished = NULL; + resp.padata = inner_pa; + resp.nonce = request->nonce; + resp.strengthen_key = NULL; + resp.finished = NULL; } if (retval == 0) - retval = encrypt_fast_reply(state, &resp, &encrypted_reply); + retval = encrypt_fast_reply(state, &resp, &encrypted_reply); if (inner_pa) - free(inner_pa); /*contained storage from caller and our stack*/ + free(inner_pa); /*contained storage from caller and our stack*/ if (cookie) { - free(cookie->contents); - free(cookie); - cookie = NULL; + free(cookie->contents); + free(cookie); + cookie = NULL; } if (retval == 0) { - pa[0].pa_type = KRB5_PADATA_FX_FAST; - pa[0].length = encrypted_reply->length; - pa[0].contents = (unsigned char *) encrypted_reply->data; - outer_pa[0] = &pa[0]; + pa[0].pa_type = KRB5_PADATA_FX_FAST; + pa[0].length = encrypted_reply->length; + pa[0].contents = (unsigned char *) encrypted_reply->data; + outer_pa[0] = &pa[0]; } retval = encode_krb5_padata_sequence(outer_pa, &encoded_e_data); if (retval == 0) { - /*process_as holds onto a pointer to the original e_data and frees it*/ - err->e_data = *encoded_e_data; - free(encoded_e_data); /*contents belong to err*/ - encoded_e_data = NULL; + /*process_as holds onto a pointer to the original e_data and frees it*/ + err->e_data = *encoded_e_data; + free(encoded_e_data); /*contents belong to err*/ + encoded_e_data = NULL; } if (encoded_e_data) - krb5_free_data(kdc_context, encoded_e_data); + krb5_free_data(kdc_context, encoded_e_data); if (encrypted_reply) - krb5_free_data(kdc_context, encrypted_reply); + krb5_free_data(kdc_context, encrypted_reply); if (encoded_fx_error) - krb5_free_data(kdc_context, encoded_fx_error); + krb5_free_data(kdc_context, encoded_fx_error); return retval; } krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state, - krb5_keyblock *existing_key, - krb5_keyblock **out_key) + krb5_keyblock *existing_key, + krb5_keyblock **out_key) { krb5_error_code retval = 0; if (state->armor_key) - retval = krb5_c_fx_cf2_simple(kdc_context, - state->strengthen_key, "strengthenkey", - existing_key, - "replykey", out_key); + retval = krb5_c_fx_cf2_simple(kdc_context, + state->strengthen_key, "strengthenkey", + existing_key, + "replykey", out_key); else retval = krb5_copy_keyblock(kdc_context, existing_key, out_key); return retval; } krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state, - krb5_pa_data **cookie) + krb5_pa_data **cookie) { char *contents; krb5_pa_data *pa = NULL; @@ -469,11 +470,11 @@ krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state, */ contents = strdup("MIT"); if (contents == NULL) - return ENOMEM; + return ENOMEM; pa = calloc(1, sizeof(krb5_pa_data)); if (pa == NULL) { - free(contents); - return ENOMEM; + free(contents); + return ENOMEM; } pa->pa_type = KRB5_PADATA_FX_COOKIE; pa->length = strlen(contents); diff --git a/src/kdc/kdc_authdata.c b/src/kdc/kdc_authdata.c index 4ccfcb9..e6d4bd2 100644 --- a/src/kdc/kdc_authdata.c +++ b/src/kdc/kdc_authdata.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/kdc_authdata.c * @@ -8,7 +9,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -22,7 +23,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * AuthorizationData routines for the KDC. */ @@ -45,74 +46,74 @@ static const char *objdirs[] = { LIBDIR "/krb5/plugins/authdata", NULL }; /* MIT Kerberos 1.6 (V0) authdata plugin callback */ typedef krb5_error_code (*authdata_proc_0) - (krb5_context, krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_enc_tkt_part * enc_tkt_reply); +(krb5_context, krb5_db_entry *client, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_enc_tkt_part * enc_tkt_reply); /* MIT Kerberos 1.8 (V2) authdata plugin callback */ typedef krb5_error_code (*authdata_proc_2) - (krb5_context, unsigned int flags, - krb5_db_entry *client, krb5_db_entry *server, - krb5_db_entry *krbtgt, - krb5_keyblock *client_key, - krb5_keyblock *server_key, - krb5_keyblock *krbtgt_key, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_const_principal for_user_princ, - krb5_enc_tkt_part *enc_tkt_request, - krb5_enc_tkt_part *enc_tkt_reply); +(krb5_context, unsigned int flags, + krb5_db_entry *client, krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *krbtgt_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply); typedef krb5_error_code (*init_proc) - (krb5_context, void **); +(krb5_context, void **); typedef void (*fini_proc) - (krb5_context, void *); +(krb5_context, void *); /* Internal authdata system for copying TGS-REQ authdata to ticket */ static krb5_error_code handle_request_authdata - (krb5_context context, - unsigned int flags, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_db_entry *krbtgt, - krb5_keyblock *client_key, - krb5_keyblock *server_key, - krb5_keyblock *krbtgt_key, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_const_principal for_user_princ, - krb5_enc_tkt_part *enc_tkt_request, - krb5_enc_tkt_part *enc_tkt_reply); +(krb5_context context, + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *krbtgt_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply); /* Internal authdata system for handling KDC-issued authdata */ static krb5_error_code handle_tgt_authdata - (krb5_context context, - unsigned int flags, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_db_entry *krbtgt, - krb5_keyblock *client_key, - krb5_keyblock *server_key, - krb5_keyblock *krbtgt_key, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_const_principal for_user_princ, - krb5_enc_tkt_part *enc_tkt_request, - krb5_enc_tkt_part *enc_tkt_reply); +(krb5_context context, + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *krbtgt_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply); typedef struct _krb5_authdata_systems { const char *name; -#define AUTHDATA_SYSTEM_UNKNOWN -1 -#define AUTHDATA_SYSTEM_V0 0 -#define AUTHDATA_SYSTEM_V2 2 +#define AUTHDATA_SYSTEM_UNKNOWN -1 +#define AUTHDATA_SYSTEM_V0 0 +#define AUTHDATA_SYSTEM_V2 2 int type; -#define AUTHDATA_FLAG_CRITICAL 0x1 +#define AUTHDATA_FLAG_CRITICAL 0x1 int flags; void *plugin_context; init_proc init; fini_proc fini; union { - authdata_proc_2 v2; - authdata_proc_0 v0; + authdata_proc_2 v2; + authdata_proc_0 v0; } handle_authdata; } krb5_authdata_systems; @@ -139,10 +140,10 @@ load_authdata_plugins(krb5_context context) /* Attempt to load all of the authdata plugins we can find. */ PLUGIN_DIR_INIT(&authdata_plugins); if (PLUGIN_DIR_OPEN(&authdata_plugins) == 0) { - if (krb5int_open_plugin_dirs(objdirs, NULL, - &authdata_plugins, &context->err) != 0) { - return KRB5_PLUGIN_NO_HANDLE; - } + if (krb5int_open_plugin_dirs(objdirs, NULL, + &authdata_plugins, &context->err) != 0) { + return KRB5_PLUGIN_NO_HANDLE; + } } /* Get the method tables provided by the loaded plugins. */ @@ -151,141 +152,141 @@ load_authdata_plugins(krb5_context context) n_authdata_systems = 0; if (krb5int_get_plugin_dir_data(&authdata_plugins, - "authdata_server_2", - &authdata_plugins_ftables_v2, &context->err) != 0 || - krb5int_get_plugin_dir_data(&authdata_plugins, - "authdata_server_0", - &authdata_plugins_ftables_v0, &context->err) != 0) { - code = KRB5_PLUGIN_NO_HANDLE; - goto cleanup; + "authdata_server_2", + &authdata_plugins_ftables_v2, &context->err) != 0 || + krb5int_get_plugin_dir_data(&authdata_plugins, + "authdata_server_0", + &authdata_plugins_ftables_v0, &context->err) != 0) { + code = KRB5_PLUGIN_NO_HANDLE; + goto cleanup; } - /* Count the valid modules. */ + /* Count the valid modules. */ module_count = 0; if (authdata_plugins_ftables_v2 != NULL) { - struct krb5plugin_authdata_server_ftable_v2 *ftable; + struct krb5plugin_authdata_server_ftable_v2 *ftable; - for (i = 0; authdata_plugins_ftables_v2[i] != NULL; i++) { - ftable = authdata_plugins_ftables_v2[i]; - if (ftable->authdata_proc != NULL) - module_count++; - } + for (i = 0; authdata_plugins_ftables_v2[i] != NULL; i++) { + ftable = authdata_plugins_ftables_v2[i]; + if (ftable->authdata_proc != NULL) + module_count++; + } } - + if (authdata_plugins_ftables_v0 != NULL) { - struct krb5plugin_authdata_server_ftable_v0 *ftable; + struct krb5plugin_authdata_server_ftable_v0 *ftable; - for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) { - ftable = authdata_plugins_ftables_v0[i]; - if (ftable->authdata_proc != NULL) - module_count++; - } + for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) { + ftable = authdata_plugins_ftables_v0[i]; + if (ftable->authdata_proc != NULL) + module_count++; + } } module_count += sizeof(static_authdata_systems) - / sizeof(static_authdata_systems[0]); + / sizeof(static_authdata_systems[0]); /* Build the complete list of supported authdata options, and * leave room for a terminator entry. */ authdata_systems = calloc(module_count + 1, sizeof(krb5_authdata_systems)); if (authdata_systems == NULL) { - code = ENOMEM; - goto cleanup; + code = ENOMEM; + goto cleanup; } k = 0; /* Add dynamically loaded V2 plugins */ if (authdata_plugins_ftables_v2 != NULL) { - struct krb5plugin_authdata_server_ftable_v2 *ftable; - - for (i = 0; authdata_plugins_ftables_v2[i] != NULL; i++) { - krb5_error_code initerr; - void *pctx = NULL; - - ftable = authdata_plugins_ftables_v2[i]; - if ((ftable->authdata_proc == NULL)) { - continue; - } - server_init_proc = ftable->init_proc; - if ((server_init_proc != NULL) && - ((initerr = (*server_init_proc)(context, &pctx)) != 0)) { - const char *emsg; - emsg = krb5_get_error_message(context, initerr); - if (emsg) { - krb5_klog_syslog(LOG_ERR, - "authdata %s failed to initialize: %s", - ftable->name, emsg); - krb5_free_error_message(context, emsg); - } - memset(&authdata_systems[k], 0, sizeof(authdata_systems[k])); - - continue; - } - - authdata_systems[k].name = ftable->name; - authdata_systems[k].type = AUTHDATA_SYSTEM_V2; - authdata_systems[k].init = server_init_proc; - authdata_systems[k].fini = ftable->fini_proc; - authdata_systems[k].handle_authdata.v2 = ftable->authdata_proc; - authdata_systems[k].plugin_context = pctx; - k++; - } + struct krb5plugin_authdata_server_ftable_v2 *ftable; + + for (i = 0; authdata_plugins_ftables_v2[i] != NULL; i++) { + krb5_error_code initerr; + void *pctx = NULL; + + ftable = authdata_plugins_ftables_v2[i]; + if ((ftable->authdata_proc == NULL)) { + continue; + } + server_init_proc = ftable->init_proc; + if ((server_init_proc != NULL) && + ((initerr = (*server_init_proc)(context, &pctx)) != 0)) { + const char *emsg; + emsg = krb5_get_error_message(context, initerr); + if (emsg) { + krb5_klog_syslog(LOG_ERR, + "authdata %s failed to initialize: %s", + ftable->name, emsg); + krb5_free_error_message(context, emsg); + } + memset(&authdata_systems[k], 0, sizeof(authdata_systems[k])); + + continue; + } + + authdata_systems[k].name = ftable->name; + authdata_systems[k].type = AUTHDATA_SYSTEM_V2; + authdata_systems[k].init = server_init_proc; + authdata_systems[k].fini = ftable->fini_proc; + authdata_systems[k].handle_authdata.v2 = ftable->authdata_proc; + authdata_systems[k].plugin_context = pctx; + k++; + } } /* Add dynamically loaded V0 plugins */ if (authdata_plugins_ftables_v0 != NULL) { - struct krb5plugin_authdata_server_ftable_v0 *ftable; - - for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) { - krb5_error_code initerr; - void *pctx = NULL; - - ftable = authdata_plugins_ftables_v0[i]; - if ((ftable->authdata_proc == NULL)) { - continue; - } - server_init_proc = ftable->init_proc; - if ((server_init_proc != NULL) && - ((initerr = (*server_init_proc)(context, &pctx)) != 0)) { - const char *emsg; - emsg = krb5_get_error_message(context, initerr); - if (emsg) { - krb5_klog_syslog(LOG_ERR, - "authdata %s failed to initialize: %s", - ftable->name, emsg); - krb5_free_error_message(context, emsg); - } - memset(&authdata_systems[k], 0, sizeof(authdata_systems[k])); - - continue; - } - - authdata_systems[k].name = ftable->name; - authdata_systems[k].type = AUTHDATA_SYSTEM_V0; - authdata_systems[k].init = server_init_proc; - authdata_systems[k].fini = ftable->fini_proc; - authdata_systems[k].handle_authdata.v0 = ftable->authdata_proc; - authdata_systems[k].plugin_context = pctx; - k++; - } + struct krb5plugin_authdata_server_ftable_v0 *ftable; + + for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) { + krb5_error_code initerr; + void *pctx = NULL; + + ftable = authdata_plugins_ftables_v0[i]; + if ((ftable->authdata_proc == NULL)) { + continue; + } + server_init_proc = ftable->init_proc; + if ((server_init_proc != NULL) && + ((initerr = (*server_init_proc)(context, &pctx)) != 0)) { + const char *emsg; + emsg = krb5_get_error_message(context, initerr); + if (emsg) { + krb5_klog_syslog(LOG_ERR, + "authdata %s failed to initialize: %s", + ftable->name, emsg); + krb5_free_error_message(context, emsg); + } + memset(&authdata_systems[k], 0, sizeof(authdata_systems[k])); + + continue; + } + + authdata_systems[k].name = ftable->name; + authdata_systems[k].type = AUTHDATA_SYSTEM_V0; + authdata_systems[k].init = server_init_proc; + authdata_systems[k].fini = ftable->fini_proc; + authdata_systems[k].handle_authdata.v0 = ftable->authdata_proc; + authdata_systems[k].plugin_context = pctx; + k++; + } } /* Add the locally-supplied mechanisms to the dynamic list first. */ for (i = 0; - i < sizeof(static_authdata_systems) / sizeof(static_authdata_systems[0]); - i++) { - authdata_systems[k] = static_authdata_systems[i]; - /* Try to initialize the authdata system. If it fails, we'll remove it - * from the list of systems we'll be using. */ - server_init_proc = static_authdata_systems[i].init; - if ((server_init_proc != NULL) && - ((*server_init_proc)(context, &authdata_systems[k].plugin_context) != 0)) { - memset(&authdata_systems[k], 0, sizeof(authdata_systems[k])); - continue; - } - k++; + i < sizeof(static_authdata_systems) / sizeof(static_authdata_systems[0]); + i++) { + authdata_systems[k] = static_authdata_systems[i]; + /* Try to initialize the authdata system. If it fails, we'll remove it + * from the list of systems we'll be using. */ + server_init_proc = static_authdata_systems[i].init; + if ((server_init_proc != NULL) && + ((*server_init_proc)(context, &authdata_systems[k].plugin_context) != 0)) { + memset(&authdata_systems[k], 0, sizeof(authdata_systems[k])); + continue; + } + k++; } n_authdata_systems = k; @@ -296,9 +297,9 @@ load_authdata_plugins(krb5_context context) cleanup: if (authdata_plugins_ftables_v2 != NULL) - krb5int_free_plugin_dir_data(authdata_plugins_ftables_v2); + krb5int_free_plugin_dir_data(authdata_plugins_ftables_v2); if (authdata_plugins_ftables_v0 != NULL) - krb5int_free_plugin_dir_data(authdata_plugins_ftables_v0); + krb5int_free_plugin_dir_data(authdata_plugins_ftables_v0); return code; } @@ -308,17 +309,17 @@ unload_authdata_plugins(krb5_context context) { int i; if (authdata_systems != NULL) { - for (i = 0; i < n_authdata_systems; i++) { - if (authdata_systems[i].fini != NULL) { - (*authdata_systems[i].fini)(context, - authdata_systems[i].plugin_context); - } - memset(&authdata_systems[i], 0, sizeof(authdata_systems[i])); - } - free(authdata_systems); - authdata_systems = NULL; - n_authdata_systems = 0; - krb5int_close_plugin_dirs(&authdata_plugins); + for (i = 0; i < n_authdata_systems; i++) { + if (authdata_systems[i].fini != NULL) { + (*authdata_systems[i].fini)(context, + authdata_systems[i].plugin_context); + } + memset(&authdata_systems[i], 0, sizeof(authdata_systems[i])); + } + free(authdata_systems); + authdata_systems = NULL; + n_authdata_systems = 0; + krb5int_close_plugin_dirs(&authdata_plugins); } return 0; } @@ -326,46 +327,46 @@ unload_authdata_plugins(krb5_context context) /* Merge authdata. If copy == 0, in_authdata is invalid on return */ static krb5_error_code merge_authdata (krb5_context context, - krb5_authdata **in_authdata, - krb5_authdata ***out_authdata, - krb5_boolean copy) + krb5_authdata **in_authdata, + krb5_authdata ***out_authdata, + krb5_boolean copy) { size_t i, nadata = 0; krb5_authdata **authdata = *out_authdata; if (in_authdata == NULL || in_authdata[0] == NULL) - return 0; + return 0; if (authdata != NULL) { - for (nadata = 0; authdata[nadata] != NULL; nadata++) - ; + for (nadata = 0; authdata[nadata] != NULL; nadata++) + ; } for (i = 0; in_authdata[i] != NULL; i++) - ; + ; if (authdata == NULL) { - authdata = (krb5_authdata **)calloc(i + 1, sizeof(krb5_authdata *)); + authdata = (krb5_authdata **)calloc(i + 1, sizeof(krb5_authdata *)); } else { - authdata = (krb5_authdata **)realloc(authdata, - ((nadata + i + 1) * sizeof(krb5_authdata *))); + authdata = (krb5_authdata **)realloc(authdata, + ((nadata + i + 1) * sizeof(krb5_authdata *))); } if (authdata == NULL) - return ENOMEM; + return ENOMEM; if (copy) { - krb5_error_code code; - krb5_authdata **tmp; + krb5_error_code code; + krb5_authdata **tmp; - code = krb5_copy_authdata(context, in_authdata, &tmp); - if (code != 0) - return code; + code = krb5_copy_authdata(context, in_authdata, &tmp); + if (code != 0) + return code; - in_authdata = tmp; + in_authdata = tmp; } for (i = 0; in_authdata[i] != NULL; i++) - authdata[nadata + i] = in_authdata[i]; + authdata[nadata + i] = in_authdata[i]; authdata[nadata + i] = NULL; @@ -379,32 +380,32 @@ merge_authdata (krb5_context context, /* Handle copying TGS-REQ authorization data into reply */ static krb5_error_code handle_request_authdata (krb5_context context, - unsigned int flags, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_db_entry *krbtgt, - krb5_keyblock *client_key, - krb5_keyblock *server_key, + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, krb5_keyblock *krbtgt_key, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_const_principal for_user_princ, - krb5_enc_tkt_part *enc_tkt_request, - krb5_enc_tkt_part *enc_tkt_reply) + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply) { krb5_error_code code; krb5_data scratch; if (request->msg_type != KRB5_TGS_REQ || - request->authorization_data.ciphertext.data == NULL) - return 0; + request->authorization_data.ciphertext.data == NULL) + return 0; assert(enc_tkt_request != NULL); scratch.length = request->authorization_data.ciphertext.length; scratch.data = malloc(scratch.length); if (scratch.data == NULL) - return ENOMEM; + return ENOMEM; /* * RFC 4120 requires authdata in the TGS body to be encrypted in @@ -418,34 +419,34 @@ handle_request_authdata (krb5_context context, * fails. */ code = krb5_c_decrypt(context, - enc_tkt_request->session, - KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY, - 0, &request->authorization_data, - &scratch); + enc_tkt_request->session, + KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY, + 0, &request->authorization_data, + &scratch); if (code != 0) - code = krb5_c_decrypt(context, - client_key, - KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY, - 0, &request->authorization_data, - &scratch); + code = krb5_c_decrypt(context, + client_key, + KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY, + 0, &request->authorization_data, + &scratch); if (code != 0) { - free(scratch.data); - return code; + free(scratch.data); + return code; } /* scratch now has the authorization data, so we decode it, and make * it available to subsequent authdata plugins */ code = decode_krb5_authdata(&scratch, &request->unenc_authdata); if (code != 0) { - free(scratch.data); - return code; + free(scratch.data); + return code; } free(scratch.data); code = merge_authdata(context, request->unenc_authdata, - &enc_tkt_reply->authorization_data, TRUE /* copy */); + &enc_tkt_reply->authorization_data, TRUE /* copy */); return code; } @@ -453,18 +454,18 @@ handle_request_authdata (krb5_context context, /* Handle backend-managed authorization data */ static krb5_error_code handle_tgt_authdata (krb5_context context, - unsigned int flags, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_db_entry *krbtgt, - krb5_keyblock *client_key, - krb5_keyblock *server_key, - krb5_keyblock *krbtgt_key, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_const_principal for_user_princ, - krb5_enc_tkt_part *enc_tkt_request, - krb5_enc_tkt_part *enc_tkt_reply) + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *krbtgt_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply) { krb5_error_code code; krb5_authdata **db_authdata = NULL; @@ -488,19 +489,19 @@ handle_tgt_authdata (krb5_context context, * for cross-realm protocol transition below). */ if (tgs_req) { - assert(enc_tkt_request != NULL); + assert(enc_tkt_request != NULL); - if (isflagset(server->attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED)) - return 0; + if (isflagset(server->attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED)) + return 0; - if (enc_tkt_request->authorization_data == NULL && - !isflagset(flags, KRB5_KDB_FLAG_CROSS_REALM | KRB5_KDB_FLAGS_S4U)) - return 0; + if (enc_tkt_request->authorization_data == NULL && + !isflagset(flags, KRB5_KDB_FLAG_CROSS_REALM | KRB5_KDB_FLAGS_S4U)) + return 0; - assert(enc_tkt_reply->times.authtime == enc_tkt_request->times.authtime); + assert(enc_tkt_reply->times.authtime == enc_tkt_request->times.authtime); } else { - if (!isflagset(flags, KRB5_KDB_FLAG_INCLUDE_PAC)) - return 0; + if (!isflagset(flags, KRB5_KDB_FLAG_INCLUDE_PAC)) + return 0; } /* @@ -509,9 +510,9 @@ handle_tgt_authdata (krb5_context context, * not be changed until the final hop. */ if (isflagset(flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) - actual_client = for_user_princ; + actual_client = for_user_princ; else - actual_client = enc_tkt_reply->client; + actual_client = enc_tkt_reply->client; /* * If the backend does not implement the sign authdata method, then @@ -524,37 +525,37 @@ handle_tgt_authdata (krb5_context context, * to influence (eg. possibly restrict) the reply auth data. */ code = sign_db_authdata(context, - flags, - actual_client, - client, - server, - krbtgt, - client_key, - server_key, /* U2U or server key */ - krbtgt_key, - enc_tkt_reply->times.authtime, - tgs_req ? enc_tkt_request->authorization_data : NULL, - enc_tkt_reply->session, - &db_authdata); + flags, + actual_client, + client, + server, + krbtgt, + client_key, + server_key, /* U2U or server key */ + krbtgt_key, + enc_tkt_reply->times.authtime, + tgs_req ? enc_tkt_request->authorization_data : NULL, + enc_tkt_reply->session, + &db_authdata); if (code == KRB5_KDB_DBTYPE_NOSUP) { - assert(db_authdata == NULL); + assert(db_authdata == NULL); - if (isflagset(flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) - return KRB5KDC_ERR_POLICY; + if (isflagset(flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) + return KRB5KDC_ERR_POLICY; - if (tgs_req) - return merge_authdata(context, enc_tkt_request->authorization_data, - &enc_tkt_reply->authorization_data, TRUE); - else - return 0; + if (tgs_req) + return merge_authdata(context, enc_tkt_request->authorization_data, + &enc_tkt_reply->authorization_data, TRUE); + else + return 0; } if (db_authdata != NULL) { - code = merge_authdata(context, db_authdata, - &enc_tkt_reply->authorization_data, - FALSE); - if (code != 0) - krb5_free_authdata(context, db_authdata); + code = merge_authdata(context, db_authdata, + &enc_tkt_reply->authorization_data, + FALSE); + if (code != 0) + krb5_free_authdata(context, db_authdata); } return code; @@ -562,60 +563,59 @@ handle_tgt_authdata (krb5_context context, krb5_error_code handle_authdata (krb5_context context, - unsigned int flags, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_db_entry *krbtgt, - krb5_keyblock *client_key, - krb5_keyblock *server_key, - krb5_keyblock *krbtgt_key, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_const_principal for_user_princ, - krb5_enc_tkt_part *enc_tkt_request, - krb5_enc_tkt_part *enc_tkt_reply) + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *krbtgt_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply) { krb5_error_code code = 0; int i; for (i = 0; i < n_authdata_systems; i++) { - const krb5_authdata_systems *asys = &authdata_systems[i]; - - switch (asys->type) { - case AUTHDATA_SYSTEM_V0: - /* V0 was only in AS-REQ code path */ - if (request->msg_type != KRB5_AS_REQ) - continue; - - code = (*asys->handle_authdata.v0)(context, client, req_pkt, - request, enc_tkt_reply); - break; - case AUTHDATA_SYSTEM_V2: - code = (*asys->handle_authdata.v2)(context, flags, - client, server, krbtgt, - client_key, server_key, krbtgt_key, - req_pkt, request, for_user_princ, - enc_tkt_request, - enc_tkt_reply); - break; - default: - code = 0; - break; - } - if (code != 0) { - const char *emsg; - - emsg = krb5_get_error_message (context, code); - krb5_klog_syslog (LOG_INFO, - "authdata (%s) handling failure: %s", - asys->name, emsg); - krb5_free_error_message (context, emsg); - - if (asys->flags & AUTHDATA_FLAG_CRITICAL) - break; - } + const krb5_authdata_systems *asys = &authdata_systems[i]; + + switch (asys->type) { + case AUTHDATA_SYSTEM_V0: + /* V0 was only in AS-REQ code path */ + if (request->msg_type != KRB5_AS_REQ) + continue; + + code = (*asys->handle_authdata.v0)(context, client, req_pkt, + request, enc_tkt_reply); + break; + case AUTHDATA_SYSTEM_V2: + code = (*asys->handle_authdata.v2)(context, flags, + client, server, krbtgt, + client_key, server_key, krbtgt_key, + req_pkt, request, for_user_princ, + enc_tkt_request, + enc_tkt_reply); + break; + default: + code = 0; + break; + } + if (code != 0) { + const char *emsg; + + emsg = krb5_get_error_message (context, code); + krb5_klog_syslog (LOG_INFO, + "authdata (%s) handling failure: %s", + asys->name, emsg); + krb5_free_error_message (context, emsg); + + if (asys->flags & AUTHDATA_FLAG_CRITICAL) + break; + } } return code; } - diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index 2149fd1..1eda93b 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/kdc_preauth.c * @@ -8,7 +9,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -22,20 +23,20 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * Preauthentication routines for the KDC. */ /* * Copyright (C) 1998 by the FundsXpress, INC. - * + * * All rights reserved. - * + * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -46,7 +47,7 @@ * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. @@ -103,7 +104,7 @@ static const char *objdirs[] = { LIBDIR "/krb5/plugins/preauth", NULL }; /* XXX This is ugly and should be in a header file somewhere */ #ifndef KRB5INT_DES_TYPES_DEFINED #define KRB5INT_DES_TYPES_DEFINED -typedef unsigned char des_cblock[8]; /* crypto-block size */ +typedef unsigned char des_cblock[8]; /* crypto-block size */ #endif typedef des_cblock mit_des_cblock; extern void mit_des_fixup_key_parity (mit_des_cblock ); @@ -111,127 +112,127 @@ extern int mit_des_is_weak_key (mit_des_cblock ); typedef struct _krb5_preauth_systems { const char *name; - int type; - int flags; + int type; + int flags; void *plugin_context; - preauth_server_init_proc init; - preauth_server_fini_proc fini; - preauth_server_edata_proc get_edata; - preauth_server_verify_proc verify_padata; - preauth_server_return_proc return_padata; - preauth_server_free_reqcontext_proc free_pa_reqctx; + preauth_server_init_proc init; + preauth_server_fini_proc fini; + preauth_server_edata_proc get_edata; + preauth_server_verify_proc verify_padata; + preauth_server_return_proc return_padata; + preauth_server_free_reqcontext_proc free_pa_reqctx; } krb5_preauth_systems; static krb5_error_code verify_enc_timestamp - (krb5_context, krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_enc_tkt_part * enc_tkt_reply, krb5_pa_data *data, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - void **pa_request_context, - krb5_data **e_data, - krb5_authdata ***authz_data); +(krb5_context, krb5_db_entry *client, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_enc_tkt_part * enc_tkt_reply, krb5_pa_data *data, + preauth_get_entry_data_proc get_entry_data, + void *pa_system_context, + void **pa_request_context, + krb5_data **e_data, + krb5_authdata ***authz_data); static krb5_error_code get_enc_ts - (krb5_context, krb5_kdc_req *request, - krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - krb5_pa_data *data); +(krb5_context, krb5_kdc_req *request, + krb5_db_entry *client, krb5_db_entry *server, + preauth_get_entry_data_proc get_entry_data, + void *pa_system_context, + krb5_pa_data *data); static krb5_error_code get_etype_info - (krb5_context, krb5_kdc_req *request, - krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - krb5_pa_data *data); +(krb5_context, krb5_kdc_req *request, + krb5_db_entry *client, krb5_db_entry *server, + preauth_get_entry_data_proc get_entry_data, + void *pa_system_context, + krb5_pa_data *data); static krb5_error_code get_etype_info2(krb5_context context, krb5_kdc_req *request, - krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - krb5_pa_data *pa_data); + krb5_db_entry *client, krb5_db_entry *server, + preauth_get_entry_data_proc get_entry_data, + void *pa_system_context, + krb5_pa_data *pa_data); static krb5_error_code -etype_info_as_rep_helper(krb5_context context, krb5_pa_data * padata, - krb5_db_entry *client, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - int etype_info2); +etype_info_as_rep_helper(krb5_context context, krb5_pa_data * padata, + krb5_db_entry *client, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa, + int etype_info2); static krb5_error_code -return_etype_info(krb5_context, krb5_pa_data * padata, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - void **pa_request_context); +return_etype_info(krb5_context, krb5_pa_data * padata, + krb5_db_entry *client, + krb5_data *req_pkt, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa, + preauth_get_entry_data_proc get_entry_data, + void *pa_system_context, + void **pa_request_context); static krb5_error_code -return_etype_info2(krb5_context, krb5_pa_data * padata, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - void **pa_request_context); +return_etype_info2(krb5_context, krb5_pa_data * padata, + krb5_db_entry *client, + krb5_data *req_pkt, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa, + preauth_get_entry_data_proc get_entry_data, + void *pa_system_context, + void **pa_request_context); static krb5_error_code return_pw_salt - (krb5_context, krb5_pa_data * padata, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - preauth_get_entry_data_proc get_entry_data, - void *pa_system_context, - void **pa_request_context); +(krb5_context, krb5_pa_data * padata, + krb5_db_entry *client, + krb5_data *req_pkt, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa, + preauth_get_entry_data_proc get_entry_data, + void *pa_system_context, + void **pa_request_context); /* SAM preauth support */ static krb5_error_code verify_sam_response - (krb5_context, krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_enc_tkt_part * enc_tkt_reply, krb5_pa_data *data, - preauth_get_entry_data_proc get_entry_data, - void *pa_module_context, - void **pa_request_context, - krb5_data **e_data, - krb5_authdata ***authz_data); +(krb5_context, krb5_db_entry *client, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_enc_tkt_part * enc_tkt_reply, krb5_pa_data *data, + preauth_get_entry_data_proc get_entry_data, + void *pa_module_context, + void **pa_request_context, + krb5_data **e_data, + krb5_authdata ***authz_data); static krb5_error_code get_sam_edata - (krb5_context, krb5_kdc_req *request, - krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc get_entry_data, - void *pa_module_context, - krb5_pa_data *data); +(krb5_context, krb5_kdc_req *request, + krb5_db_entry *client, krb5_db_entry *server, + preauth_get_entry_data_proc get_entry_data, + void *pa_module_context, + krb5_pa_data *data); static krb5_error_code return_sam_data - (krb5_context, krb5_pa_data * padata, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - preauth_get_entry_data_proc get_entry_data, - void *pa_module_context, - void **pa_request_context); +(krb5_context, krb5_pa_data * padata, + krb5_db_entry *client, + krb5_data *req_pkt, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa, + preauth_get_entry_data_proc get_entry_data, + void *pa_module_context, + void **pa_request_context); #if APPLE_PKINIT /* PKINIT preauth support */ static krb5_error_code get_pkinit_edata( - krb5_context context, + krb5_context context, krb5_kdc_req *request, - krb5_db_entry *client, + krb5_db_entry *client, krb5_db_entry *server, preauth_get_entry_data_proc get_entry_data, void *pa_module_context, @@ -241,7 +242,7 @@ static krb5_error_code verify_pkinit_request( krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request, - krb5_enc_tkt_part *enc_tkt_reply, + krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data, preauth_get_entry_data_proc get_entry_data, void *pa_module_context, @@ -249,11 +250,11 @@ static krb5_error_code verify_pkinit_request( krb5_data **e_data, krb5_authdata ***authz_data); static krb5_error_code return_pkinit_response( - krb5_context context, - krb5_pa_data * padata, + krb5_context context, + krb5_pa_data * padata, krb5_db_entry *client, krb5_data *req_pkt, - krb5_kdc_req *request, + krb5_kdc_req *request, krb5_kdc_rep *reply, krb5_key_data *client_key, krb5_keyblock *encrypting_key, @@ -266,114 +267,114 @@ static krb5_error_code return_pkinit_response( static krb5_preauth_systems static_preauth_systems[] = { #if APPLE_PKINIT { - "pkinit", - KRB5_PADATA_PK_AS_REQ, - PA_SUFFICIENT, - NULL, /* pa_sys_context */ - NULL, /* init */ - NULL, /* fini */ - get_pkinit_edata, - verify_pkinit_request, - return_pkinit_response, - NULL /* free_pa_request_context */ + "pkinit", + KRB5_PADATA_PK_AS_REQ, + PA_SUFFICIENT, + NULL, /* pa_sys_context */ + NULL, /* init */ + NULL, /* fini */ + get_pkinit_edata, + verify_pkinit_request, + return_pkinit_response, + NULL /* free_pa_request_context */ }, #endif /* APPLE_PKINIT */ { - "timestamp", + "timestamp", KRB5_PADATA_ENC_TIMESTAMP, 0, - NULL, - NULL, - NULL, + NULL, + NULL, + NULL, get_enc_ts, - verify_enc_timestamp, - 0 + verify_enc_timestamp, + 0 }, { - "FAST", + "FAST", KRB5_PADATA_FX_FAST, PA_HARDWARE, - NULL, - NULL, - NULL, NULL, - NULL, - 0 + NULL, + NULL, + NULL, + NULL, + 0 }, { - "etype-info", - KRB5_PADATA_ETYPE_INFO, - 0, - NULL, - NULL, - NULL, - get_etype_info, - 0, - return_etype_info + "etype-info", + KRB5_PADATA_ETYPE_INFO, + 0, + NULL, + NULL, + NULL, + get_etype_info, + 0, + return_etype_info }, { - "etype-info2", - KRB5_PADATA_ETYPE_INFO2, - 0, - NULL, - NULL, - NULL, - get_etype_info2, - 0, - return_etype_info2 + "etype-info2", + KRB5_PADATA_ETYPE_INFO2, + 0, + NULL, + NULL, + NULL, + get_etype_info2, + 0, + return_etype_info2 }, { - "pw-salt", - KRB5_PADATA_PW_SALT, - PA_PSEUDO, /* Don't include this in the error list */ - NULL, - NULL, - NULL, - 0, - 0, - return_pw_salt + "pw-salt", + KRB5_PADATA_PW_SALT, + PA_PSEUDO, /* Don't include this in the error list */ + NULL, + NULL, + NULL, + 0, + 0, + return_pw_salt }, { - "sam-response", - KRB5_PADATA_SAM_RESPONSE, - 0, - NULL, - NULL, - NULL, - 0, - verify_sam_response, - return_sam_data + "sam-response", + KRB5_PADATA_SAM_RESPONSE, + 0, + NULL, + NULL, + NULL, + 0, + verify_sam_response, + return_sam_data }, { - "sam-challenge", - KRB5_PADATA_SAM_CHALLENGE, - PA_HARDWARE, /* causes get_preauth_hint_list to use this */ - NULL, - NULL, - NULL, - get_sam_edata, - 0, - 0 + "sam-challenge", + KRB5_PADATA_SAM_CHALLENGE, + PA_HARDWARE, /* causes get_preauth_hint_list to use this */ + NULL, + NULL, + NULL, + get_sam_edata, + 0, + 0 }, { - "pac-request", - KRB5_PADATA_PAC_REQUEST, - PA_PSEUDO, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL + "pac-request", + KRB5_PADATA_PAC_REQUEST, + PA_PSEUDO, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL }, #if 0 { - "server-referral", - KRB5_PADATA_SERVER_REFERRAL, - PA_PSEUDO, - 0, - 0, - return_server_referral + "server-referral", + KRB5_PADATA_SERVER_REFERRAL, + PA_PSEUDO, + 0, + 0, + return_server_referral }, #endif { "[end]", -1,} @@ -396,140 +397,140 @@ load_preauth_plugins(krb5_context context) /* Attempt to load all of the preauth plugins we can find. */ PLUGIN_DIR_INIT(&preauth_plugins); if (PLUGIN_DIR_OPEN(&preauth_plugins) == 0) { - if (krb5int_open_plugin_dirs(objdirs, NULL, - &preauth_plugins, &context->err) != 0) { - return KRB5_PLUGIN_NO_HANDLE; - } + if (krb5int_open_plugin_dirs(objdirs, NULL, + &preauth_plugins, &context->err) != 0) { + return KRB5_PLUGIN_NO_HANDLE; + } } /* Get the method tables provided by the loaded plugins. */ preauth_plugins_ftables = NULL; if (krb5int_get_plugin_dir_data(&preauth_plugins, - "preauthentication_server_1", - &preauth_plugins_ftables, &context->err) != 0) { - return KRB5_PLUGIN_NO_HANDLE; + "preauthentication_server_1", + &preauth_plugins_ftables, &context->err) != 0) { + return KRB5_PLUGIN_NO_HANDLE; } /* Count the valid modules. */ module_count = sizeof(static_preauth_systems) - / sizeof(static_preauth_systems[0]); + / sizeof(static_preauth_systems[0]); if (preauth_plugins_ftables != NULL) { - for (i = 0; preauth_plugins_ftables[i] != NULL; i++) { - ftable = preauth_plugins_ftables[i]; - if ((ftable->flags_proc == NULL) && - (ftable->edata_proc == NULL) && - (ftable->verify_proc == NULL) && - (ftable->return_proc == NULL)) { - continue; - } - for (j = 0; - ftable->pa_type_list != NULL && - ftable->pa_type_list[j] > 0; - j++) { - module_count++; - } - } + for (i = 0; preauth_plugins_ftables[i] != NULL; i++) { + ftable = preauth_plugins_ftables[i]; + if ((ftable->flags_proc == NULL) && + (ftable->edata_proc == NULL) && + (ftable->verify_proc == NULL) && + (ftable->return_proc == NULL)) { + continue; + } + for (j = 0; + ftable->pa_type_list != NULL && + ftable->pa_type_list[j] > 0; + j++) { + module_count++; + } + } } /* Build the complete list of supported preauthentication options, and * leave room for a terminator entry. */ preauth_systems = malloc(sizeof(krb5_preauth_systems) * (module_count + 1)); if (preauth_systems == NULL) { - krb5int_free_plugin_dir_data(preauth_plugins_ftables); - return ENOMEM; + krb5int_free_plugin_dir_data(preauth_plugins_ftables); + return ENOMEM; } /* Build a list of the names of the supported realms for this KDC. * The list of names is terminated with a NULL. */ kdc_realm_names = malloc(sizeof(char *) * (kdc_numrealms + 1)); if (kdc_realm_names == NULL) { - krb5int_free_plugin_dir_data(preauth_plugins_ftables); - return ENOMEM; + krb5int_free_plugin_dir_data(preauth_plugins_ftables); + return ENOMEM; } for (i = 0; i < (size_t)kdc_numrealms; i++) { - kdc_realm_names[i] = kdc_realmlist[i]->realm_name; + kdc_realm_names[i] = kdc_realmlist[i]->realm_name; } kdc_realm_names[i] = NULL; /* Add the locally-supplied mechanisms to the dynamic list first. */ for (i = 0, k = 0; - i < sizeof(static_preauth_systems) / sizeof(static_preauth_systems[0]); - i++) { - if (static_preauth_systems[i].type == -1) - break; - preauth_systems[k] = static_preauth_systems[i]; - /* Try to initialize the preauth system. If it fails, we'll remove it - * from the list of systems we'll be using. */ - plugin_context = NULL; - server_init_proc = static_preauth_systems[i].init; - if ((server_init_proc != NULL) && - ((*server_init_proc)(context, &plugin_context, (const char **)kdc_realm_names) != 0)) { - memset(&preauth_systems[k], 0, sizeof(preauth_systems[k])); - continue; - } - preauth_systems[k].plugin_context = plugin_context; - k++; + i < sizeof(static_preauth_systems) / sizeof(static_preauth_systems[0]); + i++) { + if (static_preauth_systems[i].type == -1) + break; + preauth_systems[k] = static_preauth_systems[i]; + /* Try to initialize the preauth system. If it fails, we'll remove it + * from the list of systems we'll be using. */ + plugin_context = NULL; + server_init_proc = static_preauth_systems[i].init; + if ((server_init_proc != NULL) && + ((*server_init_proc)(context, &plugin_context, (const char **)kdc_realm_names) != 0)) { + memset(&preauth_systems[k], 0, sizeof(preauth_systems[k])); + continue; + } + preauth_systems[k].plugin_context = plugin_context; + k++; } /* Now add the dynamically-loaded mechanisms to the list. */ if (preauth_plugins_ftables != NULL) { - for (i = 0; preauth_plugins_ftables[i] != NULL; i++) { - ftable = preauth_plugins_ftables[i]; - if ((ftable->flags_proc == NULL) && - (ftable->edata_proc == NULL) && - (ftable->verify_proc == NULL) && - (ftable->return_proc == NULL)) { - continue; - } - plugin_context = NULL; - for (j = 0; - ftable->pa_type_list != NULL && - ftable->pa_type_list[j] > 0; - j++) { - /* Try to initialize the plugin. If it fails, we'll remove it - * from the list of modules we'll be using. */ - if (j == 0) { - server_init_proc = ftable->init_proc; - if (server_init_proc != NULL) { - krb5_error_code initerr; - initerr = (*server_init_proc)(context, &plugin_context, (const char **)kdc_realm_names); - if (initerr) { - const char *emsg; - emsg = krb5_get_error_message(context, initerr); - if (emsg) { - krb5_klog_syslog(LOG_ERR, - "preauth %s failed to initialize: %s", - ftable->name, emsg); - krb5_free_error_message(context, emsg); - } - memset(&preauth_systems[k], 0, sizeof(preauth_systems[k])); - - break; /* skip all modules in this plugin */ - } - } - } - preauth_systems[k].name = ftable->name; - preauth_systems[k].type = ftable->pa_type_list[j]; - if (ftable->flags_proc != NULL) - preauth_systems[k].flags = ftable->flags_proc(context, preauth_systems[k].type); - else - preauth_systems[k].flags = 0; - preauth_systems[k].plugin_context = plugin_context; - preauth_systems[k].init = server_init_proc; - /* Only call fini once for each plugin */ - if (j == 0) - preauth_systems[k].fini = ftable->fini_proc; - else - preauth_systems[k].fini = NULL; - preauth_systems[k].get_edata = ftable->edata_proc; - preauth_systems[k].verify_padata = ftable->verify_proc; - preauth_systems[k].return_padata = ftable->return_proc; - preauth_systems[k].free_pa_reqctx = - ftable->freepa_reqcontext_proc; - k++; - } - } - krb5int_free_plugin_dir_data(preauth_plugins_ftables); + for (i = 0; preauth_plugins_ftables[i] != NULL; i++) { + ftable = preauth_plugins_ftables[i]; + if ((ftable->flags_proc == NULL) && + (ftable->edata_proc == NULL) && + (ftable->verify_proc == NULL) && + (ftable->return_proc == NULL)) { + continue; + } + plugin_context = NULL; + for (j = 0; + ftable->pa_type_list != NULL && + ftable->pa_type_list[j] > 0; + j++) { + /* Try to initialize the plugin. If it fails, we'll remove it + * from the list of modules we'll be using. */ + if (j == 0) { + server_init_proc = ftable->init_proc; + if (server_init_proc != NULL) { + krb5_error_code initerr; + initerr = (*server_init_proc)(context, &plugin_context, (const char **)kdc_realm_names); + if (initerr) { + const char *emsg; + emsg = krb5_get_error_message(context, initerr); + if (emsg) { + krb5_klog_syslog(LOG_ERR, + "preauth %s failed to initialize: %s", + ftable->name, emsg); + krb5_free_error_message(context, emsg); + } + memset(&preauth_systems[k], 0, sizeof(preauth_systems[k])); + + break; /* skip all modules in this plugin */ + } + } + } + preauth_systems[k].name = ftable->name; + preauth_systems[k].type = ftable->pa_type_list[j]; + if (ftable->flags_proc != NULL) + preauth_systems[k].flags = ftable->flags_proc(context, preauth_systems[k].type); + else + preauth_systems[k].flags = 0; + preauth_systems[k].plugin_context = plugin_context; + preauth_systems[k].init = server_init_proc; + /* Only call fini once for each plugin */ + if (j == 0) + preauth_systems[k].fini = ftable->fini_proc; + else + preauth_systems[k].fini = NULL; + preauth_systems[k].get_edata = ftable->edata_proc; + preauth_systems[k].verify_padata = ftable->verify_proc; + preauth_systems[k].return_padata = ftable->return_proc; + preauth_systems[k].free_pa_reqctx = + ftable->freepa_reqcontext_proc; + k++; + } + } + krb5int_free_plugin_dir_data(preauth_plugins_ftables); } free(kdc_realm_names); n_preauth_systems = k; @@ -544,17 +545,17 @@ unload_preauth_plugins(krb5_context context) { int i; if (preauth_systems != NULL) { - for (i = 0; i < n_preauth_systems; i++) { - if (preauth_systems[i].fini != NULL) { - (*preauth_systems[i].fini)(context, - preauth_systems[i].plugin_context); - } - memset(&preauth_systems[i], 0, sizeof(preauth_systems[i])); - } - free(preauth_systems); - preauth_systems = NULL; - n_preauth_systems = 0; - krb5int_close_plugin_dirs(&preauth_plugins); + for (i = 0; i < n_preauth_systems; i++) { + if (preauth_systems[i].fini != NULL) { + (*preauth_systems[i].fini)(context, + preauth_systems[i].plugin_context); + } + memset(&preauth_systems[i], 0, sizeof(preauth_systems[i])); + } + free(preauth_systems); + preauth_systems = NULL; + n_preauth_systems = 0; + krb5int_close_plugin_dirs(&preauth_plugins); } return 0; } @@ -567,8 +568,8 @@ unload_preauth_plugins(krb5_context context) struct request_pa_context { int n_contexts; struct { - krb5_preauth_systems *pa_system; - void *pa_context; + krb5_preauth_systems *pa_system; + void *pa_context; } *contexts; }; @@ -580,21 +581,21 @@ make_padata_context(krb5_context context, void **padata_context) ret = malloc(sizeof(*ret)); if (ret == NULL) { - return ENOMEM; + return ENOMEM; } ret->n_contexts = n_preauth_systems; ret->contexts = malloc(sizeof(ret->contexts[0]) * ret->n_contexts); if (ret->contexts == NULL) { - free(ret); - return ENOMEM; + free(ret); + return ENOMEM; } memset(ret->contexts, 0, sizeof(ret->contexts[0]) * ret->n_contexts); for (i = 0; i < ret->n_contexts; i++) { - ret->contexts[i].pa_system = &preauth_systems[i]; - ret->contexts[i].pa_context = NULL; + ret->contexts[i].pa_system = &preauth_systems[i]; + ret->contexts[i].pa_context = NULL; } *padata_context = ret; @@ -616,20 +617,20 @@ free_padata_context(krb5_context kcontext, void **padata_context) int i; if (padata_context == NULL) - return 0; + return 0; context = *padata_context; for (i = 0; i < context->n_contexts; i++) { - if (context->contexts[i].pa_context != NULL) { - preauth_system = context->contexts[i].pa_system; - mctx = preauth_system->plugin_context; - if (preauth_system->free_pa_reqctx != NULL) { - pctx = &context->contexts[i].pa_context; - (*preauth_system->free_pa_reqctx)(kcontext, mctx, pctx); - } - context->contexts[i].pa_context = NULL; - } + if (context->contexts[i].pa_context != NULL) { + preauth_system = context->contexts[i].pa_system; + mctx = preauth_system->plugin_context; + if (preauth_system->free_pa_reqctx != NULL) { + pctx = &context->contexts[i].pa_context; + (*preauth_system->free_pa_reqctx)(kcontext, mctx, pctx); + } + context->contexts[i].pa_context = NULL; + } } free(context->contexts); @@ -642,25 +643,25 @@ free_padata_context(krb5_context kcontext, void **padata_context) * contents in a new krb5_data, which must be freed by the caller. */ static krb5_error_code get_entry_tl_data(krb5_context context, krb5_db_entry *entry, - krb5_int16 tl_data_type, krb5_data **result) + krb5_int16 tl_data_type, krb5_data **result) { krb5_tl_data *tl; for (tl = entry->tl_data; tl != NULL; tl = tl->tl_data_next) { - if (tl->tl_data_type == tl_data_type) { - *result = malloc(sizeof(krb5_data)); - if (*result == NULL) { - return ENOMEM; - } - (*result)->magic = KV5M_DATA; - (*result)->data = malloc(tl->tl_data_length); - if ((*result)->data == NULL) { - free(*result); - *result = NULL; - return ENOMEM; - } - memcpy((*result)->data, tl->tl_data_contents, tl->tl_data_length); - return 0; - } + if (tl->tl_data_type == tl_data_type) { + *result = malloc(sizeof(krb5_data)); + if (*result == NULL) { + return ENOMEM; + } + (*result)->magic = KV5M_DATA; + (*result)->data = malloc(tl->tl_data_length); + if ((*result)->data == NULL) { + free(*result); + *result = NULL; + return ENOMEM; + } + memcpy((*result)->data, tl->tl_data_contents, tl->tl_data_length); + return 0; + } } return ENOENT; } @@ -675,9 +676,9 @@ get_entry_tl_data(krb5_context context, krb5_db_entry *entry, */ static krb5_error_code get_entry_data(krb5_context context, - krb5_kdc_req *request, krb5_db_entry *entry, - krb5_int32 type, - krb5_data **result) + krb5_kdc_req *request, krb5_db_entry *entry, + krb5_int32 type, + krb5_data **result) { int i, k; krb5_data *ret; @@ -689,37 +690,37 @@ get_entry_data(krb5_context context, switch (type) { case krb5plugin_preauth_entry_request_certificate: - return get_entry_tl_data(context, entry, - KRB5_TL_USER_CERTIFICATE, result); - break; + return get_entry_tl_data(context, entry, + KRB5_TL_USER_CERTIFICATE, result); + break; case krb5plugin_preauth_entry_max_time_skew: - ret = malloc(sizeof(krb5_data)); - if (ret == NULL) - return ENOMEM; - delta = malloc(sizeof(krb5_deltat)); - if (delta == NULL) { - free(ret); - return ENOMEM; - } - *delta = context->clockskew; - ret->data = (char *) delta; - ret->length = sizeof(*delta); - *result = ret; - return 0; - break; + ret = malloc(sizeof(krb5_data)); + if (ret == NULL) + return ENOMEM; + delta = malloc(sizeof(krb5_deltat)); + if (delta == NULL) { + free(ret); + return ENOMEM; + } + *delta = context->clockskew; + ret->data = (char *) delta; + ret->length = sizeof(*delta); + *result = ret; + return 0; + break; case krb5plugin_preauth_keys: - ret = malloc(sizeof(krb5_data)); - if (ret == NULL) - return ENOMEM; - keys = malloc(sizeof(krb5_keyblock) * (request->nktypes + 1)); - if (keys == NULL) { - free(ret); - return ENOMEM; - } - ret->data = (char *) keys; - ret->length = sizeof(krb5_keyblock) * (request->nktypes + 1); - memset(ret->data, 0, ret->length); - if ((error = krb5_dbe_find_mkey(context, master_keylist, entry, + ret = malloc(sizeof(krb5_data)); + if (ret == NULL) + return ENOMEM; + keys = malloc(sizeof(krb5_keyblock) * (request->nktypes + 1)); + if (keys == NULL) { + free(ret); + return ENOMEM; + } + ret->data = (char *) keys; + ret->length = sizeof(krb5_keyblock) * (request->nktypes + 1); + memset(ret->data, 0, ret->length); + if ((error = krb5_dbe_find_mkey(context, master_keylist, entry, &mkey_ptr))) { krb5_keylist_node *tmp_mkey_list; /* try refreshing the mkey list in case it's been updated */ @@ -738,64 +739,64 @@ get_entry_data(krb5_context context, return (error); } } - k = 0; - for (i = 0; i < request->nktypes; i++) { - entry_key = NULL; - if (krb5_dbe_find_enctype(context, entry, request->ktype[i], - -1, 0, &entry_key) != 0) - continue; - if (krb5_dbekd_decrypt_key_data(context, mkey_ptr, - entry_key, &keys[k], NULL) != 0) { - if (keys[k].contents != NULL) - krb5_free_keyblock_contents(context, &keys[k]); - memset(&keys[k], 0, sizeof(keys[k])); - continue; - } - k++; - } - if (k > 0) { - *result = ret; - return 0; - } else { - free(keys); - free(ret); - } - break; + k = 0; + for (i = 0; i < request->nktypes; i++) { + entry_key = NULL; + if (krb5_dbe_find_enctype(context, entry, request->ktype[i], + -1, 0, &entry_key) != 0) + continue; + if (krb5_dbekd_decrypt_key_data(context, mkey_ptr, + entry_key, &keys[k], NULL) != 0) { + if (keys[k].contents != NULL) + krb5_free_keyblock_contents(context, &keys[k]); + memset(&keys[k], 0, sizeof(keys[k])); + continue; + } + k++; + } + if (k > 0) { + *result = ret; + return 0; + } else { + free(keys); + free(ret); + } + break; case krb5plugin_preauth_request_body: - ret = NULL; - encode_krb5_kdc_req_body(request, &ret); - if (ret != NULL) { - *result = ret; - return 0; - } - return ASN1_PARSE_ERROR; - break; + ret = NULL; + encode_krb5_kdc_req_body(request, &ret); + if (ret != NULL) { + *result = ret; + return 0; + } + return ASN1_PARSE_ERROR; + break; case krb5plugin_preauth_fast_armor: - ret = calloc(1, sizeof(krb5_data)); - if (ret == NULL) - return ENOMEM; - if (state->armor_key == NULL) { - *result = ret; - return 0; - } - error = krb5_copy_keyblock(context, state->armor_key, &keys); - if (error == 0) { - ret->data = (char *) keys; - ret->length = sizeof(krb5_keyblock); - *result = ret; - return 0; - } - free(ret); - return error; + ret = calloc(1, sizeof(krb5_data)); + if (ret == NULL) + return ENOMEM; + if (state->armor_key == NULL) { + *result = ret; + return 0; + } + error = krb5_copy_keyblock(context, state->armor_key, &keys); + if (error == 0) { + ret->data = (char *) keys; + ret->length = sizeof(krb5_keyblock); + *result = ret; + return 0; + } + free(ret); + return error; case krb5plugin_preauth_free_fast_armor: - if ((*result)->data) { - keys = (krb5_keyblock *) (*result)->data; - krb5_free_keyblock(context, keys); - } - free(*result); - return 0; + if ((*result)->data) { + keys = (krb5_keyblock *) (*result)->data; + krb5_free_keyblock(context, keys); + } + free(*result); + return 0; default: - break; + break; } return ENOENT; } @@ -807,30 +808,30 @@ find_pa_system(int type, krb5_preauth_systems **preauth) ap = preauth_systems ? preauth_systems : static_preauth_systems; while ((ap->type != -1) && (ap->type != type)) - ap++; + ap++; if (ap->type == -1) - return(KRB5_PREAUTH_BAD_TYPE); + return(KRB5_PREAUTH_BAD_TYPE); *preauth = ap; return 0; -} +} static krb5_error_code find_pa_context(krb5_preauth_systems *pa_sys, - struct request_pa_context *context, - void ***pa_context) + struct request_pa_context *context, + void ***pa_context) { int i; *pa_context = 0; if (context == NULL) - return KRB5KRB_ERR_GENERIC; + return KRB5KRB_ERR_GENERIC; for (i = 0; i < context->n_contexts; i++) { - if (context->contexts[i].pa_system == pa_sys) { - *pa_context = &context->contexts[i].pa_context; - return 0; - } + if (context->contexts[i].pa_system == pa_sys) { + *pa_context = &context->contexts[i].pa_context; + return 0; + } } return KRB5KRB_ERR_GENERIC; @@ -844,9 +845,9 @@ static krb5_boolean pa_list_includes(krb5_pa_data **pa_data, krb5_preauthtype pa_type) { while (*pa_data != NULL) { - if ((*pa_data)->pa_type == pa_type) - return TRUE; - pa_data++; + if ((*pa_data)->pa_type == pa_type) + return TRUE; + pa_data++; } return FALSE; } @@ -859,158 +860,158 @@ sort_pa_order(krb5_context context, krb5_kdc_req *request, int *pa_order) i = 0; for (j = 0; j < n_preauth_systems; j++) { if (preauth_systems[j].return_padata != NULL) - pa_order[i++] = j; + pa_order[i++] = j; } n_repliers = i; pa_order[n_repliers] = -1; /* Reorder so that PA_REPLACES_KEY modules are listed first. */ for (i = 0; i < n_repliers; i++) { - /* If this module replaces the key, then it's okay to leave it where it - * is in the order. */ - if (preauth_systems[pa_order[i]].flags & PA_REPLACES_KEY) - continue; - /* If not, search for a module which does, and swap in the first one we - * find. */ + /* If this module replaces the key, then it's okay to leave it where it + * is in the order. */ + if (preauth_systems[pa_order[i]].flags & PA_REPLACES_KEY) + continue; + /* If not, search for a module which does, and swap in the first one we + * find. */ for (j = i + 1; j < n_repliers; j++) { - if (preauth_systems[pa_order[j]].flags & PA_REPLACES_KEY) { + if (preauth_systems[pa_order[j]].flags & PA_REPLACES_KEY) { k = pa_order[j]; - pa_order[j] = pa_order[i]; - pa_order[i] = k; - break; - } + pa_order[j] = pa_order[i]; + pa_order[i] = k; + break; + } } } if (request->padata != NULL) { - /* Now reorder the subset of modules which replace the key, - * bubbling those which handle pa_data types provided by the - * client ahead of the others. */ - for (i = 0; preauth_systems[pa_order[i]].flags & PA_REPLACES_KEY; i++) { - continue; - } - n_key_replacers = i; - for (i = 0; i < n_key_replacers; i++) { - if (pa_list_includes(request->padata, - preauth_systems[pa_order[i]].type)) - continue; - for (j = i + 1; j < n_key_replacers; j++) { - if (pa_list_includes(request->padata, - preauth_systems[pa_order[j]].type)) { - k = pa_order[j]; - pa_order[j] = pa_order[i]; - pa_order[i] = k; - break; - } - } - } + /* Now reorder the subset of modules which replace the key, + * bubbling those which handle pa_data types provided by the + * client ahead of the others. */ + for (i = 0; preauth_systems[pa_order[i]].flags & PA_REPLACES_KEY; i++) { + continue; + } + n_key_replacers = i; + for (i = 0; i < n_key_replacers; i++) { + if (pa_list_includes(request->padata, + preauth_systems[pa_order[i]].type)) + continue; + for (j = i + 1; j < n_key_replacers; j++) { + if (pa_list_includes(request->padata, + preauth_systems[pa_order[j]].type)) { + k = pa_order[j]; + pa_order[j] = pa_order[i]; + pa_order[i] = k; + break; + } + } + } } #ifdef DEBUG krb5_klog_syslog(LOG_DEBUG, "original preauth mechanism list:"); for (i = 0; i < n_preauth_systems; i++) { - if (preauth_systems[i].return_padata != NULL) + if (preauth_systems[i].return_padata != NULL) krb5_klog_syslog(LOG_DEBUG, "... %s(%d)", preauth_systems[i].name, - preauth_systems[i].type); + preauth_systems[i].type); } krb5_klog_syslog(LOG_DEBUG, "sorted preauth mechanism list:"); for (i = 0; pa_order[i] != -1; i++) { krb5_klog_syslog(LOG_DEBUG, "... %s(%d)", - preauth_systems[pa_order[i]].name, - preauth_systems[pa_order[i]].type); + preauth_systems[pa_order[i]].name, + preauth_systems[pa_order[i]].type); } #endif } const char *missing_required_preauth(krb5_db_entry *client, - krb5_db_entry *server, - krb5_enc_tkt_part *enc_tkt_reply) + krb5_db_entry *server, + krb5_enc_tkt_part *enc_tkt_reply) { #if 0 /* * If this is the pwchange service, and the pre-auth bit is set, * allow it even if the HW preauth would normally be required. - * + * * Sandia national labs wanted this for some strange reason... we * leave it disabled normally. */ if (isflagset(server->attributes, KRB5_KDB_PWCHANGE_SERVICE) && - isflagset(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH)) - return 0; + isflagset(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH)) + return 0; #endif - + #ifdef DEBUG krb5_klog_syslog (LOG_DEBUG, - "client needs %spreauth, %shw preauth; request has %spreauth, %shw preauth", - isflagset (client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH) ? "" : "no ", - isflagset (client->attributes, KRB5_KDB_REQUIRES_HW_AUTH) ? "" : "no ", - isflagset (enc_tkt_reply->flags, TKT_FLG_PRE_AUTH) ? "" : "no ", - isflagset (enc_tkt_reply->flags, TKT_FLG_HW_AUTH) ? "" : "no "); + "client needs %spreauth, %shw preauth; request has %spreauth, %shw preauth", + isflagset (client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH) ? "" : "no ", + isflagset (client->attributes, KRB5_KDB_REQUIRES_HW_AUTH) ? "" : "no ", + isflagset (enc_tkt_reply->flags, TKT_FLG_PRE_AUTH) ? "" : "no ", + isflagset (enc_tkt_reply->flags, TKT_FLG_HW_AUTH) ? "" : "no "); #endif if (isflagset(client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH) && - !isflagset(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH)) - return "NEEDED_PREAUTH"; + !isflagset(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH)) + return "NEEDED_PREAUTH"; if (isflagset(client->attributes, KRB5_KDB_REQUIRES_HW_AUTH) && - !isflagset(enc_tkt_reply->flags, TKT_FLG_HW_AUTH)) - return "NEEDED_HW_PREAUTH"; + !isflagset(enc_tkt_reply->flags, TKT_FLG_HW_AUTH)) + return "NEEDED_HW_PREAUTH"; return 0; } void get_preauth_hint_list(krb5_kdc_req *request, krb5_db_entry *client, - krb5_db_entry *server, krb5_data *e_data) + krb5_db_entry *server, krb5_data *e_data) { int hw_only; krb5_preauth_systems *ap; krb5_pa_data **pa_data, **pa; krb5_data *edat; krb5_error_code retval; - + /* Zero these out in case we need to abort */ e_data->length = 0; e_data->data = 0; - + hw_only = isflagset(client->attributes, KRB5_KDB_REQUIRES_HW_AUTH); /* Allocate two extra entries for the cookie and the terminator. */ pa_data = calloc(n_preauth_systems + 2, sizeof(krb5_pa_data *)); if (pa_data == 0) - return; + return; pa = pa_data; for (ap = preauth_systems; ap->type != -1; ap++) { - if (hw_only && !(ap->flags & PA_HARDWARE)) - continue; - if (ap->flags & PA_PSEUDO) - continue; - *pa = malloc(sizeof(krb5_pa_data)); - if (*pa == 0) - goto errout; - memset(*pa, 0, sizeof(krb5_pa_data)); - (*pa)->magic = KV5M_PA_DATA; - (*pa)->pa_type = ap->type; - if (ap->get_edata) { - retval = (ap->get_edata)(kdc_context, request, client, server, - get_entry_data, ap->plugin_context, *pa); - if (retval) { - /* just failed on this type, continue */ - free(*pa); - *pa = 0; - continue; - } - } - pa++; + if (hw_only && !(ap->flags & PA_HARDWARE)) + continue; + if (ap->flags & PA_PSEUDO) + continue; + *pa = malloc(sizeof(krb5_pa_data)); + if (*pa == 0) + goto errout; + memset(*pa, 0, sizeof(krb5_pa_data)); + (*pa)->magic = KV5M_PA_DATA; + (*pa)->pa_type = ap->type; + if (ap->get_edata) { + retval = (ap->get_edata)(kdc_context, request, client, server, + get_entry_data, ap->plugin_context, *pa); + if (retval) { + /* just failed on this type, continue */ + free(*pa); + *pa = 0; + continue; + } + } + pa++; } if (pa_data[0] == 0) { - krb5_klog_syslog (LOG_INFO, - "%spreauth required but hint list is empty", - hw_only ? "hw" : ""); + krb5_klog_syslog (LOG_INFO, + "%spreauth required but hint list is empty", + hw_only ? "hw" : ""); } /* If we fail to get the cookie it is probably still reasonable to continue with the response*/ kdc_preauth_get_cookie(request->kdc_state, pa); retval = encode_krb5_padata_sequence(pa_data, &edat); if (retval) - goto errout; + goto errout; *e_data = *edat; free(edat); @@ -1031,36 +1032,36 @@ add_authorization_data(krb5_enc_tkt_part *enc_tkt_part, krb5_authdata **ad) int i; if (enc_tkt_part == NULL || ad == NULL) - return EINVAL; + return EINVAL; for (newones = 0; ad[newones] != NULL; newones++); if (newones == 0) - return 0; /* nothing to add */ + return 0; /* nothing to add */ if (enc_tkt_part->authorization_data == NULL) - oldones = 0; + oldones = 0; else - for (oldones = 0; - enc_tkt_part->authorization_data[oldones] != NULL; oldones++); + for (oldones = 0; + enc_tkt_part->authorization_data[oldones] != NULL; oldones++); newad = malloc((oldones + newones + 1) * sizeof(krb5_authdata *)); if (newad == NULL) - return ENOMEM; + return ENOMEM; /* Copy any existing pointers */ for (i = 0; i < oldones; i++) - newad[i] = enc_tkt_part->authorization_data[i]; + newad[i] = enc_tkt_part->authorization_data[i]; /* Add the new ones */ for (i = 0; i < newones; i++) - newad[oldones+i] = ad[i]; + newad[oldones+i] = ad[i]; /* Terminate the new list */ newad[oldones+i] = NULL; /* Free any existing list */ if (enc_tkt_part->authorization_data != NULL) - free(enc_tkt_part->authorization_data); + free(enc_tkt_part->authorization_data); /* Install our new list */ enc_tkt_part->authorization_data = newad; @@ -1078,25 +1079,25 @@ add_authorization_data(krb5_enc_tkt_part *enc_tkt_part, krb5_authdata **ad) krb5_error_code check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, - krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, - void **padata_context, krb5_data *e_data) + krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, + void **padata_context, krb5_data *e_data) { krb5_error_code retval = 0; krb5_pa_data **padata; krb5_preauth_systems *pa_sys; void **pa_context; krb5_data *pa_e_data = NULL, *tmp_e_data = NULL; - int pa_ok = 0, pa_found = 0; + int pa_ok = 0, pa_found = 0; krb5_error_code saved_retval = 0; int use_saved_retval = 0; const char *emsg; krb5_authdata **tmp_authz_data = NULL; if (request->padata == 0) - return 0; + return 0; if (make_padata_context(context, padata_context) != 0) { - return KRB5KRB_ERR_GENERIC; + return KRB5KRB_ERR_GENERIC; } #ifdef DEBUG @@ -1104,109 +1105,109 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, #endif for (padata = request->padata; *padata; padata++) { #ifdef DEBUG - krb5_klog_syslog (LOG_DEBUG, ".. pa_type 0x%x", (*padata)->pa_type); + krb5_klog_syslog (LOG_DEBUG, ".. pa_type 0x%x", (*padata)->pa_type); #endif - if (find_pa_system((*padata)->pa_type, &pa_sys)) - continue; - if (find_pa_context(pa_sys, *padata_context, &pa_context)) - continue; + if (find_pa_system((*padata)->pa_type, &pa_sys)) + continue; + if (find_pa_context(pa_sys, *padata_context, &pa_context)) + continue; #ifdef DEBUG - krb5_klog_syslog (LOG_DEBUG, ".. pa_type %s", pa_sys->name); + krb5_klog_syslog (LOG_DEBUG, ".. pa_type %s", pa_sys->name); #endif - if (pa_sys->verify_padata == 0) - continue; - pa_found++; - retval = pa_sys->verify_padata(context, client, req_pkt, request, - enc_tkt_reply, *padata, - get_entry_data, pa_sys->plugin_context, - pa_context, &tmp_e_data, &tmp_authz_data); - if (retval) { - emsg = krb5_get_error_message (context, retval); - krb5_klog_syslog (LOG_INFO, "preauth (%s) verify failure: %s", - pa_sys->name, emsg); - krb5_free_error_message (context, emsg); - /* Ignore authorization data returned from modules that fail */ - if (tmp_authz_data != NULL) { - krb5_free_authdata(context, tmp_authz_data); - tmp_authz_data = NULL; - } - if (pa_sys->flags & PA_REQUIRED) { - /* free up any previous edata we might have been saving */ - if (pa_e_data != NULL) - krb5_free_data(context, pa_e_data); - pa_e_data = tmp_e_data; - tmp_e_data = NULL; - use_saved_retval = 0; /* Make sure we use the current retval */ - pa_ok = 0; - break; - } - /* - * We'll return edata from either the first PA_REQUIRED module - * that fails, or the first non-PA_REQUIRED module that fails. - * Hang on to edata from the first non-PA_REQUIRED module. - * If we've already got one saved, simply discard this one. - */ - if (tmp_e_data != NULL) { - if (pa_e_data == NULL) { - /* save the first error code and e-data */ - pa_e_data = tmp_e_data; - tmp_e_data = NULL; - saved_retval = retval; - use_saved_retval = 1; - } else { - /* discard this extra e-data from non-PA_REQUIRED module */ - krb5_free_data(context, tmp_e_data); - tmp_e_data = NULL; - } - } - } else { + if (pa_sys->verify_padata == 0) + continue; + pa_found++; + retval = pa_sys->verify_padata(context, client, req_pkt, request, + enc_tkt_reply, *padata, + get_entry_data, pa_sys->plugin_context, + pa_context, &tmp_e_data, &tmp_authz_data); + if (retval) { + emsg = krb5_get_error_message (context, retval); + krb5_klog_syslog (LOG_INFO, "preauth (%s) verify failure: %s", + pa_sys->name, emsg); + krb5_free_error_message (context, emsg); + /* Ignore authorization data returned from modules that fail */ + if (tmp_authz_data != NULL) { + krb5_free_authdata(context, tmp_authz_data); + tmp_authz_data = NULL; + } + if (pa_sys->flags & PA_REQUIRED) { + /* free up any previous edata we might have been saving */ + if (pa_e_data != NULL) + krb5_free_data(context, pa_e_data); + pa_e_data = tmp_e_data; + tmp_e_data = NULL; + use_saved_retval = 0; /* Make sure we use the current retval */ + pa_ok = 0; + break; + } + /* + * We'll return edata from either the first PA_REQUIRED module + * that fails, or the first non-PA_REQUIRED module that fails. + * Hang on to edata from the first non-PA_REQUIRED module. + * If we've already got one saved, simply discard this one. + */ + if (tmp_e_data != NULL) { + if (pa_e_data == NULL) { + /* save the first error code and e-data */ + pa_e_data = tmp_e_data; + tmp_e_data = NULL; + saved_retval = retval; + use_saved_retval = 1; + } else { + /* discard this extra e-data from non-PA_REQUIRED module */ + krb5_free_data(context, tmp_e_data); + tmp_e_data = NULL; + } + } + } else { #ifdef DEBUG - krb5_klog_syslog (LOG_DEBUG, ".. .. ok"); + krb5_klog_syslog (LOG_DEBUG, ".. .. ok"); #endif - /* Ignore any edata returned on success */ - if (tmp_e_data != NULL) { - krb5_free_data(context, tmp_e_data); - tmp_e_data = NULL; - } - /* Add any authorization data to the ticket */ - if (tmp_authz_data != NULL) { - add_authorization_data(enc_tkt_reply, tmp_authz_data); - free(tmp_authz_data); - tmp_authz_data = NULL; - } - pa_ok = 1; - if (pa_sys->flags & PA_SUFFICIENT) - break; - } + /* Ignore any edata returned on success */ + if (tmp_e_data != NULL) { + krb5_free_data(context, tmp_e_data); + tmp_e_data = NULL; + } + /* Add any authorization data to the ticket */ + if (tmp_authz_data != NULL) { + add_authorization_data(enc_tkt_reply, tmp_authz_data); + free(tmp_authz_data); + tmp_authz_data = NULL; + } + pa_ok = 1; + if (pa_sys->flags & PA_SUFFICIENT) + break; + } } /* Don't bother copying and returning e-data on success */ if (pa_ok && pa_e_data != NULL) { - krb5_free_data(context, pa_e_data); - pa_e_data = NULL; + krb5_free_data(context, pa_e_data); + pa_e_data = NULL; } /* Return any e-data from the preauth that caused us to exit the loop */ if (pa_e_data != NULL) { - e_data->data = malloc(pa_e_data->length); - if (e_data->data == NULL) { - krb5_free_data(context, pa_e_data); - return KRB5KRB_ERR_GENERIC; - } - memcpy(e_data->data, pa_e_data->data, pa_e_data->length); - e_data->length = pa_e_data->length; - krb5_free_data(context, pa_e_data); - pa_e_data = NULL; - if (use_saved_retval != 0) - retval = saved_retval; + e_data->data = malloc(pa_e_data->length); + if (e_data->data == NULL) { + krb5_free_data(context, pa_e_data); + return KRB5KRB_ERR_GENERIC; + } + memcpy(e_data->data, pa_e_data->data, pa_e_data->length); + e_data->length = pa_e_data->length; + krb5_free_data(context, pa_e_data); + pa_e_data = NULL; + if (use_saved_retval != 0) + retval = saved_retval; } if (pa_ok) - return 0; + return 0; /* pa system was not found; we may return PREAUTH_REQUIRED later, but we did not actually fail to verify the pre-auth. */ if (!pa_found) - return 0; + return 0; /* The following switch statement allows us @@ -1217,7 +1218,7 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, case KRB5KRB_AP_ERR_BAD_INTEGRITY: case KRB5KRB_AP_ERR_SKEW: case KRB5KDC_ERR_ETYPE_NOSUPP: - /* rfc 4556 */ + /* rfc 4556 */ case KRB5KDC_ERR_CLIENT_NOT_TRUSTED: case KRB5KDC_ERR_INVALID_SIG: case KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED: @@ -1231,15 +1232,15 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, case KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED: case KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED: case KRB5KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED: - /* earlier drafts of what became rfc 4556 */ + /* earlier drafts of what became rfc 4556 */ case KRB5KDC_ERR_CERTIFICATE_MISMATCH: case KRB5KDC_ERR_KDC_NOT_TRUSTED: case KRB5KDC_ERR_REVOCATION_STATUS_UNAVAILABLE: - /* This value is shared with KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED. */ - /* case KRB5KDC_ERR_KEY_TOO_WEAK: */ - return retval; + /* This value is shared with KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED. */ + /* case KRB5KDC_ERR_KEY_TOO_WEAK: */ + return retval; default: - return KRB5KDC_ERR_PREAUTH_FAILED; + return KRB5KDC_ERR_PREAUTH_FAILED; } } @@ -1249,45 +1250,45 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, */ krb5_error_code return_padata(krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, krb5_keyblock *encrypting_key, - void **padata_context) + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, krb5_keyblock *encrypting_key, + void **padata_context) { - krb5_error_code retval; - krb5_pa_data ** padata; - krb5_pa_data ** send_pa_list; - krb5_pa_data ** send_pa; - krb5_pa_data * pa = 0; - krb5_preauth_systems * ap; - int * pa_order; - int * pa_type; - int size = 0; - void ** pa_context; - krb5_boolean key_modified; - krb5_keyblock original_key; + krb5_error_code retval; + krb5_pa_data ** padata; + krb5_pa_data ** send_pa_list; + krb5_pa_data ** send_pa; + krb5_pa_data * pa = 0; + krb5_preauth_systems * ap; + int * pa_order; + int * pa_type; + int size = 0; + void ** pa_context; + krb5_boolean key_modified; + krb5_keyblock original_key; if ((!*padata_context)&& (make_padata_context(context, padata_context) != 0)) { - return KRB5KRB_ERR_GENERIC; + return KRB5KRB_ERR_GENERIC; } for (ap = preauth_systems; ap->type != -1; ap++) { - if (ap->return_padata) - size++; + if (ap->return_padata) + size++; } if ((send_pa_list = malloc((size+1) * sizeof(krb5_pa_data *))) == NULL) - return ENOMEM; + return ENOMEM; if ((pa_order = malloc((size+1) * sizeof(int))) == NULL) { - free(send_pa_list); - return ENOMEM; + free(send_pa_list); + return ENOMEM; } sort_pa_order(context, request, pa_order); retval = krb5_copy_keyblock_contents(context, encrypting_key, - &original_key); + &original_key); if (retval) { - free(send_pa_list); - free(pa_order); - return retval; + free(send_pa_list); + free(pa_order); + return retval; } key_modified = FALSE; @@ -1295,117 +1296,117 @@ return_padata(krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, *send_pa = 0; for (pa_type = pa_order; *pa_type != -1; pa_type++) { - ap = &preauth_systems[*pa_type]; + ap = &preauth_systems[*pa_type]; if (!key_modified) - if (original_key.enctype != encrypting_key->enctype) + if (original_key.enctype != encrypting_key->enctype) key_modified = TRUE; if (!key_modified) - if (original_key.length != encrypting_key->length) + if (original_key.length != encrypting_key->length) key_modified = TRUE; if (!key_modified) - if (memcmp(original_key.contents, encrypting_key->contents, - original_key.length) != 0) + if (memcmp(original_key.contents, encrypting_key->contents, + original_key.length) != 0) key_modified = TRUE; - if (key_modified && (ap->flags & PA_REPLACES_KEY)) - continue; - if (ap->return_padata == 0) - continue; - if (find_pa_context(ap, *padata_context, &pa_context)) - continue; - pa = 0; - if (request->padata) { - for (padata = request->padata; *padata; padata++) { - if ((*padata)->pa_type == ap->type) { - pa = *padata; - break; - } - } - } - if ((retval = ap->return_padata(context, pa, client, req_pkt, request, reply, - client_key, encrypting_key, send_pa, - get_entry_data, ap->plugin_context, - pa_context))) { - goto cleanup; - } - - if (*send_pa) - send_pa++; - *send_pa = 0; - } - + if (key_modified && (ap->flags & PA_REPLACES_KEY)) + continue; + if (ap->return_padata == 0) + continue; + if (find_pa_context(ap, *padata_context, &pa_context)) + continue; + pa = 0; + if (request->padata) { + for (padata = request->padata; *padata; padata++) { + if ((*padata)->pa_type == ap->type) { + pa = *padata; + break; + } + } + } + if ((retval = ap->return_padata(context, pa, client, req_pkt, request, reply, + client_key, encrypting_key, send_pa, + get_entry_data, ap->plugin_context, + pa_context))) { + goto cleanup; + } + + if (*send_pa) + send_pa++; + *send_pa = 0; + } + retval = 0; if (send_pa_list[0]) { - reply->padata = send_pa_list; - send_pa_list = 0; + reply->padata = send_pa_list; + send_pa_list = 0; } - + cleanup: krb5_free_keyblock_contents(context, &original_key); free(pa_order); if (send_pa_list) - krb5_free_pa_data(context, send_pa_list); + krb5_free_pa_data(context, send_pa_list); return (retval); } static krb5_boolean request_contains_enctype (krb5_context context, const krb5_kdc_req *request, - krb5_enctype enctype) + krb5_enctype enctype) { int i; for (i =0; i < request->nktypes; i++) - if (request->ktype[i] == enctype) - return 1; + if (request->ktype[i] == enctype) + return 1; return 0; } static krb5_error_code get_enc_ts - (krb5_context context, krb5_kdc_req *request, - krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc get_entry_data_proc, - void *pa_system_context, - krb5_pa_data *data) +(krb5_context context, krb5_kdc_req *request, + krb5_db_entry *client, krb5_db_entry *server, + preauth_get_entry_data_proc get_entry_data_proc, + void *pa_system_context, + krb5_pa_data *data) { - struct kdc_request_state *state = request->kdc_state; - if (state->armor_key) - return ENOENT; - return 0; + struct kdc_request_state *state = request->kdc_state; + if (state->armor_key) + return ENOENT; + return 0; } - - + + static krb5_error_code verify_enc_timestamp(krb5_context context, krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, - krb5_pa_data *pa, - preauth_get_entry_data_proc ets_get_entry_data, - void *pa_system_context, - void **pa_request_context, - krb5_data **e_data, - krb5_authdata ***authz_data) + krb5_data *req_pkt, + krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, + krb5_pa_data *pa, + preauth_get_entry_data_proc ets_get_entry_data, + void *pa_system_context, + void **pa_request_context, + krb5_data **e_data, + krb5_authdata ***authz_data) { - krb5_pa_enc_ts * pa_enc = 0; - krb5_error_code retval; - krb5_data scratch; - krb5_data enc_ts_data; - krb5_enc_data *enc_data = 0; - krb5_keyblock key, *mkey_ptr; - krb5_key_data * client_key; - krb5_int32 start; - krb5_timestamp timenow; - krb5_error_code decrypt_err = 0; + krb5_pa_enc_ts * pa_enc = 0; + krb5_error_code retval; + krb5_data scratch; + krb5_data enc_ts_data; + krb5_enc_data *enc_data = 0; + krb5_keyblock key, *mkey_ptr; + krb5_key_data * client_key; + krb5_int32 start; + krb5_timestamp timenow; + krb5_error_code decrypt_err = 0; scratch.data = (char *)pa->contents; scratch.length = pa->length; enc_ts_data.data = 0; - + if ((retval = decode_krb5_enc_data(&scratch, &enc_data)) != 0) - goto cleanup; + goto cleanup; enc_ts_data.length = enc_data->ciphertext.length; if ((enc_ts_data.data = (char *) malloc(enc_ts_data.length)) == NULL) - goto cleanup; + goto cleanup; if ((retval = krb5_dbe_find_mkey(context, master_keylist, client, &mkey_ptr))) { @@ -1428,49 +1429,49 @@ verify_enc_timestamp(krb5_context context, krb5_db_entry *client, start = 0; decrypt_err = 0; while (1) { - if ((retval = krb5_dbe_search_enctype(context, client, - &start, enc_data->enctype, - -1, 0, &client_key))) - goto cleanup; + if ((retval = krb5_dbe_search_enctype(context, client, + &start, enc_data->enctype, + -1, 0, &client_key))) + goto cleanup; - if ((retval = krb5_dbekd_decrypt_key_data(context, mkey_ptr, - client_key, &key, NULL))) - goto cleanup; + if ((retval = krb5_dbekd_decrypt_key_data(context, mkey_ptr, + client_key, &key, NULL))) + goto cleanup; - key.enctype = enc_data->enctype; + key.enctype = enc_data->enctype; - retval = krb5_c_decrypt(context, &key, KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS, - 0, enc_data, &enc_ts_data); - krb5_free_keyblock_contents(context, &key); - if (retval == 0) - break; - else - decrypt_err = retval; + retval = krb5_c_decrypt(context, &key, KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS, + 0, enc_data, &enc_ts_data); + krb5_free_keyblock_contents(context, &key); + if (retval == 0) + break; + else + decrypt_err = retval; } if ((retval = decode_krb5_pa_enc_ts(&enc_ts_data, &pa_enc)) != 0) - goto cleanup; + goto cleanup; if ((retval = krb5_timeofday(context, &timenow)) != 0) - goto cleanup; - + goto cleanup; + if (labs(timenow - pa_enc->patimestamp) > context->clockskew) { - retval = KRB5KRB_AP_ERR_SKEW; - goto cleanup; + retval = KRB5KRB_AP_ERR_SKEW; + goto cleanup; } setflag(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH); retval = 0; - + cleanup: if (enc_data) { - krb5_free_data_contents(context, &enc_data->ciphertext); - free(enc_data); + krb5_free_data_contents(context, &enc_data->ciphertext); + free(enc_data); } krb5_free_data_contents(context, &enc_ts_data); if (pa_enc) - free(pa_enc); + free(pa_enc); /* * If we get NO_MATCHING_KEY and decryption previously failed, and * we failed to find any other keys of the correct enctype after @@ -1478,22 +1479,22 @@ cleanup: * incorrect. */ if (retval == KRB5_KDB_NO_MATCHING_KEY && decrypt_err != 0) - retval = decrypt_err; + retval = decrypt_err; return retval; } static krb5_error_code _make_etype_info_entry(krb5_context context, - krb5_principal client_princ, krb5_key_data *client_key, - krb5_enctype etype, krb5_etype_info_entry **entry, - int etype_info2) + krb5_principal client_princ, krb5_key_data *client_key, + krb5_enctype etype, krb5_etype_info_entry **entry, + int etype_info2) { - krb5_data salt; - krb5_etype_info_entry * tmp_entry; - krb5_error_code retval; + krb5_data salt; + krb5_etype_info_entry * tmp_entry; + krb5_error_code retval; if ((tmp_entry = malloc(sizeof(krb5_etype_info_entry))) == NULL) - return ENOMEM; + return ENOMEM; salt.data = 0; @@ -1505,125 +1506,125 @@ _make_etype_info_entry(krb5_context context, tmp_entry->s2kparams.length = 0; retval = get_salt_from_key(context, client_princ, client_key, &salt); if (retval) - goto fail; + goto fail; if (etype_info2 && client_key->key_data_ver > 1 && - client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_AFS3) { - switch (etype) { - case ENCTYPE_DES_CBC_CRC: - case ENCTYPE_DES_CBC_MD4: - case ENCTYPE_DES_CBC_MD5: - tmp_entry->s2kparams.data = malloc(1); - if (tmp_entry->s2kparams.data == NULL) { - retval = ENOMEM; - goto fail; - } - tmp_entry->s2kparams.length = 1; - tmp_entry->s2kparams.data[0] = 1; - break; - default: - break; - } + client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_AFS3) { + switch (etype) { + case ENCTYPE_DES_CBC_CRC: + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_MD5: + tmp_entry->s2kparams.data = malloc(1); + if (tmp_entry->s2kparams.data == NULL) { + retval = ENOMEM; + goto fail; + } + tmp_entry->s2kparams.length = 1; + tmp_entry->s2kparams.data[0] = 1; + break; + default: + break; + } } if (salt.length >= 0) { - tmp_entry->length = salt.length; - tmp_entry->salt = (unsigned char *) salt.data; - salt.data = 0; + tmp_entry->length = salt.length; + tmp_entry->salt = (unsigned char *) salt.data; + salt.data = 0; } *entry = tmp_entry; return 0; fail: if (tmp_entry) { - if (tmp_entry->s2kparams.data) - free(tmp_entry->s2kparams.data); - free(tmp_entry); + if (tmp_entry->s2kparams.data) + free(tmp_entry->s2kparams.data); + free(tmp_entry); } if (salt.data) - free(salt.data); + free(salt.data); return retval; } /* * This function returns the etype information for a particular * client, to be passed back in the preauth list in the KRB_ERROR * message. It supports generating both etype_info and etype_info2 - * as most of the work is the same. + * as most of the work is the same. */ static krb5_error_code etype_info_helper(krb5_context context, krb5_kdc_req *request, - krb5_db_entry *client, krb5_db_entry *server, - krb5_pa_data *pa_data, int etype_info2) + krb5_db_entry *client, krb5_db_entry *server, + krb5_pa_data *pa_data, int etype_info2) { - krb5_etype_info_entry ** entry = 0; - krb5_key_data *client_key; - krb5_error_code retval; - krb5_data * scratch; - krb5_enctype db_etype; - int i = 0; - int start = 0; - int seen_des = 0; + krb5_etype_info_entry ** entry = 0; + krb5_key_data *client_key; + krb5_error_code retval; + krb5_data * scratch; + krb5_enctype db_etype; + int i = 0; + int start = 0; + int seen_des = 0; entry = malloc((client->n_key_data * 2 + 1) * sizeof(krb5_etype_info_entry *)); if (entry == NULL) - return ENOMEM; + return ENOMEM; entry[0] = NULL; while (1) { - retval = krb5_dbe_search_enctype(context, client, &start, -1, - -1, 0, &client_key); - if (retval == KRB5_KDB_NO_MATCHING_KEY) - break; - if (retval) - goto cleanup; - db_etype = client_key->key_data_type[0]; - if (db_etype == ENCTYPE_DES_CBC_MD4) - db_etype = ENCTYPE_DES_CBC_MD5; - - if (request_contains_enctype(context, request, db_etype)) { - assert(etype_info2 || - !enctype_requires_etype_info_2(db_etype)); - retval = _make_etype_info_entry(context, client->princ, client_key, - db_etype, &entry[i], etype_info2); - if (retval != 0) - goto cleanup; - entry[i+1] = 0; - i++; - } - - /* - * If there is a des key in the kdb, try the "similar" enctypes, - * avoid duplicate entries. - */ - if (!seen_des) { - switch (db_etype) { - case ENCTYPE_DES_CBC_MD5: - db_etype = ENCTYPE_DES_CBC_CRC; - break; - case ENCTYPE_DES_CBC_CRC: - db_etype = ENCTYPE_DES_CBC_MD5; - break; - default: - continue; - - } - if (request_contains_enctype(context, request, db_etype)) { - retval = _make_etype_info_entry(context, client->princ, - client_key, db_etype, - &entry[i], etype_info2); - if (retval != 0) - goto cleanup; - entry[i+1] = 0; - i++; - } - seen_des++; - } + retval = krb5_dbe_search_enctype(context, client, &start, -1, + -1, 0, &client_key); + if (retval == KRB5_KDB_NO_MATCHING_KEY) + break; + if (retval) + goto cleanup; + db_etype = client_key->key_data_type[0]; + if (db_etype == ENCTYPE_DES_CBC_MD4) + db_etype = ENCTYPE_DES_CBC_MD5; + + if (request_contains_enctype(context, request, db_etype)) { + assert(etype_info2 || + !enctype_requires_etype_info_2(db_etype)); + retval = _make_etype_info_entry(context, client->princ, client_key, + db_etype, &entry[i], etype_info2); + if (retval != 0) + goto cleanup; + entry[i+1] = 0; + i++; + } + + /* + * If there is a des key in the kdb, try the "similar" enctypes, + * avoid duplicate entries. + */ + if (!seen_des) { + switch (db_etype) { + case ENCTYPE_DES_CBC_MD5: + db_etype = ENCTYPE_DES_CBC_CRC; + break; + case ENCTYPE_DES_CBC_CRC: + db_etype = ENCTYPE_DES_CBC_MD5; + break; + default: + continue; + + } + if (request_contains_enctype(context, request, db_etype)) { + retval = _make_etype_info_entry(context, client->princ, + client_key, db_etype, + &entry[i], etype_info2); + if (retval != 0) + goto cleanup; + entry[i+1] = 0; + i++; + } + seen_des++; + } } if (etype_info2) - retval = encode_krb5_etype_info2(entry, &scratch); + retval = encode_krb5_etype_info2(entry, &scratch); else - retval = encode_krb5_etype_info(entry, &scratch); + retval = encode_krb5_etype_info(entry, &scratch); if (retval) - goto cleanup; + goto cleanup; pa_data->contents = (unsigned char *)scratch->data; pa_data->length = scratch->length; free(scratch); @@ -1632,45 +1633,45 @@ etype_info_helper(krb5_context context, krb5_kdc_req *request, cleanup: if (entry) - krb5_free_etype_info(context, entry); + krb5_free_etype_info(context, entry); return retval; } static krb5_error_code get_etype_info(krb5_context context, krb5_kdc_req *request, - krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc etype_get_entry_data, - void *pa_system_context, - krb5_pa_data *pa_data) + krb5_db_entry *client, krb5_db_entry *server, + preauth_get_entry_data_proc etype_get_entry_data, + void *pa_system_context, + krb5_pa_data *pa_data) { - int i; + int i; for (i=0; i < request->nktypes; i++) { - if (enctype_requires_etype_info_2(request->ktype[i])) - return KRB5KDC_ERR_PADATA_TYPE_NOSUPP ;;;; /*Caller will - * skip this - * type*/ + if (enctype_requires_etype_info_2(request->ktype[i])) + return KRB5KDC_ERR_PADATA_TYPE_NOSUPP ;;;; /*Caller will + * skip this + * type*/ } return etype_info_helper(context, request, client, server, pa_data, 0); } static krb5_error_code get_etype_info2(krb5_context context, krb5_kdc_req *request, - krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc etype_get_entry_data, - void *pa_system_context, - krb5_pa_data *pa_data) + krb5_db_entry *client, krb5_db_entry *server, + preauth_get_entry_data_proc etype_get_entry_data, + void *pa_system_context, + krb5_pa_data *pa_data) { return etype_info_helper( context, request, client, server, pa_data, 1); } static krb5_error_code -etype_info_as_rep_helper(krb5_context context, krb5_pa_data * padata, - krb5_db_entry *client, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - int etype_info2) +etype_info_as_rep_helper(krb5_context context, krb5_pa_data * padata, + krb5_db_entry *client, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa, + int etype_info2) { int i; krb5_error_code retval; @@ -1683,181 +1684,181 @@ etype_info_as_rep_helper(krb5_context context, krb5_pa_data * padata, * enctypes. */ if (!etype_info2) { - for (i = 0; i < request->nktypes; i++) { - if (enctype_requires_etype_info_2(request->ktype[i])) { - *send_pa = NULL; - return 0; - } - } + for (i = 0; i < request->nktypes; i++) { + if (enctype_requires_etype_info_2(request->ktype[i])) { + *send_pa = NULL; + return 0; + } + } } tmp_padata = malloc( sizeof(krb5_pa_data)); if (tmp_padata == NULL) - return ENOMEM; + return ENOMEM; if (etype_info2) - tmp_padata->pa_type = KRB5_PADATA_ETYPE_INFO2; + tmp_padata->pa_type = KRB5_PADATA_ETYPE_INFO2; else - tmp_padata->pa_type = KRB5_PADATA_ETYPE_INFO; + tmp_padata->pa_type = KRB5_PADATA_ETYPE_INFO; entry = malloc(2 * sizeof(krb5_etype_info_entry *)); if (entry == NULL) { - retval = ENOMEM; - goto cleanup; + retval = ENOMEM; + goto cleanup; } entry[0] = NULL; entry[1] = NULL; retval = _make_etype_info_entry(context, client->princ, client_key, - encrypting_key->enctype, entry, - etype_info2); + encrypting_key->enctype, entry, + etype_info2); if (retval) - goto cleanup; + goto cleanup; if (etype_info2) - retval = encode_krb5_etype_info2(entry, &scratch); + retval = encode_krb5_etype_info2(entry, &scratch); else - retval = encode_krb5_etype_info(entry, &scratch); + retval = encode_krb5_etype_info(entry, &scratch); if (retval) - goto cleanup; + goto cleanup; tmp_padata->contents = (krb5_octet *)scratch->data; tmp_padata->length = scratch->length; *send_pa = tmp_padata; - /* For cleanup - we no longer own the contents of the krb5_data + /* For cleanup - we no longer own the contents of the krb5_data * only to pointer to the krb5_data */ scratch->data = 0; - cleanup: +cleanup: if (entry) - krb5_free_etype_info(context, entry); + krb5_free_etype_info(context, entry); if (retval) { - if (tmp_padata) - free(tmp_padata); + if (tmp_padata) + free(tmp_padata); } if (scratch) - krb5_free_data(context, scratch); + krb5_free_data(context, scratch); return retval; } static krb5_error_code -return_etype_info2(krb5_context context, krb5_pa_data * padata, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - preauth_get_entry_data_proc etype_get_entry_data, - void *pa_system_context, - void **pa_request_context) +return_etype_info2(krb5_context context, krb5_pa_data * padata, + krb5_db_entry *client, + krb5_data *req_pkt, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa, + preauth_get_entry_data_proc etype_get_entry_data, + void *pa_system_context, + void **pa_request_context) { return etype_info_as_rep_helper(context, padata, client, request, reply, - client_key, encrypting_key, send_pa, 1); + client_key, encrypting_key, send_pa, 1); } static krb5_error_code -return_etype_info(krb5_context context, krb5_pa_data * padata, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - preauth_get_entry_data_proc etypeget_entry_data, - void *pa_system_context, - void **pa_request_context) +return_etype_info(krb5_context context, krb5_pa_data * padata, + krb5_db_entry *client, + krb5_data *req_pkt, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa, + preauth_get_entry_data_proc etypeget_entry_data, + void *pa_system_context, + void **pa_request_context) { return etype_info_as_rep_helper(context, padata, client, request, reply, - client_key, encrypting_key, send_pa, 0); + client_key, encrypting_key, send_pa, 0); } static krb5_error_code return_pw_salt(krb5_context context, krb5_pa_data *in_padata, - krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request, - krb5_kdc_rep *reply, krb5_key_data *client_key, - krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, - preauth_get_entry_data_proc etype_get_entry_data, - void *pa_system_context, - void **pa_request_context) + krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request, + krb5_kdc_rep *reply, krb5_key_data *client_key, + krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, + preauth_get_entry_data_proc etype_get_entry_data, + void *pa_system_context, + void **pa_request_context) { - krb5_error_code retval; - krb5_pa_data * padata; - krb5_data * scratch; - krb5_data salt_data; + krb5_error_code retval; + krb5_pa_data * padata; + krb5_data * scratch; + krb5_data salt_data; int i; - + for (i = 0; i < request->nktypes; i++) { - if (enctype_requires_etype_info_2(request->ktype[i])) - return 0; + if (enctype_requires_etype_info_2(request->ktype[i])) + return 0; } if (client_key->key_data_ver == 1 || - client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL) - return 0; + client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL) + return 0; if ((padata = malloc(sizeof(krb5_pa_data))) == NULL) - return ENOMEM; + return ENOMEM; padata->magic = KV5M_PA_DATA; padata->pa_type = KRB5_PADATA_PW_SALT; - + switch (client_key->key_data_type[1]) { case KRB5_KDB_SALTTYPE_V4: - /* send an empty (V4) salt */ - padata->contents = 0; - padata->length = 0; - break; + /* send an empty (V4) salt */ + padata->contents = 0; + padata->length = 0; + break; case KRB5_KDB_SALTTYPE_NOREALM: - if ((retval = krb5_principal2salt_norealm(kdc_context, - request->client, - &salt_data))) - goto cleanup; - padata->contents = (krb5_octet *)salt_data.data; - padata->length = salt_data.length; - break; + if ((retval = krb5_principal2salt_norealm(kdc_context, + request->client, + &salt_data))) + goto cleanup; + padata->contents = (krb5_octet *)salt_data.data; + padata->length = salt_data.length; + break; case KRB5_KDB_SALTTYPE_AFS3: - /* send an AFS style realm-based salt */ - /* for now, just pass the realm back and let the client - do the work. In the future, add a kdc configuration - variable that specifies the old cell name. */ - padata->pa_type = KRB5_PADATA_AFS3_SALT; - /* it would be just like ONLYREALM, but we need to pass the 0 */ - scratch = krb5_princ_realm(kdc_context, request->client); - if ((padata->contents = malloc(scratch->length+1)) == NULL) { - retval = ENOMEM; - goto cleanup; - } - memcpy(padata->contents, scratch->data, scratch->length); - padata->length = scratch->length+1; - padata->contents[scratch->length] = 0; - break; + /* send an AFS style realm-based salt */ + /* for now, just pass the realm back and let the client + do the work. In the future, add a kdc configuration + variable that specifies the old cell name. */ + padata->pa_type = KRB5_PADATA_AFS3_SALT; + /* it would be just like ONLYREALM, but we need to pass the 0 */ + scratch = krb5_princ_realm(kdc_context, request->client); + if ((padata->contents = malloc(scratch->length+1)) == NULL) { + retval = ENOMEM; + goto cleanup; + } + memcpy(padata->contents, scratch->data, scratch->length); + padata->length = scratch->length+1; + padata->contents[scratch->length] = 0; + break; case KRB5_KDB_SALTTYPE_ONLYREALM: - scratch = krb5_princ_realm(kdc_context, request->client); - if ((padata->contents = malloc(scratch->length)) == NULL) { - retval = ENOMEM; - goto cleanup; - } - memcpy(padata->contents, scratch->data, scratch->length); - padata->length = scratch->length; - break; + scratch = krb5_princ_realm(kdc_context, request->client); + if ((padata->contents = malloc(scratch->length)) == NULL) { + retval = ENOMEM; + goto cleanup; + } + memcpy(padata->contents, scratch->data, scratch->length); + padata->length = scratch->length; + break; case KRB5_KDB_SALTTYPE_SPECIAL: - if ((padata->contents = malloc(client_key->key_data_length[1])) - == NULL) { - retval = ENOMEM; - goto cleanup; - } - memcpy(padata->contents, client_key->key_data_contents[1], - client_key->key_data_length[1]); - padata->length = client_key->key_data_length[1]; - break; + if ((padata->contents = malloc(client_key->key_data_length[1])) + == NULL) { + retval = ENOMEM; + goto cleanup; + } + memcpy(padata->contents, client_key->key_data_contents[1], + client_key->key_data_length[1]); + padata->length = client_key->key_data_length[1]; + break; default: - free(padata); - return 0; + free(padata); + return 0; } *send_pa = padata; return 0; - + cleanup: free(padata); return retval; @@ -1865,22 +1866,22 @@ cleanup: static krb5_error_code return_sam_data(krb5_context context, krb5_pa_data *in_padata, - krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request, - krb5_kdc_rep *reply, krb5_key_data *client_key, - krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, - preauth_get_entry_data_proc sam_get_entry_data, - void *pa_system_context, - void **pa_request_context) + krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request, + krb5_kdc_rep *reply, krb5_key_data *client_key, + krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, + preauth_get_entry_data_proc sam_get_entry_data, + void *pa_system_context, + void **pa_request_context) { - krb5_error_code retval; - krb5_data scratch; - int i; + krb5_error_code retval; + krb5_data scratch; + int i; - krb5_sam_response *sr = 0; - krb5_predicted_sam_response *psr = 0; + krb5_sam_response *sr = 0; + krb5_predicted_sam_response *psr = 0; if (in_padata == 0) - return 0; + return 0; /* * We start by doing the same thing verify_sam_response() does: @@ -1891,71 +1892,71 @@ return_sam_data(krb5_context context, krb5_pa_data *in_padata, scratch.data = (char *)in_padata->contents; scratch.length = in_padata->length; - + if ((retval = decode_krb5_sam_response(&scratch, &sr))) { - kdc_err(context, retval, - "return_sam_data(): decode_krb5_sam_response failed"); - goto cleanup; + kdc_err(context, retval, + "return_sam_data(): decode_krb5_sam_response failed"); + goto cleanup; } { - krb5_enc_data tmpdata; + krb5_enc_data tmpdata; - tmpdata.enctype = ENCTYPE_UNKNOWN; - tmpdata.ciphertext = sr->sam_track_id; + tmpdata.enctype = ENCTYPE_UNKNOWN; + tmpdata.ciphertext = sr->sam_track_id; - scratch.length = tmpdata.ciphertext.length; - if ((scratch.data = (char *) malloc(scratch.length)) == NULL) { - retval = ENOMEM; - goto cleanup; - } + scratch.length = tmpdata.ciphertext.length; + if ((scratch.data = (char *) malloc(scratch.length)) == NULL) { + retval = ENOMEM; + goto cleanup; + } - if ((retval = krb5_c_decrypt(context, &psr_key, /* XXX */ 0, 0, - &tmpdata, &scratch))) { - kdc_err(context, retval, - "return_sam_data(): decrypt track_id failed"); - free(scratch.data); - goto cleanup; - } + if ((retval = krb5_c_decrypt(context, &psr_key, /* XXX */ 0, 0, + &tmpdata, &scratch))) { + kdc_err(context, retval, + "return_sam_data(): decrypt track_id failed"); + free(scratch.data); + goto cleanup; + } } if ((retval = decode_krb5_predicted_sam_response(&scratch, &psr))) { - kdc_err(context, retval, - "return_sam_data(): decode_krb5_predicted_sam_response failed"); - free(scratch.data); - goto cleanup; + kdc_err(context, retval, + "return_sam_data(): decode_krb5_predicted_sam_response failed"); + free(scratch.data); + goto cleanup; } /* We could use sr->sam_flags, but it may be absent or altered. */ if (psr->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) { - kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED, - "Unsupported SAM flag must-pk-encrypt-sad"); - goto cleanup; + kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED, + "Unsupported SAM flag must-pk-encrypt-sad"); + goto cleanup; } if (psr->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) { - /* No key munging */ - goto cleanup; + /* No key munging */ + goto cleanup; } if (psr->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) { - /* Use sam_key instead of client key */ - krb5_free_keyblock_contents(context, encrypting_key); - krb5_copy_keyblock_contents(context, &psr->sam_key, encrypting_key); - /* XXX Attach a useful pa_data */ - goto cleanup; + /* Use sam_key instead of client key */ + krb5_free_keyblock_contents(context, encrypting_key); + krb5_copy_keyblock_contents(context, &psr->sam_key, encrypting_key); + /* XXX Attach a useful pa_data */ + goto cleanup; } /* Otherwise (no flags set), we XOR the keys */ /* XXX The passwords-04 draft is underspecified here wrt different - key types. We will do what I hope to get into the -05 draft. */ + key types. We will do what I hope to get into the -05 draft. */ { - krb5_octet *p = encrypting_key->contents; - krb5_octet *q = psr->sam_key.contents; - int length = ((encrypting_key->length < psr->sam_key.length) - ? encrypting_key->length - : psr->sam_key.length); + krb5_octet *p = encrypting_key->contents; + krb5_octet *q = psr->sam_key.contents; + int length = ((encrypting_key->length < psr->sam_key.length) + ? encrypting_key->length + : psr->sam_key.length); - for (i = 0; i < length; i++) - p[i] ^= q[i]; + for (i = 0; i < length; i++) + p[i] ^= q[i]; } /* Post-mixing key correction */ @@ -1964,58 +1965,58 @@ return_sam_data(krb5_context context, krb5_pa_data *in_padata, case ENCTYPE_DES_CBC_MD4: case ENCTYPE_DES_CBC_MD5: case ENCTYPE_DES_CBC_RAW: - mit_des_fixup_key_parity(encrypting_key->contents); - if (mit_des_is_weak_key(encrypting_key->contents)) - ((krb5_octet *) encrypting_key->contents)[7] ^= 0xf0; - break; + mit_des_fixup_key_parity(encrypting_key->contents); + if (mit_des_is_weak_key(encrypting_key->contents)) + ((krb5_octet *) encrypting_key->contents)[7] ^= 0xf0; + break; - /* XXX case ENCTYPE_DES3_CBC_MD5: listed in 1510bis-04 draft */ + /* XXX case ENCTYPE_DES3_CBC_MD5: listed in 1510bis-04 draft */ case ENCTYPE_DES3_CBC_SHA: /* XXX deprecated? */ case ENCTYPE_DES3_CBC_RAW: case ENCTYPE_DES3_CBC_SHA1: - for (i = 0; i < 3; i++) { - mit_des_fixup_key_parity(encrypting_key->contents + i * 8); - if (mit_des_is_weak_key(encrypting_key->contents + i * 8)) - ((krb5_octet *) encrypting_key->contents)[7 + i * 8] ^= 0xf0; - } - break; + for (i = 0; i < 3; i++) { + mit_des_fixup_key_parity(encrypting_key->contents + i * 8); + if (mit_des_is_weak_key(encrypting_key->contents + i * 8)) + ((krb5_octet *) encrypting_key->contents)[7 + i * 8] ^= 0xf0; + } + break; default: - kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED, - "Unimplemented keytype for SAM key mixing"); - goto cleanup; + kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED, + "Unimplemented keytype for SAM key mixing"); + goto cleanup; } /* XXX Attach a useful pa_data */ cleanup: if (sr) - krb5_free_sam_response(context, sr); + krb5_free_sam_response(context, sr); if (psr) - krb5_free_predicted_sam_response(context, psr); + krb5_free_predicted_sam_response(context, psr); return retval; } - + static struct { - char* name; - int sam_type; + char* name; + int sam_type; } *sam_ptr, sam_inst_map[] = { - { "SNK4", PA_SAM_TYPE_DIGI_PATH, }, - { "SECURID", PA_SAM_TYPE_SECURID, }, - { "GRAIL", PA_SAM_TYPE_GRAIL, }, - { 0, 0 }, + { "SNK4", PA_SAM_TYPE_DIGI_PATH, }, + { "SECURID", PA_SAM_TYPE_SECURID, }, + { "GRAIL", PA_SAM_TYPE_GRAIL, }, + { 0, 0 }, }; static krb5_error_code get_sam_edata(krb5_context context, krb5_kdc_req *request, - krb5_db_entry *client, krb5_db_entry *server, - preauth_get_entry_data_proc sam_get_entry_data, - void *pa_system_context, krb5_pa_data *pa_data) + krb5_db_entry *client, krb5_db_entry *server, + preauth_get_entry_data_proc sam_get_entry_data, + void *pa_system_context, krb5_pa_data *pa_data) { - krb5_error_code retval; - krb5_sam_challenge sc; - krb5_predicted_sam_response psr; - krb5_data * scratch; + krb5_error_code retval; + krb5_sam_challenge sc; + krb5_predicted_sam_response psr; + krb5_data * scratch; krb5_keyblock encrypting_key, *mkey_ptr; char response[9]; char inputblock[8]; @@ -2029,368 +2030,368 @@ get_sam_edata(krb5_context context, krb5_kdc_req *request, names that match the types of preauth used. Later we should make this mapping show up in kdc.conf. In the meantime, we hardcode the following: - /SNK4 -- Digital Pathways SNK/4 preauth. - /GRAIL -- experimental preauth + /SNK4 -- Digital Pathways SNK/4 preauth. + /GRAIL -- experimental preauth The first one found is used. See sam_inst_map above. For SNK4 in particular, the key in the database is the key for the device; kadmin needs a special interface for it. - */ + */ { - int npr = 1; - krb5_boolean more; - krb5_db_entry assoc; - krb5_key_data *assoc_key; - krb5_principal newp; - int probeslot; - - sc.sam_type = 0; - - retval = krb5_copy_principal(kdc_context, request->client, &newp); - if (retval) { - kdc_err(kdc_context, retval, "copying client name for preauth probe"); - return retval; - } - - probeslot = krb5_princ_size(context, newp)++; - krb5_princ_name(kdc_context, newp) = - realloc(krb5_princ_name(kdc_context, newp), - krb5_princ_size(context, newp) * sizeof(krb5_data)); - - for(sam_ptr = sam_inst_map; sam_ptr->name; sam_ptr++) { - krb5_princ_component(kdc_context,newp,probeslot)->data = sam_ptr->name; - krb5_princ_component(kdc_context,newp,probeslot)->length = - strlen(sam_ptr->name); - npr = 1; - retval = get_principal(kdc_context, newp, &assoc, &npr, &more); - if(!retval && npr) { - sc.sam_type = sam_ptr->sam_type; - break; - } - } - - krb5_princ_component(kdc_context,newp,probeslot)->data = 0; - krb5_princ_component(kdc_context,newp,probeslot)->length = 0; - krb5_princ_size(context, newp)--; - - krb5_free_principal(kdc_context, newp); - - /* if sc.sam_type is set, it worked */ - if (sc.sam_type) { - /* so use assoc to get the key out! */ - { - if ((retval = krb5_dbe_find_mkey(context, master_keylist, &assoc, - &mkey_ptr))) { - krb5_keylist_node *tmp_mkey_list; - /* try refreshing the mkey list in case it's been updated */ - if (krb5_db_fetch_mkey_list(context, master_princ, - &master_keyblock, 0, - &tmp_mkey_list) == 0) { - krb5_dbe_free_key_list(context, master_keylist); - master_keylist = tmp_mkey_list; - if ((retval = krb5_dbe_find_mkey(context, master_keylist, &assoc, - &mkey_ptr))) { - return (retval); - } - } else { - return (retval); - } - } - - /* here's what do_tgs_req does */ - retval = krb5_dbe_find_enctype(kdc_context, &assoc, - ENCTYPE_DES_CBC_RAW, - KRB5_KDB_SALTTYPE_NORMAL, - 0, /* Get highest kvno */ - &assoc_key); - if (retval) { - char *sname; - krb5_unparse_name(kdc_context, request->client, &sname); - kdc_err(kdc_context, retval, - "snk4 finding the enctype and key <%s>", sname); - free(sname); - return retval; - } - /* convert server.key into a real key */ - retval = krb5_dbekd_decrypt_key_data(kdc_context, - mkey_ptr, - assoc_key, &encrypting_key, - NULL); - if (retval) { - kdc_err(kdc_context, retval, - "snk4 pulling out key entry"); - return retval; - } - /* now we can use encrypting_key... */ - } - } else { - /* SAM is not an option - so don't return as hint */ - return KRB5_PREAUTH_BAD_TYPE; - } + int npr = 1; + krb5_boolean more; + krb5_db_entry assoc; + krb5_key_data *assoc_key; + krb5_principal newp; + int probeslot; + + sc.sam_type = 0; + + retval = krb5_copy_principal(kdc_context, request->client, &newp); + if (retval) { + kdc_err(kdc_context, retval, "copying client name for preauth probe"); + return retval; + } + + probeslot = krb5_princ_size(context, newp)++; + krb5_princ_name(kdc_context, newp) = + realloc(krb5_princ_name(kdc_context, newp), + krb5_princ_size(context, newp) * sizeof(krb5_data)); + + for(sam_ptr = sam_inst_map; sam_ptr->name; sam_ptr++) { + krb5_princ_component(kdc_context,newp,probeslot)->data = sam_ptr->name; + krb5_princ_component(kdc_context,newp,probeslot)->length = + strlen(sam_ptr->name); + npr = 1; + retval = get_principal(kdc_context, newp, &assoc, &npr, &more); + if(!retval && npr) { + sc.sam_type = sam_ptr->sam_type; + break; + } + } + + krb5_princ_component(kdc_context,newp,probeslot)->data = 0; + krb5_princ_component(kdc_context,newp,probeslot)->length = 0; + krb5_princ_size(context, newp)--; + + krb5_free_principal(kdc_context, newp); + + /* if sc.sam_type is set, it worked */ + if (sc.sam_type) { + /* so use assoc to get the key out! */ + { + if ((retval = krb5_dbe_find_mkey(context, master_keylist, &assoc, + &mkey_ptr))) { + krb5_keylist_node *tmp_mkey_list; + /* try refreshing the mkey list in case it's been updated */ + if (krb5_db_fetch_mkey_list(context, master_princ, + &master_keyblock, 0, + &tmp_mkey_list) == 0) { + krb5_dbe_free_key_list(context, master_keylist); + master_keylist = tmp_mkey_list; + if ((retval = krb5_dbe_find_mkey(context, master_keylist, &assoc, + &mkey_ptr))) { + return (retval); + } + } else { + return (retval); + } + } + + /* here's what do_tgs_req does */ + retval = krb5_dbe_find_enctype(kdc_context, &assoc, + ENCTYPE_DES_CBC_RAW, + KRB5_KDB_SALTTYPE_NORMAL, + 0, /* Get highest kvno */ + &assoc_key); + if (retval) { + char *sname; + krb5_unparse_name(kdc_context, request->client, &sname); + kdc_err(kdc_context, retval, + "snk4 finding the enctype and key <%s>", sname); + free(sname); + return retval; + } + /* convert server.key into a real key */ + retval = krb5_dbekd_decrypt_key_data(kdc_context, + mkey_ptr, + assoc_key, &encrypting_key, + NULL); + if (retval) { + kdc_err(kdc_context, retval, + "snk4 pulling out key entry"); + return retval; + } + /* now we can use encrypting_key... */ + } + } else { + /* SAM is not an option - so don't return as hint */ + return KRB5_PREAUTH_BAD_TYPE; + } } sc.magic = KV5M_SAM_CHALLENGE; psr.sam_flags = sc.sam_flags = KRB5_SAM_USE_SAD_AS_KEY; /* Replay prevention */ if ((retval = krb5_copy_principal(context, request->client, &psr.client))) - return retval; + return retval; #ifdef USE_RCACHE if ((retval = krb5_us_timeofday(context, &psr.stime, &psr.susec))) - return retval; + return retval; #endif /* USE_RCACHE */ switch (sc.sam_type) { case PA_SAM_TYPE_GRAIL: - sc.sam_type_name.data = "Experimental System"; - sc.sam_type_name.length = strlen(sc.sam_type_name.data); - sc.sam_challenge_label.data = "experimental challenge label"; - sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data); - sc.sam_challenge.data = "12345"; - sc.sam_challenge.length = strlen(sc.sam_challenge.data); + sc.sam_type_name.data = "Experimental System"; + sc.sam_type_name.length = strlen(sc.sam_type_name.data); + sc.sam_challenge_label.data = "experimental challenge label"; + sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data); + sc.sam_challenge.data = "12345"; + sc.sam_challenge.length = strlen(sc.sam_challenge.data); #if 0 /* Enable this to test "normal" (no flags set) mode. */ - psr.sam_flags = sc.sam_flags = 0; + psr.sam_flags = sc.sam_flags = 0; #endif - psr.magic = KV5M_PREDICTED_SAM_RESPONSE; - /* string2key on sc.sam_challenge goes in here */ - /* eblock is just to set the enctype */ - { - const krb5_enctype type = ENCTYPE_DES_CBC_MD5; - - if ((retval = krb5_c_string_to_key(context, type, &sc.sam_challenge, - 0 /* salt */, &psr.sam_key))) - goto cleanup; - - if ((retval = encode_krb5_predicted_sam_response(&psr, &scratch))) - goto cleanup; - - { - size_t enclen; - krb5_enc_data tmpdata; - - if ((retval = krb5_c_encrypt_length(context, - psr_key.enctype, - scratch->length, &enclen))) - goto cleanup; - - if ((tmpdata.ciphertext.data = (char *) malloc(enclen)) == NULL) { - retval = ENOMEM; - goto cleanup; - } - tmpdata.ciphertext.length = enclen; - - if ((retval = krb5_c_encrypt(context, &psr_key, - /* XXX */ 0, 0, scratch, &tmpdata))) - goto cleanup; - - sc.sam_track_id = tmpdata.ciphertext; - } - } - - sc.sam_response_prompt.data = "response prompt"; - sc.sam_response_prompt.length = strlen(sc.sam_response_prompt.data); - sc.sam_pk_for_sad.length = 0; - sc.sam_nonce = 0; - /* Generate checksum */ - /*krb5_checksum_size(context, ctype)*/ - /*krb5_calculate_checksum(context,ctype,in,in_length,seed, - seed_length,outcksum) */ - /*krb5_verify_checksum(context,ctype,cksum,in,in_length,seed, - seed_length) */ + psr.magic = KV5M_PREDICTED_SAM_RESPONSE; + /* string2key on sc.sam_challenge goes in here */ + /* eblock is just to set the enctype */ + { + const krb5_enctype type = ENCTYPE_DES_CBC_MD5; + + if ((retval = krb5_c_string_to_key(context, type, &sc.sam_challenge, + 0 /* salt */, &psr.sam_key))) + goto cleanup; + + if ((retval = encode_krb5_predicted_sam_response(&psr, &scratch))) + goto cleanup; + + { + size_t enclen; + krb5_enc_data tmpdata; + + if ((retval = krb5_c_encrypt_length(context, + psr_key.enctype, + scratch->length, &enclen))) + goto cleanup; + + if ((tmpdata.ciphertext.data = (char *) malloc(enclen)) == NULL) { + retval = ENOMEM; + goto cleanup; + } + tmpdata.ciphertext.length = enclen; + + if ((retval = krb5_c_encrypt(context, &psr_key, + /* XXX */ 0, 0, scratch, &tmpdata))) + goto cleanup; + + sc.sam_track_id = tmpdata.ciphertext; + } + } + + sc.sam_response_prompt.data = "response prompt"; + sc.sam_response_prompt.length = strlen(sc.sam_response_prompt.data); + sc.sam_pk_for_sad.length = 0; + sc.sam_nonce = 0; + /* Generate checksum */ + /*krb5_checksum_size(context, ctype)*/ + /*krb5_calculate_checksum(context,ctype,in,in_length,seed, + seed_length,outcksum) */ + /*krb5_verify_checksum(context,ctype,cksum,in,in_length,seed, + seed_length) */ #if 0 /* XXX a) glue appears broken; b) this gives up the SAD */ - sc.sam_cksum.contents = (krb5_octet *) - malloc(krb5_checksum_size(context, CKSUMTYPE_RSA_MD5_DES)); - if (sc.sam_cksum.contents == NULL) return(ENOMEM); - - retval = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5_DES, - sc.sam_challenge.data, - sc.sam_challenge.length, - psr.sam_key.contents, /* key */ - psr.sam_key.length, /* key length */ - &sc.sam_cksum); - if (retval) { free(sc.sam_cksum.contents); return(retval); } + sc.sam_cksum.contents = (krb5_octet *) + malloc(krb5_checksum_size(context, CKSUMTYPE_RSA_MD5_DES)); + if (sc.sam_cksum.contents == NULL) return(ENOMEM); + + retval = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5_DES, + sc.sam_challenge.data, + sc.sam_challenge.length, + psr.sam_key.contents, /* key */ + psr.sam_key.length, /* key length */ + &sc.sam_cksum); + if (retval) { free(sc.sam_cksum.contents); return(retval); } #endif /* 0 */ - - retval = encode_krb5_sam_challenge(&sc, &scratch); - if (retval) goto cleanup; - pa_data->magic = KV5M_PA_DATA; - pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE; - pa_data->contents = (krb5_octet *)scratch->data; - pa_data->length = scratch->length; - - retval = 0; - break; + + retval = encode_krb5_sam_challenge(&sc, &scratch); + if (retval) goto cleanup; + pa_data->magic = KV5M_PA_DATA; + pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE; + pa_data->contents = (krb5_octet *)scratch->data; + pa_data->length = scratch->length; + + retval = 0; + break; case PA_SAM_TYPE_DIGI_PATH: - sc.sam_type_name.data = "Digital Pathways"; - sc.sam_type_name.length = strlen(sc.sam_type_name.data); + sc.sam_type_name.data = "Digital Pathways"; + sc.sam_type_name.length = strlen(sc.sam_type_name.data); #if 1 - sc.sam_challenge_label.data = "Enter the following on your keypad"; - sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data); + sc.sam_challenge_label.data = "Enter the following on your keypad"; + sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data); #endif - /* generate digit string, take it mod 1000000 (six digits.) */ - { - int j; - krb5_keyblock session_key; - char outputblock[8]; - int i; - - session_key.contents = 0; - - memset(inputblock, 0, 8); - - retval = krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_CRC, - &session_key); - - if (retval) { - /* random key failed */ - kdc_err(kdc_context, retval, - "generating random challenge for preauth"); - return retval; - } - /* now session_key has a key which we can pick bits out of */ - /* we need six decimal digits. Grab 6 bytes, div 2, mod 10 each. */ - if (session_key.length != 8) { - kdc_err(kdc_context, retval = KRB5KDC_ERR_ETYPE_NOSUPP, - "keytype didn't match code expectations"); - return retval; - } - for(i = 0; i<6; i++) { - inputblock[i] = '0' + ((session_key.contents[i]/2) % 10); - } - if (session_key.contents) - krb5_free_keyblock_contents(kdc_context, &session_key); - - /* retval = krb5_finish_key(kdc_context, &eblock); */ - /* now we have inputblock containing the 8 byte input to DES... */ - sc.sam_challenge.data = inputblock; - sc.sam_challenge.length = 6; - - encrypting_key.enctype = ENCTYPE_DES_CBC_RAW; - - if (retval) - kdc_err(kdc_context, retval, "snk4 processing key"); - - { - krb5_data plain; - krb5_enc_data cipher; - - plain.length = 8; - plain.data = inputblock; - - /* XXX I know this is enough because of the fixed raw enctype. - if it's not, the underlying code will return a reasonable - error, which should never happen */ - cipher.ciphertext.length = 8; - cipher.ciphertext.data = outputblock; - - if ((retval = krb5_c_encrypt(kdc_context, &encrypting_key, - /* XXX */ 0, 0, &plain, &cipher))) { - kdc_err(kdc_context, retval, - "snk4 response generation failed"); - return retval; - } - } - - /* now output block is the raw bits of the response; convert it - to display form */ - for (j=0; j<4; j++) { - char n[2]; - int k; - n[0] = outputblock[j] & 0xf; - n[1] = (outputblock[j]>>4) & 0xf; - for (k=0; k<2; k++) { - if(n[k] > 9) n[k] = ((n[k]-1)>>2); - /* This is equivalent to: - if(n[k]>=0xa && n[k]<=0xc) n[k] = 2; - if(n[k]>=0xd && n[k]<=0xf) n[k] = 3; - */ - } - /* for v4, we keygen: *(j+(char*)&key1) = (n[1]<<4) | n[0]; */ - /* for v5, we just generate a string */ - response[2*j+0] = '0' + n[1]; - response[2*j+1] = '0' + n[0]; - /* and now, response has what we work with. */ - } - response[8] = 0; - predict_response.data = response; - predict_response.length = 8; -#if 0 /* for debugging, hack the output too! */ -sc.sam_challenge_label.data = response; -sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data); + /* generate digit string, take it mod 1000000 (six digits.) */ + { + int j; + krb5_keyblock session_key; + char outputblock[8]; + int i; + + session_key.contents = 0; + + memset(inputblock, 0, 8); + + retval = krb5_c_make_random_key(kdc_context, ENCTYPE_DES_CBC_CRC, + &session_key); + + if (retval) { + /* random key failed */ + kdc_err(kdc_context, retval, + "generating random challenge for preauth"); + return retval; + } + /* now session_key has a key which we can pick bits out of */ + /* we need six decimal digits. Grab 6 bytes, div 2, mod 10 each. */ + if (session_key.length != 8) { + kdc_err(kdc_context, retval = KRB5KDC_ERR_ETYPE_NOSUPP, + "keytype didn't match code expectations"); + return retval; + } + for(i = 0; i<6; i++) { + inputblock[i] = '0' + ((session_key.contents[i]/2) % 10); + } + if (session_key.contents) + krb5_free_keyblock_contents(kdc_context, &session_key); + + /* retval = krb5_finish_key(kdc_context, &eblock); */ + /* now we have inputblock containing the 8 byte input to DES... */ + sc.sam_challenge.data = inputblock; + sc.sam_challenge.length = 6; + + encrypting_key.enctype = ENCTYPE_DES_CBC_RAW; + + if (retval) + kdc_err(kdc_context, retval, "snk4 processing key"); + + { + krb5_data plain; + krb5_enc_data cipher; + + plain.length = 8; + plain.data = inputblock; + + /* XXX I know this is enough because of the fixed raw enctype. + if it's not, the underlying code will return a reasonable + error, which should never happen */ + cipher.ciphertext.length = 8; + cipher.ciphertext.data = outputblock; + + if ((retval = krb5_c_encrypt(kdc_context, &encrypting_key, + /* XXX */ 0, 0, &plain, &cipher))) { + kdc_err(kdc_context, retval, + "snk4 response generation failed"); + return retval; + } + } + + /* now output block is the raw bits of the response; convert it + to display form */ + for (j=0; j<4; j++) { + char n[2]; + int k; + n[0] = outputblock[j] & 0xf; + n[1] = (outputblock[j]>>4) & 0xf; + for (k=0; k<2; k++) { + if(n[k] > 9) n[k] = ((n[k]-1)>>2); + /* This is equivalent to: + if(n[k]>=0xa && n[k]<=0xc) n[k] = 2; + if(n[k]>=0xd && n[k]<=0xf) n[k] = 3; + */ + } + /* for v4, we keygen: *(j+(char*)&key1) = (n[1]<<4) | n[0]; */ + /* for v5, we just generate a string */ + response[2*j+0] = '0' + n[1]; + response[2*j+1] = '0' + n[0]; + /* and now, response has what we work with. */ + } + response[8] = 0; + predict_response.data = response; + predict_response.length = 8; +#if 0 /* for debugging, hack the output too! */ + sc.sam_challenge_label.data = response; + sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data); #endif - } - - psr.magic = KV5M_PREDICTED_SAM_RESPONSE; - /* string2key on sc.sam_challenge goes in here */ - /* eblock is just to set the enctype */ - { - retval = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5, - &predict_response, 0 /* salt */, - &psr.sam_key); - if (retval) goto cleanup; - - retval = encode_krb5_predicted_sam_response(&psr, &scratch); - if (retval) goto cleanup; - - { - size_t enclen; - krb5_enc_data tmpdata; - - if ((retval = krb5_c_encrypt_length(context, - psr_key.enctype, - scratch->length, &enclen))) - goto cleanup; - - if ((tmpdata.ciphertext.data = (char *) malloc(enclen)) == NULL) { - retval = ENOMEM; - goto cleanup; - } - tmpdata.ciphertext.length = enclen; - - if ((retval = krb5_c_encrypt(context, &psr_key, - /* XXX */ 0, 0, scratch, &tmpdata))) - goto cleanup; - - sc.sam_track_id = tmpdata.ciphertext; - } - if (retval) goto cleanup; - } - - sc.sam_response_prompt.data = "Enter the displayed response"; - sc.sam_response_prompt.length = strlen(sc.sam_response_prompt.data); - sc.sam_pk_for_sad.length = 0; - sc.sam_nonce = 0; - /* Generate checksum */ - /*krb5_checksum_size(context, ctype)*/ - /*krb5_calculate_checksum(context,ctype,in,in_length,seed, - seed_length,outcksum) */ - /*krb5_verify_checksum(context,ctype,cksum,in,in_length,seed, - seed_length) */ + } + + psr.magic = KV5M_PREDICTED_SAM_RESPONSE; + /* string2key on sc.sam_challenge goes in here */ + /* eblock is just to set the enctype */ + { + retval = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5, + &predict_response, 0 /* salt */, + &psr.sam_key); + if (retval) goto cleanup; + + retval = encode_krb5_predicted_sam_response(&psr, &scratch); + if (retval) goto cleanup; + + { + size_t enclen; + krb5_enc_data tmpdata; + + if ((retval = krb5_c_encrypt_length(context, + psr_key.enctype, + scratch->length, &enclen))) + goto cleanup; + + if ((tmpdata.ciphertext.data = (char *) malloc(enclen)) == NULL) { + retval = ENOMEM; + goto cleanup; + } + tmpdata.ciphertext.length = enclen; + + if ((retval = krb5_c_encrypt(context, &psr_key, + /* XXX */ 0, 0, scratch, &tmpdata))) + goto cleanup; + + sc.sam_track_id = tmpdata.ciphertext; + } + if (retval) goto cleanup; + } + + sc.sam_response_prompt.data = "Enter the displayed response"; + sc.sam_response_prompt.length = strlen(sc.sam_response_prompt.data); + sc.sam_pk_for_sad.length = 0; + sc.sam_nonce = 0; + /* Generate checksum */ + /*krb5_checksum_size(context, ctype)*/ + /*krb5_calculate_checksum(context,ctype,in,in_length,seed, + seed_length,outcksum) */ + /*krb5_verify_checksum(context,ctype,cksum,in,in_length,seed, + seed_length) */ #if 0 /* XXX a) glue appears broken; b) this gives up the SAD */ - sc.sam_cksum.contents = (krb5_octet *) - malloc(krb5_checksum_size(context, CKSUMTYPE_RSA_MD5_DES)); - if (sc.sam_cksum.contents == NULL) return(ENOMEM); - - retval = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5_DES, - sc.sam_challenge.data, - sc.sam_challenge.length, - psr.sam_key.contents, /* key */ - psr.sam_key.length, /* key length */ - &sc.sam_cksum); - if (retval) { free(sc.sam_cksum.contents); return(retval); } + sc.sam_cksum.contents = (krb5_octet *) + malloc(krb5_checksum_size(context, CKSUMTYPE_RSA_MD5_DES)); + if (sc.sam_cksum.contents == NULL) return(ENOMEM); + + retval = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5_DES, + sc.sam_challenge.data, + sc.sam_challenge.length, + psr.sam_key.contents, /* key */ + psr.sam_key.length, /* key length */ + &sc.sam_cksum); + if (retval) { free(sc.sam_cksum.contents); return(retval); } #endif /* 0 */ - - retval = encode_krb5_sam_challenge(&sc, &scratch); - if (retval) goto cleanup; - pa_data->magic = KV5M_PA_DATA; - pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE; - pa_data->contents = (krb5_octet *)scratch->data; - pa_data->length = scratch->length; - - retval = 0; - break; + + retval = encode_krb5_sam_challenge(&sc, &scratch); + if (retval) goto cleanup; + pa_data->magic = KV5M_PA_DATA; + pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE; + pa_data->contents = (krb5_octet *)scratch->data; + pa_data->length = scratch->length; + + retval = 0; + break; } cleanup: @@ -2400,138 +2401,138 @@ cleanup: static krb5_error_code verify_sam_response(krb5_context context, krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, - krb5_pa_data *pa, - preauth_get_entry_data_proc sam_get_entry_data, - void *pa_system_context, - void **pa_request_context, - krb5_data **e_data, - krb5_authdata ***authz_data) + krb5_data *req_pkt, + krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, + krb5_pa_data *pa, + preauth_get_entry_data_proc sam_get_entry_data, + void *pa_system_context, + void **pa_request_context, + krb5_data **e_data, + krb5_authdata ***authz_data) { - krb5_error_code retval; - krb5_data scratch; - krb5_sam_response *sr = 0; - krb5_predicted_sam_response *psr = 0; - krb5_enc_sam_response_enc *esre = 0; - krb5_timestamp timenow; - char *princ_req = 0, *princ_psr = 0; + krb5_error_code retval; + krb5_data scratch; + krb5_sam_response *sr = 0; + krb5_predicted_sam_response *psr = 0; + krb5_enc_sam_response_enc *esre = 0; + krb5_timestamp timenow; + char *princ_req = 0, *princ_psr = 0; scratch.data = (char *)pa->contents; scratch.length = pa->length; - + if ((retval = decode_krb5_sam_response(&scratch, &sr))) { - scratch.data = 0; - kdc_err(context, retval, "decode_krb5_sam_response failed"); - goto cleanup; + scratch.data = 0; + kdc_err(context, retval, "decode_krb5_sam_response failed"); + goto cleanup; } /* XXX We can only handle the challenge/response model of SAM. - See passwords-04, par 4.1, 4.2 */ + See passwords-04, par 4.1, 4.2 */ { - krb5_enc_data tmpdata; + krb5_enc_data tmpdata; - tmpdata.enctype = ENCTYPE_UNKNOWN; - tmpdata.ciphertext = sr->sam_track_id; + tmpdata.enctype = ENCTYPE_UNKNOWN; + tmpdata.ciphertext = sr->sam_track_id; - scratch.length = tmpdata.ciphertext.length; - if ((scratch.data = (char *) malloc(scratch.length)) == NULL) { - retval = ENOMEM; - goto cleanup; - } + scratch.length = tmpdata.ciphertext.length; + if ((scratch.data = (char *) malloc(scratch.length)) == NULL) { + retval = ENOMEM; + goto cleanup; + } - if ((retval = krb5_c_decrypt(context, &psr_key, /* XXX */ 0, 0, - &tmpdata, &scratch))) { - kdc_err(context, retval, "decrypt track_id failed"); - goto cleanup; - } + if ((retval = krb5_c_decrypt(context, &psr_key, /* XXX */ 0, 0, + &tmpdata, &scratch))) { + kdc_err(context, retval, "decrypt track_id failed"); + goto cleanup; + } } if ((retval = decode_krb5_predicted_sam_response(&scratch, &psr))) { - kdc_err(context, retval, - "decode_krb5_predicted_sam_response failed -- replay attack?"); - goto cleanup; + kdc_err(context, retval, + "decode_krb5_predicted_sam_response failed -- replay attack?"); + goto cleanup; } /* Replay detection */ if ((retval = krb5_unparse_name(context, request->client, &princ_req))) - goto cleanup; + goto cleanup; if ((retval = krb5_unparse_name(context, psr->client, &princ_psr))) - goto cleanup; + goto cleanup; if (strcmp(princ_req, princ_psr) != 0) { - kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED, - "Principal mismatch in SAM psr! -- replay attack?"); - goto cleanup; + kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED, + "Principal mismatch in SAM psr! -- replay attack?"); + goto cleanup; } if ((retval = krb5_timeofday(context, &timenow))) - goto cleanup; + goto cleanup; #ifdef USE_RCACHE { - krb5_donot_replay rep; - extern krb5_deltat rc_lifetime; - /* - * Verify this response came back in a timely manner. - * We do this b/c otherwise very old (expunged from the rcache) - * psr's would be able to be replayed. - */ - if (timenow - psr->stime > rc_lifetime) { - kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED, - "SAM psr came back too late! -- replay attack?"); - goto cleanup; - } - - /* Now check the replay cache. */ - rep.client = princ_psr; - rep.server = "SAM/rc"; /* Should not match any principal name. */ - rep.msghash = NULL; - rep.ctime = psr->stime; - rep.cusec = psr->susec; - retval = krb5_rc_store(kdc_context, kdc_rcache, &rep); - if (retval) { - kdc_err(kdc_context, retval, "SAM psr replay attack!"); - goto cleanup; - } + krb5_donot_replay rep; + extern krb5_deltat rc_lifetime; + /* + * Verify this response came back in a timely manner. + * We do this b/c otherwise very old (expunged from the rcache) + * psr's would be able to be replayed. + */ + if (timenow - psr->stime > rc_lifetime) { + kdc_err(context, retval = KRB5KDC_ERR_PREAUTH_FAILED, + "SAM psr came back too late! -- replay attack?"); + goto cleanup; + } + + /* Now check the replay cache. */ + rep.client = princ_psr; + rep.server = "SAM/rc"; /* Should not match any principal name. */ + rep.msghash = NULL; + rep.ctime = psr->stime; + rep.cusec = psr->susec; + retval = krb5_rc_store(kdc_context, kdc_rcache, &rep); + if (retval) { + kdc_err(kdc_context, retval, "SAM psr replay attack!"); + goto cleanup; + } } #endif /* USE_RCACHE */ { - free(scratch.data); - scratch.length = sr->sam_enc_nonce_or_ts.ciphertext.length; - if ((scratch.data = (char *) malloc(scratch.length)) == NULL) { - retval = ENOMEM; - goto cleanup; - } + free(scratch.data); + scratch.length = sr->sam_enc_nonce_or_ts.ciphertext.length; + if ((scratch.data = (char *) malloc(scratch.length)) == NULL) { + retval = ENOMEM; + goto cleanup; + } - if ((retval = krb5_c_decrypt(context, &psr->sam_key, /* XXX */ 0, - 0, &sr->sam_enc_nonce_or_ts, &scratch))) { - kdc_err(context, retval, "decrypt nonce_or_ts failed"); - goto cleanup; - } + if ((retval = krb5_c_decrypt(context, &psr->sam_key, /* XXX */ 0, + 0, &sr->sam_enc_nonce_or_ts, &scratch))) { + kdc_err(context, retval, "decrypt nonce_or_ts failed"); + goto cleanup; + } } if ((retval = decode_krb5_enc_sam_response_enc(&scratch, &esre))) { - kdc_err(context, retval, "decode_krb5_enc_sam_response_enc failed"); - goto cleanup; + kdc_err(context, retval, "decode_krb5_enc_sam_response_enc failed"); + goto cleanup; } if (esre->sam_timestamp != sr->sam_patimestamp) { - retval = KRB5KDC_ERR_PREAUTH_FAILED; - goto cleanup; + retval = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; } - + if (labs(timenow - sr->sam_patimestamp) > context->clockskew) { - retval = KRB5KRB_AP_ERR_SKEW; - goto cleanup; + retval = KRB5KRB_AP_ERR_SKEW; + goto cleanup; } setflag(enc_tkt_reply->flags, TKT_FLG_HW_AUTH); - cleanup: +cleanup: if (retval) - kdc_err(context, retval, "sam verify failure"); + kdc_err(context, retval, "sam verify failure"); if (scratch.data) free(scratch.data); if (sr) free(sr); if (psr) free(psr); @@ -2552,14 +2553,14 @@ verify_sam_response(krb5_context context, krb5_db_entry *client, #endif /* - * get_edata() - our only job is to determine whether this KDC is capable of - * performing PKINIT. We infer that from the presence or absence of any + * get_edata() - our only job is to determine whether this KDC is capable of + * performing PKINIT. We infer that from the presence or absence of any * KDC signing cert. */ static krb5_error_code get_pkinit_edata( - krb5_context context, + krb5_context context, krb5_kdc_req *request, - krb5_db_entry *client, + krb5_db_entry *client, krb5_db_entry *server, preauth_get_entry_data_proc pkinit_get_entry_data, void *pa_module_context, @@ -2567,17 +2568,17 @@ static krb5_error_code get_pkinit_edata( { krb5_pkinit_signing_cert_t cert = NULL; krb5_error_code err = krb5_pkinit_get_kdc_cert(0, NULL, NULL, &cert); - + kdcPkinitDebug("get_pkinit_edata: kdc cert %s\n", err ? "NOT FOUND" : "FOUND"); if(cert) { - krb5_pkinit_release_cert(cert); + krb5_pkinit_release_cert(cert); } return err; } -/* +/* * This is 0 only for testing until the KDC DB contains - * the hash of the client cert + * the hash of the client cert */ #define REQUIRE_CLIENT_CERT_MATCH 1 @@ -2586,7 +2587,7 @@ static krb5_error_code verify_pkinit_request( krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request, - krb5_enc_tkt_part *enc_tkt_reply, + krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data, preauth_get_entry_data_proc pkinit_get_entry_data, void *pa_module_context, @@ -2594,156 +2595,156 @@ static krb5_error_code verify_pkinit_request( krb5_data **e_data, krb5_authdata ***authz_data) { - krb5_error_code krtn; - krb5_data pa_data; - krb5_data *der_req = NULL; - krb5_boolean valid_cksum; - char *cert_hash = NULL; - unsigned cert_hash_len; - unsigned key_dex; - unsigned cert_match = 0; - krb5_keyblock decrypted_key, *mkey_ptr; - + krb5_error_code krtn; + krb5_data pa_data; + krb5_data *der_req = NULL; + krb5_boolean valid_cksum; + char *cert_hash = NULL; + unsigned cert_hash_len; + unsigned key_dex; + unsigned cert_match = 0; + krb5_keyblock decrypted_key, *mkey_ptr; + /* the data we get from the AS-REQ */ - krb5_timestamp client_ctime = 0; - krb5_ui_4 client_cusec = 0; - krb5_timestamp kdc_ctime = 0; - krb5_int32 kdc_cusec = 0; - krb5_ui_4 nonce = 0; - krb5_checksum pa_cksum; + krb5_timestamp client_ctime = 0; + krb5_ui_4 client_cusec = 0; + krb5_timestamp kdc_ctime = 0; + krb5_int32 kdc_cusec = 0; + krb5_ui_4 nonce = 0; + krb5_checksum pa_cksum; krb5int_cert_sig_status cert_sig_status; - krb5_data client_cert = {0, 0, NULL}; - + krb5_data client_cert = {0, 0, NULL}; + krb5_kdc_req *tmp_as_req = NULL; - + kdcPkinitDebug("verify_pkinit_request\n"); decrypted_key.contents = NULL; pa_data.data = (char *)data->contents; pa_data.length = data->length; - krtn = krb5int_pkinit_as_req_parse(context, &pa_data, - &client_ctime, &client_cusec, - &nonce, &pa_cksum, - &cert_sig_status, - NULL, NULL, /* num_cms_types, cms_types */ - &client_cert, /* signer_cert */ - /* remaining fields unused (for now) */ - NULL, NULL, /* num_all_certs, all_certs */ - NULL, NULL, /* num_trusted_CAs, trusted_CAs */ - NULL); /* kdc_cert */ + krtn = krb5int_pkinit_as_req_parse(context, &pa_data, + &client_ctime, &client_cusec, + &nonce, &pa_cksum, + &cert_sig_status, + NULL, NULL, /* num_cms_types, cms_types */ + &client_cert, /* signer_cert */ + /* remaining fields unused (for now) */ + NULL, NULL, /* num_all_certs, all_certs */ + NULL, NULL, /* num_trusted_CAs, trusted_CAs */ + NULL); /* kdc_cert */ if(krtn) { - kdcPkinitDebug("pa_pk_as_req_parse returned %d; PKINIT aborting.\n", - (int)krtn); - return krtn; + kdcPkinitDebug("pa_pk_as_req_parse returned %d; PKINIT aborting.\n", + (int)krtn); + return krtn; } - #if PKINIT_DEBUG +#if PKINIT_DEBUG if(cert_sig_status != pki_cs_good) { - kdcPkinitDebug("verify_pkinit_request: cert_sig_status %d\n", - (int)cert_sig_status); + kdcPkinitDebug("verify_pkinit_request: cert_sig_status %d\n", + (int)cert_sig_status); } - #endif /* PKINIT_DEBUG */ - - /* +#endif /* PKINIT_DEBUG */ + + /* * Verify signature and cert. * FIXME: The spec calls for an e-data with error-specific type to be * returned on error here. TD_TRUSTED_CERTIFIERS - * to be returned to the client here. There is no way for a preauth - * module to pass back e-data to process_as_req at this time. We - * might want to add such capability via an out param to check_padata - * and to its callees. + * to be returned to the client here. There is no way for a preauth + * module to pass back e-data to process_as_req at this time. We + * might want to add such capability via an out param to check_padata + * and to its callees. */ switch(cert_sig_status) { - case pki_cs_good: - break; - case pki_cs_sig_verify_fail: - /* no e-data */ - krtn = KDC_ERR_INVALID_SIG; - goto cleanup; - case pki_cs_no_root: - case pki_cs_unknown_root: - case pki_cs_untrusted: - /* - * Can't verify to known root. - * e-data TD_TRUSTED_CERTIFIERS - */ - kdcPkinitDebug("verify_pkinit_request: KDC_ERR_CANT_VERIFY_CERTIFICATE\n"); - krtn = KDC_ERR_CANT_VERIFY_CERTIFICATE; - goto cleanup; - case pki_cs_bad_leaf: - case pki_cs_expired: - case pki_cs_not_valid_yet: - /* - * Problems with client cert itself. - * e-data type TD_INVALID_CERTIFICATES - */ - krtn = KDC_ERR_INVALID_CERTIFICATE; - goto cleanup; - case pki_cs_revoked: - /* e-data type TD-INVALID-CERTIFICATES */ - krtn = KDC_ERR_REVOKED_CERTIFICATE; - goto cleanup; - case pki_bad_key_use: - krtn = KDC_ERR_INCONSISTENT_KEY_PURPOSE; - /* no e-data */ - goto cleanup; - case pki_bad_digest: - /* undefined (explicitly!) e-data */ - krtn = KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED; - goto cleanup; - case pki_bad_cms: - case pki_cs_other_err: - default: - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto cleanup; - } - + case pki_cs_good: + break; + case pki_cs_sig_verify_fail: + /* no e-data */ + krtn = KDC_ERR_INVALID_SIG; + goto cleanup; + case pki_cs_no_root: + case pki_cs_unknown_root: + case pki_cs_untrusted: + /* + * Can't verify to known root. + * e-data TD_TRUSTED_CERTIFIERS + */ + kdcPkinitDebug("verify_pkinit_request: KDC_ERR_CANT_VERIFY_CERTIFICATE\n"); + krtn = KDC_ERR_CANT_VERIFY_CERTIFICATE; + goto cleanup; + case pki_cs_bad_leaf: + case pki_cs_expired: + case pki_cs_not_valid_yet: + /* + * Problems with client cert itself. + * e-data type TD_INVALID_CERTIFICATES + */ + krtn = KDC_ERR_INVALID_CERTIFICATE; + goto cleanup; + case pki_cs_revoked: + /* e-data type TD-INVALID-CERTIFICATES */ + krtn = KDC_ERR_REVOKED_CERTIFICATE; + goto cleanup; + case pki_bad_key_use: + krtn = KDC_ERR_INCONSISTENT_KEY_PURPOSE; + /* no e-data */ + goto cleanup; + case pki_bad_digest: + /* undefined (explicitly!) e-data */ + krtn = KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED; + goto cleanup; + case pki_bad_cms: + case pki_cs_other_err: + default: + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + krtn = krb5_us_timeofday(context, &kdc_ctime, &kdc_cusec); if(krtn) { - goto cleanup; + goto cleanup; } if (labs(kdc_ctime - client_ctime) > context->clockskew) { - kdcPkinitDebug("verify_pkinit_request: clock skew violation client %d svr %d\n", - (int)client_ctime, (int)kdc_ctime); - krtn = KRB5KRB_AP_ERR_SKEW; - goto cleanup; + kdcPkinitDebug("verify_pkinit_request: clock skew violation client %d svr %d\n", + (int)client_ctime, (int)kdc_ctime); + krtn = KRB5KRB_AP_ERR_SKEW; + goto cleanup; } - + /* * The KDC may have modified the request after decoding it. * We need to compute the checksum on the data that * came from the client. Therefore, we use the original * packet contents. */ - krtn = decode_krb5_as_req(req_pkt, &tmp_as_req); + krtn = decode_krb5_as_req(req_pkt, &tmp_as_req); if(krtn) { - kdcPkinitDebug("decode_krb5_as_req returned %d\n", (int)krtn); - goto cleanup; + kdcPkinitDebug("decode_krb5_as_req returned %d\n", (int)krtn); + goto cleanup; } - + /* calculate and compare checksum */ krtn = encode_krb5_kdc_req_body(tmp_as_req, &der_req); if(krtn) { - kdcPkinitDebug("encode_krb5_kdc_req_body returned %d\n", (int)krtn); - goto cleanup; + kdcPkinitDebug("encode_krb5_kdc_req_body returned %d\n", (int)krtn); + goto cleanup; } - krtn = krb5_c_verify_checksum(context, NULL, 0, der_req, - &pa_cksum, &valid_cksum); + krtn = krb5_c_verify_checksum(context, NULL, 0, der_req, + &pa_cksum, &valid_cksum); if(krtn) { - kdcPkinitDebug("krb5_c_verify_checksum returned %d\n", (int)krtn); - goto cleanup; + kdcPkinitDebug("krb5_c_verify_checksum returned %d\n", (int)krtn); + goto cleanup; } if(!valid_cksum) { - kdcPkinitDebug("verify_pkinit_request: checksum error\n"); - krtn = KRB5KRB_AP_ERR_BAD_INTEGRITY; - goto cleanup; + kdcPkinitDebug("verify_pkinit_request: checksum error\n"); + krtn = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; } - - #if REQUIRE_CLIENT_CERT_MATCH + +#if REQUIRE_CLIENT_CERT_MATCH /* look up in the KDB to ensure correct client/cert binding */ cert_hash = krb5_pkinit_cert_hash_str(&client_cert); if(cert_hash == NULL) { - krtn = ENOMEM; - goto cleanup; + krtn = ENOMEM; + goto cleanup; } cert_hash_len = strlen(cert_hash); if ((krtn = krb5_dbe_find_mkey(context, master_keylist, &entry, &mkey_ptr))) { @@ -2763,70 +2764,70 @@ static krb5_error_code verify_pkinit_request( } } for(key_dex=0; key_dex<client->n_key_data; key_dex++) { - krb5_key_data *key_data = &client->key_data[key_dex]; - kdcPkinitDebug("--- key %u type[0] %u length[0] %u type[1] %u length[1] %u\n", - key_dex, - key_data->key_data_type[0], key_data->key_data_length[0], - key_data->key_data_type[1], key_data->key_data_length[1]); - if(key_data->key_data_type[1] != KRB5_KDB_SALTTYPE_CERTHASH) { - continue; - } - - /* - * Unfortunately this key is stored encrypted even though it's - * not sensitive... - */ - krtn = krb5_dbekd_decrypt_key_data(context, mkey_ptr, - key_data, &decrypted_key, NULL); - if(krtn) { - kdcPkinitDebug("verify_pkinit_request: error decrypting cert hash block\n"); - break; - } - if((decrypted_key.contents != NULL) && - (cert_hash_len == decrypted_key.length) && - !memcmp(decrypted_key.contents, cert_hash, cert_hash_len)) { - cert_match = 1; - break; - } + krb5_key_data *key_data = &client->key_data[key_dex]; + kdcPkinitDebug("--- key %u type[0] %u length[0] %u type[1] %u length[1] %u\n", + key_dex, + key_data->key_data_type[0], key_data->key_data_length[0], + key_data->key_data_type[1], key_data->key_data_length[1]); + if(key_data->key_data_type[1] != KRB5_KDB_SALTTYPE_CERTHASH) { + continue; + } + + /* + * Unfortunately this key is stored encrypted even though it's + * not sensitive... + */ + krtn = krb5_dbekd_decrypt_key_data(context, mkey_ptr, + key_data, &decrypted_key, NULL); + if(krtn) { + kdcPkinitDebug("verify_pkinit_request: error decrypting cert hash block\n"); + break; + } + if((decrypted_key.contents != NULL) && + (cert_hash_len == decrypted_key.length) && + !memcmp(decrypted_key.contents, cert_hash, cert_hash_len)) { + cert_match = 1; + break; + } } if(decrypted_key.contents) { - krb5_free_keyblock_contents(context, &decrypted_key); + krb5_free_keyblock_contents(context, &decrypted_key); } if(!cert_match) { - kdcPkinitDebug("verify_pkinit_request: client cert does not match\n"); - krtn = KDC_ERR_CLIENT_NOT_TRUSTED; - goto cleanup; - } - #endif /* REQUIRE_CLIENT_CERT_MATCH */ + kdcPkinitDebug("verify_pkinit_request: client cert does not match\n"); + krtn = KDC_ERR_CLIENT_NOT_TRUSTED; + goto cleanup; + } +#endif /* REQUIRE_CLIENT_CERT_MATCH */ krtn = 0; setflag(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH); - + cleanup: if(pa_cksum.contents) { - free(pa_cksum.contents); + free(pa_cksum.contents); } if (tmp_as_req) { - krb5_free_kdc_req(context, tmp_as_req); + krb5_free_kdc_req(context, tmp_as_req); } if (der_req) { - krb5_free_data(context, der_req); + krb5_free_data(context, der_req); } if(cert_hash) { - free(cert_hash); + free(cert_hash); } if(client_cert.data) { - free(client_cert.data); + free(client_cert.data); } kdcPkinitDebug("verify_pkinit_request: returning %d\n", (int)krtn); return krtn; } static krb5_error_code return_pkinit_response( - krb5_context context, - krb5_pa_data * padata, + krb5_context context, + krb5_pa_data * padata, krb5_db_entry *client, krb5_data *req_pkt, - krb5_kdc_req *request, + krb5_kdc_req *request, krb5_kdc_rep *reply, krb5_key_data *client_key, krb5_keyblock *encrypting_key, @@ -2835,79 +2836,79 @@ static krb5_error_code return_pkinit_response( void *pa_module_context, void **pa_request_context) { - krb5_error_code krtn; - krb5_data pa_data; - krb5_pkinit_signing_cert_t signing_cert = NULL; - krb5_checksum as_req_checksum = {0}; - krb5_data *encoded_as_req = NULL; - krb5int_algorithm_id *cms_types = NULL; - krb5_ui_4 num_cms_types = 0; + krb5_error_code krtn; + krb5_data pa_data; + krb5_pkinit_signing_cert_t signing_cert = NULL; + krb5_checksum as_req_checksum = {0}; + krb5_data *encoded_as_req = NULL; + krb5int_algorithm_id *cms_types = NULL; + krb5_ui_4 num_cms_types = 0; /* the data we get from the AS-REQ */ - krb5_ui_4 nonce = 0; - krb5_data client_cert = {0}; - - /* + krb5_ui_4 nonce = 0; + krb5_data client_cert = {0}; + + /* * Trusted CA list and specific KC cert optionally obtained via - * krb5int_pkinit_as_req_parse(). All are DER-encoded - * issuerAndSerialNumbers. + * krb5int_pkinit_as_req_parse(). All are DER-encoded + * issuerAndSerialNumbers. */ - krb5_data *trusted_CAs = NULL; - krb5_ui_4 num_trusted_CAs; - krb5_data kdc_cert = {0}; - + krb5_data *trusted_CAs = NULL; + krb5_ui_4 num_trusted_CAs; + krb5_data kdc_cert = {0}; + if (padata == NULL) { - /* Client has to send us something */ - return 0; + /* Client has to send us something */ + return 0; } - + kdcPkinitDebug("return_pkinit_response\n"); pa_data.data = (char *)padata->contents; pa_data.length = padata->length; - /* - * We've already verified; just obtain the fields we need to create a response + /* + * We've already verified; just obtain the fields we need to create a response */ - krtn = krb5int_pkinit_as_req_parse(context, - &pa_data, - NULL, NULL, &nonce, /* ctime, cusec, nonce */ - NULL, NULL, /* pa_cksum, cert_status */ - &num_cms_types, &cms_types, - &client_cert, /* signer_cert: we encrypt for this */ - /* remaining fields unused (for now) */ - NULL, NULL, /* num_all_certs, all_certs */ - &num_trusted_CAs, &trusted_CAs, - &kdc_cert); + krtn = krb5int_pkinit_as_req_parse(context, + &pa_data, + NULL, NULL, &nonce, /* ctime, cusec, nonce */ + NULL, NULL, /* pa_cksum, cert_status */ + &num_cms_types, &cms_types, + &client_cert, /* signer_cert: we encrypt for this */ + /* remaining fields unused (for now) */ + NULL, NULL, /* num_all_certs, all_certs */ + &num_trusted_CAs, &trusted_CAs, + &kdc_cert); if(krtn) { - kdcPkinitDebug("pa_pk_as_req_parse returned %d; PKINIT aborting.\n", (int)krtn); - goto cleanup; + kdcPkinitDebug("pa_pk_as_req_parse returned %d; PKINIT aborting.\n", (int)krtn); + goto cleanup; } if(client_cert.data == NULL) { - kdcPkinitDebug("pa_pk_as_req_parse failed to give a client_cert; aborting.\n"); - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto cleanup; + kdcPkinitDebug("pa_pk_as_req_parse failed to give a client_cert; aborting.\n"); + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; } if(krb5_pkinit_get_kdc_cert(num_trusted_CAs, trusted_CAs, - (kdc_cert.data ? &kdc_cert : NULL), - &signing_cert)) { - /* - * Since get_pkinit_edata was able to obtain *some* KDC cert, - * this means that we can't satisfy the client's requirement. - * FIXME - particular error status for this? - */ - kdcPkinitDebug("return_pkinit_response: NO appropriate signing cert!\n"); - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto cleanup; - } - - /* + (kdc_cert.data ? &kdc_cert : NULL), + &signing_cert)) { + /* + * Since get_pkinit_edata was able to obtain *some* KDC cert, + * this means that we can't satisfy the client's requirement. + * FIXME - particular error status for this? + */ + kdcPkinitDebug("return_pkinit_response: NO appropriate signing cert!\n"); + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + /* * Cook up keyblock for caller and for outgoing AS-REP. * FIXME how much is known to be valid about encrypting_key? * Will encrypting_key->enctype always be valid here? Seems that * if we allow for clients without a shared secret (i.e. preauth - * by PKINIT only) there won't be a valid encrypting_key set up - * here for us. + * by PKINIT only) there won't be a valid encrypting_key set up + * here for us. */ krb5_free_keyblock_contents(context, encrypting_key); krb5_c_make_random_key(context, encrypting_key->enctype, encrypting_key); @@ -2915,39 +2916,39 @@ static krb5_error_code return_pkinit_response( /* calculate checksum of incoming AS-REQ */ krtn = encode_krb5_as_req(request, &encoded_as_req); if(krtn) { - kdcPkinitDebug("encode_krb5_as_req returned %d; PKINIT aborting.\n", (int)krtn); - goto cleanup; + kdcPkinitDebug("encode_krb5_as_req returned %d; PKINIT aborting.\n", (int)krtn); + goto cleanup; } - krtn = krb5_c_make_checksum(context, context->kdc_req_sumtype, - encrypting_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, - encoded_as_req, &as_req_checksum); + krtn = krb5_c_make_checksum(context, context->kdc_req_sumtype, + encrypting_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, + encoded_as_req, &as_req_checksum); if(krtn) { - goto cleanup; + goto cleanup; } - - /* - * FIXME: here we assume that the client has one cert - the one that + + /* + * FIXME: here we assume that the client has one cert - the one that * signed the AuthPack in the request (and that we therefore obtained from - * krb5int_pkinit_as_req_parse()), and the one we're using to encrypt the + * krb5int_pkinit_as_req_parse()), and the one we're using to encrypt the * ReplyKeyPack with here. This may need rethinking. */ - krtn = krb5int_pkinit_as_rep_create(context, - encrypting_key, &as_req_checksum, signing_cert, TRUE, - &client_cert, - num_cms_types, cms_types, - num_trusted_CAs, trusted_CAs, - (kdc_cert.data ? &kdc_cert : NULL), - &pa_data); + krtn = krb5int_pkinit_as_rep_create(context, + encrypting_key, &as_req_checksum, signing_cert, TRUE, + &client_cert, + num_cms_types, cms_types, + num_trusted_CAs, trusted_CAs, + (kdc_cert.data ? &kdc_cert : NULL), + &pa_data); if(krtn) { - kdcPkinitDebug("pa_pk_as_rep_create returned %d; PKINIT aborting.\n", (int)krtn); - goto cleanup; + kdcPkinitDebug("pa_pk_as_rep_create returned %d; PKINIT aborting.\n", (int)krtn); + goto cleanup; } - + *send_pa = (krb5_pa_data *)malloc(sizeof(krb5_pa_data)); if(*send_pa == NULL) { - krtn = ENOMEM; - free(pa_data.data); - goto cleanup; + krtn = ENOMEM; + free(pa_data.data); + goto cleanup; } (*send_pa)->magic = KV5M_PA_DATA; (*send_pa)->pa_type = KRB5_PADATA_PK_AS_REP; @@ -2955,49 +2956,49 @@ static krb5_error_code return_pkinit_response( (*send_pa)->contents = (krb5_octet *)pa_data.data; krtn = 0; - #if PKINIT_DEBUG +#if PKINIT_DEBUG fprintf(stderr, "return_pkinit_response: SUCCESS\n"); fprintf(stderr, "nonce 0x%x enctype %d keydata %02x %02x %02x %02x...\n", - (int)nonce, (int)encrypting_key->enctype, - encrypting_key->contents[0], encrypting_key->contents[1], - encrypting_key->contents[2], encrypting_key->contents[3]); - #endif + (int)nonce, (int)encrypting_key->enctype, + encrypting_key->contents[0], encrypting_key->contents[1], + encrypting_key->contents[2], encrypting_key->contents[3]); +#endif cleanup: /* all of this was allocd by krb5int_pkinit_as_req_parse() */ if(signing_cert) { - krb5_pkinit_release_cert(signing_cert); + krb5_pkinit_release_cert(signing_cert); } if(cms_types) { - unsigned dex; - krb5int_algorithm_id *alg_id; - - for(dex=0; dex<num_cms_types; dex++) { - alg_id = &cms_types[dex]; - if(alg_id->algorithm.data) { - free(alg_id->algorithm.data); - } - if(alg_id->parameters.data) { - free(alg_id->parameters.data); - } - } - free(cms_types); + unsigned dex; + krb5int_algorithm_id *alg_id; + + for(dex=0; dex<num_cms_types; dex++) { + alg_id = &cms_types[dex]; + if(alg_id->algorithm.data) { + free(alg_id->algorithm.data); + } + if(alg_id->parameters.data) { + free(alg_id->parameters.data); + } + } + free(cms_types); } if(trusted_CAs) { - unsigned dex; - for(dex=0; dex<num_trusted_CAs; dex++) { - free(trusted_CAs[dex].data); - } - free(trusted_CAs); + unsigned dex; + for(dex=0; dex<num_trusted_CAs; dex++) { + free(trusted_CAs[dex].data); + } + free(trusted_CAs); } if(kdc_cert.data) { - free(kdc_cert.data); + free(kdc_cert.data); } if(client_cert.data) { - free(client_cert.data); + free(client_cert.data); } if(encoded_as_req) { - krb5_free_data(context, encoded_as_req); + krb5_free_data(context, encoded_as_req); } return krtn; } @@ -3010,29 +3011,29 @@ cleanup: krb5_boolean include_pac_p(krb5_context context, krb5_kdc_req *request) { - krb5_error_code code; - krb5_pa_data **padata; - krb5_boolean retval = TRUE; /* default is to return PAC */ - krb5_data data; - krb5_pa_pac_req *req = NULL; + krb5_error_code code; + krb5_pa_data **padata; + krb5_boolean retval = TRUE; /* default is to return PAC */ + krb5_data data; + krb5_pa_pac_req *req = NULL; if (request->padata == NULL) { - return retval; + return retval; } for (padata = request->padata; *padata != NULL; padata++) { - if ((*padata)->pa_type == KRB5_PADATA_PAC_REQUEST) { - data.data = (char *)(*padata)->contents; - data.length = (*padata)->length; - - code = decode_krb5_pa_pac_req(&data, &req); - if (code == 0) { - retval = req->include_pac; - krb5_free_pa_pac_req(context, req); - req = NULL; - } - break; - } + if ((*padata)->pa_type == KRB5_PADATA_PAC_REQUEST) { + data.data = (char *)(*padata)->contents; + data.length = (*padata)->length; + + code = decode_krb5_pa_pac_req(&data, &req); + if (code == 0) { + retval = req->include_pac; + krb5_free_pa_pac_req(context, req); + req = NULL; + } + break; + } } return retval; @@ -3040,12 +3041,12 @@ include_pac_p(krb5_context context, krb5_kdc_req *request) krb5_error_code return_svr_referral_data(krb5_context context, - krb5_db_entry *server, - krb5_enc_kdc_rep_part *reply_encpart) + krb5_db_entry *server, + krb5_enc_kdc_rep_part *reply_encpart) { - krb5_error_code code; - krb5_tl_data tl_data; - krb5_pa_data *pa_data; + krb5_error_code code; + krb5_tl_data tl_data; + krb5_pa_data *pa_data; /* This should be initialized and only used for Win2K compat */ assert(reply_encpart->enc_padata == NULL); @@ -3054,28 +3055,28 @@ return_svr_referral_data(krb5_context context, code = krb5_dbe_lookup_tl_data(context, server, &tl_data); if (code || tl_data.tl_data_length == 0) - return 0; /* no server referrals to return */ + return 0; /* no server referrals to return */ pa_data = (krb5_pa_data *)malloc(sizeof(*pa_data)); if (pa_data == NULL) - return ENOMEM; + return ENOMEM; pa_data->magic = KV5M_PA_DATA; pa_data->pa_type = KRB5_PADATA_SVR_REFERRAL_INFO; pa_data->length = tl_data.tl_data_length; pa_data->contents = malloc(pa_data->length); if (pa_data->contents == NULL) { - free(pa_data); - return ENOMEM; + free(pa_data); + return ENOMEM; } memcpy(pa_data->contents, tl_data.tl_data_contents, tl_data.tl_data_length); reply_encpart->enc_padata = (krb5_pa_data **)calloc(2, sizeof(krb5_pa_data *)); if (reply_encpart->enc_padata == NULL) { - free(pa_data->contents); - free(pa_data); - return ENOMEM; - } + free(pa_data->contents); + free(pa_data); + return ENOMEM; + } reply_encpart->enc_padata[0] = pa_data; reply_encpart->enc_padata[1] = NULL; @@ -3085,20 +3086,20 @@ return_svr_referral_data(krb5_context context, #if 0 static krb5_error_code return_server_referral(krb5_context context, - krb5_pa_data * padata, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa) + krb5_pa_data * padata, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa) { - krb5_error_code code; - krb5_tl_data tl_data; - krb5_pa_data *pa_data; - krb5_enc_data enc_data; - krb5_data plain; - krb5_data *enc_pa_data; + krb5_error_code code; + krb5_tl_data tl_data; + krb5_pa_data *pa_data; + krb5_enc_data enc_data; + krb5_data plain; + krb5_data *enc_pa_data; *send_pa = NULL; @@ -3106,23 +3107,23 @@ static krb5_error_code return_server_referral(krb5_context context, code = krb5_dbe_lookup_tl_data(context, server, &tl_data); if (code || tl_data.tl_data_length == 0) - return 0; /* no server referrals to return */ + return 0; /* no server referrals to return */ plain.length = tl_data.tl_data_length; plain.data = tl_data.tl_data_contents; /* Encrypt ServerReferralData */ code = krb5_encrypt_helper(context, encrypting_key, - KRB5_KEYUSAGE_PA_SERVER_REFERRAL_DATA, - &plain, &enc_data); + KRB5_KEYUSAGE_PA_SERVER_REFERRAL_DATA, + &plain, &enc_data); if (code) - return code; + return code; /* Encode ServerReferralData into PA-SERVER-REFERRAL-DATA */ code = encode_krb5_enc_data(&enc_data, &enc_pa_data); if (code) { - krb5_free_data_contents(context, &enc_data.ciphertext); - return code; + krb5_free_data_contents(context, &enc_data.ciphertext); + return code; } krb5_free_data_contents(context, &enc_data.ciphertext); @@ -3130,8 +3131,8 @@ static krb5_error_code return_server_referral(krb5_context context, /* Return PA-SERVER-REFERRAL-DATA */ pa_data = (krb5_pa_data *)malloc(sizeof(*pa_data)); if (pa_data == NULL) { - krb5_free_data(context, enc_pa_data); - return ENOMEM; + krb5_free_data(context, enc_pa_data); + return ENOMEM; } pa_data->magic = KV5M_PA_DATA; diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index 96dc341..39c6be6 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/kdc_util.c * @@ -8,7 +9,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -22,7 +23,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * Utility functions for the KDC implementation. */ @@ -82,9 +83,9 @@ const int vague_errors = 0; krb5_error_code kdc_initialize_rcache(krb5_context kcontext, char *rcache_name) { - krb5_error_code retval; - char *rcname; - char *sname; + krb5_error_code retval; + char *rcname; + char *sname; rcname = (rcache_name) ? rcache_name : kdc_current_rcname; @@ -93,24 +94,24 @@ kdc_initialize_rcache(krb5_context kcontext, char *rcache_name) rc_lifetime = kcontext->clockskew; if (!rcname) - rcname = KDCRCACHE; + rcname = KDCRCACHE; if (!(retval = krb5_rc_resolve_full(kcontext, &kdc_rcache, rcname))) { - /* Recover or initialize the replay cache */ - if (!(retval = krb5_rc_recover(kcontext, kdc_rcache)) || - !(retval = krb5_rc_initialize(kcontext, - kdc_rcache, - kcontext->clockskew)) - ) { - /* Expunge the replay cache */ - if (!(retval = krb5_rc_expunge(kcontext, kdc_rcache))) { - sname = kdc_current_rcname; - kdc_current_rcname = strdup(rcname); - if (sname) - free(sname); - } - } - if (retval) - krb5_rc_close(kcontext, kdc_rcache); + /* Recover or initialize the replay cache */ + if (!(retval = krb5_rc_recover(kcontext, kdc_rcache)) || + !(retval = krb5_rc_initialize(kcontext, + kdc_rcache, + kcontext->clockskew)) + ) { + /* Expunge the replay cache */ + if (!(retval = krb5_rc_expunge(kcontext, kdc_rcache))) { + sname = kdc_current_rcname; + kdc_current_rcname = strdup(rcname); + if (sname) + free(sname); + } + } + if (retval) + krb5_rc_close(kcontext, kdc_rcache); } return(retval); } @@ -122,7 +123,7 @@ kdc_initialize_rcache(krb5_context kcontext, char *rcache_name) */ krb5_error_code concat_authorization_data(krb5_authdata **first, krb5_authdata **second, - krb5_authdata ***output) + krb5_authdata ***output) { register int i, j; register krb5_authdata **ptr, **retdata; @@ -130,37 +131,37 @@ concat_authorization_data(krb5_authdata **first, krb5_authdata **second, /* count up the entries */ i = 0; if (first) - for (ptr = first; *ptr; ptr++) - i++; + for (ptr = first; *ptr; ptr++) + i++; if (second) - for (ptr = second; *ptr; ptr++) - i++; - + for (ptr = second; *ptr; ptr++) + i++; + retdata = (krb5_authdata **)malloc((i+1)*sizeof(*retdata)); if (!retdata) - return ENOMEM; - retdata[i] = 0; /* null-terminated array */ + return ENOMEM; + retdata[i] = 0; /* null-terminated array */ for (i = 0, j = 0, ptr = first; j < 2 ; ptr = second, j++) - while (ptr && *ptr) { - /* now walk & copy */ - retdata[i] = (krb5_authdata *)malloc(sizeof(*retdata[i])); - if (!retdata[i]) { - krb5_free_authdata(kdc_context, retdata); - return ENOMEM; - } - *retdata[i] = **ptr; - if (!(retdata[i]->contents = - (krb5_octet *)malloc(retdata[i]->length))) { - free(retdata[i]); - retdata[i] = 0; - krb5_free_authdata(kdc_context, retdata); - return ENOMEM; - } - memcpy(retdata[i]->contents, (*ptr)->contents, retdata[i]->length); - - ptr++; - i++; - } + while (ptr && *ptr) { + /* now walk & copy */ + retdata[i] = (krb5_authdata *)malloc(sizeof(*retdata[i])); + if (!retdata[i]) { + krb5_free_authdata(kdc_context, retdata); + return ENOMEM; + } + *retdata[i] = **ptr; + if (!(retdata[i]->contents = + (krb5_octet *)malloc(retdata[i]->length))) { + free(retdata[i]); + retdata[i] = 0; + krb5_free_authdata(kdc_context, retdata); + return ENOMEM; + } + memcpy(retdata[i]->contents, (*ptr)->contents, retdata[i]->length); + + ptr++; + i++; + } *output = retdata; return 0; } @@ -184,9 +185,9 @@ is_local_principal(krb5_const_principal princ1) krb5_boolean krb5_is_tgs_principal(krb5_const_principal principal) { if ((krb5_princ_size(kdc_context, principal) > 0) && - data_eq_string (*krb5_princ_component(kdc_context, principal, 0), - KRB5_TGS_NAME)) - return TRUE; + data_eq_string (*krb5_princ_component(kdc_context, principal, 0), + KRB5_TGS_NAME)) + return TRUE; return FALSE; } @@ -196,26 +197,26 @@ krb5_boolean krb5_is_tgs_principal(krb5_const_principal principal) */ static krb5_error_code comp_cksum(krb5_context kcontext, krb5_data *source, krb5_ticket *ticket, - krb5_checksum *his_cksum) + krb5_checksum *his_cksum) { - krb5_error_code retval; - krb5_boolean valid; + krb5_error_code retval; + krb5_boolean valid; - if (!krb5_c_valid_cksumtype(his_cksum->checksum_type)) - return KRB5KDC_ERR_SUMTYPE_NOSUPP; + if (!krb5_c_valid_cksumtype(his_cksum->checksum_type)) + return KRB5KDC_ERR_SUMTYPE_NOSUPP; /* must be collision proof */ if (!krb5_c_is_coll_proof_cksum(his_cksum->checksum_type)) - return KRB5KRB_AP_ERR_INAPP_CKSUM; + return KRB5KRB_AP_ERR_INAPP_CKSUM; /* verify checksum */ if ((retval = krb5_c_verify_checksum(kcontext, ticket->enc_part2->session, - KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, - source, his_cksum, &valid))) - return(retval); + KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, + source, his_cksum, &valid))) + return(retval); if (!valid) - return(KRB5KRB_AP_ERR_BAD_INTEGRITY); + return(KRB5KRB_AP_ERR_BAD_INTEGRITY); return(0); } @@ -226,180 +227,180 @@ find_pa_data(krb5_pa_data **padata, krb5_preauthtype pa_type) return krb5int_find_pa_data(kdc_context, padata, pa_type); } -krb5_error_code +krb5_error_code kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from, - krb5_data *pkt, krb5_ticket **ticket, - krb5_db_entry *krbtgt, int *nprincs, - krb5_keyblock **tgskey, - krb5_keyblock **subkey, - krb5_pa_data **pa_tgs_req) + krb5_data *pkt, krb5_ticket **ticket, + krb5_db_entry *krbtgt, int *nprincs, + krb5_keyblock **tgskey, + krb5_keyblock **subkey, + krb5_pa_data **pa_tgs_req) { krb5_pa_data * tmppa; - krb5_ap_req * apreq; - krb5_error_code retval; + krb5_ap_req * apreq; + krb5_error_code retval; krb5_authdata **authdata = NULL; - krb5_data scratch1; - krb5_data * scratch = NULL; - krb5_boolean foreign_server = FALSE; - krb5_auth_context auth_context = NULL; - krb5_authenticator * authenticator = NULL; - krb5_checksum * his_cksum = NULL; - krb5_kvno kvno = 0; + krb5_data scratch1; + krb5_data * scratch = NULL; + krb5_boolean foreign_server = FALSE; + krb5_auth_context auth_context = NULL; + krb5_authenticator * authenticator = NULL; + krb5_checksum * his_cksum = NULL; + krb5_kvno kvno = 0; *nprincs = 0; *tgskey = NULL; tmppa = find_pa_data(request->padata, KRB5_PADATA_AP_REQ); if (!tmppa) - return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; + return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; scratch1.length = tmppa->length; scratch1.data = (char *)tmppa->contents; if ((retval = decode_krb5_ap_req(&scratch1, &apreq))) - return retval; + return retval; if (isflagset(apreq->ap_options, AP_OPTS_USE_SESSION_KEY) || - isflagset(apreq->ap_options, AP_OPTS_MUTUAL_REQUIRED)) { - krb5_klog_syslog(LOG_INFO, "TGS_REQ: SESSION KEY or MUTUAL"); - retval = KRB5KDC_ERR_POLICY; - goto cleanup; + isflagset(apreq->ap_options, AP_OPTS_MUTUAL_REQUIRED)) { + krb5_klog_syslog(LOG_INFO, "TGS_REQ: SESSION KEY or MUTUAL"); + retval = KRB5KDC_ERR_POLICY; + goto cleanup; } /* If the "server" principal in the ticket is not something in the local realm, then we must refuse to service the request if the client claims to be from the local realm. - + If we don't do this, then some other realm's nasty KDC can claim to be authenticating a client from our realm, and we'll give out tickets concurring with it! - + we set a flag here for checking below. - */ + */ foreign_server = !is_local_principal(apreq->ticket->server); if ((retval = krb5_auth_con_init(kdc_context, &auth_context))) - goto cleanup; + goto cleanup; if ((retval = krb5_auth_con_setaddrs(kdc_context, auth_context, NULL, - from->address)) ) - goto cleanup_auth_context; + from->address)) ) + goto cleanup_auth_context; #ifdef USE_RCACHE if ((retval = krb5_auth_con_setrcache(kdc_context, auth_context, - kdc_rcache))) - goto cleanup_auth_context; + kdc_rcache))) + goto cleanup_auth_context; #endif if ((retval = kdc_get_server_key(apreq->ticket, 0, foreign_server, - krbtgt, nprincs, tgskey, &kvno))) - goto cleanup_auth_context; + krbtgt, nprincs, tgskey, &kvno))) + goto cleanup_auth_context; /* * We do not use the KDB keytab because other parts of the TGS need the TGT key. */ retval = krb5_auth_con_setuseruserkey(kdc_context, auth_context, *tgskey); - if (retval) - goto cleanup_auth_context; + if (retval) + goto cleanup_auth_context; - if ((retval = krb5_rd_req_decoded_anyflag(kdc_context, &auth_context, apreq, - apreq->ticket->server, - kdc_active_realm->realm_keytab, - NULL, ticket))) { + if ((retval = krb5_rd_req_decoded_anyflag(kdc_context, &auth_context, apreq, + apreq->ticket->server, + kdc_active_realm->realm_keytab, + NULL, ticket))) { #ifdef USE_RCACHE - /* - * I'm not so sure that this is right, but it's better than nothing - * at all. - * - * If we choke in the rd_req because of the replay cache, then attempt - * to reinitialize the replay cache because somebody could have deleted - * it from underneath us (e.g. a cron job) - */ - if ((retval == KRB5_RC_IO_IO) || - (retval == KRB5_RC_IO_UNKNOWN)) { - (void) krb5_rc_close(kdc_context, kdc_rcache); - kdc_rcache = (krb5_rcache) NULL; - if (!(retval = kdc_initialize_rcache(kdc_context, (char *) NULL))) { - if ((retval = krb5_auth_con_setrcache(kdc_context, auth_context, - kdc_rcache)) || - (retval = krb5_rd_req_decoded_anyflag(kdc_context, &auth_context, - apreq, apreq->ticket->server, - kdc_active_realm->realm_keytab, - NULL, ticket)) - ) - goto cleanup_auth_context; - } - } else - goto cleanup_auth_context; + /* + * I'm not so sure that this is right, but it's better than nothing + * at all. + * + * If we choke in the rd_req because of the replay cache, then attempt + * to reinitialize the replay cache because somebody could have deleted + * it from underneath us (e.g. a cron job) + */ + if ((retval == KRB5_RC_IO_IO) || + (retval == KRB5_RC_IO_UNKNOWN)) { + (void) krb5_rc_close(kdc_context, kdc_rcache); + kdc_rcache = (krb5_rcache) NULL; + if (!(retval = kdc_initialize_rcache(kdc_context, (char *) NULL))) { + if ((retval = krb5_auth_con_setrcache(kdc_context, auth_context, + kdc_rcache)) || + (retval = krb5_rd_req_decoded_anyflag(kdc_context, &auth_context, + apreq, apreq->ticket->server, + kdc_active_realm->realm_keytab, + NULL, ticket)) + ) + goto cleanup_auth_context; + } + } else + goto cleanup_auth_context; #else - goto cleanup_auth_context; + goto cleanup_auth_context; #endif } /* "invalid flag" tickets can must be used to validate */ if (isflagset((*ticket)->enc_part2->flags, TKT_FLG_INVALID) - && !isflagset(request->kdc_options, KDC_OPT_VALIDATE)) { + && !isflagset(request->kdc_options, KDC_OPT_VALIDATE)) { retval = KRB5KRB_AP_ERR_TKT_INVALID; - goto cleanup_auth_context; + goto cleanup_auth_context; } if ((retval = krb5_auth_con_getrecvsubkey(kdc_context, - auth_context, subkey))) - goto cleanup_auth_context; + auth_context, subkey))) + goto cleanup_auth_context; if ((retval = krb5_auth_con_getauthenticator(kdc_context, auth_context, - &authenticator))) - goto cleanup_auth_context; + &authenticator))) + goto cleanup_auth_context; retval = krb5int_find_authdata(kdc_context, - (*ticket)->enc_part2->authorization_data, - authenticator->authorization_data, - KRB5_AUTHDATA_FX_ARMOR, &authdata); + (*ticket)->enc_part2->authorization_data, + authenticator->authorization_data, + KRB5_AUTHDATA_FX_ARMOR, &authdata); if (retval != 0) - goto cleanup_authenticator; - if (authdata&& authdata[0]) { - krb5_set_error_message(kdc_context, KRB5KDC_ERR_POLICY, - "ticket valid only as FAST armor"); - retval = KRB5KDC_ERR_POLICY; - krb5_free_authdata(kdc_context, authdata); - goto cleanup_authenticator; + goto cleanup_authenticator; + if (authdata&& authdata[0]) { + krb5_set_error_message(kdc_context, KRB5KDC_ERR_POLICY, + "ticket valid only as FAST armor"); + retval = KRB5KDC_ERR_POLICY; + krb5_free_authdata(kdc_context, authdata); + goto cleanup_authenticator; } krb5_free_authdata(kdc_context, authdata); - - + + /* Check for a checksum */ if (!(his_cksum = authenticator->checksum)) { - retval = KRB5KRB_AP_ERR_INAPP_CKSUM; - goto cleanup_authenticator; + retval = KRB5KRB_AP_ERR_INAPP_CKSUM; + goto cleanup_authenticator; } /* make sure the client is of proper lineage (see above) */ if (foreign_server && - !find_pa_data(request->padata, KRB5_PADATA_FOR_USER)) { - if (is_local_principal((*ticket)->enc_part2->client)) { - /* someone in a foreign realm claiming to be local */ - krb5_klog_syslog(LOG_INFO, "PROCESS_TGS: failed lineage check"); - retval = KRB5KDC_ERR_POLICY; - goto cleanup_authenticator; - } + !find_pa_data(request->padata, KRB5_PADATA_FOR_USER)) { + if (is_local_principal((*ticket)->enc_part2->client)) { + /* someone in a foreign realm claiming to be local */ + krb5_klog_syslog(LOG_INFO, "PROCESS_TGS: failed lineage check"); + retval = KRB5KDC_ERR_POLICY; + goto cleanup_authenticator; + } } /* * Check application checksum vs. tgs request - * + * * We try checksumming the req-body two different ways: first we * try reaching into the raw asn.1 stream (if available), and * checksum that directly; if that fails, then we try encoding * using our local asn.1 library. */ if (pkt && (fetch_asn1_field((unsigned char *) pkt->data, - 1, 4, &scratch1) >= 0)) { - if (comp_cksum(kdc_context, &scratch1, *ticket, his_cksum)) { - if (!(retval = encode_krb5_kdc_req_body(request, &scratch))) - retval = comp_cksum(kdc_context, scratch, *ticket, his_cksum); - krb5_free_data(kdc_context, scratch); - } + 1, 4, &scratch1) >= 0)) { + if (comp_cksum(kdc_context, &scratch1, *ticket, his_cksum)) { + if (!(retval = encode_krb5_kdc_req_body(request, &scratch))) + retval = comp_cksum(kdc_context, scratch, *ticket, his_cksum); + krb5_free_data(kdc_context, scratch); + } } if (retval == 0) - *pa_tgs_req = tmppa; + *pa_tgs_req = tmppa; cleanup_authenticator: krb5_free_authenticator(kdc_context, authenticator); @@ -412,15 +413,15 @@ cleanup_auth_context: cleanup: if (retval != 0) { - krb5_free_keyblock(kdc_context, *tgskey); - *tgskey = NULL; + krb5_free_keyblock(kdc_context, *tgskey); + *tgskey = NULL; } krb5_free_ap_req(kdc_context, apreq); return retval; } -/* XXX This function should no longer be necessary. - * The KDC should take the keytab associated with the realm and pass that to +/* XXX This function should no longer be necessary. + * The KDC should take the keytab associated with the realm and pass that to * the krb5_rd_req_decode(). --proven * * It's actually still used by do_tgs_req() for u2u auth, and not too @@ -428,42 +429,42 @@ cleanup: */ krb5_error_code kdc_get_server_key(krb5_ticket *ticket, unsigned int flags, - krb5_boolean match_enctype, krb5_db_entry *server, - int *nprincs, krb5_keyblock **key, krb5_kvno *kvno) + krb5_boolean match_enctype, krb5_db_entry *server, + int *nprincs, krb5_keyblock **key, krb5_kvno *kvno) { - krb5_error_code retval; - krb5_boolean more, similar; - krb5_key_data * server_key; + krb5_error_code retval; + krb5_boolean more, similar; + krb5_key_data * server_key; krb5_keyblock * mkey_ptr; *nprincs = 1; retval = krb5_db_get_principal_ext(kdc_context, - ticket->server, - flags, - server, - nprincs, - &more); + ticket->server, + flags, + server, + nprincs, + &more); if (retval) { - return(retval); + return(retval); } if (more) { - return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE); + return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE); } else if (*nprincs != 1) { - char *sname; + char *sname; - if (!krb5_unparse_name(kdc_context, ticket->server, &sname)) { - limit_string(sname); - krb5_klog_syslog(LOG_ERR,"TGS_REQ: UNKNOWN SERVER: server='%s'", - sname); - free(sname); - } - return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN); + if (!krb5_unparse_name(kdc_context, ticket->server, &sname)) { + limit_string(sname); + krb5_klog_syslog(LOG_ERR,"TGS_REQ: UNKNOWN SERVER: server='%s'", + sname); + free(sname); + } + return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN); } if (server->attributes & KRB5_KDB_DISALLOW_SVR || - server->attributes & KRB5_KDB_DISALLOW_ALL_TIX) { - retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; - goto errout; + server->attributes & KRB5_KDB_DISALLOW_ALL_TIX) { + retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto errout; } if ((retval = krb5_dbe_find_mkey(kdc_context, master_keylist, server, @@ -475,7 +476,7 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags, &master_keyblock, 0, &tmp_mkey_list) == 0) { krb5_dbe_free_key_list(kdc_context, master_keylist); master_keylist = tmp_mkey_list; - retval = krb5_db_set_mkey_list(kdc_context, master_keylist); + retval = krb5_db_set_mkey_list(kdc_context, master_keylist); if (retval) goto errout; if ((retval = krb5_dbe_find_mkey(kdc_context, master_keylist, @@ -488,9 +489,9 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags, } retval = krb5_dbe_find_enctype(kdc_context, server, - match_enctype ? ticket->enc_part.enctype : -1, - -1, (krb5_int32)ticket->enc_part.kvno, - &server_key); + match_enctype ? ticket->enc_part.enctype : -1, + -1, (krb5_int32)ticket->enc_part.kvno, + &server_key); if (retval) goto errout; if (!server_key) { @@ -498,25 +499,25 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags, goto errout; } if ((*key = (krb5_keyblock *)malloc(sizeof **key))) { - retval = krb5_dbekd_decrypt_key_data(kdc_context, mkey_ptr, - server_key, - *key, NULL); + retval = krb5_dbekd_decrypt_key_data(kdc_context, mkey_ptr, + server_key, + *key, NULL); } else - retval = ENOMEM; + retval = ENOMEM; retval = krb5_c_enctype_compare(kdc_context, ticket->enc_part.enctype, - (*key)->enctype, &similar); + (*key)->enctype, &similar); if (retval) - goto errout; + goto errout; if (!similar) { - retval = KRB5_KDB_NO_PERMITTED_KEY; - goto errout; + retval = KRB5_KDB_NO_PERMITTED_KEY; + goto errout; } (*key)->enctype = ticket->enc_part.enctype; *kvno = server_key->key_data_kvno; errout: if (retval != 0) { - krb5_db_free_principal(kdc_context, server, *nprincs); - *nprincs = 0; + krb5_db_free_principal(kdc_context, server, *nprincs); + *nprincs = 0; } return retval; @@ -547,13 +548,13 @@ check_hot_list(krb5_ticket *ticket) #define MAX_REALM_LN 500 -/* +/* * subrealm - determine if r2 is a subrealm of r1 * - * SUBREALM takes two realms, r1 and r2, and - * determines if r2 is a subrealm of r1. + * SUBREALM takes two realms, r1 and r2, and + * determines if r2 is a subrealm of r1. * r2 is a subrealm of r1 if (r1 is a prefix - * of r2 AND r1 and r2 begin with a /) or if + * of r2 AND r1 and r2 begin with a /) or if * (r1 is a suffix of r2 and neither r1 nor r2 * begin with a /). * @@ -576,7 +577,7 @@ subrealm(char *r1, char *r2) if(l2 <= l1) return(0); if((*r1 == '/') && (*r2 == '/') && (strncmp(r1,r2,l1) == 0)) return(l1-l2); if((*r1 != '/') && (*r2 != '/') && (strncmp(r1,r2+l2-l1,l1) == 0)) - return(l2-l1); + return(l2-l1); return(0); } @@ -585,7 +586,7 @@ subrealm(char *r1, char *r2) * ticket granting ticket on which the new ticket to * be issued is based (note that this is the same as * the realm of the server listed in the ticket - * granting ticket. + * granting ticket. * * ASSUMPTIONS: This procedure assumes that the transited field from * the existing ticket granting ticket already appears @@ -616,21 +617,21 @@ subrealm(char *r1, char *r2) * * MODIFIES: new_trans: ->length will contain the length of the new * transited field. - * + * * If ->data was not null when this procedure * is called, the memory referenced by ->data - * will be deallocated. + * will be deallocated. * * Memory will be allocated for the new transited field * ->data will be updated to point to the newly - * allocated memory. + * allocated memory. * * BUGS: The space allocated for the new transited field is the * maximum that might be needed given the old transited field, * and the realm to be added. This length is calculated * assuming that no compression of the new realm is possible. * This has no adverse consequences other than the allocation - * of more space than required. + * of more space than required. * * This procedure will not yet use the null subfield notation, * and it will get confused if it sees it. @@ -645,283 +646,283 @@ data2string (krb5_data *d) char *s; s = malloc(d->length + 1); if (s) { - memcpy(s, d->data, d->length); - s[d->length] = 0; + memcpy(s, d->data, d->length); + s[d->length] = 0; } return s; } -krb5_error_code +krb5_error_code add_to_transited(krb5_data *tgt_trans, krb5_data *new_trans, - krb5_principal tgs, krb5_principal client, - krb5_principal server) + krb5_principal tgs, krb5_principal client, + krb5_principal server) { - krb5_error_code retval; - char *realm; - char *trans; - char *otrans, *otrans_ptr; - size_t bufsize; - - /* The following are for stepping through the transited field */ - - char prev[MAX_REALM_LN]; - char next[MAX_REALM_LN]; - char current[MAX_REALM_LN]; - char exp[MAX_REALM_LN]; /* Expanded current realm name */ - - int i; - int clst, nlst; /* count of last character in current and next */ - int pl, pl1; /* prefix length */ - int added; /* TRUE = new realm has been added */ - - realm = data2string(krb5_princ_realm(kdc_context, tgs)); - if (realm == NULL) - return(ENOMEM); - - otrans = data2string(tgt_trans); - if (otrans == NULL) { - free(realm); - return(ENOMEM); - } - /* Keep track of start so we can free */ - otrans_ptr = otrans; - - /* +1 for null, - +1 for extra comma which may be added between - +1 for potential space when leading slash in realm */ - bufsize = strlen(realm) + strlen(otrans) + 3; - if (bufsize > MAX_REALM_LN) - bufsize = MAX_REALM_LN; - if (!(trans = (char *) malloc(bufsize))) { - retval = ENOMEM; - goto fail; - } - - if (new_trans->data) free(new_trans->data); - new_trans->data = trans; - new_trans->length = 0; - - trans[0] = '\0'; - - /* For the purpose of appending, the realm preceding the first */ - /* realm in the transited field is considered the null realm */ - - prev[0] = '\0'; - - /* read field into current */ - for (i = 0; *otrans != '\0';) { - if (*otrans == '\\') { - if (*(++otrans) == '\0') - break; - else - continue; - } - if (*otrans == ',') { - otrans++; - break; - } - current[i++] = *otrans++; - if (i >= MAX_REALM_LN) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - } - current[i] = '\0'; - - added = (krb5_princ_realm(kdc_context, client)->length == strlen(realm) && - !strncmp(krb5_princ_realm(kdc_context, client)->data, realm, strlen(realm))) || - (krb5_princ_realm(kdc_context, server)->length == strlen(realm) && - !strncmp(krb5_princ_realm(kdc_context, server)->data, realm, strlen(realm))); - - while (current[0]) { - - /* figure out expanded form of current name */ - - clst = strlen(current) - 1; - if (current[0] == ' ') { - strncpy(exp, current+1, sizeof(exp) - 1); - exp[sizeof(exp) - 1] = '\0'; - } - else if ((current[0] == '/') && (prev[0] == '/')) { - strncpy(exp, prev, sizeof(exp) - 1); - exp[sizeof(exp) - 1] = '\0'; - if (strlen(exp) + strlen(current) + 1 >= MAX_REALM_LN) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - strncat(exp, current, sizeof(exp) - 1 - strlen(exp)); - } - else if (current[clst] == '.') { - strncpy(exp, current, sizeof(exp) - 1); - exp[sizeof(exp) - 1] = '\0'; - if (strlen(exp) + strlen(prev) + 1 >= MAX_REALM_LN) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - strncat(exp, prev, sizeof(exp) - 1 - strlen(exp)); - } - else { - strncpy(exp, current, sizeof(exp) - 1); - exp[sizeof(exp) - 1] = '\0'; - } - - /* read field into next */ - for (i = 0; *otrans != '\0';) { - if (*otrans == '\\') { - if (*(++otrans) == '\0') - break; - else - continue; - } - if (*otrans == ',') { - otrans++; - break; - } - next[i++] = *otrans++; - if (i >= MAX_REALM_LN) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - } - next[i] = '\0'; - nlst = i - 1; - - if (!strcmp(exp, realm)) added = TRUE; - - /* If we still have to insert the new realm */ + krb5_error_code retval; + char *realm; + char *trans; + char *otrans, *otrans_ptr; + size_t bufsize; - if (!added) { + /* The following are for stepping through the transited field */ + + char prev[MAX_REALM_LN]; + char next[MAX_REALM_LN]; + char current[MAX_REALM_LN]; + char exp[MAX_REALM_LN]; /* Expanded current realm name */ + + int i; + int clst, nlst; /* count of last character in current and next */ + int pl, pl1; /* prefix length */ + int added; /* TRUE = new realm has been added */ + + realm = data2string(krb5_princ_realm(kdc_context, tgs)); + if (realm == NULL) + return(ENOMEM); - /* Is the next field compressed? If not, and if the new */ - /* realm is a subrealm of the current realm, compress */ - /* the new realm, and insert immediately following the */ - /* current one. Note that we can not do this if the next*/ - /* field is already compressed since it would mess up */ - /* what has already been done. In most cases, this is */ - /* not a problem because the realm to be added will be a */ - /* subrealm of the next field too, and we will catch */ - /* it in a future iteration. */ - - /* Note that the second test here is an unsigned comparison, - so the first half (or a cast) is also required. */ - assert(nlst < 0 || nlst < (int)sizeof(next)); - if ((nlst < 0 || next[nlst] != '.') && - (next[0] != '/') && - (pl = subrealm(exp, realm))) { - added = TRUE; - current[sizeof(current) - 1] = '\0'; - if (strlen(current) + (pl>0?pl:-pl) + 2 >= MAX_REALM_LN) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - strncat(current, ",", sizeof(current) - 1 - strlen(current)); - if (pl > 0) { - strncat(current, realm, (unsigned) pl); + otrans = data2string(tgt_trans); + if (otrans == NULL) { + free(realm); + return(ENOMEM); + } + /* Keep track of start so we can free */ + otrans_ptr = otrans; + + /* +1 for null, + +1 for extra comma which may be added between + +1 for potential space when leading slash in realm */ + bufsize = strlen(realm) + strlen(otrans) + 3; + if (bufsize > MAX_REALM_LN) + bufsize = MAX_REALM_LN; + if (!(trans = (char *) malloc(bufsize))) { + retval = ENOMEM; + goto fail; + } + + if (new_trans->data) free(new_trans->data); + new_trans->data = trans; + new_trans->length = 0; + + trans[0] = '\0'; + + /* For the purpose of appending, the realm preceding the first */ + /* realm in the transited field is considered the null realm */ + + prev[0] = '\0'; + + /* read field into current */ + for (i = 0; *otrans != '\0';) { + if (*otrans == '\\') { + if (*(++otrans) == '\0') + break; + else + continue; } - else { - strncat(current, realm+strlen(realm)+pl, (unsigned) (-pl)); + if (*otrans == ',') { + otrans++; + break; } - } - - /* Whether or not the next field is compressed, if the */ - /* realm to be added is a superrealm of the current realm,*/ - /* then the current realm can be compressed. First the */ - /* realm to be added must be compressed relative to the */ - /* previous realm (if possible), and then the current */ - /* realm compressed relative to the new realm. Note that */ - /* if the realm to be added is also a superrealm of the */ - /* previous realm, it would have been added earlier, and */ - /* we would not reach this step this time around. */ - - else if ((pl = subrealm(realm, exp))) { - added = TRUE; - current[0] = '\0'; - if ((pl1 = subrealm(prev,realm))) { - if (strlen(current) + (pl1>0?pl1:-pl1) + 1 >= MAX_REALM_LN) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - if (pl1 > 0) { - strncat(current, realm, (unsigned) pl1); - } - else { - strncat(current, realm+strlen(realm)+pl1, (unsigned) (-pl1)); - } + current[i++] = *otrans++; + if (i >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; } - else { /* If not a subrealm */ - if ((realm[0] == '/') && prev[0]) { - if (strlen(current) + 2 >= MAX_REALM_LN) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - strncat(current, " ", sizeof(current) - 1 - strlen(current)); - current[sizeof(current) - 1] = '\0'; - } - if (strlen(current) + strlen(realm) + 1 >= MAX_REALM_LN) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - strncat(current, realm, sizeof(current) - 1 - strlen(current)); - current[sizeof(current) - 1] = '\0'; + } + current[i] = '\0'; + + added = (krb5_princ_realm(kdc_context, client)->length == strlen(realm) && + !strncmp(krb5_princ_realm(kdc_context, client)->data, realm, strlen(realm))) || + (krb5_princ_realm(kdc_context, server)->length == strlen(realm) && + !strncmp(krb5_princ_realm(kdc_context, server)->data, realm, strlen(realm))); + + while (current[0]) { + + /* figure out expanded form of current name */ + + clst = strlen(current) - 1; + if (current[0] == ' ') { + strncpy(exp, current+1, sizeof(exp) - 1); + exp[sizeof(exp) - 1] = '\0'; } - if (strlen(current) + (pl>0?pl:-pl) + 2 >= MAX_REALM_LN) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - strncat(current,",", sizeof(current) - 1 - strlen(current)); - current[sizeof(current) - 1] = '\0'; - if (pl > 0) { - strncat(current, exp, (unsigned) pl); + else if ((current[0] == '/') && (prev[0] == '/')) { + strncpy(exp, prev, sizeof(exp) - 1); + exp[sizeof(exp) - 1] = '\0'; + if (strlen(exp) + strlen(current) + 1 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(exp, current, sizeof(exp) - 1 - strlen(exp)); + } + else if (current[clst] == '.') { + strncpy(exp, current, sizeof(exp) - 1); + exp[sizeof(exp) - 1] = '\0'; + if (strlen(exp) + strlen(prev) + 1 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(exp, prev, sizeof(exp) - 1 - strlen(exp)); } else { - strncat(current, exp+strlen(exp)+pl, (unsigned)(-pl)); + strncpy(exp, current, sizeof(exp) - 1); + exp[sizeof(exp) - 1] = '\0'; } - } - } - if (new_trans->length != 0) { - if (strlcat(trans, ",", bufsize) >= bufsize) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - } - if (strlcat(trans, current, bufsize) >= bufsize) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - new_trans->length = strlen(trans); + /* read field into next */ + for (i = 0; *otrans != '\0';) { + if (*otrans == '\\') { + if (*(++otrans) == '\0') + break; + else + continue; + } + if (*otrans == ',') { + otrans++; + break; + } + next[i++] = *otrans++; + if (i >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + next[i] = '\0'; + nlst = i - 1; + + if (!strcmp(exp, realm)) added = TRUE; + + /* If we still have to insert the new realm */ + + if (!added) { + + /* Is the next field compressed? If not, and if the new */ + /* realm is a subrealm of the current realm, compress */ + /* the new realm, and insert immediately following the */ + /* current one. Note that we can not do this if the next*/ + /* field is already compressed since it would mess up */ + /* what has already been done. In most cases, this is */ + /* not a problem because the realm to be added will be a */ + /* subrealm of the next field too, and we will catch */ + /* it in a future iteration. */ + + /* Note that the second test here is an unsigned comparison, + so the first half (or a cast) is also required. */ + assert(nlst < 0 || nlst < (int)sizeof(next)); + if ((nlst < 0 || next[nlst] != '.') && + (next[0] != '/') && + (pl = subrealm(exp, realm))) { + added = TRUE; + current[sizeof(current) - 1] = '\0'; + if (strlen(current) + (pl>0?pl:-pl) + 2 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(current, ",", sizeof(current) - 1 - strlen(current)); + if (pl > 0) { + strncat(current, realm, (unsigned) pl); + } + else { + strncat(current, realm+strlen(realm)+pl, (unsigned) (-pl)); + } + } - strncpy(prev, exp, sizeof(prev) - 1); - prev[sizeof(prev) - 1] = '\0'; - strncpy(current, next, sizeof(current) - 1); - current[sizeof(current) - 1] = '\0'; - } + /* Whether or not the next field is compressed, if the */ + /* realm to be added is a superrealm of the current realm,*/ + /* then the current realm can be compressed. First the */ + /* realm to be added must be compressed relative to the */ + /* previous realm (if possible), and then the current */ + /* realm compressed relative to the new realm. Note that */ + /* if the realm to be added is also a superrealm of the */ + /* previous realm, it would have been added earlier, and */ + /* we would not reach this step this time around. */ + + else if ((pl = subrealm(realm, exp))) { + added = TRUE; + current[0] = '\0'; + if ((pl1 = subrealm(prev,realm))) { + if (strlen(current) + (pl1>0?pl1:-pl1) + 1 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + if (pl1 > 0) { + strncat(current, realm, (unsigned) pl1); + } + else { + strncat(current, realm+strlen(realm)+pl1, (unsigned) (-pl1)); + } + } + else { /* If not a subrealm */ + if ((realm[0] == '/') && prev[0]) { + if (strlen(current) + 2 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(current, " ", sizeof(current) - 1 - strlen(current)); + current[sizeof(current) - 1] = '\0'; + } + if (strlen(current) + strlen(realm) + 1 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(current, realm, sizeof(current) - 1 - strlen(current)); + current[sizeof(current) - 1] = '\0'; + } + if (strlen(current) + (pl>0?pl:-pl) + 2 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(current,",", sizeof(current) - 1 - strlen(current)); + current[sizeof(current) - 1] = '\0'; + if (pl > 0) { + strncat(current, exp, (unsigned) pl); + } + else { + strncat(current, exp+strlen(exp)+pl, (unsigned)(-pl)); + } + } + } - if (!added) { - if (new_trans->length != 0) { - if (strlcat(trans, ",", bufsize) >= bufsize) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } - } - if((realm[0] == '/') && trans[0]) { - if (strlcat(trans, " ", bufsize) >= bufsize) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; - } + if (new_trans->length != 0) { + if (strlcat(trans, ",", bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + if (strlcat(trans, current, bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + new_trans->length = strlen(trans); + + strncpy(prev, exp, sizeof(prev) - 1); + prev[sizeof(prev) - 1] = '\0'; + strncpy(current, next, sizeof(current) - 1); + current[sizeof(current) - 1] = '\0'; } - if (strlcat(trans, realm, bufsize) >= bufsize) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto fail; + + if (!added) { + if (new_trans->length != 0) { + if (strlcat(trans, ",", bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + if((realm[0] == '/') && trans[0]) { + if (strlcat(trans, " ", bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + if (strlcat(trans, realm, bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + new_trans->length = strlen(trans); } - new_trans->length = strlen(trans); - } - retval = 0; + retval = 0; fail: - free(realm); - free(otrans_ptr); - return (retval); + free(realm); + free(otrans_ptr); + return (retval); } /* @@ -930,67 +931,67 @@ fail: * Returns a Kerberos protocol error number, which is _not_ the same * as a com_err error number! */ -#define AS_INVALID_OPTIONS (KDC_OPT_FORWARDED | KDC_OPT_PROXY |\ - KDC_OPT_VALIDATE | KDC_OPT_RENEW | \ - KDC_OPT_ENC_TKT_IN_SKEY | KDC_OPT_CNAME_IN_ADDL_TKT) +#define AS_INVALID_OPTIONS (KDC_OPT_FORWARDED | KDC_OPT_PROXY | \ + KDC_OPT_VALIDATE | KDC_OPT_RENEW | \ + KDC_OPT_ENC_TKT_IN_SKEY | KDC_OPT_CNAME_IN_ADDL_TKT) int validate_as_request(register krb5_kdc_req *request, krb5_db_entry client, - krb5_db_entry server, krb5_timestamp kdc_time, - const char **status, krb5_data *e_data) + krb5_db_entry server, krb5_timestamp kdc_time, + const char **status, krb5_data *e_data) { - int errcode; - + int errcode; + /* * If an option is set that is only allowed in TGS requests, complain. */ if (request->kdc_options & AS_INVALID_OPTIONS) { - *status = "INVALID AS OPTIONS"; - return KDC_ERR_BADOPTION; + *status = "INVALID AS OPTIONS"; + return KDC_ERR_BADOPTION; } /* The client must not be expired */ if (client.expiration && client.expiration < kdc_time) { - *status = "CLIENT EXPIRED"; - if (vague_errors) - return(KRB_ERR_GENERIC); - else - return(KDC_ERR_NAME_EXP); + *status = "CLIENT EXPIRED"; + if (vague_errors) + return(KRB_ERR_GENERIC); + else + return(KDC_ERR_NAME_EXP); } /* The client's password must not be expired, unless the server is - a KRB5_KDC_PWCHANGE_SERVICE. */ + a KRB5_KDC_PWCHANGE_SERVICE. */ if (client.pw_expiration && client.pw_expiration < kdc_time && - !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) { - *status = "CLIENT KEY EXPIRED"; - if (vague_errors) - return(KRB_ERR_GENERIC); - else - return(KDC_ERR_KEY_EXP); + !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) { + *status = "CLIENT KEY EXPIRED"; + if (vague_errors) + return(KRB_ERR_GENERIC); + else + return(KDC_ERR_KEY_EXP); } /* The server must not be expired */ if (server.expiration && server.expiration < kdc_time) { - *status = "SERVICE EXPIRED"; - return(KDC_ERR_SERVICE_EXP); + *status = "SERVICE EXPIRED"; + return(KDC_ERR_SERVICE_EXP); } /* - * If the client requires password changing, then only allow the + * 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); + !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); + 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); } /* @@ -999,86 +1000,86 @@ validate_as_request(register krb5_kdc_req *request, krb5_db_entry client, * * - KDC_OPT_FORWARDABLE is set in KDCOptions but local * policy has KRB5_KDB_DISALLOW_FORWARDABLE set for the - * client, and; + * client, and; * - KRB5_KDB_REQUIRES_PRE_AUTH is set for the client but - * preauthentication data is absent in the request. + * preauthentication data is absent in the request. * * Hence, this check most be done after the check for preauth * data, and is now performed by validate_forwardable() (the * contents of which were previously below). */ - + /* 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); + (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); + (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_CLIENT_REVOKED); + *status = "CLIENT LOCKED OUT"; + return(KDC_ERR_CLIENT_REVOKED); } /* 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); + *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_MUST_USE_USER2USER); + *status = "SERVICE NOT ALLOWED"; + return(KDC_ERR_MUST_USE_USER2USER); } /* * Check against local policy */ errcode = against_local_policy_as(request, client, server, - kdc_time, status, e_data); + kdc_time, status, e_data); if (errcode) - return errcode; + return errcode; return 0; } int validate_forwardable(krb5_kdc_req *request, krb5_db_entry client, - krb5_db_entry server, krb5_timestamp kdc_time, - const char **status) + krb5_db_entry server, krb5_timestamp kdc_time, + const char **status) { *status = NULL; 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); + (isflagset(client.attributes, KRB5_KDB_DISALLOW_FORWARDABLE) || + isflagset(server.attributes, KRB5_KDB_DISALLOW_FORWARDABLE))) { + *status = "FORWARDABLE NOT ALLOWED"; + return(KDC_ERR_POLICY); } else - return 0; + return 0; } -#define ASN1_ID_CLASS (0xc0) +#define ASN1_ID_CLASS (0xc0) #define ASN1_ID_TYPE (0x20) -#define ASN1_ID_TAG (0x1f) -#define ASN1_CLASS_UNIV (0) -#define ASN1_CLASS_APP (1) -#define ASN1_CLASS_CTX (2) -#define ASN1_CLASS_PRIV (3) -#define asn1_id_constructed(x) (x & ASN1_ID_TYPE) -#define asn1_id_primitive(x) (!asn1_id_constructed(x)) -#define asn1_id_class(x) ((x & ASN1_ID_CLASS) >> 6) -#define asn1_id_tag(x) (x & ASN1_ID_TAG) +#define ASN1_ID_TAG (0x1f) +#define ASN1_CLASS_UNIV (0) +#define ASN1_CLASS_APP (1) +#define ASN1_CLASS_CTX (2) +#define ASN1_CLASS_PRIV (3) +#define asn1_id_constructed(x) (x & ASN1_ID_TYPE) +#define asn1_id_primitive(x) (!asn1_id_constructed(x)) +#define asn1_id_class(x) ((x & ASN1_ID_CLASS) >> 6) +#define asn1_id_tag(x) (x & ASN1_ID_TAG) /* * asn1length - return encoded length of value. @@ -1091,42 +1092,42 @@ validate_forwardable(krb5_kdc_req *request, krb5_db_entry client, static int asn1length(unsigned char **astream) { - int length; /* resulting length */ - int sublen; /* sublengths */ - int blen; /* bytes of length */ - unsigned char *p; /* substring searching */ + int length; /* resulting length */ + int sublen; /* sublengths */ + int blen; /* bytes of length */ + unsigned char *p; /* substring searching */ if (**astream & 0x80) { blen = **astream & 0x7f; - if (blen > 3) { - return(-1); - } - for (++*astream, length = 0; blen; ++*astream, blen--) { - length = (length << 8) | **astream; - } - if (length == 0) { - /* indefinite length, figure out by hand */ - p = *astream; - p++; - while (1) { - /* compute value length. */ - if ((sublen = asn1length(&p)) < 0) { - return(-1); - } - p += sublen; + if (blen > 3) { + return(-1); + } + for (++*astream, length = 0; blen; ++*astream, blen--) { + length = (length << 8) | **astream; + } + if (length == 0) { + /* indefinite length, figure out by hand */ + p = *astream; + p++; + while (1) { + /* compute value length. */ + if ((sublen = asn1length(&p)) < 0) { + return(-1); + } + p += sublen; /* check for termination */ - if ((!*p++) && (!*p)) { - p++; - break; - } - } - length = p - *astream; - } + if ((!*p++) && (!*p)) { + p++; + break; + } + } + length = p - *astream; + } } else { - length = **astream; - ++*astream; - } - return(length); + length = **astream; + ++*astream; + } + return(length); } /* @@ -1135,81 +1136,81 @@ asn1length(unsigned char **astream) * this routine is passed a context-dependent tag number and "level" and returns * the size and length of the corresponding level subfield. * - * levels and are numbered starting from 1. + * levels and are numbered starting from 1. * * returns 0 on success, -1 otherwise. */ int fetch_asn1_field(unsigned char *astream, unsigned int level, - unsigned int field, krb5_data *data) + unsigned int field, krb5_data *data) { - unsigned char *estream; /* end of stream */ - int classes; /* # classes seen so far this level */ - unsigned int levels = 0; /* levels seen so far */ + unsigned char *estream; /* end of stream */ + int classes; /* # classes seen so far this level */ + unsigned int levels = 0; /* levels seen so far */ int lastlevel = 1000; /* last level seen */ - int length; /* various lengths */ - int tag; /* tag number */ + int length; /* various lengths */ + int tag; /* tag number */ unsigned char savelen; /* saved length of our field */ classes = -1; - /* we assume that the first identifier/length will tell us + /* we assume that the first identifier/length will tell us how long the entire stream is. */ astream++; estream = astream; if ((length = asn1length(&astream)) < 0) { - return(-1); + return(-1); } estream += length; /* search down the stream, checking identifiers. we process identifiers until we hit the "level" we want, and then process that level for our subfield, always making sure we don't go off the end of the stream. */ while (astream < estream) { - if (!asn1_id_constructed(*astream)) { - return(-1); - } + if (!asn1_id_constructed(*astream)) { + return(-1); + } if (asn1_id_class(*astream) == ASN1_CLASS_CTX) { if ((tag = (int)asn1_id_tag(*astream)) <= lastlevel) { levels++; classes = -1; } - lastlevel = tag; + lastlevel = tag; if (levels == level) { - /* in our context-dependent class, is this the one we're looking for ? */ - if (tag == (int)field) { - /* return length and data */ - astream++; - savelen = *astream; - if ((data->length = asn1length(&astream)) < 0) { - return(-1); - } - /* if the field length is indefinite, we will have to subtract two + /* in our context-dependent class, is this the one we're looking for ? */ + if (tag == (int)field) { + /* return length and data */ + astream++; + savelen = *astream; + if ((data->length = asn1length(&astream)) < 0) { + return(-1); + } + /* if the field length is indefinite, we will have to subtract two (terminating octets) from the length returned since we don't want to pass any info from the "wrapper" back. asn1length will always return - the *total* length of the field, not just what's contained in it */ - if ((savelen & 0xff) == 0x80) { - data->length -=2 ; - } - data->data = (char *)astream; - return(0); - } else if (tag <= classes) { - /* we've seen this class before, something must be wrong */ - return(-1); - } else { - classes = tag; - } - } + the *total* length of the field, not just what's contained in it */ + if ((savelen & 0xff) == 0x80) { + data->length -=2 ; + } + data->data = (char *)astream; + return(0); + } else if (tag <= classes) { + /* we've seen this class before, something must be wrong */ + return(-1); + } else { + classes = tag; + } + } } /* if we're not on our level yet, process this value. otherwise skip over it */ - astream++; - if ((length = asn1length(&astream)) < 0) { - return(-1); - } - if (levels == level) { - astream += length; - } + astream++; + if ((length = asn1length(&astream)) < 0) { + return(-1); + } + if (levels == level) { + astream += length; + } } return(-1); -} +} /* * Routines that validate a TGS request; checks a lot of things. :-) @@ -1217,22 +1218,22 @@ fetch_asn1_field(unsigned char *astream, unsigned int level, * 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 | KDC_OPT_CANONICALIZE | KDC_OPT_CNAME_IN_ADDL_TKT) +#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 | KDC_OPT_CANONICALIZE | KDC_OPT_CNAME_IN_ADDL_TKT) #define NO_TGT_OPTION (KDC_OPT_FORWARDED | KDC_OPT_PROXY | KDC_OPT_RENEW | \ - KDC_OPT_VALIDATE) + KDC_OPT_VALIDATE) int validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server, - krb5_ticket *ticket, krb5_timestamp kdc_time, - const char **status, krb5_data *e_data) + krb5_ticket *ticket, krb5_timestamp kdc_time, + const char **status, krb5_data *e_data) { - int errcode; - int st_idx = 0; + int errcode; + int st_idx = 0; /* * If an illegal option is set, ignore it. @@ -1241,8 +1242,8 @@ validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server, /* Check to see if server has expired */ if (server.expiration && server.expiration < kdc_time) { - *status = "SERVICE EXPIRED"; - return(KDC_ERR_SERVICE_EXP); + *status = "SERVICE EXPIRED"; + return(KDC_ERR_SERVICE_EXP); } /* @@ -1251,172 +1252,172 @@ validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server, * originally requested) */ if (request->kdc_options & NO_TGT_OPTION) { - if (!krb5_principal_compare(kdc_context, ticket->server, request->server)) { - *status = "SERVER DIDN'T MATCH TICKET FOR RENEW/FORWARD/ETC"; - return(KDC_ERR_SERVER_NOMATCH); - } + if (!krb5_principal_compare(kdc_context, ticket->server, request->server)) { + *status = "SERVER DIDN'T MATCH TICKET FOR RENEW/FORWARD/ETC"; + return(KDC_ERR_SERVER_NOMATCH); + } } else { - /* - * OK, we need to validate the krbtgt service in the ticket. - * - * The krbtgt service is of the form: - * krbtgt/realm-A@realm-B - * - * Realm A is the "server realm"; the realm of the - * server of the requested ticket must match this realm. - * Of course, it should be a realm serviced by this KDC. - * - * Realm B is the "client realm"; this is what should be - * added to the transited field. (which is done elsewhere) - */ - - /* Make sure there are two components... */ - if (krb5_princ_size(kdc_context, ticket->server) != 2) { - *status = "BAD TGS SERVER LENGTH"; - return KRB_AP_ERR_NOT_US; - } - /* ...that the first component is krbtgt... */ - if (!krb5_is_tgs_principal(ticket->server)) { - *status = "BAD TGS SERVER NAME"; - return KRB_AP_ERR_NOT_US; - } - /* ...and that the second component matches the server realm... */ - if ((krb5_princ_size(kdc_context, ticket->server) <= 1) || - !data_eq(*krb5_princ_component(kdc_context, ticket->server, 1), - *krb5_princ_realm(kdc_context, request->server))) { - *status = "BAD TGS SERVER INSTANCE"; - return KRB_AP_ERR_NOT_US; - } - /* XXX add check that second component must match locally - * supported realm? - */ - - /* Server must allow TGS based issuances */ - if (isflagset(server.attributes, KRB5_KDB_DISALLOW_TGT_BASED)) { - *status = "TGT BASED NOT ALLOWED"; - return(KDC_ERR_POLICY); - } - } - + /* + * OK, we need to validate the krbtgt service in the ticket. + * + * The krbtgt service is of the form: + * krbtgt/realm-A@realm-B + * + * Realm A is the "server realm"; the realm of the + * server of the requested ticket must match this realm. + * Of course, it should be a realm serviced by this KDC. + * + * Realm B is the "client realm"; this is what should be + * added to the transited field. (which is done elsewhere) + */ + + /* Make sure there are two components... */ + if (krb5_princ_size(kdc_context, ticket->server) != 2) { + *status = "BAD TGS SERVER LENGTH"; + return KRB_AP_ERR_NOT_US; + } + /* ...that the first component is krbtgt... */ + if (!krb5_is_tgs_principal(ticket->server)) { + *status = "BAD TGS SERVER NAME"; + return KRB_AP_ERR_NOT_US; + } + /* ...and that the second component matches the server realm... */ + if ((krb5_princ_size(kdc_context, ticket->server) <= 1) || + !data_eq(*krb5_princ_component(kdc_context, ticket->server, 1), + *krb5_princ_realm(kdc_context, request->server))) { + *status = "BAD TGS SERVER INSTANCE"; + return KRB_AP_ERR_NOT_US; + } + /* XXX add check that second component must match locally + * supported realm? + */ + + /* 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"; + isflagset(request->kdc_options, KDC_OPT_FORWARDABLE)) && + !isflagset(ticket->enc_part2->flags, TKT_FLG_FORWARDABLE)) { + *status = "TGT NOT FORWARDABLE"; - return KDC_ERR_BADOPTION; + return KDC_ERR_BADOPTION; } - /* TGS must be proxiable to get proxiable ticket */ + /* 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; + 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; + 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; + !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; + 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 || - !data_eq_string(request->server->data[0], KRB5_TGS_NAME))) { - *status = "CAN'T PROXY TGT"; - return KDC_ERR_BADOPTION; + (!request->server->data || + !data_eq_string(request->server->data[0], KRB5_TGS_NAME))) { + *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); + 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); + 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); + 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); + 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 DISALLOWED"; - return(KDC_ERR_POLICY); + isflagset(server.attributes, KRB5_KDB_DISALLOW_DUP_SKEY)) { + *status = "DUP_SKEY DISALLOWED"; + 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); + *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_MUST_USE_USER2USER); + *status = "SERVER NOT ALLOWED"; + return(KDC_ERR_MUST_USE_USER2USER); } /* Check the hot list */ if (check_hot_list(ticket)) { - *status = "HOT_LIST"; - return(KRB_AP_ERR_REPEAT); + *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); - } + 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); + (ticket->enc_part2->times.renew_till < kdc_time)) { + *status = "TKT_EXPIRED"; + return(KRB_AP_ERR_TKT_EXPIRED); } - + /* * Checks for ENC_TKT_IN_SKEY: * @@ -1424,50 +1425,50 @@ validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server, * (2) Make sure it is a ticket granting ticket */ 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); - } - if (!krb5_principal_compare(kdc_context, request->second_ticket[st_idx]->server, - tgs_server)) { - *status = "2ND_TKT_NOT_TGS"; - return(KDC_ERR_POLICY); - } - st_idx++; + if (!request->second_ticket || + !request->second_ticket[st_idx]) { + *status = "NO_2ND_TKT"; + return(KDC_ERR_BADOPTION); + } + if (!krb5_principal_compare(kdc_context, request->second_ticket[st_idx]->server, + tgs_server)) { + *status = "2ND_TKT_NOT_TGS"; + return(KDC_ERR_POLICY); + } + st_idx++; } if (isflagset(request->kdc_options, KDC_OPT_CNAME_IN_ADDL_TKT)) { - if (!request->second_ticket || - !request->second_ticket[st_idx]) { - *status = "NO_2ND_TKT"; - return(KDC_ERR_BADOPTION); - } - st_idx++; + 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; + !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; + !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, e_data); + status, e_data); if (errcode) - return errcode; - - + return errcode; + + return 0; } @@ -1477,17 +1478,17 @@ validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server, */ int dbentry_has_key_for_enctype(krb5_context context, krb5_db_entry *client, - krb5_enctype enctype) + krb5_enctype enctype) { - krb5_error_code retval; - krb5_key_data *datap; + krb5_error_code retval; + krb5_key_data *datap; retval = krb5_dbe_find_enctype(context, client, enctype, - -1, 0, &datap); + -1, 0, &datap); if (retval) - return 0; + return 0; else - return 1; + return 1; } /* @@ -1501,7 +1502,7 @@ dbentry_has_key_for_enctype(krb5_context context, krb5_db_entry *client, */ int dbentry_supports_enctype(krb5_context context, krb5_db_entry *client, - krb5_enctype enctype) + krb5_enctype enctype) { /* * If it's DES_CBC_MD5, there's a bit in the attribute mask which @@ -1512,14 +1513,14 @@ dbentry_supports_enctype(krb5_context context, krb5_db_entry *client, * that's not the reality.... */ if (enctype == ENCTYPE_DES_CBC_MD5) - return 0; + return 0; /* * XXX we assume everything can understand DES_CBC_CRC */ if (enctype == ENCTYPE_DES_CBC_CRC) - return 1; - + return 1; + /* * If we have a key for the encryption system, we assume it's * supported. @@ -1534,19 +1535,19 @@ dbentry_supports_enctype(krb5_context context, krb5_db_entry *client, */ krb5_enctype select_session_keytype(krb5_context context, krb5_db_entry *server, - int nktypes, krb5_enctype *ktype) + int nktypes, krb5_enctype *ktype) { - int i; - + int i; + for (i = 0; i < nktypes; i++) { - if (!krb5_c_valid_enctype(ktype[i])) - continue; + if (!krb5_c_valid_enctype(ktype[i])) + continue; - if (!krb5_is_permitted_enctype(context, ktype[i])) - continue; + if (!krb5_is_permitted_enctype(context, ktype[i])) + continue; - if (dbentry_supports_enctype(context, server, ktype[i])) - return ktype[i]; + if (dbentry_supports_enctype(context, server, ktype[i])) + return ktype[i]; } return 0; } @@ -1556,53 +1557,53 @@ select_session_keytype(krb5_context context, krb5_db_entry *server, */ krb5_error_code get_salt_from_key(krb5_context context, krb5_principal client, - krb5_key_data *client_key, krb5_data *salt) + krb5_key_data *client_key, krb5_data *salt) { - krb5_error_code retval; - krb5_data * realm; - + krb5_error_code retval; + krb5_data * realm; + salt->data = 0; salt->length = SALT_TYPE_NO_LENGTH; - + if (client_key->key_data_ver == 1) - return 0; + return 0; switch (client_key->key_data_type[1]) { case KRB5_KDB_SALTTYPE_NORMAL: - /* - * The client could infer the salt from the principal, but - * might use the wrong principal name if this is an alias. So - * it's more reliable to send an explicit salt. - */ - if ((retval = krb5_principal2salt(context, client, salt))) - return retval; - break; + /* + * The client could infer the salt from the principal, but + * might use the wrong principal name if this is an alias. So + * it's more reliable to send an explicit salt. + */ + if ((retval = krb5_principal2salt(context, client, salt))) + return retval; + break; case KRB5_KDB_SALTTYPE_V4: - /* send an empty (V4) salt */ - salt->data = 0; - salt->length = 0; - break; + /* send an empty (V4) salt */ + salt->data = 0; + salt->length = 0; + break; case KRB5_KDB_SALTTYPE_NOREALM: - if ((retval = krb5_principal2salt_norealm(context, client, salt))) - return retval; - break; + if ((retval = krb5_principal2salt_norealm(context, client, salt))) + return retval; + break; case KRB5_KDB_SALTTYPE_AFS3: - /* send the same salt as with onlyrealm - but with no type info, - we just hope they figure it out on the other end. */ - /* fall through to onlyrealm: */ + /* send the same salt as with onlyrealm - but with no type info, + we just hope they figure it out on the other end. */ + /* fall through to onlyrealm: */ case KRB5_KDB_SALTTYPE_ONLYREALM: - realm = krb5_princ_realm(context, client); - salt->length = realm->length; - if ((salt->data = malloc(realm->length)) == NULL) - return ENOMEM; - memcpy(salt->data, realm->data, realm->length); - break; + realm = krb5_princ_realm(context, client); + salt->length = realm->length; + if ((salt->data = malloc(realm->length)) == NULL) + return ENOMEM; + memcpy(salt->data, realm->data, realm->length); + break; case KRB5_KDB_SALTTYPE_SPECIAL: - salt->length = client_key->key_data_length[1]; - if ((salt->data = malloc(salt->length)) == NULL) - return ENOMEM; - memcpy(salt->data, client_key->key_data_contents[1], salt->length); - break; + salt->length = client_key->key_data_length[1]; + if ((salt->data = malloc(salt->length)) == NULL) + return ENOMEM; + memcpy(salt->data, client_key->key_data_contents[1], salt->length); + break; } return 0; } @@ -1615,20 +1616,20 @@ get_salt_from_key(krb5_context context, krb5_principal client, void limit_string(char *name) { - int i; + int i; - if (!name) - return; + if (!name) + return; - if (strlen(name) < NAME_LENGTH_LIMIT) - return; + if (strlen(name) < NAME_LENGTH_LIMIT) + return; - i = NAME_LENGTH_LIMIT-4; - name[i++] = '.'; - name[i++] = '.'; - name[i++] = '.'; - name[i] = '\0'; - return; + i = NAME_LENGTH_LIMIT-4; + name[i++] = '.'; + name[i++] = '.'; + name[i++] = '.'; + name[i] = '\0'; + return; } /* @@ -1650,32 +1651,32 @@ ktypes2str(char *s, size_t len, int nktypes, krb5_enctype *ktype) char *p; if (nktypes < 0 - || len < (sizeof(" etypes {...}") + D_LEN(int))) { - *s = '\0'; - return; + || len < (sizeof(" etypes {...}") + D_LEN(int))) { + *s = '\0'; + return; } snprintf(s, len, "%d etypes {", nktypes); for (i = 0; i < nktypes; i++) { - snprintf(stmp, sizeof(stmp), "%s%ld", i ? " " : "", (long)ktype[i]); - if (strlen(s) + strlen(stmp) + sizeof("}") > len) - break; - strlcat(s, stmp, len); + snprintf(stmp, sizeof(stmp), "%s%ld", i ? " " : "", (long)ktype[i]); + if (strlen(s) + strlen(stmp) + sizeof("}") > len) + break; + strlcat(s, stmp, len); } if (i < nktypes) { - /* - * We broke out of the loop. Try to truncate the list. - */ - p = s + strlen(s); - while (p - s + sizeof("...}") > len) { - while (p > s && *p != ' ' && *p != '{') - *p-- = '\0'; - if (p > s && *p == ' ') { - *p-- = '\0'; - continue; - } - } - strlcat(s, "...", len); + /* + * We broke out of the loop. Try to truncate the list. + */ + p = s + strlen(s); + while (p - s + sizeof("...}") > len) { + while (p > s && *p != ' ' && *p != '{') + *p-- = '\0'; + if (p > s && *p == ' ') { + *p-- = '\0'; + continue; + } + } + strlcat(s, "...", len); } strlcat(s, "}", len); return; @@ -1687,25 +1688,25 @@ rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep) char stmp[sizeof("ses=") + D_LEN(krb5_enctype)]; if (len < (3 * D_LEN(krb5_enctype) - + sizeof("etypes {rep= tkt= ses=}"))) { - *s = '\0'; - return; + + sizeof("etypes {rep= tkt= ses=}"))) { + *s = '\0'; + return; } snprintf(s, len, "etypes {rep=%ld", (long)rep->enc_part.enctype); if (rep->ticket != NULL) { - snprintf(stmp, sizeof(stmp), - " tkt=%ld", (long)rep->ticket->enc_part.enctype); - strlcat(s, stmp, len); + snprintf(stmp, sizeof(stmp), + " tkt=%ld", (long)rep->ticket->enc_part.enctype); + strlcat(s, stmp, len); } if (rep->ticket != NULL - && rep->ticket->enc_part2 != NULL - && rep->ticket->enc_part2->session != NULL) { - snprintf(stmp, sizeof(stmp), " ses=%ld", - (long)rep->ticket->enc_part2->session->enctype); - strlcat(s, stmp, len); + && rep->ticket->enc_part2 != NULL + && rep->ticket->enc_part2->session != NULL) { + snprintf(stmp, sizeof(stmp), " ses=%ld", + (long)rep->ticket->enc_part2->session->enctype); + strlcat(s, stmp, len); } strlcat(s, "}", len); return; @@ -1713,40 +1714,40 @@ rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep) krb5_error_code get_principal_locked (krb5_context kcontext, - krb5_const_principal search_for, - krb5_db_entry *entries, int *nentries, - krb5_boolean *more) + krb5_const_principal search_for, + krb5_db_entry *entries, int *nentries, + krb5_boolean *more) { return krb5_db_get_principal (kcontext, search_for, entries, nentries, - more); + more); } krb5_error_code get_principal (krb5_context kcontext, - krb5_const_principal search_for, - krb5_db_entry *entries, int *nentries, krb5_boolean *more) + krb5_const_principal search_for, + krb5_db_entry *entries, int *nentries, krb5_boolean *more) { /* Eventually this will be used to manage locking while looking up principals in the database. */ return get_principal_locked (kcontext, search_for, entries, nentries, - more); + more); } krb5_error_code sign_db_authdata (krb5_context context, - unsigned int flags, - krb5_const_principal client_princ, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_db_entry *krbtgt, - krb5_keyblock *client_key, - krb5_keyblock *server_key, - krb5_keyblock *krbtgt_key, - krb5_timestamp authtime, - krb5_authdata **tgs_authdata, - krb5_keyblock *session_key, - krb5_authdata ***ret_authdata) + unsigned int flags, + krb5_const_principal client_princ, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *krbtgt_key, + krb5_timestamp authtime, + krb5_authdata **tgs_authdata, + krb5_keyblock *session_key, + krb5_authdata ***ret_authdata) { krb5_error_code code; kdb_sign_auth_data_req req; @@ -1759,17 +1760,17 @@ sign_db_authdata (krb5_context context, memset(&req, 0, sizeof(req)); memset(&rep, 0, sizeof(rep)); - req.flags = flags; - req.client_princ = client_princ; - req.client = client; - req.server = server; - req.krbtgt = krbtgt; - req.client_key = client_key; - req.server_key = server_key; - req.authtime = authtime; - req.auth_data = tgs_authdata; - req.session_key = session_key; - req.krbtgt_key = krbtgt_key; + req.flags = flags; + req.client_princ = client_princ; + req.client = client; + req.server = server; + req.krbtgt = krbtgt; + req.client_key = client_key; + req.server_key = server_key; + req.authtime = authtime; + req.auth_data = tgs_authdata; + req.session_key = session_key; + req.krbtgt_key = krbtgt_key; req_data.data = (void *)&req; req_data.length = sizeof(req); @@ -1778,29 +1779,29 @@ sign_db_authdata (krb5_context context, rep_data.length = sizeof(rep); code = krb5_db_invoke(context, - KRB5_KDB_METHOD_SIGN_AUTH_DATA, - &req_data, - &rep_data); + KRB5_KDB_METHOD_SIGN_AUTH_DATA, + &req_data, + &rep_data); *ret_authdata = rep.auth_data; - + return code; } static krb5_error_code verify_for_user_checksum(krb5_context context, - krb5_keyblock *key, - krb5_pa_for_user *req) + krb5_keyblock *key, + krb5_pa_for_user *req) { - krb5_error_code code; - int i; - krb5_int32 name_type; - char *p; - krb5_data data; - krb5_boolean valid = FALSE; + krb5_error_code code; + int i; + krb5_int32 name_type; + char *p; + krb5_data data; + krb5_boolean valid = FALSE; if (!krb5_c_is_keyed_cksum(req->cksum.checksum_type)) { - return KRB5KRB_AP_ERR_INAPP_CKSUM; + return KRB5KRB_AP_ERR_INAPP_CKSUM; } /* @@ -1809,14 +1810,14 @@ verify_for_user_checksum(krb5_context context, */ data.length = 4; for (i = 0; i < krb5_princ_size(context, req->user); i++) { - data.length += krb5_princ_component(context, req->user, i)->length; + data.length += krb5_princ_component(context, req->user, i)->length; } data.length += krb5_princ_realm(context, req->user)->length; data.length += req->auth_package.length; p = data.data = malloc(data.length); if (data.data == NULL) { - return ENOMEM; + return ENOMEM; } name_type = krb5_princ_type(context, req->user); @@ -1827,27 +1828,27 @@ verify_for_user_checksum(krb5_context context, p += 4; for (i = 0; i < krb5_princ_size(context, req->user); i++) { - memcpy(p, krb5_princ_component(context, req->user, i)->data, - krb5_princ_component(context, req->user, i)->length); - p += krb5_princ_component(context, req->user, i)->length; + memcpy(p, krb5_princ_component(context, req->user, i)->data, + krb5_princ_component(context, req->user, i)->length); + p += krb5_princ_component(context, req->user, i)->length; } memcpy(p, krb5_princ_realm(context, req->user)->data, - krb5_princ_realm(context, req->user)->length); + krb5_princ_realm(context, req->user)->length); p += krb5_princ_realm(context, req->user)->length; memcpy(p, req->auth_package.data, req->auth_package.length); p += req->auth_package.length; code = krb5_c_verify_checksum(context, - key, - KRB5_KEYUSAGE_APP_DATA_CKSUM, - &data, - &req->cksum, - &valid); + key, + KRB5_KEYUSAGE_APP_DATA_CKSUM, + &data, + &req->cksum, + &valid); if (code == 0 && valid == FALSE) - code = KRB5KRB_AP_ERR_MODIFIED; + code = KRB5KRB_AP_ERR_MODIFIED; free(data.data); @@ -1859,33 +1860,33 @@ verify_for_user_checksum(krb5_context context, */ static krb5_error_code kdc_process_for_user(krb5_context context, - krb5_pa_data *pa_data, - krb5_keyblock *tgs_session, - krb5_pa_s4u_x509_user **s4u_x509_user, - const char **status) + krb5_pa_data *pa_data, + krb5_keyblock *tgs_session, + krb5_pa_s4u_x509_user **s4u_x509_user, + const char **status) { - krb5_error_code code; - krb5_pa_for_user *for_user; - krb5_data req_data; + krb5_error_code code; + krb5_pa_for_user *for_user; + krb5_data req_data; req_data.length = pa_data->length; req_data.data = (char *)pa_data->contents; code = decode_krb5_pa_for_user(&req_data, &for_user); if (code) - return code; + return code; code = verify_for_user_checksum(context, tgs_session, for_user); if (code) { - *status = "INVALID_S4U2SELF_CHECKSUM"; - krb5_free_pa_for_user(kdc_context, for_user); - return code; + *status = "INVALID_S4U2SELF_CHECKSUM"; + krb5_free_pa_for_user(kdc_context, for_user); + return code; } *s4u_x509_user = calloc(1, sizeof(krb5_pa_s4u_x509_user)); if (*s4u_x509_user == NULL) { - krb5_free_pa_for_user(kdc_context, for_user); - return ENOMEM; + krb5_free_pa_for_user(kdc_context, for_user); + return ENOMEM; } (*s4u_x509_user)->user_id.user = for_user->user; @@ -1897,21 +1898,21 @@ kdc_process_for_user(krb5_context context, static krb5_error_code verify_s4u_x509_user_checksum(krb5_context context, - krb5_keyblock *key, - krb5_data *req_data, - krb5_int32 kdc_req_nonce, - krb5_pa_s4u_x509_user *req) + krb5_keyblock *key, + krb5_data *req_data, + krb5_int32 kdc_req_nonce, + krb5_pa_s4u_x509_user *req) { - krb5_error_code code; - krb5_data scratch; - krb5_boolean valid = FALSE; + krb5_error_code code; + krb5_data scratch; + krb5_boolean valid = FALSE; if (enctype_requires_etype_info_2(key->enctype) && - !krb5_c_is_keyed_cksum(req->cksum.checksum_type)) - return KRB5KRB_AP_ERR_INAPP_CKSUM; + !krb5_c_is_keyed_cksum(req->cksum.checksum_type)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; if (req->user_id.nonce != kdc_req_nonce) - return KRB5KRB_AP_ERR_MODIFIED; + return KRB5KRB_AP_ERR_MODIFIED; /* * Verify checksum over the encoded userid. If that fails, @@ -1919,35 +1920,35 @@ verify_s4u_x509_user_checksum(krb5_context context, * behaviour in kdc_process_tgs_req(). */ if (fetch_asn1_field((unsigned char *)req_data->data, 1, 0, &scratch) < 0) - return ASN1_PARSE_ERROR; + return ASN1_PARSE_ERROR; code = krb5_c_verify_checksum(context, - key, - KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST, - &scratch, - &req->cksum, - &valid); + key, + KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST, + &scratch, + &req->cksum, + &valid); if (code != 0) - return code; + return code; if (valid == FALSE) { - krb5_data *data; + krb5_data *data; - code = encode_krb5_s4u_userid(&req->user_id, &data); - if (code != 0) - return code; + code = encode_krb5_s4u_userid(&req->user_id, &data); + if (code != 0) + return code; - code = krb5_c_verify_checksum(context, - key, - KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST, - data, - &req->cksum, - &valid); + code = krb5_c_verify_checksum(context, + key, + KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST, + data, + &req->cksum, + &valid); - krb5_free_data(context, data); + krb5_free_data(context, data); - if (code != 0) - return code; + if (code != 0) + return code; } return valid ? 0 : KRB5KRB_AP_ERR_MODIFIED; @@ -1958,42 +1959,42 @@ verify_s4u_x509_user_checksum(krb5_context context, */ static krb5_error_code kdc_process_s4u_x509_user(krb5_context context, - krb5_kdc_req *request, - krb5_pa_data *pa_data, - krb5_keyblock *tgs_subkey, - krb5_keyblock *tgs_session, - krb5_pa_s4u_x509_user **s4u_x509_user, - const char **status) + krb5_kdc_req *request, + krb5_pa_data *pa_data, + krb5_keyblock *tgs_subkey, + krb5_keyblock *tgs_session, + krb5_pa_s4u_x509_user **s4u_x509_user, + const char **status) { - krb5_error_code code; - krb5_data req_data; + krb5_error_code code; + krb5_data req_data; req_data.length = pa_data->length; req_data.data = (char *)pa_data->contents; code = decode_krb5_pa_s4u_x509_user(&req_data, s4u_x509_user); if (code) - return code; + return code; code = verify_s4u_x509_user_checksum(context, - tgs_subkey ? tgs_subkey : - tgs_session, - &req_data, - request->nonce, *s4u_x509_user); + tgs_subkey ? tgs_subkey : + tgs_session, + &req_data, + request->nonce, *s4u_x509_user); if (code) { - *status = "INVALID_S4U2SELF_CHECKSUM"; - krb5_free_pa_s4u_x509_user(context, *s4u_x509_user); - *s4u_x509_user = NULL; - return code; + *status = "INVALID_S4U2SELF_CHECKSUM"; + krb5_free_pa_s4u_x509_user(context, *s4u_x509_user); + *s4u_x509_user = NULL; + return code; } if (krb5_princ_size(context, (*s4u_x509_user)->user_id.user) == 0 || - (*s4u_x509_user)->user_id.subject_cert.length != 0) { - *status = "INVALID_S4U2SELF_REQUEST"; - krb5_free_pa_s4u_x509_user(context, *s4u_x509_user); - *s4u_x509_user = NULL; - return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + (*s4u_x509_user)->user_id.subject_cert.length != 0) { + *status = "INVALID_S4U2SELF_REQUEST"; + krb5_free_pa_s4u_x509_user(context, *s4u_x509_user); + *s4u_x509_user = NULL; + return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; } return 0; @@ -2001,25 +2002,25 @@ kdc_process_s4u_x509_user(krb5_context context, krb5_error_code kdc_make_s4u2self_rep(krb5_context context, - krb5_keyblock *tgs_subkey, - krb5_keyblock *tgs_session, - krb5_pa_s4u_x509_user *req_s4u_user, - krb5_kdc_rep *reply, - krb5_enc_kdc_rep_part *reply_encpart) + krb5_keyblock *tgs_subkey, + krb5_keyblock *tgs_session, + krb5_pa_s4u_x509_user *req_s4u_user, + krb5_kdc_rep *reply, + krb5_enc_kdc_rep_part *reply_encpart) { - krb5_error_code code; - krb5_data *data = NULL; - krb5_pa_s4u_x509_user rep_s4u_user; - krb5_pa_data padata; - krb5_enctype enctype; - krb5_keyusage usage; + krb5_error_code code; + krb5_data *data = NULL; + krb5_pa_s4u_x509_user rep_s4u_user; + krb5_pa_data padata; + krb5_enctype enctype; + krb5_keyusage usage; memset(&rep_s4u_user, 0, sizeof(rep_s4u_user)); rep_s4u_user.user_id.nonce = req_s4u_user->user_id.nonce; rep_s4u_user.user_id.user = req_s4u_user->user_id.user; rep_s4u_user.user_id.options = - req_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE; + req_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE; code = encode_krb5_s4u_userid(&rep_s4u_user.user_id, &data); if (code != 0) @@ -2031,7 +2032,7 @@ kdc_make_s4u2self_rep(krb5_context context, usage = KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST; code = krb5_c_make_checksum(context, req_s4u_user->cksum.checksum_type, - tgs_subkey != NULL ? tgs_subkey : tgs_session, + tgs_subkey != NULL ? tgs_subkey : tgs_session, usage, data, &rep_s4u_user.cksum); if (code != 0) @@ -2051,15 +2052,15 @@ kdc_make_s4u2self_rep(krb5_context context, code = add_pa_data_element(context, &padata, &reply->padata, FALSE); if (code != 0) - goto cleanup; + goto cleanup; free(data); data = NULL; if (tgs_subkey != NULL) - enctype = tgs_subkey->enctype; + enctype = tgs_subkey->enctype; else - enctype = tgs_session->enctype; + enctype = tgs_session->enctype; /* * Owing to a bug in Windows, unkeyed checksums were used for older @@ -2067,26 +2068,26 @@ kdc_make_s4u2self_rep(krb5_context context, * includes the checksum bytes in the encrypted padata. */ if ((req_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE) && - enctype_requires_etype_info_2(enctype) == FALSE) { - padata.length = req_s4u_user->cksum.length + - rep_s4u_user.cksum.length; - padata.contents = malloc(padata.length); - if (padata.contents == NULL) { - code = ENOMEM; - goto cleanup; - } - - memcpy(padata.contents, - req_s4u_user->cksum.contents, - req_s4u_user->cksum.length); - memcpy(&padata.contents[req_s4u_user->cksum.length], - rep_s4u_user.cksum.contents, - rep_s4u_user.cksum.length); - - code = add_pa_data_element(context,&padata, - &reply_encpart->enc_padata, FALSE); - if (code != 0) - goto cleanup; + enctype_requires_etype_info_2(enctype) == FALSE) { + padata.length = req_s4u_user->cksum.length + + rep_s4u_user.cksum.length; + padata.contents = malloc(padata.length); + if (padata.contents == NULL) { + code = ENOMEM; + goto cleanup; + } + + memcpy(padata.contents, + req_s4u_user->cksum.contents, + req_s4u_user->cksum.length); + memcpy(&padata.contents[req_s4u_user->cksum.length], + rep_s4u_user.cksum.contents, + rep_s4u_user.cksum.length); + + code = add_pa_data_element(context,&padata, + &reply_encpart->enc_padata, FALSE); + if (code != 0) + goto cleanup; } cleanup: @@ -2102,48 +2103,48 @@ cleanup: */ krb5_error_code kdc_process_s4u2self_req(krb5_context context, - krb5_kdc_req *request, - krb5_const_principal client_princ, - const krb5_db_entry *server, - krb5_keyblock *tgs_subkey, - krb5_keyblock *tgs_session, - krb5_timestamp kdc_time, - krb5_pa_s4u_x509_user **s4u_x509_user, - krb5_db_entry *princ, - int *nprincs, - const char **status) + krb5_kdc_req *request, + krb5_const_principal client_princ, + const krb5_db_entry *server, + krb5_keyblock *tgs_subkey, + krb5_keyblock *tgs_session, + krb5_timestamp kdc_time, + krb5_pa_s4u_x509_user **s4u_x509_user, + krb5_db_entry *princ, + int *nprincs, + const char **status) { - krb5_error_code code; - krb5_pa_data *pa_data; - krb5_boolean more; - int flags; + krb5_error_code code; + krb5_pa_data *pa_data; + krb5_boolean more; + int flags; *nprincs = 0; memset(princ, 0, sizeof(*princ)); pa_data = find_pa_data(request->padata, KRB5_PADATA_S4U_X509_USER); if (pa_data != NULL) { - code = kdc_process_s4u_x509_user(context, - request, - pa_data, - tgs_subkey, - tgs_session, - s4u_x509_user, - status); - if (code != 0) - return code; + code = kdc_process_s4u_x509_user(context, + request, + pa_data, + tgs_subkey, + tgs_session, + s4u_x509_user, + status); + if (code != 0) + return code; } else { - pa_data = find_pa_data(request->padata, KRB5_PADATA_FOR_USER); - if (pa_data != NULL) { - code = kdc_process_for_user(context, - pa_data, - tgs_session, - s4u_x509_user, - status); - if (code != 0) - return code; - } else - return 0; + pa_data = find_pa_data(request->padata, KRB5_PADATA_FOR_USER); + if (pa_data != NULL) { + code = kdc_process_for_user(context, + pa_data, + tgs_session, + s4u_x509_user, + status); + if (code != 0) + return code; + } else + return 0; } /* @@ -2174,23 +2175,23 @@ kdc_process_s4u2self_req(krb5_context context, */ flags = 0; switch (krb5_princ_type(context, request->server)) { - case KRB5_NT_SRV_HST: /* (1) */ - if (krb5_princ_size(context, request->server) == 2) - flags |= KRB5_PRINCIPAL_COMPARE_IGNORE_REALM; - break; - case KRB5_NT_ENTERPRISE_PRINCIPAL: /* (2) */ - flags |= KRB5_PRINCIPAL_COMPARE_ENTERPRISE; - break; - default: /* (3) */ - break; + case KRB5_NT_SRV_HST: /* (1) */ + if (krb5_princ_size(context, request->server) == 2) + flags |= KRB5_PRINCIPAL_COMPARE_IGNORE_REALM; + break; + case KRB5_NT_ENTERPRISE_PRINCIPAL: /* (2) */ + flags |= KRB5_PRINCIPAL_COMPARE_ENTERPRISE; + break; + default: /* (3) */ + break; } if (!krb5_principal_compare_flags(context, - request->server, - client_princ, - flags)) { - *status = "INVALID_S4U2SELF_REQUEST"; - return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; /* match Windows error code */ + request->server, + client_princ, + flags)) { + *status = "INVALID_S4U2SELF_REQUEST"; + return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; /* match Windows error code */ } /* @@ -2202,45 +2203,45 @@ kdc_process_s4u2self_req(krb5_context context, * that is validated previously in validate_tgs_request(). */ if (request->kdc_options & AS_INVALID_OPTIONS) { - *status = "INVALID AS OPTIONS"; - return KRB5KDC_ERR_BADOPTION; + *status = "INVALID AS OPTIONS"; + return KRB5KDC_ERR_BADOPTION; } /* * Do not attempt to lookup principals in foreign realms. */ if (is_local_principal((*s4u_x509_user)->user_id.user)) { - krb5_db_entry no_server; - krb5_data e_data; - - e_data.data = NULL; - *nprincs = 1; - code = krb5_db_get_principal_ext(context, - (*s4u_x509_user)->user_id.user, - KRB5_KDB_FLAG_INCLUDE_PAC, - princ, nprincs, &more); - if (code) { - *status = "LOOKING_UP_S4U2SELF_PRINCIPAL"; - *nprincs = 0; - return code; /* caller can free for_user */ - } - - if (more) { - *status = "NON_UNIQUE_S4U2SELF_PRINCIPAL"; - return KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; - } else if (*nprincs != 1) { - *status = "UNKNOWN_S4U2SELF_PRINCIPAL"; - return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - } - - memset(&no_server, 0, sizeof(no_server)); - - code = validate_as_request(request, *princ, - no_server, kdc_time, status, &e_data); - if (code) { - krb5_free_data_contents(context, &e_data); - return code; - } + krb5_db_entry no_server; + krb5_data e_data; + + e_data.data = NULL; + *nprincs = 1; + code = krb5_db_get_principal_ext(context, + (*s4u_x509_user)->user_id.user, + KRB5_KDB_FLAG_INCLUDE_PAC, + princ, nprincs, &more); + if (code) { + *status = "LOOKING_UP_S4U2SELF_PRINCIPAL"; + *nprincs = 0; + return code; /* caller can free for_user */ + } + + if (more) { + *status = "NON_UNIQUE_S4U2SELF_PRINCIPAL"; + return KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; + } else if (*nprincs != 1) { + *status = "UNKNOWN_S4U2SELF_PRINCIPAL"; + return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + } + + memset(&no_server, 0, sizeof(no_server)); + + code = validate_as_request(request, *princ, + no_server, kdc_time, status, &e_data); + if (code) { + krb5_free_data_contents(context, &e_data); + return code; + } } return 0; @@ -2248,23 +2249,23 @@ kdc_process_s4u2self_req(krb5_context context, static krb5_error_code check_allowed_to_delegate_to(krb5_context context, - krb5_const_principal client, - const krb5_db_entry *server, - krb5_const_principal proxy) + krb5_const_principal client, + const krb5_db_entry *server, + krb5_const_principal proxy) { kdb_check_allowed_to_delegate_req req; - krb5_data req_data; - krb5_data rep_data; - krb5_error_code code; + krb5_data req_data; + krb5_data rep_data; + krb5_error_code code; /* Can't get a TGT (otherwise it would be unconstrained delegation) */ if (krb5_is_tgs_principal(proxy)) { - return KRB5KDC_ERR_POLICY; + return KRB5KDC_ERR_POLICY; } /* Must be in same realm */ if (!krb5_realm_compare(context, server->princ, proxy)) { - return KRB5KDC_ERR_POLICY; + return KRB5KDC_ERR_POLICY; } req.server = server; @@ -2278,11 +2279,11 @@ check_allowed_to_delegate_to(krb5_context context, rep_data.length = 0; code = krb5_db_invoke(context, - KRB5_KDB_METHOD_CHECK_ALLOWED_TO_DELEGATE, - &req_data, - &rep_data); + KRB5_KDB_METHOD_CHECK_ALLOWED_TO_DELEGATE, + &req_data, + &rep_data); if (code == KRB5_KDB_DBTYPE_NOSUP) { - code = KRB5KDC_ERR_POLICY; + code = KRB5KDC_ERR_POLICY; } assert(rep_data.length == 0); @@ -2292,12 +2293,12 @@ check_allowed_to_delegate_to(krb5_context context, krb5_error_code kdc_process_s4u2proxy_req(krb5_context context, - krb5_kdc_req *request, - const krb5_enc_tkt_part *t2enc, - const krb5_db_entry *server, - krb5_const_principal server_princ, - krb5_const_principal proxy_princ, - const char **status) + krb5_kdc_req *request, + const krb5_enc_tkt_part *t2enc, + const krb5_db_entry *server, + krb5_const_principal server_princ, + krb5_const_principal proxy_princ, + const char **status) { krb5_error_code errcode; @@ -2307,29 +2308,29 @@ kdc_process_s4u2proxy_req(krb5_context context, * that is validated previously in validate_tgs_request(). */ if (request->kdc_options & (NO_TGT_OPTION | KDC_OPT_ENC_TKT_IN_SKEY)) { - return KRB5KDC_ERR_BADOPTION; + return KRB5KDC_ERR_BADOPTION; } /* Ensure that evidence ticket server matches TGT client */ if (!krb5_principal_compare(kdc_context, - server->princ, /* after canon */ - server_princ)) { - return KRB5KDC_ERR_SERVER_NOMATCH; + server->princ, /* after canon */ + server_princ)) { + return KRB5KDC_ERR_SERVER_NOMATCH; } if (!isflagset(t2enc->flags, TKT_FLG_FORWARDABLE)) { - *status = "EVIDENCE_TKT_NOT_FORWARDABLE"; - return KRB5_TKT_NOT_FORWARDABLE; + *status = "EVIDENCE_TKT_NOT_FORWARDABLE"; + return KRB5_TKT_NOT_FORWARDABLE; } /* Backend policy check */ errcode = check_allowed_to_delegate_to(kdc_context, - t2enc->client, - server, - proxy_princ); + t2enc->client, + server, + proxy_princ); if (errcode) { - *status = "NOT_ALLOWED_TO_DELEGATE"; - return errcode; + *status = "NOT_ALLOWED_TO_DELEGATE"; + return errcode; } return 0; @@ -2337,25 +2338,25 @@ kdc_process_s4u2proxy_req(krb5_context context, krb5_error_code kdc_check_transited_list(krb5_context context, - const krb5_data *trans, - const krb5_data *realm1, - const krb5_data *realm2) + const krb5_data *trans, + const krb5_data *realm1, + const krb5_data *realm2) { - krb5_error_code code; - kdb_check_transited_realms_req req; - krb5_data req_data; - krb5_data rep_data; + krb5_error_code code; + kdb_check_transited_realms_req req; + krb5_data req_data; + krb5_data rep_data; /* First check using krb5.conf */ code = krb5_check_transited_list(kdc_context, trans, realm1, realm2); if (code) - return code; + return code; memset(&req, 0, sizeof(req)); - req.tr_contents = trans; - req.client_realm = realm1; - req.server_realm = realm2; + req.tr_contents = trans; + req.client_realm = realm1; + req.server_realm = realm2; req_data.data = (void *)&req; req_data.length = sizeof(req); @@ -2364,11 +2365,11 @@ kdc_check_transited_list(krb5_context context, rep_data.length = 0; code = krb5_db_invoke(context, - KRB5_KDB_METHOD_CHECK_TRANSITED_REALMS, - &req_data, - &rep_data); + KRB5_KDB_METHOD_CHECK_TRANSITED_REALMS, + &req_data, + &rep_data); if (code == KRB5_KDB_DBTYPE_NOSUP) { - code = 0; + code = 0; } assert(rep_data.length == 0); @@ -2378,20 +2379,20 @@ kdc_check_transited_list(krb5_context context, krb5_error_code validate_transit_path(krb5_context context, - krb5_const_principal client, - krb5_db_entry *server, - krb5_db_entry *krbtgt) + krb5_const_principal client, + krb5_db_entry *server, + krb5_db_entry *krbtgt) { /* Incoming */ if (isflagset(server->attributes, KRB5_KDB_XREALM_NON_TRANSITIVE)) { - return KRB5KDC_ERR_PATH_NOT_ACCEPTED; + return KRB5KDC_ERR_PATH_NOT_ACCEPTED; } /* Outgoing */ if (isflagset(krbtgt->attributes, KRB5_KDB_XREALM_NON_TRANSITIVE) && - (!krb5_principal_compare(context, server->princ, krbtgt->princ) || - !krb5_realm_compare(context, client, krbtgt->princ))) { - return KRB5KDC_ERR_PATH_NOT_ACCEPTED; + (!krb5_principal_compare(context, server->princ, krbtgt->princ) || + !krb5_realm_compare(context, client, krbtgt->princ))) { + return KRB5KDC_ERR_PATH_NOT_ACCEPTED; } return 0; @@ -2410,11 +2411,11 @@ validate_transit_path(krb5_context context, /* Currently no info about name canonicalization is logged. */ void log_as_req(const krb5_fulladdr *from, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_db_entry *client, const char *cname, - krb5_db_entry *server, const char *sname, - krb5_timestamp authtime, - const char *status, krb5_error_code errcode, const char *emsg) + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_db_entry *client, const char *cname, + krb5_db_entry *server, const char *sname, + krb5_timestamp authtime, + const char *status, krb5_error_code errcode, const char *emsg) { const char *fromstring = 0; char fromstringbuf[70]; @@ -2423,26 +2424,26 @@ log_as_req(const krb5_fulladdr *from, const char *sname2 = sname ? sname : "<unknown server>"; fromstring = inet_ntop(ADDRTYPE2FAMILY (from->address->addrtype), - from->address->contents, - fromstringbuf, sizeof(fromstringbuf)); + from->address->contents, + fromstringbuf, sizeof(fromstringbuf)); if (!fromstring) - fromstring = "<unknown>"; + fromstring = "<unknown>"; ktypes2str(ktypestr, sizeof(ktypestr), - request->nktypes, request->ktype); + request->nktypes, request->ktype); if (status == NULL) { - /* success */ - char rep_etypestr[128]; - rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply); - krb5_klog_syslog(LOG_INFO, - "AS_REQ (%s) %s: ISSUE: authtime %d, %s, %s for %s", - ktypestr, fromstring, authtime, - rep_etypestr, cname2, sname2); + /* success */ + char rep_etypestr[128]; + rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply); + krb5_klog_syslog(LOG_INFO, + "AS_REQ (%s) %s: ISSUE: authtime %d, %s, %s for %s", + ktypestr, fromstring, authtime, + rep_etypestr, cname2, sname2); } else { - /* fail */ + /* fail */ krb5_klog_syslog(LOG_INFO, "AS_REQ (%s) %s: %s: %s for %s%s%s", - ktypestr, fromstring, status, - cname2, sname2, emsg ? ", " : "", emsg ? emsg : ""); + ktypestr, fromstring, status, + cname2, sname2, emsg ? ", " : "", emsg ? emsg : ""); } #if 0 /* Sun (OpenSolaris) version would probably something like this. @@ -2450,33 +2451,33 @@ log_as_req(const krb5_fulladdr *from, logging routines used above. Note that a struct in_addr is used, but the real address could be an IPv6 address. */ audit_krb5kdc_as_req(some in_addr *, (in_port_t)from->port, 0, - cname, sname, errcode); + cname, sname, errcode); #endif #if 1 { - kdb_audit_as_req req; - krb5_data req_data; - krb5_data rep_data; + kdb_audit_as_req req; + krb5_data req_data; + krb5_data rep_data; - memset(&req, 0, sizeof(req)); + memset(&req, 0, sizeof(req)); - req.request = request; - req.client = client; - req.server = server; - req.authtime = authtime; - req.error_code = errcode; + req.request = request; + req.client = client; + req.server = server; + req.authtime = authtime; + req.error_code = errcode; - req_data.data = (void *)&req; - req_data.length = sizeof(req); + req_data.data = (void *)&req; + req_data.length = sizeof(req); - rep_data.data = NULL; - rep_data.length = 0; + rep_data.data = NULL; + rep_data.length = 0; - (void) krb5_db_invoke(kdc_context, - KRB5_KDB_METHOD_AUDIT_AS, - &req_data, - &rep_data); - assert(rep_data.length == 0); + (void) krb5_db_invoke(kdc_context, + KRB5_KDB_METHOD_AUDIT_AS, + &req_data, + &rep_data); + assert(rep_data.length == 0); } #endif } @@ -2487,11 +2488,11 @@ log_as_req(const krb5_fulladdr *from, Currently no info about name canonicalization is logged. */ void log_tgs_req(const krb5_fulladdr *from, - krb5_kdc_req *request, krb5_kdc_rep *reply, - const char *cname, const char *sname, const char *altcname, - krb5_timestamp authtime, - unsigned int c_flags, const char *s4u_name, - const char *status, krb5_error_code errcode, const char *emsg) + krb5_kdc_req *request, krb5_kdc_rep *reply, + const char *cname, const char *sname, const char *altcname, + krb5_timestamp authtime, + unsigned int c_flags, const char *s4u_name, + const char *status, krb5_error_code errcode, const char *emsg) { char ktypestr[128]; const char *fromstring = 0; @@ -2499,49 +2500,49 @@ log_tgs_req(const krb5_fulladdr *from, char rep_etypestr[128]; fromstring = inet_ntop(ADDRTYPE2FAMILY(from->address->addrtype), - from->address->contents, - fromstringbuf, sizeof(fromstringbuf)); + from->address->contents, + fromstringbuf, sizeof(fromstringbuf)); if (!fromstring) - fromstring = "<unknown>"; + fromstring = "<unknown>"; ktypes2str(ktypestr, sizeof(ktypestr), request->nktypes, request->ktype); if (!errcode) - rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply); + rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply); else - rep_etypestr[0] = 0; + rep_etypestr[0] = 0; /* Differences: server-nomatch message logs 2nd ticket's client name (useful), and doesn't log ktypestr (probably not important). */ if (errcode != KRB5KDC_ERR_SERVER_NOMATCH) { - krb5_klog_syslog(LOG_INFO, - "TGS_REQ (%s) %s: %s: authtime %d, %s%s %s for %s%s%s", - ktypestr, - fromstring, status, authtime, - rep_etypestr, - !errcode ? "," : "", - cname ? cname : "<unknown client>", - sname ? sname : "<unknown server>", - errcode ? ", " : "", - errcode ? emsg : ""); - if (s4u_name) { - assert(isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) || - isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)); - if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) - krb5_klog_syslog(LOG_INFO, - "... PROTOCOL-TRANSITION s4u-client=%s", - s4u_name); - else if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) - krb5_klog_syslog(LOG_INFO, - "... CONSTRAINED-DELEGATION s4u-client=%s", - s4u_name); - } + krb5_klog_syslog(LOG_INFO, + "TGS_REQ (%s) %s: %s: authtime %d, %s%s %s for %s%s%s", + ktypestr, + fromstring, status, authtime, + rep_etypestr, + !errcode ? "," : "", + cname ? cname : "<unknown client>", + sname ? sname : "<unknown server>", + errcode ? ", " : "", + errcode ? emsg : ""); + if (s4u_name) { + assert(isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) || + isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)); + if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) + krb5_klog_syslog(LOG_INFO, + "... PROTOCOL-TRANSITION s4u-client=%s", + s4u_name); + else if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) + krb5_klog_syslog(LOG_INFO, + "... CONSTRAINED-DELEGATION s4u-client=%s", + s4u_name); + } } else - krb5_klog_syslog(LOG_INFO, - "TGS_REQ %s: %s: authtime %d, %s for %s, 2nd tkt client %s", - fromstring, status, authtime, - cname ? cname : "<unknown client>", - sname ? sname : "<unknown server>", - altcname ? altcname : "<unknown>"); + krb5_klog_syslog(LOG_INFO, + "TGS_REQ %s: %s: authtime %d, %s for %s, 2nd tkt client %s", + fromstring, status, authtime, + cname ? cname : "<unknown client>", + sname ? sname : "<unknown server>", + altcname ? altcname : "<unknown>"); /* OpenSolaris: audit_krb5kdc_tgs_req(...) or audit_krb5kdc_tgs_req_2ndtktmm(...) */ @@ -2553,12 +2554,12 @@ log_tgs_alt_tgt(krb5_principal p) { char *sname; if (krb5_unparse_name(kdc_context, p, &sname)) { - krb5_klog_syslog(LOG_INFO, - "TGS_REQ: issuing alternate <un-unparseable> TGT"); + krb5_klog_syslog(LOG_INFO, + "TGS_REQ: issuing alternate <un-unparseable> TGT"); } else { - limit_string(sname); - krb5_klog_syslog(LOG_INFO, "TGS_REQ: issuing TGT %s", sname); - free(sname); + limit_string(sname); + krb5_klog_syslog(LOG_INFO, "TGS_REQ: issuing TGT %s", sname); + free(sname); } /* OpenSolaris: audit_krb5kdc_tgs_req_alt_tgt(...) */ } @@ -2574,50 +2575,50 @@ enctype_requires_etype_info_2(krb5_enctype enctype) case ENCTYPE_DES3_CBC_RAW: case ENCTYPE_ARCFOUR_HMAC: case ENCTYPE_ARCFOUR_HMAC_EXP : - return 0; + return 0; default: - return krb5_c_valid_enctype(enctype); + return krb5_c_valid_enctype(enctype); } } /* XXX where are the generic helper routines for this? */ krb5_error_code add_pa_data_element(krb5_context context, - krb5_pa_data *padata, - krb5_pa_data ***inout_padata, - krb5_boolean copy) + krb5_pa_data *padata, + krb5_pa_data ***inout_padata, + krb5_boolean copy) { - int i; - krb5_pa_data **p; + int i; + krb5_pa_data **p; if (*inout_padata != NULL) { - for (i = 0; (*inout_padata)[i] != NULL; i++) - ; + for (i = 0; (*inout_padata)[i] != NULL; i++) + ; } else - i = 0; + i = 0; p = realloc(*inout_padata, (i + 2) * sizeof(krb5_pa_data *)); if (p == NULL) - return ENOMEM; + return ENOMEM; *inout_padata = p; p[i] = (krb5_pa_data *)malloc(sizeof(krb5_pa_data)); if (p[i] == NULL) - return ENOMEM; + return ENOMEM; *(p[i]) = *padata; p[i + 1] = NULL; if (copy) { - p[i]->contents = (krb5_octet *)malloc(padata->length); - if (p[i]->contents == NULL) { - free(p[i]); - p[i] = NULL; - return ENOMEM; - } + p[i]->contents = (krb5_octet *)malloc(padata->length); + if (p[i]->contents == NULL) { + free(p[i]); + p[i] = NULL; + return ENOMEM; + } - memcpy(p[i]->contents, padata->contents, padata->length); + memcpy(p[i]->contents, padata->contents, padata->length); } return 0; @@ -2625,29 +2626,28 @@ add_pa_data_element(krb5_context context, void kdc_get_ticket_endtime(krb5_context context, - krb5_timestamp starttime, - krb5_timestamp endtime, - krb5_timestamp till, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_timestamp *out_endtime) + krb5_timestamp starttime, + krb5_timestamp endtime, + krb5_timestamp till, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_timestamp *out_endtime) { krb5_timestamp until, life; if (till == 0) - till = kdc_infinity; + till = kdc_infinity; until = min(till, endtime); life = until - starttime; if (client->max_life != 0) - life = min(life, client->max_life); + life = min(life, client->max_life); if (server->max_life != 0) - life = min(life, server->max_life); + life = min(life, server->max_life); if (max_life_for_realm != 0) - life = min(life, max_life_for_realm); + life = min(life, max_life_for_realm); *out_endtime = starttime + life; } - diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index 84319f7..1950ec0 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/kdc_util.h * @@ -8,7 +9,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -22,7 +23,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * Declarations for policy.c */ @@ -34,8 +35,8 @@ #include "kdb_ext.h" typedef struct _krb5_fulladdr { - krb5_address * address; - krb5_ui_4 port; + krb5_address * address; + krb5_ui_4 port; } krb5_fulladdr; krb5_error_code check_hot_list (krb5_ticket *); @@ -43,71 +44,71 @@ krb5_boolean realm_compare (krb5_const_principal, krb5_const_principal); krb5_boolean is_local_principal(krb5_const_principal princ1); krb5_boolean krb5_is_tgs_principal (krb5_const_principal); krb5_error_code add_to_transited (krb5_data *, - krb5_data *, - krb5_principal, - krb5_principal, - krb5_principal); + krb5_data *, + krb5_principal, + krb5_principal, + krb5_principal); krb5_error_code compress_transited (krb5_data *, - krb5_principal, - krb5_data *); + krb5_principal, + krb5_data *); krb5_error_code concat_authorization_data (krb5_authdata **, - krb5_authdata **, - krb5_authdata ***); + krb5_authdata **, + krb5_authdata ***); krb5_error_code fetch_last_req_info (krb5_db_entry *, - krb5_last_req_entry ***); + krb5_last_req_entry ***); krb5_error_code kdc_convert_key (krb5_keyblock *, - krb5_keyblock *, - int); -krb5_error_code kdc_process_tgs_req - (krb5_kdc_req *, - const krb5_fulladdr *, - krb5_data *, - krb5_ticket **, - krb5_db_entry *krbtgt, - int *nprincs, - krb5_keyblock **, krb5_keyblock **, - krb5_pa_data **pa_tgs_req); + krb5_keyblock *, + int); +krb5_error_code kdc_process_tgs_req +(krb5_kdc_req *, + const krb5_fulladdr *, + krb5_data *, + krb5_ticket **, + krb5_db_entry *krbtgt, + int *nprincs, + krb5_keyblock **, krb5_keyblock **, + krb5_pa_data **pa_tgs_req); krb5_error_code kdc_get_server_key (krb5_ticket *, unsigned int, - krb5_boolean match_enctype, - krb5_db_entry *, int *, - krb5_keyblock **, krb5_kvno *); + krb5_boolean match_enctype, + krb5_db_entry *, int *, + krb5_keyblock **, krb5_kvno *); -int validate_as_request (krb5_kdc_req *, krb5_db_entry, - krb5_db_entry, krb5_timestamp, - const char **, krb5_data *); +int validate_as_request (krb5_kdc_req *, krb5_db_entry, + krb5_db_entry, krb5_timestamp, + const char **, krb5_data *); -int validate_forwardable(krb5_kdc_req *, krb5_db_entry, - krb5_db_entry, krb5_timestamp, - const char **); +int validate_forwardable(krb5_kdc_req *, krb5_db_entry, + krb5_db_entry, krb5_timestamp, + const char **); -int validate_tgs_request (krb5_kdc_req *, krb5_db_entry, - krb5_ticket *, krb5_timestamp, - const char **, krb5_data *); +int validate_tgs_request (krb5_kdc_req *, krb5_db_entry, + krb5_ticket *, krb5_timestamp, + const char **, krb5_data *); int fetch_asn1_field (unsigned char *, unsigned int, unsigned int, - krb5_data *); + krb5_data *); int dbentry_has_key_for_enctype (krb5_context context, - krb5_db_entry *client, - krb5_enctype enctype); - + krb5_db_entry *client, + krb5_enctype enctype); + int dbentry_supports_enctype (krb5_context context, - krb5_db_entry *client, - krb5_enctype enctype); + krb5_db_entry *client, + krb5_enctype enctype); krb5_enctype select_session_keytype (krb5_context context, - krb5_db_entry *server, - int nktypes, - krb5_enctype *ktypes); + krb5_db_entry *server, + int nktypes, + krb5_enctype *ktypes); krb5_error_code get_salt_from_key (krb5_context, krb5_principal, - krb5_key_data *, krb5_data *); + krb5_key_data *, krb5_data *); void limit_string (char *name); @@ -119,17 +120,17 @@ rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep); /* do_as_req.c */ krb5_error_code process_as_req (krb5_kdc_req *, krb5_data *, - const krb5_fulladdr *, - krb5_data ** ); + const krb5_fulladdr *, + krb5_data ** ); /* do_tgs_req.c */ krb5_error_code process_tgs_req (krb5_data *, - const krb5_fulladdr *, - krb5_data ** ); + const krb5_fulladdr *, + krb5_data ** ); /* dispatch.c */ krb5_error_code dispatch (krb5_data *, - const krb5_fulladdr *, - krb5_data **); + const krb5_fulladdr *, + krb5_data **); /* main.c */ krb5_error_code kdc_initialize_rcache (krb5_context, char *); @@ -144,48 +145,48 @@ krb5_error_code closedown_network (void); /* policy.c */ int against_local_policy_as (krb5_kdc_req *, krb5_db_entry, - krb5_db_entry, krb5_timestamp, - const char **, krb5_data *); + krb5_db_entry, krb5_timestamp, + const char **, krb5_data *); int against_local_policy_tgs (krb5_kdc_req *, krb5_db_entry, - krb5_ticket *, const char **, - krb5_data *); + krb5_ticket *, const char **, + krb5_data *); /* kdc_preauth.c */ krb5_boolean enctype_requires_etype_info_2(krb5_enctype enctype); const char * missing_required_preauth - (krb5_db_entry *client, krb5_db_entry *server, - krb5_enc_tkt_part *enc_tkt_reply); +(krb5_db_entry *client, krb5_db_entry *server, + krb5_enc_tkt_part *enc_tkt_reply); void get_preauth_hint_list (krb5_kdc_req * request, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_data *e_data); + krb5_db_entry *client, + krb5_db_entry *server, + krb5_data *e_data); krb5_error_code load_preauth_plugins(krb5_context context); krb5_error_code unload_preauth_plugins(krb5_context context); krb5_error_code check_padata - (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, - krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, - void **padata_context, krb5_data *e_data); - +(krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, + krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, + void **padata_context, krb5_data *e_data); + krb5_error_code return_padata - (krb5_context context, krb5_db_entry *client, - krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_key_data *client_key, krb5_keyblock *encrypting_key, - void **padata_context); - +(krb5_context context, krb5_db_entry *client, + krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_key_data *client_key, krb5_keyblock *encrypting_key, + void **padata_context); + krb5_error_code free_padata_context - (krb5_context context, void **padata_context); +(krb5_context context, void **padata_context); krb5_pa_data *find_pa_data - (krb5_pa_data **padata, krb5_preauthtype pa_type); +(krb5_pa_data **padata, krb5_preauthtype pa_type); krb5_error_code add_pa_data_element - (krb5_context context, - krb5_pa_data *padata, - krb5_pa_data ***out_padata, - krb5_boolean copy); +(krb5_context context, + krb5_pa_data *padata, + krb5_pa_data ***out_padata, + krb5_boolean copy); /* kdc_authdata.c */ krb5_error_code load_authdata_plugins(krb5_context context); @@ -193,18 +194,18 @@ krb5_error_code unload_authdata_plugins(krb5_context context); krb5_error_code handle_authdata (krb5_context context, - unsigned int flags, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_db_entry *krbtgt, - krb5_keyblock *client_key, - krb5_keyblock *server_key, - krb5_keyblock *krbtgt_key, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_const_principal for_user_princ, - krb5_enc_tkt_part *enc_tkt_request, - krb5_enc_tkt_part *enc_tkt_reply); + unsigned int flags, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *krbtgt_key, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_request, + krb5_enc_tkt_part *enc_tkt_reply); /* replay.c */ krb5_boolean kdc_check_lookaside (krb5_data *, krb5_data **); @@ -214,122 +215,122 @@ void kdc_free_lookaside(krb5_context); /* kdc_util.c */ krb5_error_code get_principal_locked (krb5_context kcontext, - krb5_const_principal search_for, - krb5_db_entry *entries, int *nentries, - krb5_boolean *more); + krb5_const_principal search_for, + krb5_db_entry *entries, int *nentries, + krb5_boolean *more); krb5_error_code get_principal (krb5_context kcontext, - krb5_const_principal search_for, - krb5_db_entry *entries, int *nentries, krb5_boolean *more); + krb5_const_principal search_for, + krb5_db_entry *entries, int *nentries, krb5_boolean *more); krb5_boolean include_pac_p(krb5_context context, krb5_kdc_req *request); krb5_error_code return_svr_referral_data - (krb5_context context, - krb5_db_entry *server, - krb5_enc_kdc_rep_part *reply_encpart); +(krb5_context context, + krb5_db_entry *server, + krb5_enc_kdc_rep_part *reply_encpart); krb5_error_code sign_db_authdata - (krb5_context context, - unsigned int flags, - krb5_const_principal client_princ, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_db_entry *krbtgt, - krb5_keyblock *client_key, - krb5_keyblock *server_key, - krb5_keyblock *krbtgt_key, - krb5_timestamp authtime, - krb5_authdata **tgs_authdata, - krb5_keyblock *session_key, - krb5_authdata ***ret_authdata); +(krb5_context context, + unsigned int flags, + krb5_const_principal client_princ, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_db_entry *krbtgt, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *krbtgt_key, + krb5_timestamp authtime, + krb5_authdata **tgs_authdata, + krb5_keyblock *session_key, + krb5_authdata ***ret_authdata); krb5_error_code kdc_process_s4u2self_req - (krb5_context context, - krb5_kdc_req *request, - krb5_const_principal client_princ, - const krb5_db_entry *server, - krb5_keyblock *tgs_subkey, - krb5_keyblock *tgs_session, - krb5_timestamp kdc_time, - krb5_pa_s4u_x509_user **s4u2self_req, - krb5_db_entry *princ, - int *nprincs, - const char **status); +(krb5_context context, + krb5_kdc_req *request, + krb5_const_principal client_princ, + const krb5_db_entry *server, + krb5_keyblock *tgs_subkey, + krb5_keyblock *tgs_session, + krb5_timestamp kdc_time, + krb5_pa_s4u_x509_user **s4u2self_req, + krb5_db_entry *princ, + int *nprincs, + const char **status); krb5_error_code kdc_make_s4u2self_rep - (krb5_context context, - krb5_keyblock *tgs_subkey, - krb5_keyblock *tgs_session, - krb5_pa_s4u_x509_user *req_s4u_user, - krb5_kdc_rep *reply, - krb5_enc_kdc_rep_part *reply_encpart); +(krb5_context context, + krb5_keyblock *tgs_subkey, + krb5_keyblock *tgs_session, + krb5_pa_s4u_x509_user *req_s4u_user, + krb5_kdc_rep *reply, + krb5_enc_kdc_rep_part *reply_encpart); krb5_error_code kdc_process_s4u2proxy_req - (krb5_context context, - krb5_kdc_req *request, - const krb5_enc_tkt_part *t2enc, - const krb5_db_entry *server, - krb5_const_principal server_princ, - krb5_const_principal proxy_princ, - const char **status); +(krb5_context context, + krb5_kdc_req *request, + const krb5_enc_tkt_part *t2enc, + const krb5_db_entry *server, + krb5_const_principal server_princ, + krb5_const_principal proxy_princ, + const char **status); krb5_error_code kdc_check_transited_list - (krb5_context context, - const krb5_data *trans, - const krb5_data *realm1, - const krb5_data *realm2); +(krb5_context context, + const krb5_data *trans, + const krb5_data *realm1, + const krb5_data *realm2); krb5_error_code audit_as_request - (krb5_kdc_req *request, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_timestamp authtime, - krb5_error_code errcode); +(krb5_kdc_req *request, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_timestamp authtime, + krb5_error_code errcode); krb5_error_code audit_tgs_request - (krb5_kdc_req *request, - krb5_const_principal client, - krb5_db_entry *server, - krb5_timestamp authtime, - krb5_error_code errcode); +(krb5_kdc_req *request, + krb5_const_principal client, + krb5_db_entry *server, + krb5_timestamp authtime, + krb5_error_code errcode); krb5_error_code validate_transit_path(krb5_context context, - krb5_const_principal client, - krb5_db_entry *server, - krb5_db_entry *krbtgt); + krb5_const_principal client, + krb5_db_entry *server, + krb5_db_entry *krbtgt); void kdc_get_ticket_endtime(krb5_context context, - krb5_timestamp now, - krb5_timestamp endtime, - krb5_timestamp till, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_timestamp *out_endtime); + krb5_timestamp now, + krb5_timestamp endtime, + krb5_timestamp till, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_timestamp *out_endtime); void log_as_req(const krb5_fulladdr *from, - krb5_kdc_req *request, krb5_kdc_rep *reply, - krb5_db_entry *client, const char *cname, - krb5_db_entry *server, const char *sname, - krb5_timestamp authtime, - const char *status, krb5_error_code errcode, const char *emsg); + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_db_entry *client, const char *cname, + krb5_db_entry *server, const char *sname, + krb5_timestamp authtime, + const char *status, krb5_error_code errcode, const char *emsg); void log_tgs_req(const krb5_fulladdr *from, - krb5_kdc_req *request, krb5_kdc_rep *reply, - const char *cname, const char *sname, const char *altcname, - krb5_timestamp authtime, - unsigned int c_flags, const char *s4u_name, - const char *status, krb5_error_code errcode, const char *emsg); + krb5_kdc_req *request, krb5_kdc_rep *reply, + const char *cname, const char *sname, const char *altcname, + krb5_timestamp authtime, + unsigned int c_flags, const char *s4u_name, + const char *status, krb5_error_code errcode, const char *emsg); void log_tgs_alt_tgt(krb5_principal p); /*Request state*/ struct kdc_request_state { krb5_keyblock *armor_key; - krb5_keyblock *strengthen_key; + krb5_keyblock *strengthen_key; krb5_pa_data *cookie; krb5_int32 fast_options; krb5_int32 fast_internal_flags; @@ -361,31 +362,31 @@ krb5_error_code kdc_fast_handle_error krb5_pa_data **in_padata, krb5_error *err); krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state, - krb5_keyblock *existing_key, - krb5_keyblock **out_key); + krb5_keyblock *existing_key, + krb5_keyblock **out_key); krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state, - krb5_pa_data **cookie); + krb5_pa_data **cookie); + - #define isflagset(flagfield, flag) (flagfield & (flag)) #define setflag(flagfield, flag) (flagfield |= (flag)) #define clear(flagfield, flag) (flagfield &= ~(flag)) -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#define max(a, b) ((a) > (b) ? (a) : (b)) +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) > (b) ? (a) : (b)) #endif #ifdef KRB5_USE_INET6 -#define ADDRTYPE2FAMILY(X) \ - ((X) == ADDRTYPE_INET6 ? AF_INET6 : (X) == ADDRTYPE_INET ? AF_INET : -1) +#define ADDRTYPE2FAMILY(X) \ + ((X) == ADDRTYPE_INET6 ? AF_INET6 : (X) == ADDRTYPE_INET ? AF_INET : -1) #else -#define ADDRTYPE2FAMILY(X) \ - ((X) == ADDRTYPE_INET ? AF_INET : -1) +#define ADDRTYPE2FAMILY(X) \ + ((X) == ADDRTYPE_INET ? AF_INET : -1) #endif /* RFC 4120: KRB5KDC_ERR_KEY_TOO_WEAK diff --git a/src/kdc/main.c b/src/kdc/main.c index 039d918..64b6beb 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/main.c * @@ -7,7 +8,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -21,7 +22,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * Main procedure body for the KDC server process. */ @@ -95,7 +96,7 @@ static int rkey_init_done = 0; static struct sigaction s_action; #endif /* POSIX_SIGNALS */ -#define KRB5_KDC_MAX_REALMS 32 +#define KRB5_KDC_MAX_REALMS 32 static krb5_context kdc_err_context; static const char *kdc_progname; @@ -116,7 +117,7 @@ kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...) va_list ap; if (call_context) - krb5_copy_error_message(kdc_err_context, call_context); + krb5_copy_error_message(kdc_err_context, call_context); va_start(ap, fmt); com_err_va(kdc_progname, code, fmt, ap); va_end(ap); @@ -130,9 +131,9 @@ find_realm_data(char *rname, krb5_ui_4 rsize) { int i; for (i=0; i<kdc_numrealms; i++) { - if ((rsize == strlen(kdc_realmlist[i]->realm_name)) && - !strncmp(rname, kdc_realmlist[i]->realm_name, rsize)) - return(kdc_realmlist[i]); + if ((rsize == strlen(kdc_realmlist[i]->realm_name)) && + !strncmp(rname, kdc_realmlist[i]->realm_name, rsize)) + return(kdc_realmlist[i]); } return((kdc_realm_t *) NULL); } @@ -140,19 +141,19 @@ find_realm_data(char *rname, krb5_ui_4 rsize) krb5_error_code setup_server_realm(krb5_principal sprinc) { - krb5_error_code kret; - kdc_realm_t *newrealm; + krb5_error_code kret; + kdc_realm_t *newrealm; kret = 0; if (kdc_numrealms > 1) { - if (!(newrealm = find_realm_data(sprinc->realm.data, - (krb5_ui_4) sprinc->realm.length))) - kret = ENOENT; - else - kdc_active_realm = newrealm; + if (!(newrealm = find_realm_data(sprinc->realm.data, + (krb5_ui_4) sprinc->realm.length))) + kret = ENOENT; + else + kdc_active_realm = newrealm; } else - kdc_active_realm = kdc_realmlist[0]; + kdc_active_realm = kdc_realmlist[0]; return(kret); } @@ -160,43 +161,43 @@ static void finish_realm(kdc_realm_t *rdp) { if (rdp->realm_dbname) - free(rdp->realm_dbname); + free(rdp->realm_dbname); if (rdp->realm_mpname) - free(rdp->realm_mpname); + free(rdp->realm_mpname); if (rdp->realm_stash) - free(rdp->realm_stash); + free(rdp->realm_stash); if (rdp->realm_ports) - free(rdp->realm_ports); + free(rdp->realm_ports); if (rdp->realm_tcp_ports) - free(rdp->realm_tcp_ports); + free(rdp->realm_tcp_ports); if (rdp->realm_keytab) - krb5_kt_close(rdp->realm_context, rdp->realm_keytab); + krb5_kt_close(rdp->realm_context, rdp->realm_keytab); if (rdp->realm_host_based_services) - free(rdp->realm_host_based_services); + free(rdp->realm_host_based_services); if (rdp->realm_no_host_referral) - free(rdp->realm_no_host_referral); + free(rdp->realm_no_host_referral); if (rdp->realm_context) { - if (rdp->realm_mprinc) - krb5_free_principal(rdp->realm_context, rdp->realm_mprinc); - if (rdp->realm_mkey.length && rdp->realm_mkey.contents) { + if (rdp->realm_mprinc) + krb5_free_principal(rdp->realm_context, rdp->realm_mprinc); + if (rdp->realm_mkey.length && rdp->realm_mkey.contents) { /* XXX shouldn't memset be zap for safety? */ - memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length); - free(rdp->realm_mkey.contents); - } + memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length); + free(rdp->realm_mkey.contents); + } if (rdp->mkey_list) krb5_dbe_free_key_list(rdp->realm_context, rdp->mkey_list); - krb5_db_fini(rdp->realm_context); - if (rdp->realm_tgsprinc) - krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc); - krb5_free_context(rdp->realm_context); + krb5_db_fini(rdp->realm_context); + if (rdp->realm_tgsprinc) + krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc); + krb5_free_context(rdp->realm_context); } memset(rdp, 0, sizeof(*rdp)); free(rdp); } -static krb5_error_code -handle_referral_params(krb5_realm_params *rparams, - char *no_refrls, char *host_based_srvcs, +static krb5_error_code +handle_referral_params(krb5_realm_params *rparams, + char *no_refrls, char *host_based_srvcs, kdc_realm_t *rdp ) { krb5_error_code retval = 0; @@ -210,46 +211,46 @@ handle_referral_params(krb5_realm_params *rparams, rdp->realm_no_host_referral = strdup(KRB5_CONF_ASTERISK); if (!rdp->realm_no_host_referral) retval = ENOMEM; - } else if (no_refrls && (asprintf(&(rdp->realm_no_host_referral), "%s%s%s%s%s", - " ", no_refrls," ",rparams->realm_no_host_referral, " ") < 0)) - retval = ENOMEM; - else if (asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", - rparams->realm_no_host_referral, " ") < 0) - retval = ENOMEM; + } else if (no_refrls && (asprintf(&(rdp->realm_no_host_referral), "%s%s%s%s%s", + " ", no_refrls," ",rparams->realm_no_host_referral, " ") < 0)) + retval = ENOMEM; + else if (asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", + rparams->realm_no_host_referral, " ") < 0) + retval = ENOMEM; } else if( no_refrls != NULL) { if ( asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", no_refrls, " ") < 0) - retval = ENOMEM; + retval = ENOMEM; } else rdp->realm_no_host_referral = NULL; } if (rdp->realm_no_host_referral && krb5_match_config_pattern(rdp->realm_no_host_referral, KRB5_CONF_ASTERISK) == TRUE) { - rdp->realm_host_based_services = NULL; + rdp->realm_host_based_services = NULL; return 0; } if (host_based_srvcs && (krb5_match_config_pattern(host_based_srvcs, KRB5_CONF_ASTERISK) == TRUE)) { - rdp->realm_host_based_services = strdup(KRB5_CONF_ASTERISK); - if (!rdp->realm_host_based_services) - retval = ENOMEM; + rdp->realm_host_based_services = strdup(KRB5_CONF_ASTERISK); + if (!rdp->realm_host_based_services) + retval = ENOMEM; } else { - if (rparams && rparams->realm_host_based_services) { - if (krb5_match_config_pattern(rparams->realm_host_based_services, KRB5_CONF_ASTERISK) == TRUE) { - rdp->realm_host_based_services = strdup(KRB5_CONF_ASTERISK); - if (!rdp->realm_host_based_services) - retval = ENOMEM; - } else if (host_based_srvcs) { - if (asprintf(&(rdp->realm_host_based_services), "%s%s%s%s%s", - " ", host_based_srvcs," ",rparams->realm_host_based_services, " ") < 0) - retval = ENOMEM; - } else if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", - rparams->realm_host_based_services, " ") < 0) - retval = ENOMEM; + if (rparams && rparams->realm_host_based_services) { + if (krb5_match_config_pattern(rparams->realm_host_based_services, KRB5_CONF_ASTERISK) == TRUE) { + rdp->realm_host_based_services = strdup(KRB5_CONF_ASTERISK); + if (!rdp->realm_host_based_services) + retval = ENOMEM; } else if (host_based_srvcs) { - if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", host_based_srvcs, " ") < 0) - retval = ENOMEM; - } else - rdp->realm_host_based_services = NULL; + if (asprintf(&(rdp->realm_host_based_services), "%s%s%s%s%s", + " ", host_based_srvcs," ",rparams->realm_host_based_services, " ") < 0) + retval = ENOMEM; + } else if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", + rparams->realm_host_based_services, " ") < 0) + retval = ENOMEM; + } else if (host_based_srvcs) { + if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", host_based_srvcs, " ") < 0) + retval = ENOMEM; + } else + rdp->realm_host_based_services = NULL; } return retval; @@ -263,39 +264,39 @@ handle_referral_params(krb5_realm_params *rparams, */ static krb5_error_code init_realm(kdc_realm_t *rdp, char *realm, char *def_mpname, - krb5_enctype def_enctype, char *def_udp_ports, char *def_tcp_ports, - krb5_boolean def_manual, char **db_args, char *no_refrls, - char *host_based_srvcs) + krb5_enctype def_enctype, char *def_udp_ports, char *def_tcp_ports, + krb5_boolean def_manual, char **db_args, char *no_refrls, + char *host_based_srvcs) { - krb5_error_code kret; - krb5_boolean manual; - krb5_realm_params *rparams; - int kdb_open_flags; + krb5_error_code kret; + krb5_boolean manual; + krb5_realm_params *rparams; + int kdb_open_flags; krb5_kvno mkvno = IGNORE_VNO; memset(rdp, 0, sizeof(kdc_realm_t)); if (!realm) { - kret = EINVAL; - goto whoops; + kret = EINVAL; + goto whoops; } - + rdp->realm_name = realm; kret = krb5int_init_context_kdc(&rdp->realm_context); if (kret) { - kdc_err(NULL, kret, "while getting context for realm %s", realm); - goto whoops; + kdc_err(NULL, kret, "while getting context for realm %s", realm); + goto whoops; } kret = krb5_read_realm_params(rdp->realm_context, rdp->realm_name, - &rparams); + &rparams); if (kret) { - kdc_err(rdp->realm_context, kret, "while reading realm parameters"); - goto whoops; + kdc_err(rdp->realm_context, kret, "while reading realm parameters"); + goto whoops; } - + /* Handle profile file name */ if (rparams && rparams->realm_profile) { - rdp->realm_profile = strdup(rparams->realm_profile); + rdp->realm_profile = strdup(rparams->realm_profile); if (!rdp->realm_profile) { kret = ENOMEM; goto whoops; @@ -304,10 +305,10 @@ init_realm(kdc_realm_t *rdp, char *realm, char *def_mpname, /* Handle master key name */ if (rparams && rparams->realm_mkey_name) - rdp->realm_mpname = strdup(rparams->realm_mkey_name); + rdp->realm_mpname = strdup(rparams->realm_mkey_name); else - rdp->realm_mpname = (def_mpname) ? strdup(def_mpname) : - strdup(KRB5_KDB_M_NAME); + rdp->realm_mpname = (def_mpname) ? strdup(def_mpname) : + strdup(KRB5_KDB_M_NAME); if (!rdp->realm_mpname) { kret = ENOMEM; goto whoops; @@ -315,59 +316,59 @@ init_realm(kdc_realm_t *rdp, char *realm, char *def_mpname, /* Handle KDC ports */ if (rparams && rparams->realm_kdc_ports) - rdp->realm_ports = strdup(rparams->realm_kdc_ports); + rdp->realm_ports = strdup(rparams->realm_kdc_ports); else - rdp->realm_ports = strdup(def_udp_ports); + rdp->realm_ports = strdup(def_udp_ports); if (!rdp->realm_ports) { kret = ENOMEM; goto whoops; } if (rparams && rparams->realm_kdc_tcp_ports) - rdp->realm_tcp_ports = strdup(rparams->realm_kdc_tcp_ports); + rdp->realm_tcp_ports = strdup(rparams->realm_kdc_tcp_ports); else - rdp->realm_tcp_ports = strdup(def_tcp_ports); + rdp->realm_tcp_ports = strdup(def_tcp_ports); if (!rdp->realm_tcp_ports) { kret = ENOMEM; goto whoops; } /* Handle stash file */ if (rparams && rparams->realm_stash_file) { - rdp->realm_stash = strdup(rparams->realm_stash_file); + rdp->realm_stash = strdup(rparams->realm_stash_file); if (!rdp->realm_stash) { kret = ENOMEM; goto whoops; } - manual = FALSE; + manual = FALSE; } else - manual = def_manual; + manual = def_manual; /* Handle master key type */ if (rparams && rparams->realm_enctype_valid) - rdp->realm_mkey.enctype = (krb5_enctype) rparams->realm_enctype; + rdp->realm_mkey.enctype = (krb5_enctype) rparams->realm_enctype; else - rdp->realm_mkey.enctype = manual ? def_enctype : ENCTYPE_UNKNOWN; + rdp->realm_mkey.enctype = manual ? def_enctype : ENCTYPE_UNKNOWN; /* Handle reject-bad-transit flag */ if (rparams && rparams->realm_reject_bad_transit_valid) - rdp->realm_reject_bad_transit = rparams->realm_reject_bad_transit; + rdp->realm_reject_bad_transit = rparams->realm_reject_bad_transit; else - rdp->realm_reject_bad_transit = 1; - + rdp->realm_reject_bad_transit = 1; + /* Handle ticket maximum life */ rdp->realm_maxlife = (rparams && rparams->realm_max_life_valid) ? - rparams->realm_max_life : KRB5_KDB_MAX_LIFE; + rparams->realm_max_life : KRB5_KDB_MAX_LIFE; /* Handle ticket renewable maximum life */ rdp->realm_maxrlife = (rparams && rparams->realm_max_rlife_valid) ? - rparams->realm_max_rlife : KRB5_KDB_MAX_RLIFE; + rparams->realm_max_rlife : KRB5_KDB_MAX_RLIFE; /* Handle KDC referrals */ kret = handle_referral_params(rparams, no_refrls, host_based_srvcs, rdp); if (kret == ENOMEM) - goto whoops; + goto whoops; if (rparams) - krb5_free_realm_params(rdp->realm_context, rparams); + krb5_free_realm_params(rdp->realm_context, rparams); /* * We've got our parameters, now go and setup our realm context. @@ -375,40 +376,40 @@ init_realm(kdc_realm_t *rdp, char *realm, char *def_mpname, /* Set the default realm of this context */ if ((kret = krb5_set_default_realm(rdp->realm_context, realm))) { - kdc_err(rdp->realm_context, kret, "while setting default realm to %s", - realm); - goto whoops; + kdc_err(rdp->realm_context, kret, "while setting default realm to %s", + realm); + goto whoops; } /* first open the database before doing anything */ kdb_open_flags = KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_KDC; if ((kret = krb5_db_open(rdp->realm_context, db_args, kdb_open_flags))) { - kdc_err(rdp->realm_context, kret, - "while initializing database for realm %s", realm); - goto whoops; + kdc_err(rdp->realm_context, kret, + "while initializing database for realm %s", realm); + goto whoops; } /* Assemble and parse the master key name */ if ((kret = krb5_db_setup_mkey_name(rdp->realm_context, rdp->realm_mpname, - rdp->realm_name, (char **) NULL, - &rdp->realm_mprinc))) { - kdc_err(rdp->realm_context, kret, - "while setting up master key name %s for realm %s", - rdp->realm_mpname, realm); - goto whoops; + rdp->realm_name, (char **) NULL, + &rdp->realm_mprinc))) { + kdc_err(rdp->realm_context, kret, + "while setting up master key name %s for realm %s", + rdp->realm_mpname, realm); + goto whoops; } /* * Get the master key (note, may not be the most current mkey). */ if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc, - rdp->realm_mkey.enctype, manual, - FALSE, rdp->realm_stash, - &mkvno, NULL, &rdp->realm_mkey))) { - kdc_err(rdp->realm_context, kret, - "while fetching master key %s for realm %s", - rdp->realm_mpname, realm); - goto whoops; + rdp->realm_mkey.enctype, manual, + FALSE, rdp->realm_stash, + &mkvno, NULL, &rdp->realm_mkey))) { + kdc_err(rdp->realm_context, kret, + "while fetching master key %s for realm %s", + rdp->realm_mpname, realm); + goto whoops; } #if 0 /************** Begin IFDEF'ed OUT *******************************/ /* @@ -419,26 +420,26 @@ init_realm(kdc_realm_t *rdp, char *realm, char *def_mpname, */ /* Verify the master key */ if ((kret = krb5_db_verify_master_key(rdp->realm_context, - rdp->realm_mprinc, + rdp->realm_mprinc, IGNORE_VNO, - &rdp->realm_mkey))) { - kdc_err(rdp->realm_context, kret, - "while verifying master key for realm %s", realm); - goto whoops; + &rdp->realm_mkey))) { + kdc_err(rdp->realm_context, kret, + "while verifying master key for realm %s", realm); + goto whoops; } #endif /**************** END IFDEF'ed OUT *******************************/ if ((kret = krb5_db_fetch_mkey_list(rdp->realm_context, rdp->realm_mprinc, - &rdp->realm_mkey, mkvno, &rdp->mkey_list))) { - kdc_err(rdp->realm_context, kret, - "while fetching master keys list for realm %s", realm); - goto whoops; + &rdp->realm_mkey, mkvno, &rdp->mkey_list))) { + kdc_err(rdp->realm_context, kret, + "while fetching master keys list for realm %s", realm); + goto whoops; } if ((kret = krb5_db_set_mkey(rdp->realm_context, &rdp->realm_mkey))) { - kdc_err(rdp->realm_context, kret, - "while setting master key for realm %s", realm); - goto whoops; + kdc_err(rdp->realm_context, kret, + "while setting master key for realm %s", realm); + goto whoops; } kret = krb5_db_set_mkey_list(rdp->realm_context, rdp->mkey_list); if (kret) { @@ -449,44 +450,44 @@ init_realm(kdc_realm_t *rdp, char *realm, char *def_mpname, /* Set up the keytab */ if ((kret = krb5_ktkdb_resolve(rdp->realm_context, NULL, - &rdp->realm_keytab))) { - kdc_err(rdp->realm_context, kret, - "while resolving kdb keytab for realm %s", realm); - goto whoops; + &rdp->realm_keytab))) { + kdc_err(rdp->realm_context, kret, + "while resolving kdb keytab for realm %s", realm); + goto whoops; } /* Preformat the TGS name */ if ((kret = krb5_build_principal(rdp->realm_context, &rdp->realm_tgsprinc, - strlen(realm), realm, KRB5_TGS_NAME, - realm, (char *) NULL))) { - kdc_err(rdp->realm_context, kret, - "while building TGS name for realm %s", realm); - goto whoops; + strlen(realm), realm, KRB5_TGS_NAME, + realm, (char *) NULL))) { + kdc_err(rdp->realm_context, kret, + "while building TGS name for realm %s", realm); + goto whoops; } if (!rkey_init_done) { - krb5_data seed; - /* - * If all that worked, then initialize the random key - * generators. - */ + krb5_data seed; + /* + * If all that worked, then initialize the random key + * generators. + */ - seed.length = rdp->realm_mkey.length; - seed.data = (char *)rdp->realm_mkey.contents; + seed.length = rdp->realm_mkey.length; + seed.data = (char *)rdp->realm_mkey.contents; - if ((kret = krb5_c_random_add_entropy(rdp->realm_context, - KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed))) - goto whoops; + if ((kret = krb5_c_random_add_entropy(rdp->realm_context, + KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed))) + goto whoops; - rkey_init_done = 1; + rkey_init_done = 1; } - whoops: +whoops: /* * If we choked, then clean up any dirt we may have dropped on the floor. */ if (kret) { - - finish_realm(rdp); + + finish_realm(rdp); } return(kret); } @@ -548,9 +549,9 @@ void usage(char *name) { fprintf(stderr, "usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname]\n\t\t[-R replaycachename] [-m] [-k masterenctype] [-M masterkeyname]\n\t\t[-p port] [-n]\n" - "\nwhere,\n\t[-x db_args]* - Any number of database specific arguments. Look at\n" - "\t\t\teach database module documentation for supported\n\t\t\targuments\n", - name); + "\nwhere,\n\t[-x db_args]* - Any number of database specific arguments. Look at\n" + "\t\t\teach database module documentation for supported\n\t\t\targuments\n", + name); return; } @@ -558,19 +559,19 @@ char **db_args = NULL; void initialize_realms(krb5_context kcontext, int argc, char **argv) { - int c; - char *db_name = (char *) NULL; - char *lrealm = (char *) NULL; - char *mkey_name = (char *) NULL; - char *rcname = KDCRCACHE; - krb5_error_code retval; - krb5_enctype menctype = ENCTYPE_UNKNOWN; - kdc_realm_t *rdatap = NULL; - krb5_boolean manual = FALSE; - char *default_udp_ports = 0; - char *default_tcp_ports = 0; - krb5_pointer aprof; - const char *hierarchy[3]; + int c; + char *db_name = (char *) NULL; + char *lrealm = (char *) NULL; + char *mkey_name = (char *) NULL; + char *rcname = KDCRCACHE; + krb5_error_code retval; + krb5_enctype menctype = ENCTYPE_UNKNOWN; + kdc_realm_t *rdatap = NULL; + krb5_boolean manual = FALSE; + char *default_udp_ports = 0; + char *default_tcp_ports = 0; + krb5_pointer aprof; + const char *hierarchy[3]; char *no_refrls = NULL; char *host_based_srvcs = NULL; int db_args_size = 0; @@ -578,19 +579,19 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) extern char *optarg; if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) { - hierarchy[0] = KRB5_CONF_KDCDEFAULTS; - hierarchy[1] = KRB5_CONF_KDC_PORTS; - hierarchy[2] = (char *) NULL; - if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports)) - default_udp_ports = 0; - hierarchy[1] = KRB5_CONF_KDC_TCP_PORTS; - if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports)) - default_tcp_ports = 0; - hierarchy[1] = KRB5_CONF_MAX_DGRAM_REPLY_SIZE; - if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, &max_dgram_reply_size)) - max_dgram_reply_size = MAX_DGRAM_SIZE; + hierarchy[0] = KRB5_CONF_KDCDEFAULTS; + hierarchy[1] = KRB5_CONF_KDC_PORTS; + hierarchy[2] = (char *) NULL; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports)) + default_udp_ports = 0; + hierarchy[1] = KRB5_CONF_KDC_TCP_PORTS; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports)) + default_tcp_ports = 0; + hierarchy[1] = KRB5_CONF_MAX_DGRAM_REPLY_SIZE; + if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, &max_dgram_reply_size)) + max_dgram_reply_size = MAX_DGRAM_SIZE; hierarchy[1] = KRB5_CONF_NO_HOST_REFERRAL; - if (krb5_aprof_get_string_all(aprof, hierarchy, &no_refrls)) + if (krb5_aprof_get_string_all(aprof, hierarchy, &no_refrls)) no_refrls = 0; if (!no_refrls || krb5_match_config_pattern(no_refrls, KRB5_CONF_ASTERISK) == FALSE) { hierarchy[1] = KRB5_CONF_HOST_BASED_SERVICES; @@ -598,13 +599,13 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) host_based_srvcs = 0; } - /* aprof_init can return 0 with aprof == NULL */ - if (aprof) - krb5_aprof_finish(aprof); + /* aprof_init can return 0 with aprof == NULL */ + if (aprof) + krb5_aprof_finish(aprof); } - + if (default_udp_ports == 0) { - default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST); + default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST); if (default_udp_ports == 0) { fprintf(stderr," KDC cannot initialize. Not enough memory\n"); exit(1); @@ -623,140 +624,140 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) * use the previously scanned options to fill in for defaults. */ while ((c = getopt(argc, argv, "x:r:d:mM:k:R:e:p:s:n4:X3")) != -1) { - switch(c) { - case 'x': - db_args_size++; - { - char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ - if( temp == NULL ) - { - fprintf(stderr,"%s: KDC cannot initialize. Not enough memory\n", - argv[0]); - exit(1); - } - - db_args = temp; - } - db_args[db_args_size-1] = optarg; - db_args[db_args_size] = NULL; - break; - - case 'r': /* realm name for db */ - if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) { - if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { - if ((retval = init_realm(rdatap, optarg, mkey_name, - menctype, default_udp_ports, - default_tcp_ports, manual, db_args, + switch(c) { + case 'x': + db_args_size++; + { + char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ + if( temp == NULL ) + { + fprintf(stderr,"%s: KDC cannot initialize. Not enough memory\n", + argv[0]); + exit(1); + } + + db_args = temp; + } + db_args[db_args_size-1] = optarg; + db_args[db_args_size] = NULL; + break; + + case 'r': /* realm name for db */ + if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) { + if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { + if ((retval = init_realm(rdatap, optarg, mkey_name, + menctype, default_udp_ports, + default_tcp_ports, manual, db_args, no_refrls, host_based_srvcs))) { - fprintf(stderr,"%s: cannot initialize realm %s - see log file for details\n", - argv[0], optarg); - exit(1); - } - kdc_realmlist[kdc_numrealms] = rdatap; - kdc_numrealms++; - free(db_args), db_args=NULL, db_args_size = 0; - } - else - { - fprintf(stderr,"%s: cannot initialize realm %s. Not enough memory\n", - argv[0], optarg); - exit(1); - } - } - break; - case 'd': /* pathname for db */ - /* now db_name is not a seperate argument. It has to be passed as part of the db_args */ - if( db_name == NULL ) { - if (asprintf(&db_name, "dbname=%s", optarg) < 0) { - fprintf(stderr, - "%s: KDC cannot initialize. Not enough memory\n", - argv[0]); - exit(1); - } - } - - db_args_size++; - { - char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ - if( temp == NULL ) - { - fprintf(stderr,"%s: KDC cannot initialize. Not enough memory\n", - argv[0]); - exit(1); - } - - db_args = temp; - } - db_args[db_args_size-1] = db_name; - db_args[db_args_size] = NULL; - break; - case 'm': /* manual type-in of master key */ - manual = TRUE; - if (menctype == ENCTYPE_UNKNOWN) - menctype = ENCTYPE_DES_CBC_CRC; - break; - case 'M': /* master key name in DB */ - mkey_name = optarg; - break; - case 'n': - nofork++; /* don't detach from terminal */ - break; - case 'k': /* enctype for master key */ - if (krb5_string_to_enctype(optarg, &menctype)) - com_err(argv[0], 0, "invalid enctype %s", optarg); - break; - case 'R': - rcname = optarg; - break; - case 'p': - if (default_udp_ports) - free(default_udp_ports); - default_udp_ports = strdup(optarg); + fprintf(stderr,"%s: cannot initialize realm %s - see log file for details\n", + argv[0], optarg); + exit(1); + } + kdc_realmlist[kdc_numrealms] = rdatap; + kdc_numrealms++; + free(db_args), db_args=NULL, db_args_size = 0; + } + else + { + fprintf(stderr,"%s: cannot initialize realm %s. Not enough memory\n", + argv[0], optarg); + exit(1); + } + } + break; + case 'd': /* pathname for db */ + /* now db_name is not a seperate argument. It has to be passed as part of the db_args */ + if( db_name == NULL ) { + if (asprintf(&db_name, "dbname=%s", optarg) < 0) { + fprintf(stderr, + "%s: KDC cannot initialize. Not enough memory\n", + argv[0]); + exit(1); + } + } + + db_args_size++; + { + char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ + if( temp == NULL ) + { + fprintf(stderr,"%s: KDC cannot initialize. Not enough memory\n", + argv[0]); + exit(1); + } + + db_args = temp; + } + db_args[db_args_size-1] = db_name; + db_args[db_args_size] = NULL; + break; + case 'm': /* manual type-in of master key */ + manual = TRUE; + if (menctype == ENCTYPE_UNKNOWN) + menctype = ENCTYPE_DES_CBC_CRC; + break; + case 'M': /* master key name in DB */ + mkey_name = optarg; + break; + case 'n': + nofork++; /* don't detach from terminal */ + break; + case 'k': /* enctype for master key */ + if (krb5_string_to_enctype(optarg, &menctype)) + com_err(argv[0], 0, "invalid enctype %s", optarg); + break; + case 'R': + rcname = optarg; + break; + case 'p': + if (default_udp_ports) + free(default_udp_ports); + default_udp_ports = strdup(optarg); if (!default_udp_ports) { fprintf(stderr," KDC cannot initialize. Not enough memory\n"); exit(1); } #if 0 /* not yet */ - if (default_tcp_ports) - free(default_tcp_ports); - default_tcp_ports = strdup(optarg); + if (default_tcp_ports) + free(default_tcp_ports); + default_tcp_ports = strdup(optarg); #endif - break; - case '4': - break; - case 'X': - break; - case '?': - default: - usage(argv[0]); - exit(1); - } + break; + case '4': + break; + case 'X': + break; + case '?': + default: + usage(argv[0]); + exit(1); + } } /* * Check to see if we processed any realms. */ if (kdc_numrealms == 0) { - /* no realm specified, use default realm */ - if ((retval = krb5_get_default_realm(kcontext, &lrealm))) { - com_err(argv[0], retval, - "while attempting to retrieve default realm"); - fprintf (stderr, "%s: %s, attempting to retrieve default realm\n", - argv[0], krb5_get_error_message(kcontext, retval)); - exit(1); - } - if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { - if ((retval = init_realm(rdatap, lrealm, mkey_name, menctype, - default_udp_ports, default_tcp_ports, - manual, db_args, no_refrls, - host_based_srvcs))) { - fprintf(stderr,"%s: cannot initialize realm %s - see log file for details\n", - argv[0], lrealm); - exit(1); - } - kdc_realmlist[0] = rdatap; - kdc_numrealms++; - } + /* no realm specified, use default realm */ + if ((retval = krb5_get_default_realm(kcontext, &lrealm))) { + com_err(argv[0], retval, + "while attempting to retrieve default realm"); + fprintf (stderr, "%s: %s, attempting to retrieve default realm\n", + argv[0], krb5_get_error_message(kcontext, retval)); + exit(1); + } + if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { + if ((retval = init_realm(rdatap, lrealm, mkey_name, menctype, + default_udp_ports, default_tcp_ports, + manual, db_args, no_refrls, + host_based_srvcs))) { + fprintf(stderr,"%s: cannot initialize realm %s - see log file for details\n", + argv[0], lrealm); + exit(1); + } + kdc_realmlist[0] = rdatap; + kdc_numrealms++; + } } #ifdef USE_RCACHE @@ -764,22 +765,22 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) * Now handle the replay cache. */ if ((retval = kdc_initialize_rcache(kcontext, rcname))) { - com_err(argv[0], retval, "while initializing KDC replay cache '%s'", - rcname); - exit(1); + com_err(argv[0], retval, "while initializing KDC replay cache '%s'", + rcname); + exit(1); } #endif /* Ensure that this is set for our first request. */ kdc_active_realm = kdc_realmlist[0]; if (default_udp_ports) - free(default_udp_ports); + free(default_udp_ports); if (default_tcp_ports) - free(default_tcp_ports); + free(default_tcp_ports); if (db_args) - free(db_args); + free(db_args); if (db_name) - free(db_name); + free(db_name); if (host_based_srvcs) free(host_based_srvcs); if (no_refrls) @@ -794,53 +795,53 @@ finish_realms() int i; for (i = 0; i < kdc_numrealms; i++) { - finish_realm(kdc_realmlist[i]); - kdc_realmlist[i] = 0; + finish_realm(kdc_realmlist[i]); + kdc_realmlist[i] = 0; } } /* - outline: + outline: - process args & setup + process args & setup - initialize database access (fetch master key, open DB) + initialize database access (fetch master key, open DB) - initialize network + initialize network - loop: - listen for packet + loop: + listen for packet - determine packet type, dispatch to handling routine - (AS or TGS (or V4?)) + determine packet type, dispatch to handling routine + (AS or TGS (or V4?)) - reflect response + reflect response - exit on signal + exit on signal - clean up secrets, close db + clean up secrets, close db - shut down network + shut down network - exit - */ + exit +*/ int main(int argc, char **argv) { - krb5_error_code retval; - krb5_context kcontext; + krb5_error_code retval; + krb5_context kcontext; int errout = 0; if (strrchr(argv[0], '/')) - argv[0] = strrchr(argv[0], '/')+1; + argv[0] = strrchr(argv[0], '/')+1; - if (!(kdc_realmlist = (kdc_realm_t **) malloc(sizeof(kdc_realm_t *) * - KRB5_KDC_MAX_REALMS))) { - fprintf(stderr, "%s: cannot get memory for realm list\n", argv[0]); - exit(1); + if (!(kdc_realmlist = (kdc_realm_t **) malloc(sizeof(kdc_realm_t *) * + KRB5_KDC_MAX_REALMS))) { + fprintf(stderr, "%s: cannot get memory for realm list\n", argv[0]); + exit(1); } memset(kdc_realmlist, 0, - (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS)); + (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS)); /* * A note about Kerberos contexts: This context, "kcontext", is used @@ -850,8 +851,8 @@ int main(int argc, char **argv) */ retval = krb5int_init_context_kdc(&kcontext); if (retval) { - com_err(argv[0], retval, "while initializing krb5"); - exit(1); + com_err(argv[0], retval, "while initializing krb5"); + exit(1); } krb5_klog_init(kcontext, "kdc", argv[0], 1); kdc_err_context = kcontext; @@ -875,39 +876,39 @@ int main(int argc, char **argv) retval = setup_sam(); if (retval) { - kdc_err(kcontext, retval, "while initializing SAM"); - finish_realms(); - return 1; + kdc_err(kcontext, retval, "while initializing SAM"); + finish_realms(); + return 1; } if ((retval = setup_network())) { - kdc_err(kcontext, retval, "while initializing network"); - finish_realms(); - return 1; + kdc_err(kcontext, retval, "while initializing network"); + finish_realms(); + return 1; } if (!nofork && daemon(0, 0)) { - kdc_err(kcontext, errno, "while detaching from tty"); - finish_realms(); - return 1; + kdc_err(kcontext, errno, "while detaching from tty"); + finish_realms(); + return 1; } krb5_klog_syslog(LOG_INFO, "commencing operation"); if (nofork) - fprintf(stderr, "%s: starting...\n", kdc_progname); + fprintf(stderr, "%s: starting...\n", kdc_progname); if ((retval = listen_and_process())) { - kdc_err(kcontext, retval, "while processing network requests"); - errout++; + kdc_err(kcontext, retval, "while processing network requests"); + errout++; } if ((retval = closedown_network())) { - kdc_err(kcontext, retval, "while shutting down network"); - errout++; + kdc_err(kcontext, retval, "while shutting down network"); + errout++; } krb5_klog_syslog(LOG_INFO, "shutting down"); unload_preauth_plugins(kcontext); unload_authdata_plugins(kcontext); krb5_klog_close(kdc_context); finish_realms(); - if (kdc_realmlist) - free(kdc_realmlist); + if (kdc_realmlist) + free(kdc_realmlist); #ifdef USE_RCACHE (void) krb5_rc_close(kcontext, kdc_rcache); #endif @@ -917,5 +918,3 @@ int main(int argc, char **argv) krb5_free_context(kcontext); return errout; } - - diff --git a/src/kdc/network.c b/src/kdc/network.c index 4fdfcf1..ec02622 100644 --- a/src/kdc/network.c +++ b/src/kdc/network.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/network.c * @@ -7,7 +8,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -21,7 +22,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * Network code for Kerberos v5 KDC. */ @@ -58,7 +59,7 @@ #endif #ifdef HAVE_SYS_FILIO_H -#include <sys/filio.h> /* FIONBIO */ +#include <sys/filio.h> /* FIONBIO */ #endif #include "fake-addrinfo.h" @@ -69,15 +70,15 @@ set_sa_port(struct sockaddr *addr, int port) { switch (addr->sa_family) { case AF_INET: - sa2sin(addr)->sin_port = port; - break; + sa2sin(addr)->sin_port = port; + break; #ifdef KRB5_USE_INET6 case AF_INET6: - sa2sin6(addr)->sin6_port = port; - break; + sa2sin6(addr)->sin6_port = port; + break; #endif default: - break; + break; } } @@ -86,13 +87,13 @@ static int ipv6_enabled() #ifdef KRB5_USE_INET6 static int result = -1; if (result == -1) { - int s; - s = socket(AF_INET6, SOCK_STREAM, 0); - if (s >= 0) { - result = 1; - close(s); - } else - result = 0; + int s; + s = socket(AF_INET6, SOCK_STREAM, 0); + if (s >= 0) { + result = 1; + close(s); + } else + result = 0; } return result; #else @@ -133,21 +134,21 @@ set_pktinfo(int sock, int family) switch (family) { #if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO) case AF_INET: - proto = IPPROTO_IP; - option = IP_RECVPKTINFO; - break; + proto = IPPROTO_IP; + option = IP_RECVPKTINFO; + break; #endif #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO) case AF_INET6: - proto = IPPROTO_IPV6; - option = IPV6_RECVPKTINFO; - break; + proto = IPPROTO_IPV6; + option = IPV6_RECVPKTINFO; + break; #endif default: - return EINVAL; + return EINVAL; } if (setsockopt(sock, proto, option, &sockopt, sizeof(sockopt))) - return errno; + return errno; return 0; } @@ -157,17 +158,17 @@ static const char *paddr (struct sockaddr *sa) static char buf[100]; char portbuf[10]; if (getnameinfo(sa, socklen(sa), - buf, sizeof(buf), portbuf, sizeof(portbuf), - NI_NUMERICHOST|NI_NUMERICSERV)) - strlcpy(buf, "<unprintable>", sizeof(buf)); + buf, sizeof(buf), portbuf, sizeof(portbuf), + NI_NUMERICHOST|NI_NUMERICSERV)) + strlcpy(buf, "<unprintable>", sizeof(buf)); else { - unsigned int len = sizeof(buf) - strlen(buf); - char *p = buf + strlen(buf); - if (len > 2+strlen(portbuf)) { - *p++ = '.'; - len--; - strncpy(p, portbuf, len); - } + unsigned int len = sizeof(buf) - strlen(buf); + char *p = buf + strlen(buf); + if (len > 2+strlen(portbuf)) { + *p++ = '.'; + len--; + strncpy(p, portbuf, len); + } } return buf; } @@ -185,28 +186,28 @@ struct connection { enum conn_type type; void (*service)(struct connection *, int); union { - /* Type-specific information. */ - struct { - /* connection */ - struct sockaddr_storage addr_s; - socklen_t addrlen; - char addrbuf[56]; - krb5_fulladdr faddr; - krb5_address kaddr; - /* incoming */ - size_t bufsiz; - size_t offset; - char *buffer; - size_t msglen; - /* outgoing */ - krb5_data *response; - unsigned char lenbuf[4]; - sg_buf sgbuf[2]; - sg_buf *sgp; - int sgnum; - /* crude denial-of-service avoidance support */ - time_t start_time; - } tcp; + /* Type-specific information. */ + struct { + /* connection */ + struct sockaddr_storage addr_s; + socklen_t addrlen; + char addrbuf[56]; + krb5_fulladdr faddr; + krb5_address kaddr; + /* incoming */ + size_t bufsiz; + size_t offset; + char *buffer; + size_t msglen; + /* outgoing */ + krb5_data *response; + unsigned char lenbuf[4]; + sg_buf sgbuf[2]; + sg_buf *sgp; + int sgnum; + /* crude denial-of-service avoidance support */ + time_t start_time; + } tcp; } u; }; @@ -216,78 +217,78 @@ struct connection { /* Start at the top and work down -- this should allow for deletions without disrupting the iteration, since we delete by overwriting the element to be removed with the last element. */ -#define FOREACH_ELT(set,idx,vvar) \ - for (idx = set.n-1; idx >= 0 && (vvar = set.data[idx], 1); idx--) - -#define GROW_SET(set, incr, tmpptr) \ - (((int)(set.max + incr) < set.max \ - || (((size_t)((int)(set.max + incr) * sizeof(set.data[0])) \ - / sizeof(set.data[0])) \ - != (set.max + incr))) \ - ? 0 /* overflow */ \ - : ((tmpptr = realloc(set.data, \ - (int)(set.max + incr) * sizeof(set.data[0]))) \ - ? (set.data = tmpptr, set.max += incr, 1) \ - : 0)) +#define FOREACH_ELT(set,idx,vvar) \ + for (idx = set.n-1; idx >= 0 && (vvar = set.data[idx], 1); idx--) + +#define GROW_SET(set, incr, tmpptr) \ + (((int)(set.max + incr) < set.max \ + || (((size_t)((int)(set.max + incr) * sizeof(set.data[0])) \ + / sizeof(set.data[0])) \ + != (set.max + incr))) \ + ? 0 /* overflow */ \ + : ((tmpptr = realloc(set.data, \ + (int)(set.max + incr) * sizeof(set.data[0]))) \ + ? (set.data = tmpptr, set.max += incr, 1) \ + : 0)) /* 1 = success, 0 = failure */ -#define ADD(set, val, tmpptr) \ - ((set.n < set.max || GROW_SET(set, 10, tmpptr)) \ - ? (set.data[set.n++] = val, 1) \ - : 0) +#define ADD(set, val, tmpptr) \ + ((set.n < set.max || GROW_SET(set, 10, tmpptr)) \ + ? (set.data[set.n++] = val, 1) \ + : 0) -#define DEL(set, idx) \ - (set.data[idx] = set.data[--set.n], 0) +#define DEL(set, idx) \ + (set.data[idx] = set.data[--set.n], 0) -#define FREE_SET_DATA(set) \ - (free(set.data), set.data = 0, set.max = 0, set.n = 0) +#define FREE_SET_DATA(set) \ + (free(set.data), set.data = 0, set.max = 0, set.n = 0) /* Set<struct connection *> connections; */ static SET(struct connection *) connections; -#define n_sockets connections.n -#define conns connections.data +#define n_sockets connections.n +#define conns connections.data /* Set<u_short> udp_port_data, tcp_port_data; */ static SET(u_short) udp_port_data, tcp_port_data; #include "cm.h" -static struct select_state sstate; + static struct select_state sstate; -static krb5_error_code add_udp_port(int port) + static krb5_error_code add_udp_port(int port) { - int i; + int i; void *tmp; u_short val; u_short s_port = port; if (s_port != port) - return EINVAL; + return EINVAL; FOREACH_ELT (udp_port_data, i, val) - if (s_port == val) - return 0; + if (s_port == val) + return 0; if (!ADD(udp_port_data, s_port, tmp)) - return ENOMEM; + return ENOMEM; return 0; } static krb5_error_code add_tcp_port(int port) { - int i; + int i; void *tmp; u_short val; u_short s_port = port; if (s_port != port) - return EINVAL; + return EINVAL; FOREACH_ELT (tcp_port_data, i, val) - if (s_port == val) - return 0; + if (s_port == val) + return 0; if (!ADD(tcp_port_data, s_port, tmp)) - return ENOMEM; + return ENOMEM; return 0; } @@ -307,29 +308,29 @@ struct socksetup { static struct connection * add_fd (struct socksetup *data, int sock, enum conn_type conntype, - void (*service)(struct connection *, int)) + void (*service)(struct connection *, int)) { struct connection *newconn; void *tmp; #ifndef _WIN32 if (sock >= FD_SETSIZE) { - data->retval = EMFILE; /* XXX */ - kdc_err(NULL, 0, "file descriptor number %d too high", sock); - return 0; + data->retval = EMFILE; /* XXX */ + kdc_err(NULL, 0, "file descriptor number %d too high", sock); + return 0; } #endif newconn = malloc(sizeof(*newconn)); if (newconn == 0) { - data->retval = ENOMEM; - kdc_err(NULL, ENOMEM, "cannot allocate storage for connection info"); - return 0; + data->retval = ENOMEM; + kdc_err(NULL, ENOMEM, "cannot allocate storage for connection info"); + return 0; } if (!ADD(connections, newconn, tmp)) { - data->retval = ENOMEM; - kdc_err(NULL, ENOMEM, "cannot save socket info"); - free(newconn); - return 0; + data->retval = ENOMEM; + kdc_err(NULL, ENOMEM, "cannot save socket info"); + free(newconn); + return 0; } memset(newconn, 0, sizeof(*newconn)); @@ -347,7 +348,7 @@ static struct connection * add_udp_fd (struct socksetup *data, int sock, int pktinfo) { return add_fd(data, sock, pktinfo ? CONN_UDP_PKTINFO : CONN_UDP, - process_packet); + process_packet); } static struct connection * @@ -369,10 +370,10 @@ delete_fd (struct connection *xconn) int i; FOREACH_ELT(connections, i, conn) - if (conn == xconn) { - DEL(connections, i); - break; - } + if (conn == xconn) { + DEL(connections, i); + break; + } free(xconn); } @@ -405,57 +406,57 @@ setup_a_tcp_listener(struct socksetup *data, struct sockaddr *addr) sock = socket(addr->sa_family, SOCK_STREAM, 0); if (sock == -1) { - kdc_err(NULL, errno, "Cannot create TCP server socket on %s", - paddr(addr)); - return -1; + kdc_err(NULL, errno, "Cannot create TCP server socket on %s", + paddr(addr)); + return -1; } set_cloexec_fd(sock); #ifndef _WIN32 if (sock >= FD_SETSIZE) { - close(sock); - kdc_err(NULL, 0, "TCP socket fd number %d (for %s) too high", - sock, paddr(addr)); - return -1; + close(sock); + kdc_err(NULL, 0, "TCP socket fd number %d (for %s) too high", + sock, paddr(addr)); + return -1; } #endif if (setreuseaddr(sock, 1) < 0) - kdc_err(NULL, errno, "Cannot enable SO_REUSEADDR on fd %d", sock); + kdc_err(NULL, errno, "Cannot enable SO_REUSEADDR on fd %d", sock); #ifdef KRB5_USE_INET6 if (addr->sa_family == AF_INET6) { #ifdef IPV6_V6ONLY - if (setv6only(sock, 1)) - kdc_err(NULL, errno, "setsockopt(%d,IPV6_V6ONLY,1) failed", sock); - else - kdc_err(NULL, 0, "setsockopt(%d,IPV6_V6ONLY,1) worked", sock); + if (setv6only(sock, 1)) + kdc_err(NULL, errno, "setsockopt(%d,IPV6_V6ONLY,1) failed", sock); + else + kdc_err(NULL, 0, "setsockopt(%d,IPV6_V6ONLY,1) worked", sock); #else - krb5_klog_syslog(LOG_INFO, "no IPV6_V6ONLY socket option support"); + krb5_klog_syslog(LOG_INFO, "no IPV6_V6ONLY socket option support"); #endif /* IPV6_V6ONLY */ } #endif /* KRB5_USE_INET6 */ if (bind(sock, addr, socklen(addr)) == -1) { - kdc_err(NULL, errno, "Cannot bind TCP server socket on %s", - paddr(addr)); - close(sock); - return -1; + kdc_err(NULL, errno, "Cannot bind TCP server socket on %s", + paddr(addr)); + close(sock); + return -1; } if (listen(sock, 5) < 0) { - kdc_err(NULL, errno, "Cannot listen on TCP server socket on %s", - paddr(addr)); - close(sock); - return -1; + kdc_err(NULL, errno, "Cannot listen on TCP server socket on %s", + paddr(addr)); + close(sock); + return -1; } if (setnbio(sock)) { - kdc_err(NULL, errno, - "cannot set listening tcp socket on %s non-blocking", - paddr(addr)); - close(sock); - return -1; + kdc_err(NULL, errno, + "cannot set listening tcp socket on %s non-blocking", + paddr(addr)); + close(sock); + return -1; } if (setnolinger(sock)) { - kdc_err(NULL, errno, "disabling SO_LINGER on TCP socket on %s", - paddr(addr)); - close(sock); - return -1; + kdc_err(NULL, errno, "disabling SO_LINGER on TCP socket on %s", + paddr(addr)); + close(sock); + return -1; } return sock; } @@ -486,58 +487,58 @@ setup_tcp_listener_ports(struct socksetup *data) #endif FOREACH_ELT (tcp_port_data, i, port) { - int s4, s6; - - set_sa_port((struct sockaddr *)&sin4, htons(port)); - if (!ipv6_enabled()) { - s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4); - if (s4 < 0) - return -1; - s6 = -1; - } else { + int s4, s6; + + set_sa_port((struct sockaddr *)&sin4, htons(port)); + if (!ipv6_enabled()) { + s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4); + if (s4 < 0) + return -1; + s6 = -1; + } else { #ifndef KRB5_USE_INET6 - abort(); + abort(); #else - s4 = s6 = -1; + s4 = s6 = -1; - set_sa_port((struct sockaddr *)&sin6, htons(port)); + set_sa_port((struct sockaddr *)&sin6, htons(port)); - s6 = setup_a_tcp_listener(data, (struct sockaddr *)&sin6); - if (s6 < 0) - return -1; + s6 = setup_a_tcp_listener(data, (struct sockaddr *)&sin6); + if (s6 < 0) + return -1; - s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4); + s4 = setup_a_tcp_listener(data, (struct sockaddr *)&sin4); #endif /* KRB5_USE_INET6 */ - } - - /* Sockets are created, prepare to listen on them. */ - if (s4 >= 0) { - if (add_tcp_listener_fd(data, s4) == NULL) - close(s4); - else { - FD_SET(s4, &sstate.rfds); - if (s4 >= sstate.max) - sstate.max = s4 + 1; - krb5_klog_syslog(LOG_INFO, "listening on fd %d: tcp %s", - s4, paddr((struct sockaddr *)&sin4)); - } - } + } + + /* Sockets are created, prepare to listen on them. */ + if (s4 >= 0) { + if (add_tcp_listener_fd(data, s4) == NULL) + close(s4); + else { + FD_SET(s4, &sstate.rfds); + if (s4 >= sstate.max) + sstate.max = s4 + 1; + krb5_klog_syslog(LOG_INFO, "listening on fd %d: tcp %s", + s4, paddr((struct sockaddr *)&sin4)); + } + } #ifdef KRB5_USE_INET6 - if (s6 >= 0) { - if (add_tcp_listener_fd(data, s6) == NULL) { - close(s6); - s6 = -1; - } else { - FD_SET(s6, &sstate.rfds); - if (s6 >= sstate.max) - sstate.max = s6 + 1; - krb5_klog_syslog(LOG_INFO, "listening on fd %d: tcp %s", - s6, paddr((struct sockaddr *)&sin6)); - } - if (s4 < 0) - krb5_klog_syslog(LOG_INFO, - "assuming IPv6 socket accepts IPv4"); - } + if (s6 >= 0) { + if (add_tcp_listener_fd(data, s6) == NULL) { + close(s6); + s6 = -1; + } else { + FD_SET(s6, &sstate.rfds); + if (s6 >= sstate.max) + sstate.max = s6 + 1; + krb5_klog_syslog(LOG_INFO, "listening on fd %d: tcp %s", + s6, paddr((struct sockaddr *)&sin6)); + } + if (s4 < 0) + krb5_klog_syslog(LOG_INFO, + "assuming IPv6 socket accepts IPv4"); + } #endif } return 0; @@ -556,39 +557,39 @@ union pktinfo { static int setup_udp_port_1(struct socksetup *data, struct sockaddr *addr, - char *haddrbuf, int pktinfo); + char *haddrbuf, int pktinfo); static void setup_udp_pktinfo_ports(struct socksetup *data) { #ifdef IP_PKTINFO { - struct sockaddr_in sa; - int r; + struct sockaddr_in sa; + int r; - memset(&sa, 0, sizeof(sa)); - sa.sin_family = AF_INET; + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; #ifdef HAVE_SA_LEN - sa.sin_len = sizeof(sa); + sa.sin_len = sizeof(sa); #endif - r = setup_udp_port_1(data, (struct sockaddr *) &sa, "0.0.0.0", 4); - if (r == 0) - data->udp_flags &= ~UDP_DO_IPV4; + r = setup_udp_port_1(data, (struct sockaddr *) &sa, "0.0.0.0", 4); + if (r == 0) + data->udp_flags &= ~UDP_DO_IPV4; } #endif #ifdef IPV6_PKTINFO { - struct sockaddr_in6 sa; - int r; + struct sockaddr_in6 sa; + int r; - memset(&sa, 0, sizeof(sa)); - sa.sin6_family = AF_INET6; + memset(&sa, 0, sizeof(sa)); + sa.sin6_family = AF_INET6; #ifdef HAVE_SA_LEN - sa.sin6_len = sizeof(sa); + sa.sin6_len = sizeof(sa); #endif - r = setup_udp_port_1(data, (struct sockaddr *) &sa, "::", 6); - if (r == 0) - data->udp_flags &= ~UDP_DO_IPV6; + r = setup_udp_port_1(data, (struct sockaddr *) &sa, "::", 6); + if (r == 0) + data->udp_flags &= ~UDP_DO_IPV6; } #endif } @@ -601,66 +602,66 @@ setup_udp_pktinfo_ports(struct socksetup *data) static int setup_udp_port_1(struct socksetup *data, struct sockaddr *addr, - char *haddrbuf, int pktinfo) + char *haddrbuf, int pktinfo) { int sock = -1, i, r; u_short port; FOREACH_ELT (udp_port_data, i, port) { - sock = socket (addr->sa_family, SOCK_DGRAM, 0); - if (sock == -1) { - data->retval = errno; - kdc_err(NULL, data->retval, - "Cannot create server socket for port %d address %s", - port, haddrbuf); - return 1; - } - set_cloexec_fd(sock); + sock = socket (addr->sa_family, SOCK_DGRAM, 0); + if (sock == -1) { + data->retval = errno; + kdc_err(NULL, data->retval, + "Cannot create server socket for port %d address %s", + port, haddrbuf); + return 1; + } + set_cloexec_fd(sock); #ifdef KRB5_USE_INET6 - if (addr->sa_family == AF_INET6) { + if (addr->sa_family == AF_INET6) { #ifdef IPV6_V6ONLY - if (setv6only(sock, 1)) - kdc_err(NULL, errno, "setsockopt(%d,IPV6_V6ONLY,1) failed", - sock); - else - kdc_err(NULL, 0, "setsockopt(%d,IPV6_V6ONLY,1) worked", sock); + if (setv6only(sock, 1)) + kdc_err(NULL, errno, "setsockopt(%d,IPV6_V6ONLY,1) failed", + sock); + else + kdc_err(NULL, 0, "setsockopt(%d,IPV6_V6ONLY,1) worked", sock); #else - krb5_klog_syslog(LOG_INFO, "no IPV6_V6ONLY socket option support"); + krb5_klog_syslog(LOG_INFO, "no IPV6_V6ONLY socket option support"); #endif /* IPV6_V6ONLY */ - } + } #endif - set_sa_port(addr, htons(port)); - if (bind (sock, (struct sockaddr *)addr, socklen (addr)) == -1) { - data->retval = errno; - kdc_err(NULL, data->retval, - "Cannot bind server socket to port %d address %s", - port, haddrbuf); - close(sock); - return 1; - } + set_sa_port(addr, htons(port)); + if (bind (sock, (struct sockaddr *)addr, socklen (addr)) == -1) { + data->retval = errno; + kdc_err(NULL, data->retval, + "Cannot bind server socket to port %d address %s", + port, haddrbuf); + close(sock); + return 1; + } #if !(defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && (defined(IP_PKTINFO) || defined(IPV6_PKTINFO))) - assert(pktinfo == 0); + assert(pktinfo == 0); #endif - if (pktinfo) { - r = set_pktinfo(sock, addr->sa_family); - if (r) { - kdc_err(NULL, r, - "Cannot request packet info for udp socket address %s port %d", - haddrbuf, port); - close(sock); - return 1; - } - } - krb5_klog_syslog (LOG_INFO, "listening on fd %d: udp %s%s", sock, - paddr((struct sockaddr *)addr), - pktinfo ? " (pktinfo)" : ""); - if (add_udp_fd (data, sock, pktinfo) == 0) { - close(sock); - return 1; - } - FD_SET (sock, &sstate.rfds); - if (sock >= sstate.max) - sstate.max = sock + 1; + if (pktinfo) { + r = set_pktinfo(sock, addr->sa_family); + if (r) { + kdc_err(NULL, r, + "Cannot request packet info for udp socket address %s port %d", + haddrbuf, port); + close(sock); + return 1; + } + } + krb5_klog_syslog (LOG_INFO, "listening on fd %d: udp %s%s", sock, + paddr((struct sockaddr *)addr), + pktinfo ? " (pktinfo)" : ""); + if (add_udp_fd (data, sock, pktinfo) == 0) { + close(sock); + return 1; + } + FD_SET (sock, &sstate.rfds); + if (sock >= sstate.max) + sstate.max = sock + 1; } return 0; } @@ -673,51 +674,51 @@ setup_udp_port(void *P_data, struct sockaddr *addr) int err; if (addr->sa_family == AF_INET && !(data->udp_flags & UDP_DO_IPV4)) - return 0; + return 0; #ifdef AF_INET6 if (addr->sa_family == AF_INET6 && !(data->udp_flags & UDP_DO_IPV6)) - return 0; + return 0; #endif err = getnameinfo(addr, socklen(addr), haddrbuf, sizeof(haddrbuf), - 0, 0, NI_NUMERICHOST); + 0, 0, NI_NUMERICHOST); if (err) - strlcpy(haddrbuf, "<unprintable>", sizeof(haddrbuf)); + strlcpy(haddrbuf, "<unprintable>", sizeof(haddrbuf)); switch (addr->sa_family) { case AF_INET: - break; + break; #ifdef AF_INET6 case AF_INET6: #ifdef KRB5_USE_INET6 - break; + break; #else - { - static int first = 1; - if (first) { - krb5_klog_syslog (LOG_INFO, "skipping local ipv6 addresses"); - first = 0; - } - return 0; - } + { + static int first = 1; + if (first) { + krb5_klog_syslog (LOG_INFO, "skipping local ipv6 addresses"); + first = 0; + } + return 0; + } #endif #endif #ifdef AF_LINK /* some BSD systems, AIX */ case AF_LINK: - return 0; + return 0; #endif #ifdef AF_DLI /* Direct Link Interface - DEC Ultrix/OSF1 link layer? */ case AF_DLI: - return 0; + return 0; #endif #ifdef AF_APPLETALK case AF_APPLETALK: - return 0; + return 0; #endif default: - krb5_klog_syslog (LOG_INFO, - "skipping unrecognized local address family %d", - addr->sa_family); - return 0; + krb5_klog_syslog (LOG_INFO, + "skipping unrecognized local address family %d", + addr->sa_family); + return 0; } return setup_udp_port_1(data, addr, haddrbuf, 0); } @@ -729,40 +730,40 @@ static void klog_handler(const void *data, size_t len) static int bufoffset; void *p; -#define flush_buf() \ - (bufoffset \ - ? (((buf[0] == 0 || buf[0] == '\n') \ - ? (fork()==0?abort():(void)0) \ - : (void)0), \ - krb5_klog_syslog(LOG_INFO, "%s", buf), \ - memset(buf, 0, sizeof(buf)), \ - bufoffset = 0) \ - : 0) +#define flush_buf() \ + (bufoffset \ + ? (((buf[0] == 0 || buf[0] == '\n') \ + ? (fork()==0?abort():(void)0) \ + : (void)0), \ + krb5_klog_syslog(LOG_INFO, "%s", buf), \ + memset(buf, 0, sizeof(buf)), \ + bufoffset = 0) \ + : 0) p = memchr(data, 0, len); if (p) - len = (const char *)p - (const char *)data; + len = (const char *)p - (const char *)data; scan_for_newlines: if (len == 0) - return; + return; p = memchr(data, '\n', len); if (p) { - if (p != data) - klog_handler(data, (size_t)((const char *)p - (const char *)data)); - flush_buf(); - len -= ((const char *)p - (const char *)data) + 1; - data = 1 + (const char *)p; - goto scan_for_newlines; + if (p != data) + klog_handler(data, (size_t)((const char *)p - (const char *)data)); + flush_buf(); + len -= ((const char *)p - (const char *)data) + 1; + data = 1 + (const char *)p; + goto scan_for_newlines; } else if (len > sizeof(buf) - 1 || len + bufoffset > sizeof(buf) - 1) { - size_t x = sizeof(buf) - len - 1; - klog_handler(data, x); - flush_buf(); - len -= x; - data = (const char *)data + x; - goto scan_for_newlines; + size_t x = sizeof(buf) - len - 1; + klog_handler(data, x); + flush_buf(); + len -= x; + data = (const char *)data + x; + goto scan_for_newlines; } else { - memcpy(buf + bufoffset, data, len); - bufoffset += len; + memcpy(buf + bufoffset, data, len); + bufoffset += len; } } #endif @@ -801,73 +802,73 @@ static void process_routing_update(struct connection *conn, int selflags) struct rt_msghdr rtm; while ((n_read = read(conn->fd, &rtm, sizeof(rtm))) > 0) { - if (n_read < sizeof(rtm)) { - /* Quick hack to figure out if the interesting - fields are present in a short read. + if (n_read < sizeof(rtm)) { + /* Quick hack to figure out if the interesting + fields are present in a short read. - A short read seems to be normal for some message types. - Only complain if we don't have the critical initial - header fields. */ + A short read seems to be normal for some message types. + Only complain if we don't have the critical initial + header fields. */ #define RS(FIELD) (offsetof(struct rt_msghdr, FIELD) + sizeof(rtm.FIELD)) - if (n_read < RS(rtm_type) || - n_read < RS(rtm_version) || - n_read < RS(rtm_msglen)) { - krb5_klog_syslog(LOG_ERR, - "short read (%d/%d) from routing socket", - n_read, (int) sizeof(rtm)); - return; - } - } + if (n_read < RS(rtm_type) || + n_read < RS(rtm_version) || + n_read < RS(rtm_msglen)) { + krb5_klog_syslog(LOG_ERR, + "short read (%d/%d) from routing socket", + n_read, (int) sizeof(rtm)); + return; + } + } #if 0 - krb5_klog_syslog(LOG_INFO, - "got routing msg type %d(%s) v%d", - rtm.rtm_type, rtm_type_name(rtm.rtm_type), - rtm.rtm_version); + krb5_klog_syslog(LOG_INFO, + "got routing msg type %d(%s) v%d", + rtm.rtm_type, rtm_type_name(rtm.rtm_type), + rtm.rtm_version); #endif - if (rtm.rtm_msglen > sizeof(rtm)) { - /* It appears we get a partial message and the rest is - thrown away? */ - } else if (rtm.rtm_msglen != n_read) { - krb5_klog_syslog(LOG_ERR, - "read %d from routing socket but msglen is %d", - n_read, rtm.rtm_msglen); - } - switch (rtm.rtm_type) { - case RTM_ADD: - case RTM_DELETE: - case RTM_NEWADDR: - case RTM_DELADDR: - case RTM_IFINFO: - case RTM_OLDADD: - case RTM_OLDDEL: + if (rtm.rtm_msglen > sizeof(rtm)) { + /* It appears we get a partial message and the rest is + thrown away? */ + } else if (rtm.rtm_msglen != n_read) { + krb5_klog_syslog(LOG_ERR, + "read %d from routing socket but msglen is %d", + n_read, rtm.rtm_msglen); + } + switch (rtm.rtm_type) { + case RTM_ADD: + case RTM_DELETE: + case RTM_NEWADDR: + case RTM_DELADDR: + case RTM_IFINFO: + case RTM_OLDADD: + case RTM_OLDDEL: #if 0 - krb5_klog_syslog(LOG_DEBUG, - "network reconfiguration message (%s) received", - rtm_type_name(rtm.rtm_type)); + krb5_klog_syslog(LOG_DEBUG, + "network reconfiguration message (%s) received", + rtm_type_name(rtm.rtm_type)); #endif - network_reconfiguration_needed = 1; - break; - case RTM_RESOLVE: + network_reconfiguration_needed = 1; + break; + case RTM_RESOLVE: #ifdef RTM_NEWMADDR - case RTM_NEWMADDR: - case RTM_DELMADDR: + case RTM_NEWMADDR: + case RTM_DELMADDR: #endif - case RTM_MISS: - case RTM_REDIRECT: - case RTM_LOSING: - case RTM_GET: - /* Not interesting. */ + case RTM_MISS: + case RTM_REDIRECT: + case RTM_LOSING: + case RTM_GET: + /* Not interesting. */ #if 0 - krb5_klog_syslog(LOG_DEBUG, "routing msg not interesting"); + krb5_klog_syslog(LOG_DEBUG, "routing msg not interesting"); #endif - break; - default: - krb5_klog_syslog(LOG_INFO, - "unhandled routing message type %d, will reconfigure just for the fun of it", - rtm.rtm_type); - network_reconfiguration_needed = 1; - break; - } + break; + default: + krb5_klog_syslog(LOG_INFO, + "unhandled routing message type %d, will reconfigure just for the fun of it", + rtm.rtm_type); + network_reconfiguration_needed = 1; + break; + } } } @@ -876,14 +877,14 @@ setup_routing_socket(struct socksetup *data) { int sock = socket(PF_ROUTE, SOCK_RAW, 0); if (sock < 0) { - int e = errno; - krb5_klog_syslog(LOG_INFO, "couldn't set up routing socket: %s", - strerror(e)); + int e = errno; + krb5_klog_syslog(LOG_INFO, "couldn't set up routing socket: %s", + strerror(e)); } else { - krb5_klog_syslog(LOG_INFO, "routing socket is fd %d", sock); - add_fd(data, sock, CONN_ROUTING, process_routing_update); - setnbio(sock); - FD_SET(sock, &sstate.rfds); + krb5_klog_syslog(LOG_INFO, "routing socket is fd %d", sock); + add_fd(data, sock, CONN_ROUTING, process_routing_update); + setnbio(sock); + FD_SET(sock, &sstate.rfds); } } #endif @@ -910,33 +911,33 @@ setup_network() /* Handle each realm's ports */ for (i=0; i<kdc_numrealms; i++) { - cp = kdc_realmlist[i]->realm_ports; - while (cp && *cp) { - if (*cp == ',' || isspace((int) *cp)) { - cp++; - continue; - } - port = strtol(cp, &cp, 10); - if (cp == 0) - break; - retval = add_udp_port(port); - if (retval) - return retval; - } - - cp = kdc_realmlist[i]->realm_tcp_ports; - while (cp && *cp) { - if (*cp == ',' || isspace((int) *cp)) { - cp++; - continue; - } - port = strtol(cp, &cp, 10); - if (cp == 0) - break; - retval = add_tcp_port(port); - if (retval) - return retval; - } + cp = kdc_realmlist[i]->realm_ports; + while (cp && *cp) { + if (*cp == ',' || isspace((int) *cp)) { + cp++; + continue; + } + port = strtol(cp, &cp, 10); + if (cp == 0) + break; + retval = add_udp_port(port); + if (retval) + return retval; + } + + cp = kdc_realmlist[i]->realm_tcp_ports; + while (cp && *cp) { + if (*cp == ',' || isspace((int) *cp)) { + cp++; + continue; + } + port = strtol(cp, &cp, 10); + if (cp == 0) + break; + retval = add_tcp_port(port); + if (retval) + return retval; + } } setup_data.retval = 0; @@ -951,15 +952,15 @@ setup_network() setup_data.udp_flags = UDP_DO_IPV4 | UDP_DO_IPV6; setup_udp_pktinfo_ports(&setup_data); if (setup_data.udp_flags) { - if (foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) { - return setup_data.retval; - } + if (foreach_localaddr (&setup_data, setup_udp_port, 0, 0)) { + return setup_data.retval; + } } setup_tcp_listener_ports(&setup_data); krb5_klog_syslog (LOG_INFO, "set up %d sockets", n_sockets); if (n_sockets == 0) { - kdc_err(NULL, 0, "no sockets set up?"); - exit (1); + kdc_err(NULL, 0, "no sockets set up?"); + exit (1); } return 0; @@ -969,45 +970,45 @@ static void init_addr(krb5_fulladdr *faddr, struct sockaddr *sa) { switch (sa->sa_family) { case AF_INET: - faddr->address->addrtype = ADDRTYPE_INET; - faddr->address->length = 4; - faddr->address->contents = (krb5_octet *) &sa2sin(sa)->sin_addr; - faddr->port = ntohs(sa2sin(sa)->sin_port); - break; + faddr->address->addrtype = ADDRTYPE_INET; + faddr->address->length = 4; + faddr->address->contents = (krb5_octet *) &sa2sin(sa)->sin_addr; + faddr->port = ntohs(sa2sin(sa)->sin_port); + break; #ifdef KRB5_USE_INET6 case AF_INET6: - if (IN6_IS_ADDR_V4MAPPED(&sa2sin6(sa)->sin6_addr)) { - faddr->address->addrtype = ADDRTYPE_INET; - faddr->address->length = 4; - faddr->address->contents = 12 + (krb5_octet *) &sa2sin6(sa)->sin6_addr; - } else { - faddr->address->addrtype = ADDRTYPE_INET6; - faddr->address->length = 16; - faddr->address->contents = (krb5_octet *) &sa2sin6(sa)->sin6_addr; - } - faddr->port = ntohs(sa2sin6(sa)->sin6_port); - break; + if (IN6_IS_ADDR_V4MAPPED(&sa2sin6(sa)->sin6_addr)) { + faddr->address->addrtype = ADDRTYPE_INET; + faddr->address->length = 4; + faddr->address->contents = 12 + (krb5_octet *) &sa2sin6(sa)->sin6_addr; + } else { + faddr->address->addrtype = ADDRTYPE_INET6; + faddr->address->length = 16; + faddr->address->contents = (krb5_octet *) &sa2sin6(sa)->sin6_addr; + } + faddr->port = ntohs(sa2sin6(sa)->sin6_port); + break; #endif default: - faddr->address->addrtype = -1; - faddr->address->length = 0; - faddr->address->contents = 0; - faddr->port = 0; - break; + faddr->address->addrtype = -1; + faddr->address->length = 0; + faddr->address->contents = 0; + faddr->port = 0; + break; } } static int recv_from_to(int s, void *buf, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen, - struct sockaddr *to, socklen_t *tolen) + struct sockaddr *from, socklen_t *fromlen, + struct sockaddr *to, socklen_t *tolen) { #if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE) if (to && tolen) { - /* Clobber with something recognizeable in case we try to use - the address. */ - memset(to, 0x40, *tolen); - *tolen = 0; + /* Clobber with something recognizeable in case we try to use + the address. */ + memset(to, 0x40, *tolen); + *tolen = 0; } return recvfrom(s, buf, len, flags, from, fromlen); #else @@ -1018,7 +1019,7 @@ recv_from_to(int s, void *buf, size_t len, int flags, struct msghdr msg; if (!to || !tolen) - return recvfrom(s, buf, len, flags, from, fromlen); + return recvfrom(s, buf, len, flags, from, fromlen); /* Clobber with something recognizeable in case we can't extract the address but try to use it anyways. */ @@ -1036,7 +1037,7 @@ recv_from_to(int s, void *buf, size_t len, int flags, r = recvmsg(s, &msg, flags); if (r < 0) - return r; + return r; *fromlen = msg.msg_namelen; /* On Darwin (and presumably all *BSD with KAME stacks), @@ -1044,36 +1045,36 @@ recv_from_to(int s, void *buf, size_t len, int flags, 3542 recommends making this check, even though the (new) spec for CMSG_FIRSTHDR says it's supposed to do the check. */ if (msg.msg_controllen) { - cmsgptr = CMSG_FIRSTHDR(&msg); - while (cmsgptr) { + cmsgptr = CMSG_FIRSTHDR(&msg); + while (cmsgptr) { #ifdef IP_PKTINFO - if (cmsgptr->cmsg_level == IPPROTO_IP - && cmsgptr->cmsg_type == IP_PKTINFO - && *tolen >= sizeof(struct sockaddr_in)) { - struct in_pktinfo *pktinfo; - memset(to, 0, sizeof(struct sockaddr_in)); - pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsgptr); - ((struct sockaddr_in *)to)->sin_addr = pktinfo->ipi_addr; - ((struct sockaddr_in *)to)->sin_family = AF_INET; - *tolen = sizeof(struct sockaddr_in); - return r; - } + if (cmsgptr->cmsg_level == IPPROTO_IP + && cmsgptr->cmsg_type == IP_PKTINFO + && *tolen >= sizeof(struct sockaddr_in)) { + struct in_pktinfo *pktinfo; + memset(to, 0, sizeof(struct sockaddr_in)); + pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsgptr); + ((struct sockaddr_in *)to)->sin_addr = pktinfo->ipi_addr; + ((struct sockaddr_in *)to)->sin_family = AF_INET; + *tolen = sizeof(struct sockaddr_in); + return r; + } #endif #if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO)&& defined(HAVE_STRUCT_IN6_PKTINFO) - if (cmsgptr->cmsg_level == IPPROTO_IPV6 - && cmsgptr->cmsg_type == IPV6_PKTINFO - && *tolen >= sizeof(struct sockaddr_in6)) { - struct in6_pktinfo *pktinfo; - memset(to, 0, sizeof(struct sockaddr_in6)); - pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); - ((struct sockaddr_in6 *)to)->sin6_addr = pktinfo->ipi6_addr; - ((struct sockaddr_in6 *)to)->sin6_family = AF_INET6; - *tolen = sizeof(struct sockaddr_in6); - return r; - } + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IPV6_PKTINFO + && *tolen >= sizeof(struct sockaddr_in6)) { + struct in6_pktinfo *pktinfo; + memset(to, 0, sizeof(struct sockaddr_in6)); + pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + ((struct sockaddr_in6 *)to)->sin6_addr = pktinfo->ipi6_addr; + ((struct sockaddr_in6 *)to)->sin6_family = AF_INET6; + *tolen = sizeof(struct sockaddr_in6); + return r; + } #endif - cmsgptr = CMSG_NXTHDR(&msg, cmsgptr); - } + cmsgptr = CMSG_NXTHDR(&msg, cmsgptr); + } } /* No info about destination addr was available. */ *tolen = 0; @@ -1083,8 +1084,8 @@ recv_from_to(int s, void *buf, size_t len, int flags, static int send_to_from(int s, void *buf, size_t len, int flags, - const struct sockaddr *to, socklen_t tolen, - const struct sockaddr *from, socklen_t fromlen) + const struct sockaddr *to, socklen_t tolen, + const struct sockaddr *from, socklen_t fromlen) { #if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE) return sendto(s, buf, len, flags, to, tolen); @@ -1096,14 +1097,14 @@ send_to_from(int s, void *buf, size_t len, int flags, if (from == 0 || fromlen == 0 || from->sa_family != to->sa_family) { use_sendto: - return sendto(s, buf, len, flags, to, tolen); + return sendto(s, buf, len, flags, to, tolen); } iov.iov_base = buf; iov.iov_len = len; /* Truncation? */ if (iov.iov_len != len) - return EINVAL; + return EINVAL; memset(cbuf, 0, sizeof(cbuf)); memset(&msg, 0, sizeof(msg)); msg.msg_name = (void *) to; @@ -1120,36 +1121,36 @@ send_to_from(int s, void *buf, size_t len, int flags, switch (from->sa_family) { #if defined(IP_PKTINFO) case AF_INET: - if (fromlen != sizeof(struct sockaddr_in)) - goto use_sendto; - cmsgptr->cmsg_level = IPPROTO_IP; - cmsgptr->cmsg_type = IP_PKTINFO; - cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); - { - struct in_pktinfo *p = (struct in_pktinfo *)CMSG_DATA(cmsgptr); - const struct sockaddr_in *from4 = (const struct sockaddr_in *)from; - p->ipi_spec_dst = from4->sin_addr; - } - msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); - break; + if (fromlen != sizeof(struct sockaddr_in)) + goto use_sendto; + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_PKTINFO; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + { + struct in_pktinfo *p = (struct in_pktinfo *)CMSG_DATA(cmsgptr); + const struct sockaddr_in *from4 = (const struct sockaddr_in *)from; + p->ipi_spec_dst = from4->sin_addr; + } + msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); + break; #endif #if defined(KRB5_USE_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO) case AF_INET6: - if (fromlen != sizeof(struct sockaddr_in6)) - goto use_sendto; - cmsgptr->cmsg_level = IPPROTO_IPV6; - cmsgptr->cmsg_type = IPV6_PKTINFO; - cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); - { - struct in6_pktinfo *p = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); - const struct sockaddr_in6 *from6 = (const struct sockaddr_in6 *)from; - p->ipi6_addr = from6->sin6_addr; - } - msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); - break; + if (fromlen != sizeof(struct sockaddr_in6)) + goto use_sendto; + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_PKTINFO; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + { + struct in6_pktinfo *p = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + const struct sockaddr_in6 *from6 = (const struct sockaddr_in6 *)from; + p->ipi6_addr = from6->sin6_addr; + } + msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + break; #endif default: - goto use_sendto; + goto use_sendto; } return sendmsg(s, &msg, flags); #endif @@ -1167,7 +1168,7 @@ make_too_big_error (krb5_data **out) retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec); if (retval) - return retval; + return retval; errpkt.error = KRB_ERR_RESPONSE_TOO_BIG; errpkt.server = tgs_server; errpkt.client = NULL; @@ -1177,11 +1178,11 @@ make_too_big_error (krb5_data **out) errpkt.e_data.data = 0; scratch = malloc(sizeof(*scratch)); if (scratch == NULL) - return ENOMEM; + return ENOMEM; retval = krb5_mk_error(kdc_context, &errpkt, scratch); if (retval) { - free(scratch); - return retval; + free(scratch); + return retval; } *out = scratch; @@ -1205,28 +1206,28 @@ static void process_packet(struct connection *conn, int selflags) saddr_len = sizeof(saddr); daddr_len = sizeof(daddr); cc = recv_from_to(port_fd, pktbuf, sizeof(pktbuf), 0, - (struct sockaddr *)&saddr, &saddr_len, - (struct sockaddr *)&daddr, &daddr_len); + (struct sockaddr *)&saddr, &saddr_len, + (struct sockaddr *)&daddr, &daddr_len); if (cc == -1) { - if (errno != EINTR - /* This is how Linux indicates that a previous - transmission was refused, e.g., if the client timed out - before getting the response packet. */ - && errno != ECONNREFUSED - ) - kdc_err(NULL, errno, "while receiving from network"); - return; + if (errno != EINTR + /* This is how Linux indicates that a previous + transmission was refused, e.g., if the client timed out + before getting the response packet. */ + && errno != ECONNREFUSED + ) + kdc_err(NULL, errno, "while receiving from network"); + return; } if (!cc) - return; /* zero-length packet? */ + return; /* zero-length packet? */ #if 0 if (daddr_len > 0) { - char addrbuf[100]; - if (getnameinfo(ss2sa(&daddr), daddr_len, addrbuf, sizeof(addrbuf), - 0, 0, NI_NUMERICHOST)) - strlcpy(addrbuf, "?", sizeof(addrbuf)); - kdc_err(NULL, 0, "pktinfo says local addr is %s", addrbuf); + char addrbuf[100]; + if (getnameinfo(ss2sa(&daddr), daddr_len, addrbuf, sizeof(addrbuf), + 0, 0, NI_NUMERICHOST)) + strlcpy(addrbuf, "?", sizeof(addrbuf)); + kdc_err(NULL, 0, "pktinfo says local addr is %s", addrbuf); } #endif @@ -1236,38 +1237,38 @@ static void process_packet(struct connection *conn, int selflags) init_addr(&faddr, ss2sa(&saddr)); /* this address is in net order */ if ((retval = dispatch(&request, &faddr, &response))) { - kdc_err(NULL, retval, "while dispatching (udp)"); - return; + kdc_err(NULL, retval, "while dispatching (udp)"); + return; } if (response == NULL) - return; + return; if (response->length > max_dgram_reply_size) { - krb5_free_data(kdc_context, response); - retval = make_too_big_error(&response); - if (retval) { - krb5_klog_syslog(LOG_ERR, - "error constructing KRB_ERR_RESPONSE_TOO_BIG error: %s", - error_message(retval)); - return; - } + krb5_free_data(kdc_context, response); + retval = make_too_big_error(&response); + if (retval) { + krb5_klog_syslog(LOG_ERR, + "error constructing KRB_ERR_RESPONSE_TOO_BIG error: %s", + error_message(retval)); + return; + } } cc = send_to_from(port_fd, response->data, (socklen_t) response->length, 0, - (struct sockaddr *)&saddr, saddr_len, - (struct sockaddr *)&daddr, daddr_len); + (struct sockaddr *)&saddr, saddr_len, + (struct sockaddr *)&daddr, daddr_len); if (cc == -1) { - char addrbuf[46]; + char addrbuf[46]; krb5_free_data(kdc_context, response); - if (inet_ntop(((struct sockaddr *)&saddr)->sa_family, - addr.contents, addrbuf, sizeof(addrbuf)) == 0) { - strlcpy(addrbuf, "?", sizeof(addrbuf)); - } - kdc_err(NULL, errno, "while sending reply to %s/%d", - addrbuf, faddr.port); - return; + if (inet_ntop(((struct sockaddr *)&saddr)->sa_family, + addr.contents, addrbuf, sizeof(addrbuf)) == 0) { + strlcpy(addrbuf, "?", sizeof(addrbuf)); + } + kdc_err(NULL, errno, "while sending reply to %s/%d", + addrbuf, faddr.port); + return; } if (cc != response->length) { - kdc_err(NULL, 0, "short reply write %d vs %d\n", - response->length, cc); + kdc_err(NULL, 0, "short reply write %d vs %d\n", + response->length, cc); } krb5_free_data(kdc_context, response); return; @@ -1290,12 +1291,12 @@ static void accept_tcp_connection(struct connection *conn, int selflags) s = accept(conn->fd, addr, &addrlen); if (s < 0) - return; + return; set_cloexec_fd(s); #ifndef _WIN32 if (s >= FD_SETSIZE) { - close(s); - return; + close(s); + return; } #endif setnbio(s), setnolinger(s), setkeepalive(s); @@ -1304,26 +1305,26 @@ static void accept_tcp_connection(struct connection *conn, int selflags) newconn = add_tcp_data_fd(&sockdata, s); if (newconn == NULL) - return; + return; if (getnameinfo((struct sockaddr *)&addr_s, addrlen, - newconn->u.tcp.addrbuf, sizeof(newconn->u.tcp.addrbuf), - tmpbuf, sizeof(tmpbuf), - NI_NUMERICHOST | NI_NUMERICSERV)) - strlcpy(newconn->u.tcp.addrbuf, "???", sizeof(newconn->u.tcp.addrbuf)); + newconn->u.tcp.addrbuf, sizeof(newconn->u.tcp.addrbuf), + tmpbuf, sizeof(tmpbuf), + NI_NUMERICHOST | NI_NUMERICSERV)) + strlcpy(newconn->u.tcp.addrbuf, "???", sizeof(newconn->u.tcp.addrbuf)); else { - char *p, *end; - p = newconn->u.tcp.addrbuf; - end = p + sizeof(newconn->u.tcp.addrbuf); - p += strlen(p); - if (end - p > 2 + strlen(tmpbuf)) { - *p++ = '.'; - strlcpy(p, tmpbuf, end - p); - } + char *p, *end; + p = newconn->u.tcp.addrbuf; + end = p + sizeof(newconn->u.tcp.addrbuf); + p += strlen(p); + if (end - p > 2 + strlen(tmpbuf)) { + *p++ = '.'; + strlcpy(p, tmpbuf, end - p); + } } #if 0 krb5_klog_syslog(LOG_INFO, "accepted TCP connection on socket %d from %s", - s, newconn->u.tcp.addrbuf); + s, newconn->u.tcp.addrbuf); #endif newconn->u.tcp.addr_s = addr_s; @@ -1333,38 +1334,38 @@ static void accept_tcp_connection(struct connection *conn, int selflags) newconn->u.tcp.start_time = time(0); if (++tcp_data_counter > max_tcp_data_connections) { - struct connection *oldest_tcp = NULL; - struct connection *c; - int i; + struct connection *oldest_tcp = NULL; + struct connection *c; + int i; - krb5_klog_syslog(LOG_INFO, "too many connections"); + krb5_klog_syslog(LOG_INFO, "too many connections"); - FOREACH_ELT (connections, i, c) { - if (c->type != CONN_TCP) - continue; - if (c == newconn) - continue; + FOREACH_ELT (connections, i, c) { + if (c->type != CONN_TCP) + continue; + if (c == newconn) + continue; #if 0 - krb5_klog_syslog(LOG_INFO, "fd %d started at %ld", c->fd, - c->u.tcp.start_time); + krb5_klog_syslog(LOG_INFO, "fd %d started at %ld", c->fd, + c->u.tcp.start_time); #endif - if (oldest_tcp == NULL - || oldest_tcp->u.tcp.start_time > c->u.tcp.start_time) - oldest_tcp = c; - } - if (oldest_tcp != NULL) { - krb5_klog_syslog(LOG_INFO, "dropping tcp fd %d from %s", - oldest_tcp->fd, oldest_tcp->u.tcp.addrbuf); - kill_tcp_connection(oldest_tcp); - } + if (oldest_tcp == NULL + || oldest_tcp->u.tcp.start_time > c->u.tcp.start_time) + oldest_tcp = c; + } + if (oldest_tcp != NULL) { + krb5_klog_syslog(LOG_INFO, "dropping tcp fd %d from %s", + oldest_tcp->fd, oldest_tcp->u.tcp.addrbuf); + kill_tcp_connection(oldest_tcp); + } } if (newconn->u.tcp.buffer == 0) { - kdc_err(NULL, errno, "allocating buffer for new TCP session from %s", - newconn->u.tcp.addrbuf); - delete_fd(newconn); - close(s); - tcp_data_counter--; - return; + kdc_err(NULL, errno, "allocating buffer for new TCP session from %s", + newconn->u.tcp.addrbuf); + delete_fd(newconn); + close(s); + tcp_data_counter--; + return; } newconn->u.tcp.offset = 0; newconn->u.tcp.faddr.address = &newconn->u.tcp.kaddr; @@ -1374,25 +1375,25 @@ static void accept_tcp_connection(struct connection *conn, int selflags) FD_SET(s, &sstate.rfds); if (sstate.max <= s) - sstate.max = s + 1; + sstate.max = s + 1; } static void kill_tcp_connection(struct connection *conn) { if (conn->u.tcp.response) - krb5_free_data(kdc_context, conn->u.tcp.response); + krb5_free_data(kdc_context, conn->u.tcp.response); if (conn->u.tcp.buffer) - free(conn->u.tcp.buffer); + free(conn->u.tcp.buffer); FD_CLR(conn->fd, &sstate.rfds); FD_CLR(conn->fd, &sstate.wfds); if (sstate.max == conn->fd + 1) - while (sstate.max > 0 - && ! FD_ISSET(sstate.max-1, &sstate.rfds) - && ! FD_ISSET(sstate.max-1, &sstate.wfds) - /* && ! FD_ISSET(sstate.max-1, &sstate.xfds) */ - ) - sstate.max--; + while (sstate.max > 0 + && ! FD_ISSET(sstate.max-1, &sstate.rfds) + && ! FD_ISSET(sstate.max-1, &sstate.wfds) + /* && ! FD_ISSET(sstate.max-1, &sstate.xfds) */ + ) + sstate.max--; close(conn->fd); conn->fd = -1; delete_fd(conn); @@ -1408,7 +1409,7 @@ make_toolong_error (krb5_data **out) retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec); if (retval) - return retval; + return retval; errpkt.error = KRB_ERR_FIELD_TOOLONG; errpkt.server = tgs_server; errpkt.client = NULL; @@ -1420,11 +1421,11 @@ make_toolong_error (krb5_data **out) errpkt.e_data.data = 0; scratch = malloc(sizeof(*scratch)); if (scratch == NULL) - return ENOMEM; + return ENOMEM; retval = krb5_mk_error(kdc_context, &errpkt, scratch); if (retval) { - free(scratch); - return retval; + free(scratch); + return retval; } *out = scratch; @@ -1436,7 +1437,7 @@ queue_tcp_outgoing_response(struct connection *conn) { store_32_be(conn->u.tcp.response->length, conn->u.tcp.lenbuf); SG_SET(&conn->u.tcp.sgbuf[1], conn->u.tcp.response->data, - conn->u.tcp.response->length); + conn->u.tcp.response->length); conn->u.tcp.sgp = conn->u.tcp.sgbuf; conn->u.tcp.sgnum = 2; FD_SET(conn->fd, &sstate.wfds); @@ -1446,112 +1447,112 @@ static void process_tcp_connection(struct connection *conn, int selflags) { if (selflags & SSF_WRITE) { - ssize_t nwrote; - SOCKET_WRITEV_TEMP tmp; - - nwrote = SOCKET_WRITEV(conn->fd, conn->u.tcp.sgp, conn->u.tcp.sgnum, - tmp); - if (nwrote < 0) { - goto kill_tcp_connection; - } - if (nwrote == 0) - /* eof */ - goto kill_tcp_connection; - while (nwrote) { - sg_buf *sgp = conn->u.tcp.sgp; - if (nwrote < SG_LEN(sgp)) { - SG_ADVANCE(sgp, nwrote); - nwrote = 0; - } else { - nwrote -= SG_LEN(sgp); - conn->u.tcp.sgp++; - conn->u.tcp.sgnum--; - if (conn->u.tcp.sgnum == 0 && nwrote != 0) - abort(); - } - } - if (conn->u.tcp.sgnum == 0) { - /* finished sending */ - /* We should go back to reading, though if we sent a - FIELD_TOOLONG error in reply to a length with the high - bit set, RFC 4120 says we have to close the TCP - stream. */ - goto kill_tcp_connection; - } + ssize_t nwrote; + SOCKET_WRITEV_TEMP tmp; + + nwrote = SOCKET_WRITEV(conn->fd, conn->u.tcp.sgp, conn->u.tcp.sgnum, + tmp); + if (nwrote < 0) { + goto kill_tcp_connection; + } + if (nwrote == 0) + /* eof */ + goto kill_tcp_connection; + while (nwrote) { + sg_buf *sgp = conn->u.tcp.sgp; + if (nwrote < SG_LEN(sgp)) { + SG_ADVANCE(sgp, nwrote); + nwrote = 0; + } else { + nwrote -= SG_LEN(sgp); + conn->u.tcp.sgp++; + conn->u.tcp.sgnum--; + if (conn->u.tcp.sgnum == 0 && nwrote != 0) + abort(); + } + } + if (conn->u.tcp.sgnum == 0) { + /* finished sending */ + /* We should go back to reading, though if we sent a + FIELD_TOOLONG error in reply to a length with the high + bit set, RFC 4120 says we have to close the TCP + stream. */ + goto kill_tcp_connection; + } } else if (selflags & SSF_READ) { - /* Read message length and data into one big buffer, already - allocated at connect time. If we have a complete message, - we stop reading, so we should only be here if there is no - data in the buffer, or only an incomplete message. */ - size_t len; - ssize_t nread; - if (conn->u.tcp.offset < 4) { - /* msglen has not been computed */ - /* XXX Doing at least two reads here, letting the kernel - worry about buffering. It'll be faster when we add - code to manage the buffer here. */ - len = 4 - conn->u.tcp.offset; - nread = SOCKET_READ(conn->fd, - conn->u.tcp.buffer + conn->u.tcp.offset, len); - if (nread < 0) - /* error */ - goto kill_tcp_connection; - if (nread == 0) - /* eof */ - goto kill_tcp_connection; - conn->u.tcp.offset += nread; - if (conn->u.tcp.offset == 4) { - unsigned char *p = (unsigned char *)conn->u.tcp.buffer; - conn->u.tcp.msglen = load_32_be(p); - if (conn->u.tcp.msglen > conn->u.tcp.bufsiz - 4) { - krb5_error_code err; - /* message too big */ - krb5_klog_syslog(LOG_ERR, "TCP client %s wants %lu bytes, cap is %lu", - conn->u.tcp.addrbuf, (unsigned long) conn->u.tcp.msglen, - (unsigned long) conn->u.tcp.bufsiz - 4); - /* XXX Should return an error. */ - err = make_toolong_error (&conn->u.tcp.response); - if (err) { - krb5_klog_syslog(LOG_ERR, - "error constructing KRB_ERR_FIELD_TOOLONG error! %s", - error_message(err)); - goto kill_tcp_connection; - } - goto have_response; - } - } - } else { - /* msglen known */ - krb5_data request; - krb5_error_code err; - - len = conn->u.tcp.msglen - (conn->u.tcp.offset - 4); - nread = SOCKET_READ(conn->fd, - conn->u.tcp.buffer + conn->u.tcp.offset, len); - if (nread < 0) - /* error */ - goto kill_tcp_connection; - if (nread == 0) - /* eof */ - goto kill_tcp_connection; - conn->u.tcp.offset += nread; - if (conn->u.tcp.offset < conn->u.tcp.msglen + 4) - return; - /* have a complete message, and exactly one message */ - request.length = conn->u.tcp.msglen; - request.data = conn->u.tcp.buffer + 4; - err = dispatch(&request, &conn->u.tcp.faddr, - &conn->u.tcp.response); - if (err) { - kdc_err(NULL, err, "while dispatching (tcp)"); - goto kill_tcp_connection; - } - have_response: - queue_tcp_outgoing_response(conn); - FD_CLR(conn->fd, &sstate.rfds); - } + /* Read message length and data into one big buffer, already + allocated at connect time. If we have a complete message, + we stop reading, so we should only be here if there is no + data in the buffer, or only an incomplete message. */ + size_t len; + ssize_t nread; + if (conn->u.tcp.offset < 4) { + /* msglen has not been computed */ + /* XXX Doing at least two reads here, letting the kernel + worry about buffering. It'll be faster when we add + code to manage the buffer here. */ + len = 4 - conn->u.tcp.offset; + nread = SOCKET_READ(conn->fd, + conn->u.tcp.buffer + conn->u.tcp.offset, len); + if (nread < 0) + /* error */ + goto kill_tcp_connection; + if (nread == 0) + /* eof */ + goto kill_tcp_connection; + conn->u.tcp.offset += nread; + if (conn->u.tcp.offset == 4) { + unsigned char *p = (unsigned char *)conn->u.tcp.buffer; + conn->u.tcp.msglen = load_32_be(p); + if (conn->u.tcp.msglen > conn->u.tcp.bufsiz - 4) { + krb5_error_code err; + /* message too big */ + krb5_klog_syslog(LOG_ERR, "TCP client %s wants %lu bytes, cap is %lu", + conn->u.tcp.addrbuf, (unsigned long) conn->u.tcp.msglen, + (unsigned long) conn->u.tcp.bufsiz - 4); + /* XXX Should return an error. */ + err = make_toolong_error (&conn->u.tcp.response); + if (err) { + krb5_klog_syslog(LOG_ERR, + "error constructing KRB_ERR_FIELD_TOOLONG error! %s", + error_message(err)); + goto kill_tcp_connection; + } + goto have_response; + } + } + } else { + /* msglen known */ + krb5_data request; + krb5_error_code err; + + len = conn->u.tcp.msglen - (conn->u.tcp.offset - 4); + nread = SOCKET_READ(conn->fd, + conn->u.tcp.buffer + conn->u.tcp.offset, len); + if (nread < 0) + /* error */ + goto kill_tcp_connection; + if (nread == 0) + /* eof */ + goto kill_tcp_connection; + conn->u.tcp.offset += nread; + if (conn->u.tcp.offset < conn->u.tcp.msglen + 4) + return; + /* have a complete message, and exactly one message */ + request.length = conn->u.tcp.msglen; + request.data = conn->u.tcp.buffer + 4; + err = dispatch(&request, &conn->u.tcp.faddr, + &conn->u.tcp.response); + if (err) { + kdc_err(NULL, err, "while dispatching (tcp)"); + goto kill_tcp_connection; + } + have_response: + queue_tcp_outgoing_response(conn); + FD_CLR(conn->fd, &sstate.rfds); + } } else - abort(); + abort(); return; @@ -1581,79 +1582,79 @@ static int getcurtime(struct timeval *tvp) krb5_error_code listen_and_process() { - int nfound; + int nfound; /* This struct contains 3 fd_set objects; on some platforms, they can be rather large. Making this static avoids putting all that junk on the stack. */ static struct select_state sout; - int i, sret, netchanged = 0; - krb5_error_code err; + int i, sret, netchanged = 0; + krb5_error_code err; if (conns == (struct connection **) NULL) - return KDC5_NONET; - + return KDC5_NONET; + while (!signal_requests_exit) { - if (signal_requests_hup) { - int k; - - krb5_klog_reopen(kdc_context); - for (k = 0; k < kdc_numrealms; k++) - krb5_db_invoke(kdc_realmlist[k]->realm_context, - KRB5_KDB_METHOD_REFRESH_POLICY, - NULL, NULL); - signal_requests_hup = 0; - } - - if (network_reconfiguration_needed) { - /* No point in re-logging what we've just logged. */ - if (netchanged == 0) - krb5_klog_syslog(LOG_INFO, "network reconfiguration needed"); - /* It might be tidier to add a timer-callback interface to - the control loop here, but for this one use, it's not a - big deal. */ - err = getcurtime(&sstate.end_time); - if (err) { - kdc_err(NULL, err, "while getting the time"); - continue; - } - sstate.end_time.tv_sec += 3; - netchanged = 1; - } else - sstate.end_time.tv_sec = sstate.end_time.tv_usec = 0; - - err = krb5int_cm_call_select(&sstate, &sout, &sret); - if (err) { - if (err != EINTR) - kdc_err(NULL, err, "while selecting for network input(1)"); - continue; - } - if (sret == 0 && netchanged) { - network_reconfiguration_needed = 0; - closedown_network(); - err = setup_network(); - if (err) { - kdc_err(NULL, err, "while reinitializing network"); - return err; - } - netchanged = 0; - } - if (sret == -1) { - if (errno != EINTR) - kdc_err(NULL, errno, "while selecting for network input(2)"); - continue; - } - nfound = sret; - for (i=0; i<n_sockets && nfound > 0; i++) { - int sflags = 0; - if (conns[i]->fd < 0) - abort(); - if (FD_ISSET(conns[i]->fd, &sout.rfds)) - sflags |= SSF_READ, nfound--; - if (FD_ISSET(conns[i]->fd, &sout.wfds)) - sflags |= SSF_WRITE, nfound--; - if (sflags) - service_conn(conns[i], sflags); - } + if (signal_requests_hup) { + int k; + + krb5_klog_reopen(kdc_context); + for (k = 0; k < kdc_numrealms; k++) + krb5_db_invoke(kdc_realmlist[k]->realm_context, + KRB5_KDB_METHOD_REFRESH_POLICY, + NULL, NULL); + signal_requests_hup = 0; + } + + if (network_reconfiguration_needed) { + /* No point in re-logging what we've just logged. */ + if (netchanged == 0) + krb5_klog_syslog(LOG_INFO, "network reconfiguration needed"); + /* It might be tidier to add a timer-callback interface to + the control loop here, but for this one use, it's not a + big deal. */ + err = getcurtime(&sstate.end_time); + if (err) { + kdc_err(NULL, err, "while getting the time"); + continue; + } + sstate.end_time.tv_sec += 3; + netchanged = 1; + } else + sstate.end_time.tv_sec = sstate.end_time.tv_usec = 0; + + err = krb5int_cm_call_select(&sstate, &sout, &sret); + if (err) { + if (err != EINTR) + kdc_err(NULL, err, "while selecting for network input(1)"); + continue; + } + if (sret == 0 && netchanged) { + network_reconfiguration_needed = 0; + closedown_network(); + err = setup_network(); + if (err) { + kdc_err(NULL, err, "while reinitializing network"); + return err; + } + netchanged = 0; + } + if (sret == -1) { + if (errno != EINTR) + kdc_err(NULL, errno, "while selecting for network input(2)"); + continue; + } + nfound = sret; + for (i=0; i<n_sockets && nfound > 0; i++) { + int sflags = 0; + if (conns[i]->fd < 0) + abort(); + if (FD_ISSET(conns[i]->fd, &sout.rfds)) + sflags |= SSF_READ, nfound--; + if (FD_ISSET(conns[i]->fd, &sout.wfds)) + sflags |= SSF_WRITE, nfound--; + if (sflags) + service_conn(conns[i], sflags); + } } krb5_klog_syslog(LOG_INFO, "shutdown signal received"); return 0; @@ -1666,19 +1667,19 @@ closedown_network() struct connection *conn; if (conns == (struct connection **) NULL) - return KDC5_NONET; + return KDC5_NONET; FOREACH_ELT (connections, i, conn) { - if (conn->fd >= 0) { - krb5_klog_syslog(LOG_INFO, "closing down fd %d", conn->fd); - (void) close(conn->fd); - } - DEL (connections, i); - /* There may also be per-connection data in the tcp structure - (tcp.buffer, tcp.response) that we're not freeing here. - That should only happen if we quit with a connection in - progress. */ - free(conn); + if (conn->fd >= 0) { + krb5_klog_syslog(LOG_INFO, "closing down fd %d", conn->fd); + (void) close(conn->fd); + } + DEL (connections, i); + /* There may also be per-connection data in the tcp structure + (tcp.buffer, tcp.response) that we're not freeing here. + That should only happen if we quit with a connection in + progress. */ + free(conn); } FREE_SET_DATA(connections); FREE_SET_DATA(udp_port_data); diff --git a/src/kdc/pkinit_apple_server.c b/src/kdc/pkinit_apple_server.c index b86c634..ade1b8b 100644 --- a/src/kdc/pkinit_apple_server.c +++ b/src/kdc/pkinit_apple_server.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. * @@ -37,47 +38,47 @@ #include <assert.h> #define PKINIT_DEBUG 0 -#if PKINIT_DEBUG +#if PKINIT_DEBUG #define pkiDebug(args...) printf(args) #else #define pkiDebug(args...) #endif /* - * Parse PA-PK-AS-REQ message. Optionally evaluates the message's certificate chain. - * Optionally returns various components. + * Parse PA-PK-AS-REQ message. Optionally evaluates the message's certificate chain. + * Optionally returns various components. */ krb5_error_code krb5int_pkinit_as_req_parse( - krb5_context context, - const krb5_data *as_req, - krb5_timestamp *kctime, /* optionally RETURNED */ - krb5_ui_4 *cusec, /* microseconds, optionally RETURNED */ - krb5_ui_4 *nonce, /* optionally RETURNED */ - krb5_checksum *pa_cksum, /* optional, contents mallocd and RETURNED */ + krb5_context context, + const krb5_data *as_req, + krb5_timestamp *kctime, /* optionally RETURNED */ + krb5_ui_4 *cusec, /* microseconds, optionally RETURNED */ + krb5_ui_4 *nonce, /* optionally RETURNED */ + krb5_checksum *pa_cksum, /* optional, contents mallocd and RETURNED */ krb5int_cert_sig_status *cert_status,/* optionally RETURNED */ - krb5_ui_4 *num_cms_types, /* optionally RETURNED */ - krb5int_algorithm_id **cms_types, /* optionally mallocd and RETURNED */ + krb5_ui_4 *num_cms_types, /* optionally RETURNED */ + krb5int_algorithm_id **cms_types, /* optionally mallocd and RETURNED */ /* * Cert fields, all optionally RETURNED. * * signer_cert is the full X.509 leaf cert from the incoming SignedData. * all_certs is an array of all of the certs in the incoming SignedData, - * in full X.509 form. + * in full X.509 form. */ - krb5_data *signer_cert, /* content mallocd */ - krb5_ui_4 *num_all_certs, /* sizeof *all_certs */ - krb5_data **all_certs, /* krb5_data's and their content mallocd */ - + krb5_data *signer_cert, /* content mallocd */ + krb5_ui_4 *num_all_certs, /* sizeof *all_certs */ + krb5_data **all_certs, /* krb5_data's and their content mallocd */ + /* - * Array of trustedCertifiers, optionally RETURNED. These are DER-encoded - * issuer/serial numbers. + * Array of trustedCertifiers, optionally RETURNED. These are DER-encoded + * issuer/serial numbers. */ - krb5_ui_4 *num_trusted_CAs, /* sizeof *trusted_CAs */ - krb5_data **trusted_CAs, /* krb5_data's and their content mallocd */ - + krb5_ui_4 *num_trusted_CAs, /* sizeof *trusted_CAs */ + krb5_data **trusted_CAs, /* krb5_data's and their content mallocd */ + /* KDC cert specified by client as kdcPkId. DER-encoded issuer/serial number. */ - krb5_data *kdc_cert) + krb5_data *kdc_cert) { krb5_error_code krtn; krb5_data signed_auth_pack = {0, 0, NULL}; @@ -89,84 +90,84 @@ krb5_error_code krb5int_pkinit_as_req_parse( krb5_pkinit_cert_db_t cert_db = NULL; krb5_boolean is_signed; krb5_boolean is_encrypted; - + assert(as_req != NULL); - - /* + + /* * We always have to decode the top-level AS-REQ... */ krtn = krb5int_pkinit_pa_pk_as_req_decode(as_req, &signed_auth_pack, - num_trusted_CAs, trusted_CAs, /* optional */ - kdc_cert); /* optional */ + num_trusted_CAs, trusted_CAs, /* optional */ + kdc_cert); /* optional */ if (krtn) { - pkiDebug("krb5int_pkinit_pa_pk_as_req_decode returned %d\n", (int)krtn); - return krtn; + pkiDebug("krb5int_pkinit_pa_pk_as_req_decode returned %d\n", (int)krtn); + return krtn; } /* Do we need info about or from the ContentInto or AuthPack? */ - if ((kctime != NULL) || (cusec != NULL) || (nonce != NULL) || + if ((kctime != NULL) || (cusec != NULL) || (nonce != NULL) || (pa_cksum != NULL) || (cms_types != NULL)) { - need_auth_pack = TRUE; - raw_auth_pack_p = &raw_auth_pack; + need_auth_pack = TRUE; + raw_auth_pack_p = &raw_auth_pack; } if (need_auth_pack || (cert_status != NULL) || (signer_cert != NULL) || (all_certs != NULL)) { - proceed = TRUE; + proceed = TRUE; } if (!proceed) { - krtn = 0; - goto err_out; + krtn = 0; + goto err_out; } - + /* Parse and possibly verify the ContentInfo */ krtn = krb5_pkinit_get_kdc_cert_db(&cert_db); if (krtn) { - pkiDebug("pa_pk_as_req_parse: error in krb5_pkinit_get_kdc_cert_db\n"); - goto err_out; + pkiDebug("pa_pk_as_req_parse: error in krb5_pkinit_get_kdc_cert_db\n"); + goto err_out; } krtn = krb5int_pkinit_parse_cms_msg(&signed_auth_pack, cert_db, TRUE, - &is_signed, &is_encrypted, - raw_auth_pack_p, &content_type, signer_cert, cert_status, - num_all_certs, all_certs); + &is_signed, &is_encrypted, + raw_auth_pack_p, &content_type, signer_cert, cert_status, + num_all_certs, all_certs); if (krtn) { - pkiDebug("krb5int_pkinit_parse_content_info returned %d\n", (int)krtn); - goto err_out; + pkiDebug("krb5int_pkinit_parse_content_info returned %d\n", (int)krtn); + goto err_out; } if (is_encrypted || !is_signed) { - pkiDebug("pkinit_parse_content_info: is_encrypted %s is_signed %s!\n", - is_encrypted ? "true" :"false", - is_signed ? "true" : "false"); - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto err_out; + pkiDebug("pkinit_parse_content_info: is_encrypted %s is_signed %s!\n", + is_encrypted ? "true" :"false", + is_signed ? "true" : "false"); + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto err_out; } if (content_type != ECT_PkAuthData) { - pkiDebug("authPack eContentType %d!\n", (int)content_type); - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto err_out; + pkiDebug("authPack eContentType %d!\n", (int)content_type); + krtn = KRB5KDC_ERR_PREAUTH_FAILED; + goto err_out; } - + /* optionally parse contents of authPack */ if (need_auth_pack) { - krtn = krb5int_pkinit_auth_pack_decode(&raw_auth_pack, kctime, - cusec, nonce, pa_cksum, + krtn = krb5int_pkinit_auth_pack_decode(&raw_auth_pack, kctime, + cusec, nonce, pa_cksum, cms_types, num_cms_types); - if(krtn) { - pkiDebug("krb5int_pkinit_auth_pack_decode returned %d\n", (int)krtn); - goto err_out; - } + if(krtn) { + pkiDebug("krb5int_pkinit_auth_pack_decode returned %d\n", (int)krtn); + goto err_out; + } } err_out: /* free temp mallocd data that we didn't pass back to caller */ if(signed_auth_pack.data) { - free(signed_auth_pack.data); + free(signed_auth_pack.data); } if(raw_auth_pack.data) { - free(raw_auth_pack.data); + free(raw_auth_pack.data); } if(cert_db) { - krb5_pkinit_release_cert_db(cert_db); + krb5_pkinit_release_cert_db(cert_db); } return krtn; } @@ -179,61 +180,61 @@ err_out: * PA-PK-AS-REP ::= EnvelopedData(SignedData(ReplyKeyPack)) */ krb5_error_code krb5int_pkinit_as_rep_create( - krb5_context context, - const krb5_keyblock *key_block, - const krb5_checksum *checksum, /* checksum of corresponding AS-REQ */ - krb5_pkinit_signing_cert_t signer_cert, /* server's cert */ - krb5_boolean include_server_cert,/* include signer_cert in SignerInfo */ - const krb5_data *recipient_cert, /* client's cert */ - - /* - * These correspond to the same out-parameters from - * krb5int_pkinit_as_req_parse(). All are optional. + krb5_context context, + const krb5_keyblock *key_block, + const krb5_checksum *checksum, /* checksum of corresponding AS-REQ */ + krb5_pkinit_signing_cert_t signer_cert, /* server's cert */ + krb5_boolean include_server_cert,/* include signer_cert in SignerInfo */ + const krb5_data *recipient_cert, /* client's cert */ + + /* + * These correspond to the same out-parameters from + * krb5int_pkinit_as_req_parse(). All are optional. */ - krb5_ui_4 num_cms_types, - const krb5int_algorithm_id *cms_types, - krb5_ui_4 num_trusted_CAs, - krb5_data *trusted_CAs, - krb5_data *kdc_cert, - - krb5_data *as_rep) /* mallocd and RETURNED */ + krb5_ui_4 num_cms_types, + const krb5int_algorithm_id *cms_types, + krb5_ui_4 num_trusted_CAs, + krb5_data *trusted_CAs, + krb5_data *kdc_cert, + + krb5_data *as_rep) /* mallocd and RETURNED */ { krb5_data reply_key_pack = {0, 0, NULL}; krb5_error_code krtn; krb5_data enc_key_pack = {0, 0, NULL}; - + /* innermost content = ReplyKeyPack */ - krtn = krb5int_pkinit_reply_key_pack_encode(key_block, checksum, + krtn = krb5int_pkinit_reply_key_pack_encode(key_block, checksum, &reply_key_pack); if (krtn) { - return krtn; + return krtn; } - - /* + + /* * Put that in an EnvelopedData(SignedData) * -- SignedData.EncapsulatedData.ContentType = id-pkinit-rkeyData */ krtn = krb5int_pkinit_create_cms_msg(&reply_key_pack, - signer_cert, - recipient_cert, - ECT_PkReplyKeyKata, - num_cms_types, cms_types, - &enc_key_pack); + signer_cert, + recipient_cert, + ECT_PkReplyKeyKata, + num_cms_types, cms_types, + &enc_key_pack); if (krtn) { - goto err_out; + goto err_out; } - + /* * Finally, wrap that inside of PA-PK-AS-REP */ krtn = krb5int_pkinit_pa_pk_as_rep_encode(NULL, &enc_key_pack, as_rep); - + err_out: if (reply_key_pack.data) { - free(reply_key_pack.data); + free(reply_key_pack.data); } if (enc_key_pack.data) { - free(enc_key_pack.data); + free(enc_key_pack.data); } return krtn; } diff --git a/src/kdc/pkinit_server.h b/src/kdc/pkinit_server.h index 773b497..b97cb98 100644 --- a/src/kdc/pkinit_server.h +++ b/src/kdc/pkinit_server.h @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. * @@ -42,41 +43,41 @@ extern "C" { /* * Parse PA-PK-AS-REQ message. Optionally evaluates the message's certificate chain - * if cert_status is non-NULL. Optionally returns various components. + * if cert_status is non-NULL. Optionally returns various components. */ krb5_error_code krb5int_pkinit_as_req_parse( - krb5_context context, - const krb5_data *as_req, - krb5_timestamp *kctime, /* optionally RETURNED */ - krb5_ui_4 *cusec, /* microseconds, optionally RETURNED */ - krb5_ui_4 *nonce, /* optionally RETURNED */ - krb5_checksum *pa_cksum, /* optional, contents mallocd and RETURNED */ + krb5_context context, + const krb5_data *as_req, + krb5_timestamp *kctime, /* optionally RETURNED */ + krb5_ui_4 *cusec, /* microseconds, optionally RETURNED */ + krb5_ui_4 *nonce, /* optionally RETURNED */ + krb5_checksum *pa_cksum, /* optional, contents mallocd and RETURNED */ krb5int_cert_sig_status *cert_status, /* optionally RETURNED */ - krb5_ui_4 *num_cms_types, /* optionally RETURNED */ - krb5int_algorithm_id **cms_types, /* optionally mallocd and RETURNED */ + krb5_ui_4 *num_cms_types, /* optionally RETURNED */ + krb5int_algorithm_id **cms_types, /* optionally mallocd and RETURNED */ /* * Cert fields, all optionally RETURNED. * * signer_cert is the full X.509 leaf cert from the incoming SignedData. * all_certs is an array of all of the certs in the incoming SignedData, - * in full X.509 form. + * in full X.509 form. */ - krb5_data *signer_cert, /* content mallocd */ - krb5_ui_4 *num_all_certs, /* sizeof *all_certs */ - krb5_data **all_certs, /* krb5_data's and their content mallocd */ - + krb5_data *signer_cert, /* content mallocd */ + krb5_ui_4 *num_all_certs, /* sizeof *all_certs */ + krb5_data **all_certs, /* krb5_data's and their content mallocd */ + /* - * Array of trustedCertifiers, optionally RETURNED. These are DER-encoded - * issuer/serial numbers. + * Array of trustedCertifiers, optionally RETURNED. These are DER-encoded + * issuer/serial numbers. */ - krb5_ui_4 *num_trusted_CAs, /* sizeof *trustedCAs */ - krb5_data **trusted_CAs, /* krb5_data's and their content mallocd */ - + krb5_ui_4 *num_trusted_CAs, /* sizeof *trustedCAs */ + krb5_data **trusted_CAs, /* krb5_data's and their content mallocd */ + /* KDC cert specified by client as kdcPkId. DER-encoded issuer/serial number. */ - krb5_data *kdc_cert); - - + krb5_data *kdc_cert); + + /* * Create a PA-PK-AS-REP message, public key (no Diffie Hellman) version. * @@ -85,26 +86,26 @@ krb5_error_code krb5int_pkinit_as_req_parse( * PA-PK-AS-REP ::= EnvelopedData(SignedData(ReplyKeyPack)) */ krb5_error_code krb5int_pkinit_as_rep_create( - krb5_context context, - const krb5_keyblock *key_block, - const krb5_checksum *checksum, /* checksum of corresponding AS-REQ */ - krb5_pkinit_signing_cert_t signer_cert, /* server's cert */ - krb5_boolean include_server_cert, /* include signer_cert in SignerInfo */ - const krb5_data *recipient_cert, /* client's cert */ - - /* - * These correspond to the same out-parameters from - * krb5int_pkinit_as_req_parse(). All are optional. + krb5_context context, + const krb5_keyblock *key_block, + const krb5_checksum *checksum, /* checksum of corresponding AS-REQ */ + krb5_pkinit_signing_cert_t signer_cert, /* server's cert */ + krb5_boolean include_server_cert, /* include signer_cert in SignerInfo */ + const krb5_data *recipient_cert, /* client's cert */ + + /* + * These correspond to the same out-parameters from + * krb5int_pkinit_as_req_parse(). All are optional. */ - krb5_ui_4 num_cms_types, - const krb5int_algorithm_id *cms_types, - krb5_ui_4 num_trusted_CAs, - krb5_data *trusted_CAs, - krb5_data *kdc_cert, - + krb5_ui_4 num_cms_types, + const krb5int_algorithm_id *cms_types, + krb5_ui_4 num_trusted_CAs, + krb5_data *trusted_CAs, + krb5_data *kdc_cert, + /* result here, mallocd and RETURNED */ - krb5_data *as_rep); - + krb5_data *as_rep); + #ifdef __cplusplus } #endif diff --git a/src/kdc/policy.c b/src/kdc/policy.c index d4a70fe..aefddff 100644 --- a/src/kdc/policy.c +++ b/src/kdc/policy.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/policy.c * @@ -7,7 +8,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -21,7 +22,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * Policy decision routines for KDC. */ @@ -59,30 +60,30 @@ int against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client, - krb5_db_entry server, krb5_timestamp kdc_time, - const char **status, krb5_data *e_data) + krb5_db_entry server, krb5_timestamp kdc_time, + const char **status, krb5_data *e_data) { - krb5_error_code code; - kdb_check_policy_as_req req; - kdb_check_policy_as_rep rep; - krb5_data req_data; - krb5_data rep_data; + krb5_error_code code; + kdb_check_policy_as_req req; + kdb_check_policy_as_rep rep; + krb5_data req_data; + krb5_data rep_data; #if 0 - /* An AS request must include the addresses field */ + /* An AS request must include the addresses field */ if (request->addresses == 0) { - *status = "NO ADDRESS"; - return KRB5KDC_ERR_POLICY; + *status = "NO ADDRESS"; + return KRB5KDC_ERR_POLICY; } #endif memset(&req, 0, sizeof(req)); memset(&rep, 0, sizeof(rep)); - req.request = request; - req.client = &client; - req.server = &server; - req.kdc_time = kdc_time; + req.request = request; + req.client = &client; + req.server = &server; + req.kdc_time = kdc_time; req_data.data = (void *)&req; req_data.length = sizeof(req); @@ -91,19 +92,19 @@ against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client, rep_data.length = sizeof(rep); code = krb5_db_invoke(kdc_context, - KRB5_KDB_METHOD_CHECK_POLICY_AS, - &req_data, - &rep_data); + KRB5_KDB_METHOD_CHECK_POLICY_AS, + &req_data, + &rep_data); if (code == KRB5_KDB_DBTYPE_NOSUP) - return 0; + return 0; *status = rep.status; *e_data = rep.e_data; if (code != 0) { - code -= ERROR_TABLE_BASE_krb5; - if (code < 0 || code > 128) - code = KRB_ERR_GENERIC; + code -= ERROR_TABLE_BASE_krb5; + if (code < 0 || code > 128) + code = KRB_ERR_GENERIC; } return code; @@ -114,33 +115,33 @@ against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client, */ krb5_error_code against_local_policy_tgs(register krb5_kdc_req *request, krb5_db_entry server, - krb5_ticket *ticket, const char **status, - krb5_data *e_data) + krb5_ticket *ticket, const char **status, + krb5_data *e_data) { - krb5_error_code code; - kdb_check_policy_tgs_req req; - kdb_check_policy_tgs_rep rep; - krb5_data req_data; - krb5_data rep_data; + krb5_error_code code; + kdb_check_policy_tgs_req req; + kdb_check_policy_tgs_rep rep; + krb5_data req_data; + krb5_data rep_data; #if 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; + *status = "FORWARD POLICY"; + return KRB5KDC_ERR_POLICY; } #endif memset(&req, 0, sizeof(req)); memset(&rep, 0, sizeof(rep)); - req.request = request; - req.server = &server; - req.ticket = ticket; + req.request = request; + req.server = &server; + req.ticket = ticket; req_data.data = (void *)&req; req_data.length = sizeof(req); @@ -149,21 +150,20 @@ against_local_policy_tgs(register krb5_kdc_req *request, krb5_db_entry server, rep_data.length = sizeof(rep); code = krb5_db_invoke(kdc_context, - KRB5_KDB_METHOD_CHECK_POLICY_TGS, - &req_data, - &rep_data); + KRB5_KDB_METHOD_CHECK_POLICY_TGS, + &req_data, + &rep_data); if (code == KRB5_KDB_DBTYPE_NOSUP) - return 0; + return 0; *status = rep.status; *e_data = rep.e_data; if (code != 0) { - code -= ERROR_TABLE_BASE_krb5; - if (code < 0 || code > 128) - code = KRB_ERR_GENERIC; + code -= ERROR_TABLE_BASE_krb5; + if (code < 0 || code > 128) + code = KRB_ERR_GENERIC; } return code; } - diff --git a/src/kdc/policy.h b/src/kdc/policy.h index fe83076..9ccf392 100644 --- a/src/kdc/policy.h +++ b/src/kdc/policy.h @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/policy.h * @@ -7,7 +8,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -21,7 +22,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * Declarations for policy.c */ @@ -34,6 +35,6 @@ extern int against_postdate_policy (krb5_timestamp); extern int against_flag_policy_as (const krb5_kdc_req *); extern int against_flag_policy_tgs (const krb5_kdc_req *, - const krb5_ticket *); + const krb5_ticket *); #endif /* __KRB5_KDC_POLICY__ */ diff --git a/src/kdc/replay.c b/src/kdc/replay.c index e6c48a4..d53936f 100644 --- a/src/kdc/replay.c +++ b/src/kdc/replay.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/replay.c * @@ -8,7 +9,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -22,7 +23,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * Replay lookaside cache for the KDC, to avoid extra work. * @@ -50,17 +51,17 @@ static int calls = 0; static int max_hits_per_entry = 0; static int num_entries = 0; -#define STALE_TIME 2*60 /* two minutes */ -#define STALE(ptr) ((abs((ptr)->timein - timenow) >= STALE_TIME) || \ - ((ptr)->db_age != db_age)) +#define STALE_TIME 2*60 /* two minutes */ +#define STALE(ptr) ((abs((ptr)->timein - timenow) >= STALE_TIME) || \ + ((ptr)->db_age != db_age)) -#define MATCH(ptr) (((ptr)->req_packet->length == inpkt->length) && \ - !memcmp((ptr)->req_packet->data, inpkt->data, \ - inpkt->length) && \ - ((ptr)->db_age == db_age)) +#define MATCH(ptr) (((ptr)->req_packet->length == inpkt->length) && \ + !memcmp((ptr)->req_packet->data, inpkt->data, \ + inpkt->length) && \ + ((ptr)->db_age == db_age)) /* XXX Todo: quench the size of the queue... - */ +*/ /* return TRUE if outpkt is filled in with a packet to reply with, FALSE if the caller should do the work */ @@ -72,9 +73,9 @@ kdc_check_lookaside(krb5_data *inpkt, krb5_data **outpkt) register krb5_kdc_replay_ent *eptr, *last, *hold; time_t db_age; - if (krb5_timeofday(kdc_context, &timenow) || - krb5_db_get_age(kdc_context, 0, &db_age)) - return FALSE; + if (krb5_timeofday(kdc_context, &timenow) || + krb5_db_get_age(kdc_context, 0, &db_age)) + return FALSE; calls++; @@ -82,34 +83,34 @@ kdc_check_lookaside(krb5_data *inpkt, krb5_data **outpkt) stale entries while we're here */ if (root_ptr.next) { - for (last = &root_ptr, eptr = root_ptr.next; - eptr; - eptr = eptr->next) { - if (MATCH(eptr)) { - eptr->num_hits++; - hits++; - - if (krb5_copy_data(kdc_context, eptr->reply_packet, outpkt)) - return FALSE; - else - return TRUE; - /* return here, don't bother flushing even if it is stale. - if we just matched, we may get another retransmit... */ - } - if (STALE(eptr)) { - /* flush it and collect stats */ - max_hits_per_entry = max(max_hits_per_entry, eptr->num_hits); - krb5_free_data(kdc_context, eptr->req_packet); - krb5_free_data(kdc_context, eptr->reply_packet); - hold = eptr; - last->next = eptr->next; - eptr = last; - free(hold); - } else { - /* this isn't it, just move along */ - last = eptr; - } - } + for (last = &root_ptr, eptr = root_ptr.next; + eptr; + eptr = eptr->next) { + if (MATCH(eptr)) { + eptr->num_hits++; + hits++; + + if (krb5_copy_data(kdc_context, eptr->reply_packet, outpkt)) + return FALSE; + else + return TRUE; + /* return here, don't bother flushing even if it is stale. + if we just matched, we may get another retransmit... */ + } + if (STALE(eptr)) { + /* flush it and collect stats */ + max_hits_per_entry = max(max_hits_per_entry, eptr->num_hits); + krb5_free_data(kdc_context, eptr->req_packet); + krb5_free_data(kdc_context, eptr->reply_packet); + hold = eptr; + last->next = eptr->next; + eptr = last; + free(hold); + } else { + /* this isn't it, just move along */ + last = eptr; + } + } } return FALSE; } @@ -120,18 +121,18 @@ kdc_check_lookaside(krb5_data *inpkt, krb5_data **outpkt) void kdc_insert_lookaside(krb5_data *inpkt, krb5_data *outpkt) { - register krb5_kdc_replay_ent *eptr; + register krb5_kdc_replay_ent *eptr; krb5_int32 timenow; time_t db_age; - if (krb5_timeofday(kdc_context, &timenow) || - krb5_db_get_age(kdc_context, 0, &db_age)) - return; + if (krb5_timeofday(kdc_context, &timenow) || + krb5_db_get_age(kdc_context, 0, &db_age)) + return; /* this is a new entry */ eptr = (krb5_kdc_replay_ent *)calloc(1, sizeof(*eptr)); if (!eptr) - return; + return; eptr->timein = timenow; eptr->db_age = db_age; /* @@ -140,13 +141,13 @@ kdc_insert_lookaside(krb5_data *inpkt, krb5_data *outpkt) * ARGH! */ if (krb5_copy_data(kdc_context, inpkt, &eptr->req_packet)) { - free(eptr); - return; + free(eptr); + return; } if (krb5_copy_data(kdc_context, outpkt, &eptr->reply_packet)) { - krb5_free_data(kdc_context, eptr->req_packet); - free(eptr); - return; + krb5_free_data(kdc_context, eptr->req_packet); + free(eptr); + return; } eptr->next = root_ptr.next; root_ptr.next = eptr; @@ -161,14 +162,14 @@ kdc_free_lookaside(krb5_context kcontext) register krb5_kdc_replay_ent *eptr, *last, *hold; if (root_ptr.next) { for (last = &root_ptr, eptr = root_ptr.next; - eptr; eptr = eptr->next) { - krb5_free_data(kcontext, eptr->req_packet); - krb5_free_data(kcontext, eptr->reply_packet); - hold = eptr; - last->next = eptr->next; - eptr = last; - free(hold); - } + eptr; eptr = eptr->next) { + krb5_free_data(kcontext, eptr->req_packet); + krb5_free_data(kcontext, eptr->reply_packet); + hold = eptr; + last->next = eptr->next; + eptr = last; + free(hold); + } } } diff --git a/src/kdc/rtest.c b/src/kdc/rtest.c index 87f4a96..4e3cd7b 100644 --- a/src/kdc/rtest.c +++ b/src/kdc/rtest.c @@ -1,3 +1,4 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * kdc/rtest.c * @@ -8,7 +9,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -22,7 +23,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * */ @@ -33,84 +34,84 @@ void krb5_klog_syslog(void); -static krb5_principal +static krb5_principal make_princ(krb5_context ctx, const char *str, const char *prog) { krb5_principal ret; char *dat; if(!(ret = (krb5_principal) malloc(sizeof(krb5_principal_data)))) { - com_err(prog, ENOMEM, "while allocating principal data"); - exit(3); + com_err(prog, ENOMEM, "while allocating principal data"); + exit(3); } memset(ret, 0, sizeof(krb5_principal_data)); /* We do not include the null... */ if(!(dat = (char *) malloc(strlen(str)))) { - com_err(prog, ENOMEM, "while allocating principal realm data"); - exit(3); + com_err(prog, ENOMEM, "while allocating principal realm data"); + exit(3); } memcpy(dat, str, strlen(str)); krb5_princ_set_realm_data(ctx, ret, dat); krb5_princ_set_realm_length(ctx, ret, strlen(str)); - + return ret; } int main(int argc, char **argv) { - krb5_data otrans; - krb5_data ntrans; - krb5_principal tgs, cl, sv; - krb5_error_code kret; - kdc_realm_t kdc_realm; - - if (argc < 4) { - fprintf(stderr, "not enough args\n"); - exit(1); - } - - - /* Get a context */ - kret = krb5int_init_context_kdc(&kdc_realm.realm_context); - if (kret) { - com_err(argv[0], kret, "while getting krb5 context"); - exit(2); - } - /* Needed so kdc_context will work */ - kdc_active_realm = &kdc_realm; - - ntrans.length = 0; - ntrans.data = 0; - - otrans.length = strlen(argv[1]); - if (otrans.length) - otrans.data = (char *) malloc(otrans.length); - else - otrans.data = 0; - memcpy(otrans.data,argv[1], otrans.length); - - tgs = make_princ(kdc_context, argv[2], argv[0]); - cl = make_princ(kdc_context, argv[3], argv[0]); - sv = make_princ(kdc_context, argv[4], argv[0]); - - add_to_transited(&otrans,&ntrans,tgs,cl,sv); - - printf("%s\n",ntrans.data); - - /* Free up all memory so we can profile for leaks */ - if (otrans.data) - free(otrans.data); - free(ntrans.data); - - krb5_free_principal(kdc_realm.realm_context, tgs); - krb5_free_principal(kdc_realm.realm_context, cl); - krb5_free_principal(kdc_realm.realm_context, sv); - krb5_free_context(kdc_realm.realm_context); - - exit(0); + krb5_data otrans; + krb5_data ntrans; + krb5_principal tgs, cl, sv; + krb5_error_code kret; + kdc_realm_t kdc_realm; + + if (argc < 4) { + fprintf(stderr, "not enough args\n"); + exit(1); + } + + + /* Get a context */ + kret = krb5int_init_context_kdc(&kdc_realm.realm_context); + if (kret) { + com_err(argv[0], kret, "while getting krb5 context"); + exit(2); } + /* Needed so kdc_context will work */ + kdc_active_realm = &kdc_realm; + + ntrans.length = 0; + ntrans.data = 0; + + otrans.length = strlen(argv[1]); + if (otrans.length) + otrans.data = (char *) malloc(otrans.length); + else + otrans.data = 0; + memcpy(otrans.data,argv[1], otrans.length); + + tgs = make_princ(kdc_context, argv[2], argv[0]); + cl = make_princ(kdc_context, argv[3], argv[0]); + sv = make_princ(kdc_context, argv[4], argv[0]); + + add_to_transited(&otrans,&ntrans,tgs,cl,sv); + + printf("%s\n",ntrans.data); + + /* Free up all memory so we can profile for leaks */ + if (otrans.data) + free(otrans.data); + free(ntrans.data); + + krb5_free_principal(kdc_realm.realm_context, tgs); + krb5_free_principal(kdc_realm.realm_context, cl); + krb5_free_principal(kdc_realm.realm_context, sv); + krb5_free_context(kdc_realm.realm_context); + + exit(0); +} void krb5_klog_syslog(void) {} kdc_realm_t *find_realm_data (char *rname, krb5_ui_4 rsize) { return 0; } |