Authen-Krb5Password

 view release on metacpan or  search on metacpan

Krb5Password.pm  view on Meta::CPAN


=head1 DESCRIPTION

This module provides a Perl function to perform password verification
using Kerberos 5. It is intended for use by applications that cannot
use the Kerberos protocol directly. If it must be run on a system that 
receives a username and password over the network, steps should be 
taken to ensure that these are passed to the server in a cryptographically
secure manner.

kpass() attempts to obtain credentials for the given username and password
from the Kerberos AS, then obtain credentials for a local service from the
Kerberos TGS to verify the authenticity of the AS response. Empty strings 
can be passed as the 3rd and/or 4th arguments to use the default service 
name ("host") and the fully canonicalized primary hostname of the system 
that the function is executed on. The fifth argument may be omitted to use 
the system's default keytab file.

kpass() returns -1 if an error occurs, 0 if the username or password is
incorrect, or 1 if password verification is successful. Errors and
authentication failures are recorded via syslog(3). Because of deficiencies
in Perl's syslog implementation in Sys::Syslog(3), there's no clean way

kpass.c  view on Meta::CPAN

	if (err) { \
	    void (*proc)(const char *, long, const char *, va_list); \
	    proc = set_com_err_hook(syslog_err); \
	    com_err("kpass", (err), (tag)); \
	    (void)set_com_err_hook(proc); \
	    goto cleanup; \
	}

/*
 * Kerberos password verification. Attempt to obtain short term 
 * credentials for a given username and password from Kerberos AS, 
 * then obtain credentials for a local service from Kerberos TGS 
 * to verify the authenticity of the AS response.
 *
 * Arguments:
 *	username, password	The username and password to verify.
 *	service, host		A local service whose key will be used to
 *                              verify the authenticity of the Kerberos 
 *                              credentials. Specifying host as NULL
 *                              says use my primary hostname.
 *	kt_pathname		Path of keytab file, or NULL to use default.
 *                              (Typical form "FILE:/abs/path/name".)
 *
 * Return -1 if an error occurs, 0 if the username or password is incorrect,
 * or 1 if password verification is successful.
 */

int kpass(username, password, service, host, kt_pathname)
     char *username;
     char *password;
     char *service;
     char *host;
     char *kt_pathname;
{
    krb5_error_code               err;
    krb5_context                  context;
    krb5_auth_context             auth_context = NULL;
    krb5_creds                    credentials;
    krb5_principal                user_principal,
	                          service_principal;
    krb5_keytab                   keytab = NULL;
    krb5_ccache                   ccache;
    char                          ccache_name[L_tmpnam + 8];
    krb5_get_init_creds_opt       gic_options;
#ifndef NO_REPLAYCACHE
    krb5_verify_init_creds_opt    vic_options;
#endif
    krb5_data                     apreq_pkt;
    char                          myhostname[256], sprinc[256];

    int                           have_user_principal = 0,
	                          have_service_principal = 0,
	                          have_keytab = 0,
                                  have_credentials = 0,
                                  success = -1;

    apreq_pkt.data = NULL;

    err = krb5_init_context(&context);
    FAIL(err, "from krb5_init_context");

#ifdef NEED_INIT_ETS
    krb5_init_ets(context);
#endif

kpass.c  view on Meta::CPAN

        host = NULL;
#endif /* CALL_FROM_PERL */

    err = krb5_parse_name(context, username, &user_principal);
    FAIL(err, "from krb_parse_name");
    have_user_principal = 1;

    err = krb5_cc_initialize(context, ccache, user_principal);
    FAIL(err, "from krb_cc_initialize");

    (void) memset( (char *)&credentials, 0, sizeof(credentials) );
    if (!host) {
        (void) gethostname(myhostname, sizeof(myhostname));
        snprintf(sprinc, sizeof(sprinc), "%s/%s", service, myhostname);
    } else
        snprintf(sprinc, sizeof(sprinc), "%s/%s", service, host);

    krb5_get_init_creds_opt_init(&gic_options);
    krb5_get_init_creds_opt_set_tkt_life(&gic_options, TKT_LIFETIME);

    err = krb5_get_init_creds_password(context, &credentials,
                                       user_principal, password,
                                       0, 0, 0, sprinc, &gic_options);


    switch (err) {
    case 0:
	/* Success. */
	have_credentials = 1;
	break;
    case KRB5KDC_ERR_PREAUTH_FAILED:
    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
	/* Bad username or password, unknown user etc */
	success = 0;
	/* fall through */
    default:
	/* Some other sort of failure. */
	FAIL(err, "from krb5_get_init_creds_password");
	break;
    }

    err = krb5_cc_store_cred(context, ccache, &credentials);
    FAIL(err, "from krb5_cc_store_cred");

    err = krb5_sname_to_principal(context, host, service,
				  KRB5_NT_SRV_HST, &service_principal);
    FAIL(err, "from krb5_sname_to_principal");
    have_service_principal = 1;

    if (kt_pathname && *kt_pathname) {
	err = krb5_kt_resolve(context, kt_pathname, &keytab);
	FAIL(err, "from krb5_kt_resolve");
	have_keytab = 1;
    }

#ifndef NO_REPLAYCACHE

    krb5_verify_init_creds_opt_init(&vic_options);
    krb5_verify_init_creds_opt_set_ap_req_nofail(&vic_options, 1);
    err = krb5_verify_init_creds(context, &credentials, service_principal,
                                 keytab, 0, &vic_options);
    FAIL(err, "from krb5_verify_init_creds");

#else

    err = krb5_mk_req(context, &auth_context, 0, service, host,
		      NULL, ccache, &apreq_pkt);
    FAIL(err, "from krb5_mk_req");

    if (auth_context) {

kpass.c  view on Meta::CPAN

    if (have_keytab)
	if (err = krb5_kt_close(context, keytab))
	    com_err("kpass", err, "from krb5_kt_close");

    if (have_user_principal)
        krb5_free_principal(context, user_principal);

    if (have_service_principal)
	krb5_free_principal(context, service_principal);

    if (have_credentials)
	krb5_free_cred_contents(context, &credentials);

    if (context)
        krb5_free_context(context);

    return success;
}



( run in 0.241 second using v1.01-cache-2.11-cpan-4d50c553e7e )