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