Blame src/clients/ksu/krb_auth_su.c

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
}