Skip to content

Commit

Permalink
Improve Kerberos support when using Heimdal
Browse files Browse the repository at this point in the history
- Allow specifying a keytab location
- Improved logging

Patch obtained from Thomas Kula <kula@tproa.net>

- Fix krb_auth parameters/casting
- Use strlcpy() instead of strncpy()
- Fix style issues
  • Loading branch information
zi0r authored and arr2036 committed Oct 23, 2012
1 parent f541672 commit 63de016
Showing 1 changed file with 90 additions and 21 deletions.
111 changes: 90 additions & 21 deletions src/modules/rlm_krb5/rlm_krb5.c
Expand Up @@ -32,6 +32,9 @@ RCSID("$Id$")
#include <krb5.h>
#include <com_err.h>

/* Arbitrary 64char limit on service names */
#define SERVICE_NAME_LEN 64;

typedef struct rlm_krb5_t {
const char *keytab;
const char *service_princ;
Expand Down Expand Up @@ -86,9 +89,7 @@ static int verify_krb5_tgt(krb5_context context, rlm_krb5_t *instance,
krb5_data packet, *server;
krb5_auth_context auth_context = NULL;
krb5_keytab keytab;
/* arbitrary 64-byte limit on service names; I've never seen a
service name this long, and hope never to. -srl */
char service[64] = "host";
char service[SERVICE_NAME_LEN] = "host";
char *servername = NULL;

if (instance->service_princ != NULL) {
Expand Down Expand Up @@ -254,8 +255,9 @@ static int krb5_detach(void *instance)
#ifndef HEIMDAL_KRB5
static int krb5_auth(void *instance, REQUEST *request)
{
rlm_krb5_t *inst = instance;
int r;

krb5_data tgtname = {
0,
KRB5_TGS_NAME_SIZE,
Expand All @@ -265,7 +267,7 @@ static int krb5_auth(void *instance, REQUEST *request)
krb5_ccache ccache;
char cache_name[L_tmpnam + 8];

krb5_context context = *((rlm_krb5_t *)instance)->context; /* copy data */
krb5_context context = *(inst->context); /* copy data */
const char *user, *pass;

/*
Expand Down Expand Up @@ -355,7 +357,7 @@ static int krb5_auth(void *instance, REQUEST *request)
return RLM_MODULE_REJECT;
} else {
/* Now verify the KDC's identity. */
r = verify_krb5_tgt(context, (rlm_krb5_t *)instance, user, ccache);
r = verify_krb5_tgt(context, inst, user, ccache);
krb5_free_cred_contents(context, &kcreds);
krb5_cc_destroy(context, ccache);
return r;
Expand All @@ -369,14 +371,35 @@ static int krb5_auth(void *instance, REQUEST *request)
/* validate user/pass, heimdal krb5 way */
static int krb5_auth(void *instance, REQUEST *request)
{
rlm_krb5_t *inst = instance;
int r;
krb5_error_code ret;
krb5_ccache id;
krb5_principal userP;

krb5_context context = *((rlm_krb5_t *)instance)->context; /* copy data */
krb5_context context = *(inst->context); /* copy data */
const char *user, *pass;

char service[SERVICE_NAME_LEN] = "host";
char *servername = NULL;
char *princ_name;

krb5_verify_opt krb_verify_options;
krb5_keytab keytab;

if (inst->service_princ != NULL) {
servername = strchr(inst->service_princ, '/');
if (servername != NULL) {
*servername = '\0';
}

strlcpy(service, inst->service_princ, sizeof(service));
if (servername != NULL) {
*servername = '/';
servername++;
}
}

/*
* We can only authenticate user requests which HAVE
* a User-Name attribute.
Expand Down Expand Up @@ -419,26 +442,72 @@ static int krb5_auth(void *instance, REQUEST *request)
/*
* Heimdal krb5 verification
*/
radlog(L_AUTH, "rlm_krb5: Parsed name is: %s@%s\n",
*userP->name.name_string.val,
userP->realm);


/*
* The following bit allows us to also log user/instance@REALM if someone
* logs in using an instance
*/
ret = krb5_unparse_name(context, userP, &princ_name);
if (ret != 0) {
radlog(L_AUTH, "rlm_krb5: Unparsable name");
} else {
radlog(L_AUTH, "rlm_krb5: Parsed name is: %s", princ_name);
free(princ_name);
}

krb5_cc_default(context, &id);

ret = krb5_verify_user(context,
userP,
id,
pass, 1, "radius");
/* Set up krb5_verify_user options */
krb5_verify_opt_init(&krb_verify_options);

krb5_verify_opt_set_ccache(&krb_verify_options, id);

/*
* Resolve keytab name. This allows us to use something other than
* the default system keytab
*/
if (inst->keytab != NULL) {
ret = krb5_kt_resolve(context, inst->keytab, &keytab);

if (ret) {
radlog(L_AUTH, "rlm_krb: unable to resolve keytab %s: %s",
inst->keytab, error_message(ret));
krb5_kt_close(context, keytab);
return RLM_MODULE_REJECT;
}
krb5_verify_opt_set_keytab(&krb_verify_options, keytab);
}

/*
* Verify aquired credentials against the keytab
*/
krb5_verify_opt_set_secure(&krb_verify_options, 1);

/*
* Allow us to use an arbitrary service name
*/
krb5_verify_opt_set_service(&krb_verify_options, service);

if (ret == 0)
return RLM_MODULE_OK;
/*
* Verify the user, using the above set options
*/
ret = krb5_verify_user_opt(context, userP, pass, &krb_verify_options);

radlog(L_AUTH, "rlm_krb5: failed verify_user: %s (%s@%s )",
error_message(ret),
*userP->name.name_string.val,
userP->realm);
/*
* We are done with the keytab, close it
*/
krb5_kt_close(context, keytab);

return RLM_MODULE_REJECT;
if (ret == 0)
return RLM_MODULE_OK;

radlog(L_AUTH, "rlm_krb5: failed verify_user: %s (%s@%s)",
error_message(ret),
*userP->name.name_string.val,
userP->realm);

return RLM_MODULE_REJECT;
}

#endif /* HEIMDAL_KRB5 */
Expand Down

0 comments on commit 63de016

Please sign in to comment.