## freeradius-krb5.patch # This patch makes the freeradius krb5 module useful to us. # In particular... # - It does validation of the tickets it obtains # - It provides a 'keytab' option to set the keytab location # - It provides a 'service' option to set the service principal name # - It actually links against -lkrb5, so it can be useful # # -- Jeffrey Hutzelman, jhutz+@cmu.edu, 15-Jan-2002 diff -ru X/freeradius-0.3/src/modules/rlm_krb5/configure.in freeradius-0.3/src/modules/rlm_krb5/configure.in --- X/freeradius-0.3/src/modules/rlm_krb5/configure.in Sat Jul 28 13:59:39 2001 +++ freeradius-0.3/src/modules/rlm_krb5/configure.in Tue Nov 27 17:18:04 2001 @@ -63,7 +63,7 @@ AC_CHECK_LIB(krb5, krb5_init_context, [ - krb5_ldflags="${krblibcrypto} ${krb5libcomerr}" + krb5_ldflags="-lkrb5 ${krb5libcrypto} ${krb5libcomerr}" krb5_cflags="" #fixme? ], [ fail=$fail" krb5" ], diff -ru X/freeradius-0.3/src/modules/rlm_krb5/rlm_krb5.c freeradius-0.3/src/modules/rlm_krb5/rlm_krb5.c --- X/freeradius-0.3/src/modules/rlm_krb5/rlm_krb5.c Tue Feb 20 15:51:33 2001 +++ freeradius-0.3/src/modules/rlm_krb5/rlm_krb5.c Thu Nov 29 13:42:22 2001 @@ -39,29 +39,52 @@ #include #include +typedef struct rlm_krb5_t { + krb5_context context; + char *keytab; + char *service; +} rlm_krb5_t; + +static CONF_PARSER module_config[] = { + { "keytab", PW_TYPE_STRING_PTR, offsetof(rlm_krb5_t,keytab), NULL, NULL }, + { "service", PW_TYPE_STRING_PTR, offsetof(rlm_krb5_t,service), NULL, "radius" }, + { NULL, -1, 0, NULL, NULL } +}; + /* instantiate */ static int krb5_instantiate(CONF_SECTION *conf, void **instance) { int r; - krb5_context *context; + rlm_krb5_t *data; + + data = rad_malloc(sizeof(*data)); - context = rad_malloc(sizeof(*context)); + if (cf_section_parse(conf, data, module_config) < 0) { + free(data); + return -1; + } - if ((r = krb5_init_context(context)) ) { + if ((r = krb5_init_context(&data->context)) ) { radlog(L_AUTH, "rlm_krb5: krb5_init failed: %s", error_message(r)); + if (data->keytab) free(data->keytab); + if (data->service) free(data->service); return -1; } else { radlog(L_AUTH, "rlm_krb5: krb5_init ok"); } - *instance = context; + *instance = data; return 0; } /* detach */ static int krb5_detach(void *instance) { + rlm_krb5_t *data = (rlm_krb5_t *)instance; + krb5_free_context(data->context); + if (data->keytab) free(data->keytab); + if (data->service) free(data->service); free(instance); return 0; } @@ -69,15 +92,13 @@ /* validate userid/passwd */ static int krb5_auth(void *instance, REQUEST *request) { - int r; - krb5_data tgtname = { - 0, - KRB5_TGS_NAME_SIZE, - KRB5_TGS_NAME - }; - krb5_creds kcreds; - krb5_context context = *(krb5_context *) instance; /* copy data */ - const char *user, *pass; + rlm_krb5_t *data = (rlm_krb5_t *)instance; + krb5_verify_opt opt; + krb5_error_code ret; + krb5_principal userP; + krb5_keytab kt = NULL; + const char *user; + char *name; /* * We can only authenticate user requests which HAVE @@ -87,6 +108,7 @@ radlog(L_AUTH, "rlm_krb5: Attribute \"User-Name\" is required for authentication."); return RLM_MODULE_INVALID; } + user = request->username->strvalue; /* * We can only authenticate user requests which HAVE @@ -107,45 +129,53 @@ } /* - * shortcuts + * Open the keytab */ - user = request->username->strvalue; - pass = request->password->strvalue; + if (data->keytab) { + if ((ret = krb5_kt_resolve(data->context, data->keytab, &kt))) { + radlog(L_AUTH, "rlm_krb5: [%s] krb5_kt_resolve failed: %s", + user, error_message(ret)); + return RLM_MODULE_REJECT; + } + } /* * Actually perform the authentication */ - memset((char *)&kcreds, 0, sizeof(kcreds)); + + krb5_verify_opt_init(&opt); + krb5_verify_opt_set_keytab(&opt, kt); + krb5_verify_opt_set_secure(&opt, 1); + krb5_verify_opt_set_service(&opt, data->service); - if ( (r = krb5_parse_name(context, user, &kcreds.client)) ) { + if ((ret = krb5_parse_name(data->context, request->username->strvalue, &userP))) { radlog(L_AUTH, "rlm_krb5: [%s] krb5_parse_name failed: %s", - user, error_message(r)); + user, error_message(ret)); + if (kt) krb5_kt_close(data->context, kt); return RLM_MODULE_REJECT; } - if ( (r = krb5_build_principal_ext(context, &kcreds.server, - krb5_princ_realm(context, kcreds.client)->length, - krb5_princ_realm(context, kcreds.client)->data, - tgtname.length, - tgtname.data, - krb5_princ_realm(context, kcreds.client)->length, - krb5_princ_realm(context, kcreds.client)->data, - 0)) ) { - radlog(L_AUTH, "rlm_krb5: [%s] krb5_build_principal_ext failed: %s", - user, error_message(r)); + if ((ret = krb5_unparse_name(data->context, userP, &name))) { + radlog(L_AUTH, "rlm_krb5: [%s] krb5_unparse_name failed: %s", + user, error_message(ret)); + if (kt) krb5_kt_close(data->context, kt); return RLM_MODULE_REJECT; } - if ( (r = krb5_get_in_tkt_with_password(context, - 0, NULL, NULL, NULL, pass, 0, &kcreds, 0)) ) { - radlog(L_AUTH, "rlm_krb5: [%s] krb5_g_i_t_w_p failed: %s", - user, error_message(r)); - return RLM_MODULE_REJECT; - } else { + radlog(L_AUTH, "rlm_krb5: Parsed name is: %s\n", name); + + ret = krb5_verify_user_opt(data->context, userP, request->password->strvalue, &opt); + if (kt) krb5_kt_close(data->context, kt); + + if (ret == 0) { + free(name); return RLM_MODULE_OK; } + + radlog(L_AUTH, "rlm_krb5: failed verify_user: %s (%s)", error_message(ret), name); - return RLM_MODULE_REJECT; + free(name); + return RLM_MODULE_REJECT; } module_t rlm_krb5 = {