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