155682Smarkm/*
2233294Sstas * Copyright (c) 1997 - 2006 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
955682Smarkm *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
2055682Smarkm *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "kadmin_locl.h"
35178825Sdfr#include "kadmin-commands.h"
3655682Smarkm
3755682Smarkmstruct ext_keytab_data {
3855682Smarkm    krb5_keytab keytab;
3955682Smarkm};
4055682Smarkm
4155682Smarkmstatic int
4255682Smarkmdo_ext_keytab(krb5_principal principal, void *data)
4355682Smarkm{
4455682Smarkm    krb5_error_code ret;
4555682Smarkm    kadm5_principal_ent_rec princ;
4655682Smarkm    struct ext_keytab_data *e = data;
47178825Sdfr    krb5_keytab_entry *keys = NULL;
48178825Sdfr    krb5_keyblock *k = NULL;
49178825Sdfr    int i, n_k;
50233294Sstas
51233294Sstas    ret = kadm5_get_principal(kadm_handle, principal, &princ,
5255682Smarkm			      KADM5_PRINCIPAL|KADM5_KVNO|KADM5_KEY_DATA);
5355682Smarkm    if(ret)
5455682Smarkm	return ret;
55178825Sdfr
56178825Sdfr    if (princ.n_key_data) {
57178825Sdfr	keys = malloc(sizeof(*keys) * princ.n_key_data);
58178825Sdfr	if (keys == NULL) {
59178825Sdfr	    kadm5_free_principal_ent(kadm_handle, &princ);
60233294Sstas	    krb5_clear_error_message(context);
61178825Sdfr	    return ENOMEM;
62178825Sdfr	}
63178825Sdfr	for (i = 0; i < princ.n_key_data; i++) {
64178825Sdfr	    krb5_key_data *kd = &princ.key_data[i];
65178825Sdfr
66178825Sdfr	    keys[i].principal = princ.principal;
67178825Sdfr	    keys[i].vno = kd->key_data_kvno;
68178825Sdfr	    keys[i].keyblock.keytype = kd->key_data_type[0];
69178825Sdfr	    keys[i].keyblock.keyvalue.length = kd->key_data_length[0];
70178825Sdfr	    keys[i].keyblock.keyvalue.data = kd->key_data_contents[0];
71178825Sdfr	    keys[i].timestamp = time(NULL);
72178825Sdfr	}
73178825Sdfr
74178825Sdfr	n_k = princ.n_key_data;
75178825Sdfr    } else {
76178825Sdfr	ret = kadm5_randkey_principal(kadm_handle, principal, &k, &n_k);
77178825Sdfr	if (ret) {
78178825Sdfr	    kadm5_free_principal_ent(kadm_handle, &princ);
79178825Sdfr	    return ret;
80178825Sdfr	}
81178825Sdfr	keys = malloc(sizeof(*keys) * n_k);
82178825Sdfr	if (keys == NULL) {
83178825Sdfr	    kadm5_free_principal_ent(kadm_handle, &princ);
84233294Sstas	    krb5_clear_error_message(context);
85178825Sdfr	    return ENOMEM;
86178825Sdfr	}
87178825Sdfr	for (i = 0; i < n_k; i++) {
88178825Sdfr	    keys[i].principal = principal;
89178825Sdfr	    keys[i].vno = princ.kvno + 1; /* XXX get entry again */
90178825Sdfr	    keys[i].keyblock = k[i];
91178825Sdfr	    keys[i].timestamp = time(NULL);
92178825Sdfr	}
93178825Sdfr    }
94178825Sdfr
95178825Sdfr    for(i = 0; i < n_k; i++) {
96178825Sdfr	ret = krb5_kt_add_entry(context, e->keytab, &keys[i]);
9755682Smarkm	if(ret)
98178825Sdfr	    krb5_warn(context, ret, "krb5_kt_add_entry(%d)", i);
9955682Smarkm    }
100178825Sdfr
101178825Sdfr    if (k) {
102178825Sdfr	memset(k, 0, n_k * sizeof(*k));
103178825Sdfr	free(k);
104178825Sdfr    }
105178825Sdfr    if (keys)
106178825Sdfr	free(keys);
10755682Smarkm    kadm5_free_principal_ent(kadm_handle, &princ);
10855682Smarkm    return 0;
10955682Smarkm}
11055682Smarkm
11155682Smarkmint
112178825Sdfrext_keytab(struct ext_keytab_options *opt, int argc, char **argv)
11355682Smarkm{
11455682Smarkm    krb5_error_code ret;
11555682Smarkm    int i;
11655682Smarkm    struct ext_keytab_data data;
117178825Sdfr
118178825Sdfr    if (opt->keytab_string == NULL)
11990926Snectar	ret = krb5_kt_default(context, &data.keytab);
12090926Snectar    else
121178825Sdfr	ret = krb5_kt_resolve(context, opt->keytab_string, &data.keytab);
12290926Snectar
12355682Smarkm    if(ret){
12455682Smarkm	krb5_warn(context, ret, "krb5_kt_resolve");
125178825Sdfr	return 1;
12655682Smarkm    }
12755682Smarkm
128178825Sdfr    for(i = 0; i < argc; i++) {
129178825Sdfr	ret = foreach_principal(argv[i], do_ext_keytab, "ext", &data);
130178825Sdfr	if (ret)
131178825Sdfr	    break;
132178825Sdfr    }
13355682Smarkm
13455682Smarkm    krb5_kt_close(context, data.keytab);
13555682Smarkm
136178825Sdfr    return ret != 0;
13755682Smarkm}
138