|
Packit |
fd8b60 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Copyright (c) 1994 by the University of Southern California
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* EXPORT OF THIS SOFTWARE from the United States of America may
|
|
Packit |
fd8b60 |
* require a specific license from the United States Government.
|
|
Packit |
fd8b60 |
* It is the responsibility of any person or organization contemplating
|
|
Packit |
fd8b60 |
* export to obtain such a license before exporting.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute
|
|
Packit |
fd8b60 |
* this software and its documentation in source and binary forms is
|
|
Packit |
fd8b60 |
* hereby granted, provided that any documentation or other materials
|
|
Packit |
fd8b60 |
* related to such distribution or use acknowledge that the software
|
|
Packit |
fd8b60 |
* was developed by the University of Southern California.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The
|
|
Packit |
fd8b60 |
* University of Southern California MAKES NO REPRESENTATIONS OR
|
|
Packit |
fd8b60 |
* WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
|
|
Packit |
fd8b60 |
* limitation, the University of Southern California MAKES NO
|
|
Packit |
fd8b60 |
* REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
|
|
Packit |
fd8b60 |
* PARTICULAR PURPOSE. The University of Southern
|
|
Packit |
fd8b60 |
* California shall not be held liable for any liability nor for any
|
|
Packit |
fd8b60 |
* direct, indirect, or consequential damages with respect to any
|
|
Packit |
fd8b60 |
* claim by the user or distributor of the ksu software.
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* KSU was writen by: Ari Medvinsky, ari@isi.edu
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#include "ksu.h"
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
void plain_dump_principal ();
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_boolean krb5_auth_check(context, client_pname, hostname, options,
|
|
Packit |
fd8b60 |
target_user, cc, path_passwd, target_uid)
|
|
Packit |
fd8b60 |
krb5_context context;
|
|
Packit |
fd8b60 |
krb5_principal client_pname;
|
|
Packit |
fd8b60 |
char *hostname;
|
|
Packit |
fd8b60 |
krb5_get_init_creds_opt *options;
|
|
Packit |
fd8b60 |
char *target_user;
|
|
Packit |
fd8b60 |
uid_t target_uid;
|
|
Packit |
fd8b60 |
krb5_ccache cc;
|
|
Packit |
fd8b60 |
int *path_passwd;
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_principal client;
|
|
Packit |
fd8b60 |
krb5_verify_init_creds_opt vfy_opts;
|
|
Packit |
fd8b60 |
krb5_creds tgt, tgtq;
|
|
Packit |
fd8b60 |
krb5_error_code retval =0;
|
|
Packit |
fd8b60 |
int got_it = 0;
|
|
Packit |
fd8b60 |
krb5_boolean zero_password;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*path_passwd = 0;
|
|
Packit |
fd8b60 |
memset(&tgtq, 0, sizeof(tgtq));
|
|
Packit |
fd8b60 |
memset(&tgt, 0, sizeof(tgt));
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if ((retval= krb5_copy_principal(context, client_pname, &client))){
|
|
Packit |
fd8b60 |
com_err(prog_name, retval, _("while copying client principal"));
|
|
Packit |
fd8b60 |
return (FALSE) ;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if ((retval= krb5_copy_principal(context, client, &tgtq.client))){
|
|
Packit |
fd8b60 |
com_err(prog_name, retval, _("while copying client principal"));
|
|
Packit |
fd8b60 |
return (FALSE) ;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if ((retval = ksu_tgtname(context, krb5_princ_realm(context, client),
|
|
Packit |
fd8b60 |
krb5_princ_realm(context, client),
|
|
Packit |
fd8b60 |
&tgtq.server))){
|
|
Packit |
fd8b60 |
com_err(prog_name, retval, _("while creating tgt for local realm"));
|
|
Packit |
fd8b60 |
krb5_free_principal(context, client);
|
|
Packit |
fd8b60 |
return (FALSE) ;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (auth_debug){ dump_principal(context, "local tgt principal name", tgtq.server ); }
|
|
Packit |
fd8b60 |
retval = krb5_cc_retrieve_cred(context, cc,
|
|
Packit |
fd8b60 |
KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES,
|
|
Packit |
fd8b60 |
&tgtq, &tgt);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (! retval) retval = krb5_check_exp(context, tgt.times);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (retval){
|
|
Packit |
fd8b60 |
if ((retval != KRB5_CC_NOTFOUND) &&
|
|
Packit |
fd8b60 |
(retval != KRB5KRB_AP_ERR_TKT_EXPIRED)){
|
|
Packit |
fd8b60 |
com_err(prog_name, retval, _("while retrieving creds from cache"));
|
|
Packit |
fd8b60 |
return (FALSE) ;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
} else{
|
|
Packit |
fd8b60 |
got_it = 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (! got_it){
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifdef GET_TGT_VIA_PASSWD
|
|
Packit |
fd8b60 |
if (krb5_seteuid(0)||krb5_seteuid(target_uid)) {
|
|
Packit |
fd8b60 |
com_err("ksu", errno, _("while switching to target uid"));
|
|
Packit |
fd8b60 |
return FALSE;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
fprintf(stderr, _("WARNING: Your password may be exposed if you enter "
|
|
Packit |
fd8b60 |
"it here and are logged \n"));
|
|
Packit |
fd8b60 |
fprintf(stderr, _(" in remotely using an unsecure "
|
|
Packit |
fd8b60 |
"(non-encrypted) channel. \n"));
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*get the ticket granting ticket, via passwd(prompt for passwd)*/
|
|
Packit |
fd8b60 |
if (ksu_get_tgt_via_passwd(context, client, options, &zero_password,
|
|
Packit |
fd8b60 |
&tgt) == FALSE) {
|
|
Packit |
fd8b60 |
krb5_seteuid(0);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
return FALSE;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
*path_passwd = 1;
|
|
Packit |
fd8b60 |
if (krb5_seteuid(0)) {
|
|
Packit |
fd8b60 |
com_err("ksu", errno, _("while reclaiming root uid"));
|
|
Packit |
fd8b60 |
return FALSE;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
plain_dump_principal (context, client);
|
|
Packit |
fd8b60 |
fprintf(stderr,
|
|
Packit |
fd8b60 |
_("does not have any appropriate tickets in the cache.\n"));
|
|
Packit |
fd8b60 |
return FALSE;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#endif /* GET_TGT_VIA_PASSWD */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_verify_init_creds_opt_init(&vfy_opts);
|
|
Packit |
fd8b60 |
krb5_verify_init_creds_opt_set_ap_req_nofail( &vfy_opts, 1);
|
|
Packit |
fd8b60 |
retval = krb5_verify_init_creds(context, &tgt, NULL, NULL, NULL,
|
|
Packit |
fd8b60 |
&vfy_opts);
|
|
Packit |
fd8b60 |
if (retval) {
|
|
Packit |
fd8b60 |
com_err(prog_name, retval, _("while verifying ticket for server"));
|
|
Packit |
fd8b60 |
return (FALSE);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
return (TRUE);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_boolean ksu_get_tgt_via_passwd(context, client, options, zero_password,
|
|
Packit |
fd8b60 |
creds_out)
|
|
Packit |
fd8b60 |
krb5_context context;
|
|
Packit |
fd8b60 |
krb5_principal client;
|
|
Packit |
fd8b60 |
krb5_get_init_creds_opt *options;
|
|
Packit |
fd8b60 |
krb5_boolean *zero_password;
|
|
Packit |
fd8b60 |
krb5_creds *creds_out;
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code code;
|
|
Packit |
fd8b60 |
krb5_creds creds;
|
|
Packit |
fd8b60 |
krb5_timestamp now;
|
|
Packit |
fd8b60 |
unsigned int pwsize;
|
|
Packit |
fd8b60 |
char password[255], *client_name, prompt[255];
|
|
Packit |
fd8b60 |
int result;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
*zero_password = FALSE;
|
|
Packit |
fd8b60 |
if (creds_out != NULL)
|
|
Packit |
fd8b60 |
memset(creds_out, 0, sizeof(*creds_out));
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if ((code = krb5_unparse_name(context, client, &client_name))) {
|
|
Packit |
fd8b60 |
com_err (prog_name, code, _("when unparsing name"));
|
|
Packit |
fd8b60 |
return (FALSE);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
memset(&creds, 0, sizeof(creds));
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if ((code = krb5_timeofday(context, &now))) {
|
|
Packit |
fd8b60 |
com_err(prog_name, code, _("while getting time of day"));
|
|
Packit |
fd8b60 |
return (FALSE);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
result = snprintf(prompt, sizeof(prompt), _("Kerberos password for %s: "),
|
|
Packit |
fd8b60 |
client_name);
|
|
Packit |
fd8b60 |
if (SNPRINTF_OVERFLOW(result, sizeof(prompt))) {
|
|
Packit |
fd8b60 |
fprintf(stderr,
|
|
Packit |
fd8b60 |
_("principal name %s too long for internal buffer space\n"),
|
|
Packit |
fd8b60 |
client_name);
|
|
Packit |
fd8b60 |
return FALSE;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
pwsize = sizeof(password);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
code = krb5_read_password(context, prompt, 0, password, &pwsize);
|
|
Packit |
fd8b60 |
if (code ) {
|
|
Packit |
fd8b60 |
com_err(prog_name, code, _("while reading password for '%s'\n"),
|
|
Packit |
fd8b60 |
client_name);
|
|
Packit |
fd8b60 |
return (FALSE);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if ( pwsize == 0) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _("No password given\n"));
|
|
Packit |
fd8b60 |
*zero_password = TRUE;
|
|
Packit |
fd8b60 |
return (FALSE);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
code = krb5_get_init_creds_password(context, &creds, client, password,
|
|
Packit |
fd8b60 |
krb5_prompter_posix, NULL, 0, NULL,
|
|
Packit |
fd8b60 |
options);
|
|
Packit |
fd8b60 |
zap(password, sizeof(password));
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (code) {
|
|
Packit |
fd8b60 |
if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
|
|
Packit |
fd8b60 |
fprintf(stderr, _("%s: Password incorrect\n"), prog_name);
|
|
Packit |
fd8b60 |
else
|
|
Packit |
fd8b60 |
com_err(prog_name, code, _("while getting initial credentials"));
|
|
Packit |
fd8b60 |
return (FALSE);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (creds_out != NULL)
|
|
Packit |
fd8b60 |
*creds_out = creds;
|
|
Packit |
fd8b60 |
else
|
|
Packit |
fd8b60 |
krb5_free_cred_contents(context, &creds);
|
|
Packit |
fd8b60 |
return (TRUE);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
void dump_principal (context, str, p)
|
|
Packit |
fd8b60 |
krb5_context context;
|
|
Packit |
fd8b60 |
char *str;
|
|
Packit |
fd8b60 |
krb5_principal p;
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
char * stname;
|
|
Packit |
fd8b60 |
krb5_error_code retval;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if ((retval = krb5_unparse_name(context, p, &stname))) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _(" %s while unparsing name\n"),
|
|
Packit |
fd8b60 |
error_message(retval));
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
fprintf(stderr, " %s: %s\n", str, stname);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
void plain_dump_principal (context, p)
|
|
Packit |
fd8b60 |
krb5_context context;
|
|
Packit |
fd8b60 |
krb5_principal p;
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
char * stname;
|
|
Packit |
fd8b60 |
krb5_error_code retval;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if ((retval = krb5_unparse_name(context, p, &stname))) {
|
|
Packit |
fd8b60 |
fprintf(stderr, _(" %s while unparsing name\n"),
|
|
Packit |
fd8b60 |
error_message(retval));
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
fprintf(stderr, "%s ", stname);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/**********************************************************************
|
|
Packit |
fd8b60 |
returns the principal that is closest to client. plist contains
|
|
Packit |
fd8b60 |
a principal list obtained from .k5login and parhaps .k5users file.
|
|
Packit |
fd8b60 |
This routine gets called before getting the password for a tgt.
|
|
Packit |
fd8b60 |
A principal is picked that has the best chance of getting in.
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
**********************************************************************/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
krb5_error_code get_best_principal(context, plist, client)
|
|
Packit |
fd8b60 |
krb5_context context;
|
|
Packit |
fd8b60 |
char **plist;
|
|
Packit |
fd8b60 |
krb5_principal *client;
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
krb5_error_code retval =0;
|
|
Packit |
fd8b60 |
krb5_principal temp_client, best_client = NULL;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
int i = 0, nelem;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (! plist ) return 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
nelem = krb5_princ_size(context, *client);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
while(plist[i]){
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if ((retval = krb5_parse_name(context, plist[i], &temp_client))){
|
|
Packit |
fd8b60 |
return retval;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (data_eq(*krb5_princ_realm(context, *client),
|
|
Packit |
fd8b60 |
*krb5_princ_realm(context, temp_client))) {
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (nelem &&
|
|
Packit |
fd8b60 |
krb5_princ_size(context, *client) > 0 &&
|
|
Packit |
fd8b60 |
krb5_princ_size(context, temp_client) > 0) {
|
|
Packit |
fd8b60 |
krb5_data *p1 =
|
|
Packit |
fd8b60 |
krb5_princ_component(context, *client, 0);
|
|
Packit |
fd8b60 |
krb5_data *p2 =
|
|
Packit |
fd8b60 |
krb5_princ_component(context, temp_client, 0);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (data_eq(*p1, *p2)) {
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (auth_debug){
|
|
Packit |
fd8b60 |
fprintf(stderr,
|
|
Packit |
fd8b60 |
"get_best_principal: compare with %s\n",
|
|
Packit |
fd8b60 |
plist[i]);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if(best_client){
|
|
Packit |
fd8b60 |
if(krb5_princ_size(context, best_client) >
|
|
Packit |
fd8b60 |
krb5_princ_size(context, temp_client)){
|
|
Packit |
fd8b60 |
best_client = temp_client;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}else{
|
|
Packit |
fd8b60 |
best_client = temp_client;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
i++;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (best_client) *client = best_client;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|