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
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
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) {
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 )