#include "ksu.h"
void plain_dump_principal(krb5_context, krb5_principal);
krb5_boolean
krb5_auth_check(krb5_context context, krb5_principal client_pname,
char *hostname, krb5_get_init_creds_opt *options,
char *target_user, krb5_ccache cc, int *path_passwd,
uid_t target_uid)
{
krb5_principal client = NULL;
krb5_verify_init_creds_opt vfy_opts;
krb5_creds tgt = { 0 }, tgtq = { 0 };
krb5_error_code retval =0;
int got_it = 0;
krb5_boolean zero_password;
krb5_boolean ok = FALSE;
*path_passwd = 0;
if ((retval= krb5_copy_principal(context, client_pname, &client))){
com_err(prog_name, retval, _("while copying client principal"));
goto cleanup;
}
if ((retval= krb5_copy_principal(context, client, &tgtq.client))){
com_err(prog_name, retval, _("while copying client principal"));
goto cleanup;
}
if ((retval = ksu_tgtname(context, krb5_princ_realm(context, client),
krb5_princ_realm(context, client),
&tgtq.server))){
com_err(prog_name, retval, _("while creating tgt for local realm"));
goto cleanup;
}
if (auth_debug){ dump_principal(context, "local tgt principal name", tgtq.server ); }
retval = krb5_cc_retrieve_cred(context, cc,
KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES,
&tgtq, &tgt);
if (! retval) retval = krb5_check_exp(context, tgt.times);
if (retval){
if ((retval != KRB5_CC_NOTFOUND) &&
(retval != KRB5KRB_AP_ERR_TKT_EXPIRED)){
com_err(prog_name, retval, _("while retrieving creds from cache"));
goto cleanup;
}
} else{
got_it = 1;
}
if (! got_it){
#ifdef GET_TGT_VIA_PASSWD
if (krb5_seteuid(0)||krb5_seteuid(target_uid)) {
com_err("ksu", errno, _("while switching to target uid"));
goto cleanup;
}
fprintf(stderr, _("WARNING: Your password may be exposed if you enter "
"it here and are logged \n"));
fprintf(stderr, _(" in remotely using an unsecure "
"(non-encrypted) channel. \n"));
if (ksu_get_tgt_via_passwd(context, client, options, &zero_password,
&tgt) == FALSE) {
krb5_seteuid(0);
goto cleanup;
}
*path_passwd = 1;
if (krb5_seteuid(0)) {
com_err("ksu", errno, _("while reclaiming root uid"));
goto cleanup;
}
#else
plain_dump_principal (context, client);
fprintf(stderr,
_("does not have any appropriate tickets in the cache.\n"));
goto cleanup;
#endif
}
krb5_verify_init_creds_opt_init(&vfy_opts);
krb5_verify_init_creds_opt_set_ap_req_nofail( &vfy_opts, 1);
retval = krb5_verify_init_creds(context, &tgt, NULL, NULL, NULL,
&vfy_opts);
if (retval) {
com_err(prog_name, retval, _("while verifying ticket for server"));
goto cleanup;
}
ok = TRUE;
cleanup:
krb5_free_principal(context, client);
krb5_free_cred_contents(context, &tgt);
krb5_free_cred_contents(context, &tgtq);
return ok;
}
krb5_boolean
ksu_get_tgt_via_passwd(krb5_context context, krb5_principal client,
krb5_get_init_creds_opt *options,
krb5_boolean *zero_password, krb5_creds *creds_out)
{
krb5_boolean ok = FALSE;
krb5_error_code code;
krb5_creds creds = { 0 };
krb5_timestamp now;
unsigned int pwsize;
char password[255], prompt[255], *client_name = NULL;
int result;
*zero_password = FALSE;
if (creds_out != NULL)
memset(creds_out, 0, sizeof(*creds_out));
if ((code = krb5_unparse_name(context, client, &client_name))) {
com_err (prog_name, code, _("when unparsing name"));
goto cleanup;
}
memset(&creds, 0, sizeof(creds));
if ((code = krb5_timeofday(context, &now))) {
com_err(prog_name, code, _("while getting time of day"));
goto cleanup;
}
result = snprintf(prompt, sizeof(prompt), _("Kerberos password for %s: "),
client_name);
if (SNPRINTF_OVERFLOW(result, sizeof(prompt))) {
fprintf(stderr,
_("principal name %s too long for internal buffer space\n"),
client_name);
goto cleanup;
}
pwsize = sizeof(password);
code = krb5_read_password(context, prompt, 0, password, &pwsize);
if (code ) {
com_err(prog_name, code, _("while reading password for '%s'\n"),
client_name);
goto cleanup;
}
if ( pwsize == 0) {
fprintf(stderr, _("No password given\n"));
*zero_password = TRUE;
goto cleanup;
}
code = krb5_get_init_creds_password(context, &creds, client, password,
krb5_prompter_posix, NULL, 0, NULL,
options);
zap(password, sizeof(password));
if (code) {
if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
fprintf(stderr, _("%s: Password incorrect\n"), prog_name);
else
com_err(prog_name, code, _("while getting initial credentials"));
goto cleanup;
}
if (creds_out != NULL) {
*creds_out = creds;
memset(&creds, 0, sizeof(creds));
}
ok = TRUE;
cleanup:
krb5_free_cred_contents(context, &creds);
free(client_name);
return ok;
}
void
dump_principal(krb5_context context, char *str, krb5_principal p)
{
char * stname;
krb5_error_code retval;
if ((retval = krb5_unparse_name(context, p, &stname))) {
fprintf(stderr, _(" %s while unparsing name\n"),
error_message(retval));
return;
}
fprintf(stderr, " %s: %s\n", str, stname);
free(stname);
}
void
plain_dump_principal (krb5_context context, krb5_principal p)
{
char * stname;
krb5_error_code retval;
if ((retval = krb5_unparse_name(context, p, &stname))) {
fprintf(stderr, _(" %s while unparsing name\n"),
error_message(retval));
return;
}
fprintf(stderr, "%s ", stname);
free(stname);
}