/ admin / get.c
get.c
  1  /*
  2   * Copyright (c) 1997-2004 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 "ktutil_locl.h"
 35  
 36  RCSID("$Id$");
 37  
 38  static void*
 39  open_kadmin_connection(char *principal,
 40  		       const char *realm,
 41  		       char *admin_server,
 42  		       int server_port)
 43  {
 44      static kadm5_config_params conf;
 45      krb5_error_code ret;
 46      void *kadm_handle;
 47      memset(&conf, 0, sizeof(conf));
 48  
 49      if(realm) {
 50  	conf.realm = strdup(realm);
 51  	if (conf.realm == NULL) {
 52  	    krb5_set_error_message(context, 0, "malloc: out of memory");
 53  	    return NULL;
 54  	}
 55  	conf.mask |= KADM5_CONFIG_REALM;
 56      }
 57  
 58      if (admin_server) {
 59  	conf.admin_server = admin_server;
 60  	conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
 61      }
 62  
 63      if (server_port) {
 64  	conf.kadmind_port = htons(server_port);
 65  	conf.mask |= KADM5_CONFIG_KADMIND_PORT;
 66      }
 67  
 68      /* should get realm from each principal, instead of doing
 69         everything with the same (local) realm */
 70  
 71      ret = kadm5_init_with_password_ctx(context,
 72  				       principal,
 73  				       NULL,
 74  				       KADM5_ADMIN_SERVICE,
 75  				       &conf, 0, 0,
 76  				       &kadm_handle);
 77      free(conf.realm);
 78      if(ret) {
 79  	krb5_warn(context, ret, "kadm5_init_with_password");
 80  	return NULL;
 81      }
 82      return kadm_handle;
 83  }
 84  
 85  int
 86  kt_get(struct get_options *opt, int argc, char **argv)
 87  {
 88      krb5_error_code ret = 0;
 89      krb5_keytab keytab;
 90      void *kadm_handle = NULL;
 91      krb5_enctype *etypes = NULL;
 92      size_t netypes = 0;
 93      size_t i;
 94      int a, j;
 95      unsigned int failed = 0;
 96  
 97      if((keytab = ktutil_open_keytab()) == NULL)
 98  	return 1;
 99  
100      if(opt->realm_string)
101  	krb5_set_default_realm(context, opt->realm_string);
102  
103      if (opt->enctypes_strings.num_strings != 0) {
104  
105  	etypes = malloc (opt->enctypes_strings.num_strings * sizeof(*etypes));
106  	if (etypes == NULL) {
107  	    krb5_warnx(context, "malloc failed");
108  	    goto out;
109  	}
110  	netypes = opt->enctypes_strings.num_strings;
111  	for(i = 0; i < netypes; i++) {
112  	    ret = krb5_string_to_enctype(context,
113  					 opt->enctypes_strings.strings[i],
114  					 &etypes[i]);
115  	    if(ret) {
116  		krb5_warnx(context, "unrecognized enctype: %s",
117  			   opt->enctypes_strings.strings[i]);
118  		goto out;
119  	    }
120  	}
121      }
122  
123  
124      for(a = 0; a < argc; a++){
125  	krb5_principal princ_ent;
126  	kadm5_principal_ent_rec princ;
127  	int mask = 0;
128  	krb5_keyblock *keys;
129  	int n_keys;
130  	int created = 0;
131  	krb5_keytab_entry entry;
132  
133  	ret = krb5_parse_name(context, argv[a], &princ_ent);
134  	if (ret) {
135  	    krb5_warn(context, ret, "can't parse principal %s", argv[a]);
136  	    failed++;
137  	    continue;
138  	}
139  	memset(&princ, 0, sizeof(princ));
140  	princ.principal = princ_ent;
141  	mask |= KADM5_PRINCIPAL;
142  	princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
143  	mask |= KADM5_ATTRIBUTES;
144  	princ.princ_expire_time = 0;
145  	mask |= KADM5_PRINC_EXPIRE_TIME;
146  
147  	if(kadm_handle == NULL) {
148  	    const char *r;
149  	    if(opt->realm_string != NULL)
150  		r = opt->realm_string;
151  	    else
152  		r = krb5_principal_get_realm(context, princ_ent);
153  	    kadm_handle = open_kadmin_connection(opt->principal_string,
154  						 r,
155  						 opt->admin_server_string,
156  						 opt->server_port_integer);
157  	    if(kadm_handle == NULL)
158  		break;
159  	}
160  
161  	ret = kadm5_create_principal(kadm_handle, &princ, mask, "x");
162  	if(ret == 0)
163  	    created = 1;
164  	else if(ret != KADM5_DUP) {
165  	    krb5_warn(context, ret, "kadm5_create_principal(%s)", argv[a]);
166  	    krb5_free_principal(context, princ_ent);
167  	    failed++;
168  	    continue;
169  	}
170  	ret = kadm5_randkey_principal(kadm_handle, princ_ent, &keys, &n_keys);
171  	if (ret) {
172  	    krb5_warn(context, ret, "kadm5_randkey_principal(%s)", argv[a]);
173  	    krb5_free_principal(context, princ_ent);
174  	    failed++;
175  	    continue;
176  	}
177  
178  	ret = kadm5_get_principal(kadm_handle, princ_ent, &princ,
179  			      KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
180  	if (ret) {
181  	    krb5_warn(context, ret, "kadm5_get_principal(%s)", argv[a]);
182  	    for (j = 0; j < n_keys; j++)
183  		krb5_free_keyblock_contents(context, &keys[j]);
184  	    krb5_free_principal(context, princ_ent);
185  	    failed++;
186  	    continue;
187  	}
188  	if(!created && (princ.attributes & KRB5_KDB_DISALLOW_ALL_TIX))
189  	    krb5_warnx(context, "%s: disallow-all-tix flag set - clearing", argv[a]);
190  	princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
191  	mask = KADM5_ATTRIBUTES;
192  	if(created) {
193  	    princ.kvno = 1;
194  	    mask |= KADM5_KVNO;
195  	}
196  	ret = kadm5_modify_principal(kadm_handle, &princ, mask);
197  	if (ret) {
198  	    krb5_warn(context, ret, "kadm5_modify_principal(%s)", argv[a]);
199  	    for (j = 0; j < n_keys; j++)
200  		krb5_free_keyblock_contents(context, &keys[j]);
201  	    krb5_free_principal(context, princ_ent);
202  	    failed++;
203  	    continue;
204  	}
205  	for(j = 0; j < n_keys; j++) {
206  	    int do_add = TRUE;
207  
208  	    if (netypes) {
209  		size_t k;
210  
211  		do_add = FALSE;
212  		for (k = 0; k < netypes; ++k)
213  		    if (keys[j].keytype == etypes[k]) {
214  			do_add = TRUE;
215  			break;
216  		    }
217  	    }
218  	    if (do_add) {
219  		entry.principal = princ_ent;
220  		entry.vno = princ.kvno;
221  		entry.keyblock = keys[j];
222  		entry.timestamp = (uint32_t)time (NULL);
223  		ret = krb5_kt_add_entry(context, keytab, &entry);
224  		if (ret)
225  		    krb5_warn(context, ret, "krb5_kt_add_entry");
226  	    }
227  	    krb5_free_keyblock_contents(context, &keys[j]);
228  	}
229  
230  	kadm5_free_principal_ent(kadm_handle, &princ);
231  	krb5_free_principal(context, princ_ent);
232      }
233   out:
234      free(etypes);
235      if (kadm_handle)
236  	kadm5_destroy(kadm_handle);
237      krb5_kt_close(context, keytab);
238      return ret != 0 || failed > 0;
239  }