Home | History | Annotate | Line # | Download | only in kuser
      1 /*	$NetBSD: kvno.c,v 1.2 2017/01/28 21:31:45 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 1998 by the FundsXpress, INC.
      5  *
      6  * All rights reserved.
      7  *
      8  * Export of this software from the United States of America may require
      9  * a specific license from the United States Government.  It is the
     10  * responsibility of any person or organization contemplating export to
     11  * obtain such a license before exporting.
     12  *
     13  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
     14  * distribute this software and its documentation for any purpose and
     15  * without fee is hereby granted, provided that the above copyright
     16  * notice appear in all copies and that both that copyright notice and
     17  * this permission notice appear in supporting documentation, and that
     18  * the name of FundsXpress. not be used in advertising or publicity pertaining
     19  * to distribution of the software without specific, written prior
     20  * permission.  FundsXpress makes no representations about the suitability of
     21  * this software for any purpose.  It is provided "as is" without express
     22  * or implied warranty.
     23  *
     24  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     25  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     26  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     27  */
     28 
     29 #include "kuser_locl.h"
     30 
     31 static char *etype_str = NULL;
     32 static char *ccache_name = NULL;
     33 static char *keytab_name = NULL;
     34 static char *sname = NULL;
     35 
     36 static int  version_flag = 0;
     37 static int  help_flag = 0;
     38 static int  quiet_flag = 0;
     39 
     40 static void do_v5_kvno (int argc, char *argv[],
     41                         char *ccache_name, char *etype_str, char *keytab_name,
     42 			char *sname);
     43 
     44 struct getargs args[] = {
     45     { "enctype",        'e', arg_string, &etype_str,
     46       NP_("Encryption type to use", ""), "enctype" },
     47     { "cache",          'c', arg_string, &ccache_name,
     48       NP_("Credentials cache", ""), "cachename" },
     49     { "keytab",         'k', arg_string, &keytab_name,
     50       NP_("Keytab to use", ""), "keytabname" },
     51     { "server",         'S', arg_string, &sname,
     52       NP_("Server to get ticket for", ""), "principal" },
     53     { "quiet",          'q', arg_flag, &quiet_flag,
     54       NP_("Quiet", "") },
     55     { "version",        0, arg_flag, &version_flag },
     56     { "help",           0, arg_flag, &help_flag }
     57 };
     58 
     59 static void
     60 usage(int ret)
     61 {
     62     arg_printusage_i18n (args, sizeof(args)/sizeof(*args),
     63                          N_("Usage: ", ""), NULL,
     64                          "principal1 [principal2 ...]",
     65                          getarg_i18n);
     66     exit (ret);
     67 }
     68 
     69 int main(int argc, char *argv[])
     70 {
     71     int optidx = 0;
     72 
     73     setprogname (argv[0]);
     74 
     75     setlocale(LC_ALL, "");
     76     bindtextdomain ("heimdal_kuser", HEIMDAL_LOCALEDIR);
     77     textdomain("heimdal_kuser");
     78 
     79     if (getarg(args, sizeof(args)/sizeof(args[0]), argc, argv, &optidx))
     80         usage(1);
     81 
     82     if (help_flag)
     83         usage (0);
     84 
     85     if (version_flag) {
     86         print_version(NULL);
     87         exit (0);
     88     }
     89 
     90     argc -= optidx;
     91     argv += optidx;
     92 
     93     do_v5_kvno(argc, argv, ccache_name, etype_str, keytab_name, sname);
     94 
     95     return 0;
     96 }
     97 
     98 static void do_v5_kvno (int count, char *names[],
     99                         char * ccache_name, char *etype_str, char *keytab_name,
    100 			char *sname)
    101 {
    102     krb5_error_code ret;
    103     krb5_context context = 0;
    104     int i, errors;
    105     krb5_enctype etype;
    106     krb5_ccache ccache;
    107     krb5_principal me;
    108     krb5_creds in_creds, *out_creds = NULL;
    109     Ticket ticket;
    110     size_t len;
    111     char *princ = NULL;
    112     krb5_keytab keytab = NULL;
    113 
    114     ret = krb5_init_context(&context);
    115     if (ret)
    116 	errx(1, "krb5_init_context failed: %d", ret);
    117 
    118     if (etype_str) {
    119         ret = krb5_string_to_enctype(context, etype_str, &etype);
    120 	if (ret)
    121 	    krb5_err(context, 1, ret, "Failed to convert encryption type %s", etype_str);
    122     } else {
    123 	etype = 0;
    124     }
    125 
    126     if (ccache_name)
    127         ret = krb5_cc_resolve(context, ccache_name, &ccache);
    128     else
    129         ret = krb5_cc_default(context, &ccache);
    130     if (ret)
    131         krb5_err(context, 1, ret, "Failed to open credentials cache %s",
    132                  (ccache_name) ? ccache_name : "(Default)");
    133 
    134     if (keytab_name) {
    135 	ret = krb5_kt_resolve(context, keytab_name, &keytab);
    136 	if (ret)
    137             krb5_err(context, 1, ret, "Can't resolve keytab %s", keytab_name);
    138     }
    139 
    140     ret = krb5_cc_get_principal(context, ccache, &me);
    141     if (ret)
    142         krb5_err(context, 1, ret, "krb5_cc_get_principal");
    143 
    144     errors = 0;
    145 
    146     for (i = 0; i < count; i++) {
    147 	memset(&in_creds, 0, sizeof(in_creds));
    148         memset(&ticket, 0, sizeof(ticket));
    149 
    150 	in_creds.client = me;
    151 
    152 	if (sname != NULL) {
    153 	    ret = krb5_sname_to_principal(context, names[i],
    154 					  sname, KRB5_NT_SRV_HST,
    155 					  &in_creds.server);
    156 	} else {
    157 	    ret = krb5_parse_name(context, names[i], &in_creds.server);
    158 	}
    159 	if (ret) {
    160 	    if (!quiet_flag)
    161                 krb5_warn(context, ret, "Couldn't parse principal name %s", names[i]);
    162             errors++;
    163 	    continue;
    164 	}
    165 
    166 	ret = krb5_unparse_name(context, in_creds.server, &princ);
    167 	if (ret) {
    168             krb5_warn(context, ret, "Couldn't format parsed principal name for '%s'",
    169                       names[i]);
    170 	    errors++;
    171             goto next;
    172 	}
    173 
    174 	in_creds.session.keytype = etype;
    175 
    176 	ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds);
    177 
    178 	if (ret) {
    179             krb5_warn(context, ret, "Couldn't get credentials for %s", princ);
    180 	    errors++;
    181 	    goto next;
    182 	}
    183 
    184 	ret = decode_Ticket(out_creds->ticket.data, out_creds->ticket.length,
    185                             &ticket, &len);
    186 	if (ret) {
    187 	    krb5_err(context, 1, ret, "Can't decode ticket for %s", princ);
    188 	    errors++;
    189             goto next;
    190 	    continue;
    191 	}
    192 
    193 	if (keytab) {
    194             krb5_keytab_entry   kte;
    195             krb5_crypto         crypto;
    196             krb5_data           dec_data;
    197             EncTicketPart       decr_part;
    198 
    199             ret = krb5_kt_get_entry(context, keytab, in_creds.server,
    200                                     (ticket.enc_part.kvno != NULL)?
    201                                     *ticket.enc_part.kvno : 0,
    202                                     ticket.enc_part.etype,
    203                                     &kte);
    204             if (ret) {
    205                 krb5_warn(context, ret, "Can't decrypt ticket for %s", princ);
    206                 if (!quiet_flag)
    207                     printf("%s: kvno = %d, keytab entry invalid", princ,
    208                            (ticket.enc_part.kvno != NULL)?
    209                            *ticket.enc_part.kvno : 0);
    210                 errors ++;
    211                 goto next;
    212             }
    213 
    214             ret = krb5_crypto_init(context, &kte.keyblock, 0, &crypto);
    215             if (ret) {
    216                 krb5_warn(context, ret, "krb5_crypto_init");
    217                 errors ++;
    218                 krb5_kt_free_entry(context, &kte);
    219                 goto next;
    220             }
    221 
    222             ret = krb5_decrypt_EncryptedData (context, crypto, KRB5_KU_TICKET,
    223                                               &ticket.enc_part, &dec_data);
    224             krb5_crypto_destroy(context, crypto);
    225             krb5_kt_free_entry(context, &kte);
    226 
    227             if (ret) {
    228                 krb5_warn(context, ret, "krb5_decrypt_EncryptedData");
    229                 errors ++;
    230                 goto next;
    231             }
    232 
    233             ret = decode_EncTicketPart(dec_data.data, dec_data.length,
    234                                        &decr_part, &len);
    235             krb5_data_free(&dec_data);
    236             if (ret) {
    237                 krb5_warn(context, ret, "decode_EncTicketPart");
    238                 errors ++;
    239                 goto next;
    240             }
    241 
    242             if (!quiet_flag)
    243 		printf("%s: kvno = %d, keytab entry valid\n", princ,
    244                        (ticket.enc_part.kvno != NULL)?
    245                        *ticket.enc_part.kvno : 0);
    246 
    247             free_EncTicketPart(&decr_part);
    248 	} else {
    249 	    if (!quiet_flag)
    250 		printf("%s: kvno = %d\n", princ,
    251                        (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0);
    252 	}
    253 
    254     next:
    255         if (out_creds) {
    256             krb5_free_creds(context, out_creds);
    257             out_creds = NULL;
    258         }
    259 
    260         if (princ) {
    261             krb5_free_unparsed_name(context, princ);
    262             princ = NULL;
    263         }
    264 
    265 	krb5_free_principal(context, in_creds.server);
    266 
    267         free_Ticket(&ticket);
    268     }
    269 
    270     if (keytab)
    271 	krb5_kt_close(context, keytab);
    272     krb5_free_principal(context, me);
    273     krb5_cc_close(context, ccache);
    274     krb5_free_context(context);
    275 
    276     if (errors)
    277 	exit(1);
    278 
    279     exit(0);
    280 }
    281