INN commit: branches/2.5 (TODO authprogs/auth_krb5.c)
INN Commit
rra at isc.org
Thu Aug 20 23:33:13 UTC 2009
Date: Thursday, August 20, 2009 @ 16:33:13
Author: eagle
Revision: 8588
Rewrite auth_krb5 to use modern Kerberos APIs
Use krb5_get_init_creds_password and the current APIs and remove a bunch
of cruft that's unnecessary and uninteresting. The library defaults will
take care of things like building the correct service principal.
Add a call to krb5_verify_init_creds, although this will only work if
nnrpd is pointed to a keytab that it can read or if it's run as root.
Looking in a different keytab for a local key with which to validate the
credentials is left as future work and requires additional configuration
to point to the correct keytab.
Modified:
branches/2.5/TODO
branches/2.5/authprogs/auth_krb5.c
-----------------------+
TODO | 4 -
authprogs/auth_krb5.c | 185 ++++++++++++++----------------------------------
2 files changed, 56 insertions(+), 133 deletions(-)
Modified: TODO
===================================================================
--- TODO 2009-08-20 23:31:59 UTC (rev 8587)
+++ TODO 2009-08-20 23:33:13 UTC (rev 8588)
@@ -365,10 +365,6 @@
Setting cnfscheckfudgesize clears up issues that otherwises causes INN
to crash.
-* The way Kerberos authentication is done uses an obsolete interface and
- doesn't verify the user's authentication by getting a service ticket.
- It needs to be overhauled to use the right API.
-
* There should be a way, with the Perl authentication hooks, to either
immediately return a list of newsgroups one has access to based on the
hostname or to indicate that authentication is required and make the
Modified: authprogs/auth_krb5.c
===================================================================
--- authprogs/auth_krb5.c 2009-08-20 23:31:59 UTC (rev 8587)
+++ authprogs/auth_krb5.c 2009-08-20 23:33:13 UTC (rev 8588)
@@ -27,149 +27,76 @@
# include <com_err.h>
#endif
-/* krb5_get_in_tkt_with_password is deprecated. */
-#define KRB5_DEPRECATED 1
#include <krb5.h>
#include "inn/messages.h"
#include "inn/libinn.h"
/*
- * Default life of the ticket we are getting. Since we are just checking
- * to see if the user can get one, it doesn't need a long lifetime.
- */
-#define KRB5_DEFAULT_LIFE 60 * 5 /* 5 minutes */
-
-
-/*
** Check the username and password by attempting to get a TGT. Returns 1 on
** success and 0 on failure. Errors are reported via com_err.
*/
static int
-krb5_check_password (char *principal_name, char *password)
+krb5_check_password(const char *principal, const char *password)
{
- krb5_context kcontext;
- krb5_creds creds;
- krb5_principal user_principal;
- krb5_data *user_realm;
- krb5_principal service_principal;
- krb5_timestamp now;
- krb5_address **addrs = (krb5_address **) NULL; /* Use default */
- long lifetime = KRB5_DEFAULT_LIFE;
- int options = 0;
+ krb5_error_code code;
+ krb5_context ctx;
+ krb5_creds creds;
+ krb5_principal princ = NULL;
+ krb5_get_init_creds_opt opts;
+ bool creds_valid = false;
+ int result = 0;
- krb5_preauthtype *preauth = NULL;
+ code = krb5_init_context(&ctx);
+ if (code != 0) {
+ com_err(message_program_name, code, "initializing krb5 context");
+ return 0;
+ }
+ code = krb5_parse_name(ctx, principal, &princ);
+ if (code != 0) {
+ com_err(message_program_name, code, "parsing principal name %.100s",
+ principal);
+ goto cleanup;
+ }
+ memset(&opts, 0, sizeof(opts));
+ krb5_get_init_creds_opt_init(&opts);
+ krb5_get_init_creds_opt_set_forwardable(&opts, 0);
+ krb5_get_init_creds_opt_set_proxiable(&opts, 0);
+ code = krb5_get_init_creds_password(ctx, &creds, princ, (char *) password,
+ NULL, NULL, 0, NULL, &opts);
+ if (code == 0) {
+ krb5_verify_init_creds_opt vopts;
- krb5_error_code code;
-
- /* Our return code - 1 is success */
- int result = 0;
+ creds_valid = true;
+ memset(&opts, 0, sizeof(vopts));
+ krb5_verify_init_creds_opt_init(&vopts);
+ code = krb5_verify_init_creds(ctx, &creds, princ, NULL, NULL, &vopts);
+ }
+ if (code == 0)
+ result = 1;
+ else {
+ switch (code) {
+ case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+ com_err(message_program_name, 0, "bad password for %.100s",
+ principal);
+ break;
+ case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
+ com_err(message_program_name, 0, "unknown user %.100s",
+ principal);
+ break;
+ default:
+ com_err(message_program_name, code,
+ "checking Kerberos password for %.100s", principal);
+ }
+ }
- /* Initialize our Kerberos state */
- code = krb5_init_context (&kcontext);
- if (code) {
- com_err (message_program_name, code, "initializing krb5 context");
- return 0;
- }
-
-#ifdef HAVE_KRB5_INIT_ETS
- /* Initialize krb5 error tables */
- krb5_init_ets (kcontext);
-#endif
-
- /* Get current time */
- code = krb5_timeofday (kcontext, &now);
- if (code) {
- com_err (message_program_name, code, "getting time of day");
- return 0;
- }
-
- /* Set up credentials to be filled in */
- memset (&creds, 0, sizeof(creds));
-
- /* From here on, goto cleanup to exit */
-
- /* Parse the username into a krb5 principal */
- if (!principal_name) {
- com_err (message_program_name, 0, "passed NULL principal name");
- goto cleanup;
- }
-
- code = krb5_parse_name (kcontext, principal_name, &user_principal);
- if (code) {
- com_err (message_program_name, code,
- "parsing user principal name %.100s", principal_name);
- goto cleanup;
- }
-
- creds.client = user_principal;
-
- /* Get the user's realm for building service principal */
- user_realm = krb5_princ_realm (kcontext, user_principal);
-
- /*
- * Build the service name into a principal. Right now this is
- * a TGT for the user's realm.
- */
- code = krb5_build_principal_ext (kcontext,
- &service_principal,
- user_realm->length,
- user_realm->data,
- KRB5_TGS_NAME_SIZE,
- KRB5_TGS_NAME,
- user_realm->length,
- user_realm->data,
- 0 /* terminator */);
- if (code) {
- com_err(message_program_name, code, "building service principal name");
- goto cleanup;
- }
-
- creds.server = service_principal;
-
- creds.times.starttime = 0; /* Now */
- creds.times.endtime = now + lifetime;
- creds.times.renew_till = 0; /* Unrenewable */
-
- /* DO IT */
- code = krb5_get_in_tkt_with_password (kcontext,
- options,
- addrs,
- NULL,
- preauth,
- password,
- 0,
- &creds,
- 0);
-
- /* We are done with password at this point... */
-
- if (code) {
- /* FAILURE - Parse a few common errors here */
- switch (code) {
- case KRB5KRB_AP_ERR_BAD_INTEGRITY:
- com_err (message_program_name, 0, "bad password for %.100s",
- principal_name);
- break;
- case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
- com_err (message_program_name, 0, "unknown user \"%.100s\"",
- principal_name);
- break;
- default:
- com_err (message_program_name, code,
- "checking Kerberos password for %.100s", principal_name);
- }
- result = 0;
- } else {
- /* SUCCESS */
- result = 1;
- }
-
- /* Cleanup */
- cleanup:
- krb5_free_cred_contents (kcontext, &creds);
-
- return result;
+cleanup:
+ if (creds_valid)
+ krb5_free_cred_contents(ctx, &creds);
+ if (princ != NULL)
+ krb5_free_principal(ctx, princ);
+ krb5_free_context(ctx);
+ return result;
}
int
More information about the inn-committers
mailing list