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 31static char *etype_str = NULL; 32static char *ccache_name = NULL; 33static char *keytab_name = NULL; 34static char *sname = NULL; 35 36static int version_flag = 0; 37static int help_flag = 0; 38static int quiet_flag = 0; 39 40static void do_v5_kvno (int argc, char *argv[], 41 char *ccache_name, char *etype_str, char *keytab_name, 42 char *sname); 43 44struct 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 59static void 60usage(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 69int 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 98static 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