/ kadmin / ext.c
ext.c
  1  /*
  2   * Copyright (c) 1997 - 2006 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 "kadmin_locl.h"
 35  #include "kadmin-commands.h"
 36  
 37  struct ext_keytab_data {
 38      krb5_keytab keytab;
 39  };
 40  
 41  static int
 42  do_ext_keytab(krb5_principal principal, void *data)
 43  {
 44      krb5_error_code ret;
 45      kadm5_principal_ent_rec princ;
 46      struct ext_keytab_data *e = data;
 47      krb5_keytab_entry *keys = NULL;
 48      krb5_keyblock *k = NULL;
 49      int i, n_k;
 50      int have_keys = 0;
 51  
 52      ret = kadm5_get_principal(kadm_handle, principal, &princ,
 53  			      KADM5_PRINCIPAL|KADM5_KVNO|KADM5_KEY_DATA);
 54      if(ret)
 55  	return ret;
 56  
 57      /* 
 58       * Make sure that we have keys, some backends doesn't support
 59       * getting keys, so in that case we fallback to
 60       * kadm5_randkey_principal() instead.
 61       */
 62      for (i = 0; i < princ.n_key_data; i++)
 63  	if (princ.key_data[i].key_data_length[0] > 0)
 64  	    have_keys = 1;
 65  
 66      if (princ.n_key_data && have_keys) {
 67  	keys = malloc(sizeof(*keys) * princ.n_key_data);
 68  	if (keys == NULL) {
 69  	    kadm5_free_principal_ent(kadm_handle, &princ);
 70  	    krb5_clear_error_message(context);
 71  	    return ENOMEM;
 72  	}
 73  	for (i = 0; i < princ.n_key_data; i++) {
 74  	    krb5_key_data *kd = &princ.key_data[i];
 75  
 76  	    keys[i].principal = princ.principal;
 77  	    keys[i].vno = kd->key_data_kvno;
 78  	    keys[i].keyblock.keytype = kd->key_data_type[0];
 79  	    keys[i].keyblock.keyvalue.length = kd->key_data_length[0];
 80  	    keys[i].keyblock.keyvalue.data = kd->key_data_contents[0];
 81  	    keys[i].timestamp = (uint32_t)time(NULL);
 82  	}
 83  
 84  	n_k = princ.n_key_data;
 85      } else {
 86  	ret = kadm5_randkey_principal(kadm_handle, principal, &k, &n_k);
 87  	if (ret) {
 88  	    kadm5_free_principal_ent(kadm_handle, &princ);
 89  	    return ret;
 90  	}
 91  	keys = malloc(sizeof(*keys) * n_k);
 92  	if (keys == NULL) {
 93  	    kadm5_free_principal_ent(kadm_handle, &princ);
 94  	    krb5_clear_error_message(context);
 95  	    return ENOMEM;
 96  	}
 97  	for (i = 0; i < n_k; i++) {
 98  	    keys[i].principal = principal;
 99  	    keys[i].vno = princ.kvno + 1; /* XXX get entry again */
100  	    keys[i].keyblock = k[i];
101  	    keys[i].timestamp = (uint32_t)time(NULL);
102  	}
103      }
104  
105      for(i = 0; i < n_k; i++) {
106  	ret = krb5_kt_add_entry(context, e->keytab, &keys[i]);
107  	if(ret)
108  	    krb5_warn(context, ret, "krb5_kt_add_entry(%d)", i);
109      }
110  
111      if (k) {
112  	memset(k, 0, n_k * sizeof(*k));
113  	free(k);
114      }
115      if (keys)
116  	free(keys);
117      kadm5_free_principal_ent(kadm_handle, &princ);
118      return 0;
119  }
120  
121  int
122  ext_keytab(struct ext_keytab_options *opt, int argc, char **argv)
123  {
124      krb5_error_code ret;
125      int i;
126      struct ext_keytab_data data;
127  
128      if (opt->keytab_string == NULL)
129  	ret = krb5_kt_default(context, &data.keytab);
130      else
131  	ret = krb5_kt_resolve(context, opt->keytab_string, &data.keytab);
132  
133      if(ret){
134  	krb5_warn(context, ret, "krb5_kt_resolve");
135  	return 1;
136      }
137  
138      for(i = 0; i < argc; i++) {
139  	ret = foreach_principal(argv[i], do_ext_keytab, "ext", &data);
140  	if (ret)
141  	    break;
142      }
143  
144      krb5_kt_close(context, data.keytab);
145  
146      return ret != 0;
147  }