xref: /minix3/crypto/external/bsd/heimdal/dist/kuser/kswitch.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: kswitch.c,v 1.1.1.2 2014/04/24 12:45:28 pettai Exp $	*/
2ebfedea0SLionel Sambuc 
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc  * Copyright (c) 2008 - 2010 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc  * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc  * All rights reserved.
7ebfedea0SLionel Sambuc  *
8ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc  * are met:
11ebfedea0SLionel Sambuc  *
12ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
13ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
14ebfedea0SLionel Sambuc  *
15ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18ebfedea0SLionel Sambuc  *
19ebfedea0SLionel Sambuc  * 3. Neither the name of the Institute nor the names of its contributors
20ebfedea0SLionel Sambuc  *    may be used to endorse or promote products derived from this software
21ebfedea0SLionel Sambuc  *    without specific prior written permission.
22ebfedea0SLionel Sambuc  *
23ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ebfedea0SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ebfedea0SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ebfedea0SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ebfedea0SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ebfedea0SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ebfedea0SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ebfedea0SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ebfedea0SLionel Sambuc  * SUCH DAMAGE.
34ebfedea0SLionel Sambuc  */
35ebfedea0SLionel Sambuc 
36ebfedea0SLionel Sambuc #include "kuser_locl.h"
37ebfedea0SLionel Sambuc #include "kcc-commands.h"
38ebfedea0SLionel Sambuc 
39ebfedea0SLionel Sambuc #ifdef HAVE_READLINE
40*0a6a1f1dSLionel Sambuc char *readline(const char *prompt);
41ebfedea0SLionel Sambuc #else
42ebfedea0SLionel Sambuc 
43ebfedea0SLionel Sambuc static char *
readline(const char * prompt)44*0a6a1f1dSLionel Sambuc readline(const char *prompt)
45ebfedea0SLionel Sambuc {
46ebfedea0SLionel Sambuc     char buf[BUFSIZ];
47ebfedea0SLionel Sambuc     printf ("%s", prompt);
48ebfedea0SLionel Sambuc     fflush (stdout);
49ebfedea0SLionel Sambuc     if(fgets(buf, sizeof(buf), stdin) == NULL)
50ebfedea0SLionel Sambuc 	return NULL;
51ebfedea0SLionel Sambuc     buf[strcspn(buf, "\r\n")] = '\0';
52ebfedea0SLionel Sambuc     return strdup(buf);
53ebfedea0SLionel Sambuc }
54ebfedea0SLionel Sambuc 
55ebfedea0SLionel Sambuc #endif
56ebfedea0SLionel Sambuc 
57ebfedea0SLionel Sambuc /*
58ebfedea0SLionel Sambuc  *
59ebfedea0SLionel Sambuc  */
60ebfedea0SLionel Sambuc 
61ebfedea0SLionel Sambuc int
kswitch(struct kswitch_options * opt,int argc,char ** argv)62ebfedea0SLionel Sambuc kswitch(struct kswitch_options *opt, int argc, char **argv)
63ebfedea0SLionel Sambuc {
64ebfedea0SLionel Sambuc     krb5_error_code ret;
65ebfedea0SLionel Sambuc     krb5_ccache id = NULL;
66ebfedea0SLionel Sambuc 
67ebfedea0SLionel Sambuc     if (opt->cache_string && opt->principal_string)
68ebfedea0SLionel Sambuc 	krb5_errx(kcc_context, 1,
69ebfedea0SLionel Sambuc 		  N_("Both --cache and --principal given, choose one", ""));
70ebfedea0SLionel Sambuc 
71ebfedea0SLionel Sambuc     if (opt->interactive_flag) {
72ebfedea0SLionel Sambuc 	krb5_cc_cache_cursor cursor;
73ebfedea0SLionel Sambuc 	krb5_ccache *ids = NULL;
74ebfedea0SLionel Sambuc 	size_t i, len = 0;
75ebfedea0SLionel Sambuc 	char *name;
76ebfedea0SLionel Sambuc 	rtbl_t ct;
77ebfedea0SLionel Sambuc 
78ebfedea0SLionel Sambuc 	ct = rtbl_create();
79ebfedea0SLionel Sambuc 
80*0a6a1f1dSLionel Sambuc 	rtbl_add_column_by_id(ct, 0, "#", 0);
81*0a6a1f1dSLionel Sambuc 	rtbl_add_column_by_id(ct, 1, "Principal", 0);
82*0a6a1f1dSLionel Sambuc 	rtbl_set_column_affix_by_id(ct, 1, "    ", "");
83*0a6a1f1dSLionel Sambuc         rtbl_add_column_by_id(ct, 2, "Type", 0);
84*0a6a1f1dSLionel Sambuc         rtbl_set_column_affix_by_id(ct, 2, "  ", "");
85ebfedea0SLionel Sambuc 
86ebfedea0SLionel Sambuc 	ret = krb5_cc_cache_get_first(kcc_context, NULL, &cursor);
87ebfedea0SLionel Sambuc 	if (ret)
88ebfedea0SLionel Sambuc 	    krb5_err(kcc_context, 1, ret, "krb5_cc_cache_get_first");
89ebfedea0SLionel Sambuc 
90ebfedea0SLionel Sambuc 	while (krb5_cc_cache_next(kcc_context, cursor, &id) == 0) {
91ebfedea0SLionel Sambuc 	    krb5_principal p;
92ebfedea0SLionel Sambuc 	    char num[10];
93ebfedea0SLionel Sambuc 
94ebfedea0SLionel Sambuc 	    ret = krb5_cc_get_principal(kcc_context, id, &p);
95ebfedea0SLionel Sambuc 	    if (ret)
96ebfedea0SLionel Sambuc 		continue;
97ebfedea0SLionel Sambuc 
98ebfedea0SLionel Sambuc 	    ret = krb5_unparse_name(kcc_context, p, &name);
99ebfedea0SLionel Sambuc 	    krb5_free_principal(kcc_context, p);
100ebfedea0SLionel Sambuc 
101ebfedea0SLionel Sambuc 	    snprintf(num, sizeof(num), "%d", (int)(len + 1));
102*0a6a1f1dSLionel Sambuc 	    rtbl_add_column_entry_by_id(ct, 0, num);
103*0a6a1f1dSLionel Sambuc 	    rtbl_add_column_entry_by_id(ct, 1, name);
104*0a6a1f1dSLionel Sambuc             rtbl_add_column_entry_by_id(ct, 2, krb5_cc_get_type(kcc_context, id));
105ebfedea0SLionel Sambuc 	    free(name);
106ebfedea0SLionel Sambuc 
107ebfedea0SLionel Sambuc 	    ids = erealloc(ids, (len + 1) * sizeof(ids[0]));
108ebfedea0SLionel Sambuc 	    ids[len] = id;
109ebfedea0SLionel Sambuc 	    len++;
110ebfedea0SLionel Sambuc 	}
111ebfedea0SLionel Sambuc 	krb5_cc_cache_end_seq_get(kcc_context, cursor);
112ebfedea0SLionel Sambuc 
113ebfedea0SLionel Sambuc 	rtbl_format(ct, stdout);
114ebfedea0SLionel Sambuc 	rtbl_destroy(ct);
115ebfedea0SLionel Sambuc 
116ebfedea0SLionel Sambuc 	name = readline("Select number: ");
117ebfedea0SLionel Sambuc 	if (name) {
118ebfedea0SLionel Sambuc 	    i = atoi(name);
119ebfedea0SLionel Sambuc 	    if (i == 0)
120ebfedea0SLionel Sambuc 		krb5_errx(kcc_context, 1, "Cache number '%s' is invalid", name);
121ebfedea0SLionel Sambuc 	    if (i > len)
122ebfedea0SLionel Sambuc 		krb5_errx(kcc_context, 1, "Cache number '%s' is too large", name);
123ebfedea0SLionel Sambuc 
124ebfedea0SLionel Sambuc 	    id = ids[i - 1];
125ebfedea0SLionel Sambuc 	    ids[i - 1] = NULL;
126ebfedea0SLionel Sambuc 	} else
127ebfedea0SLionel Sambuc 	    krb5_errx(kcc_context, 1, "No cache selected");
128ebfedea0SLionel Sambuc 	for (i = 0; i < len; i++)
129ebfedea0SLionel Sambuc 	    if (ids[i])
130ebfedea0SLionel Sambuc 		krb5_cc_close(kcc_context, ids[i]);
131ebfedea0SLionel Sambuc 
132ebfedea0SLionel Sambuc     } else if (opt->principal_string) {
133ebfedea0SLionel Sambuc 	krb5_principal p;
134ebfedea0SLionel Sambuc 
135ebfedea0SLionel Sambuc 	ret = krb5_parse_name(kcc_context, opt->principal_string, &p);
136ebfedea0SLionel Sambuc 	if (ret)
137ebfedea0SLionel Sambuc 	    krb5_err(kcc_context, 1, ret, "krb5_parse_name: %s",
138ebfedea0SLionel Sambuc 		     opt->principal_string);
139ebfedea0SLionel Sambuc 
140ebfedea0SLionel Sambuc 	ret = krb5_cc_cache_match(kcc_context, p, &id);
141ebfedea0SLionel Sambuc 	if (ret)
142ebfedea0SLionel Sambuc 	    krb5_err(kcc_context, 1, ret,
143ebfedea0SLionel Sambuc 		     N_("Did not find principal: %s", ""),
144ebfedea0SLionel Sambuc 		     opt->principal_string);
145ebfedea0SLionel Sambuc 
146ebfedea0SLionel Sambuc 	krb5_free_principal(kcc_context, p);
147ebfedea0SLionel Sambuc 
148ebfedea0SLionel Sambuc     } else if (opt->cache_string) {
149ebfedea0SLionel Sambuc 	const krb5_cc_ops *ops;
150ebfedea0SLionel Sambuc 	char *str;
151ebfedea0SLionel Sambuc 
152ebfedea0SLionel Sambuc 	ops = krb5_cc_get_prefix_ops(kcc_context, opt->type_string);
153ebfedea0SLionel Sambuc 	if (ops == NULL)
154ebfedea0SLionel Sambuc 	    krb5_err(kcc_context, 1, 0, "krb5_cc_get_prefix_ops");
155ebfedea0SLionel Sambuc 
156ebfedea0SLionel Sambuc 	asprintf(&str, "%s:%s", ops->prefix, opt->cache_string);
157ebfedea0SLionel Sambuc 	if (str == NULL)
158ebfedea0SLionel Sambuc 	    krb5_errx(kcc_context, 1, N_("out of memory", ""));
159ebfedea0SLionel Sambuc 
160ebfedea0SLionel Sambuc 	ret = krb5_cc_resolve(kcc_context, str, &id);
161ebfedea0SLionel Sambuc 	if (ret)
162ebfedea0SLionel Sambuc 	    krb5_err(kcc_context, 1, ret, "krb5_cc_resolve: %s", str);
163ebfedea0SLionel Sambuc 
164ebfedea0SLionel Sambuc 	free(str);
165ebfedea0SLionel Sambuc     } else {
166ebfedea0SLionel Sambuc 	krb5_errx(kcc_context, 1, "missing option for kswitch");
167ebfedea0SLionel Sambuc     }
168ebfedea0SLionel Sambuc 
169ebfedea0SLionel Sambuc     ret = krb5_cc_switch(kcc_context, id);
170ebfedea0SLionel Sambuc     if (ret)
171ebfedea0SLionel Sambuc 	krb5_err(kcc_context, 1, ret, "krb5_cc_switch");
172ebfedea0SLionel Sambuc 
173ebfedea0SLionel Sambuc     return 0;
174ebfedea0SLionel Sambuc }
175