xref: /minix/crypto/external/bsd/heimdal/dist/kuser/kvno.c (revision 0a6a1f1d)
1 /*	$NetBSD: kvno.c,v 1.1.1.2 2014/04/24 12:45:28 pettai 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
usage(int ret)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 
main(int argc,char * argv[])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 
do_v5_kvno(int count,char * names[],char * ccache_name,char * etype_str,char * keytab_name,char * sname)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