1 /* $NetBSD: ext.c,v 1.3 2023/06/19 21:41:41 christos Exp $ */
2
3 /*
4 * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include "kadmin_locl.h"
37 #include "kadmin-commands.h"
38
39 struct ext_keytab_data {
40 krb5_keytab keytab;
41 int random_key_flag;
42 };
43
44 static int
do_ext_keytab(krb5_principal principal,void * data)45 do_ext_keytab(krb5_principal principal, void *data)
46 {
47 krb5_error_code ret;
48 kadm5_principal_ent_rec princ;
49 struct ext_keytab_data *e = data;
50 krb5_keytab_entry *keys = NULL;
51 krb5_keyblock *k = NULL;
52 size_t i;
53 int n_k = 0;
54 uint32_t mask;
55 char *unparsed = NULL;
56
57 mask = KADM5_PRINCIPAL;
58 if (!e->random_key_flag)
59 mask |= KADM5_KVNO | KADM5_KEY_DATA;
60
61 ret = kadm5_get_principal(kadm_handle, principal, &princ, mask);
62 if (ret)
63 return ret;
64
65 ret = krb5_unparse_name(context, principal, &unparsed);
66 if (ret)
67 goto out;
68
69 if (!e->random_key_flag) {
70 if (princ.n_key_data == 0) {
71 krb5_warnx(context, "principal has no keys, or user lacks "
72 "get-keys privilege for %s", unparsed);
73 goto out;
74 }
75 /*
76 * kadmin clients and servers from master between 1.5 and 1.6
77 * can have corrupted a principal's keys in the HDB. If some
78 * are bogus but not all are, then that must have happened.
79 *
80 * If all keys are bogus then the server may be a pre-1.6,
81 * post-1.5 server and the client lacks get-keys privilege, or
82 * the keys are corrupted. We can't tell here.
83 */
84 if (kadm5_all_keys_are_bogus(princ.n_key_data, princ.key_data)) {
85 krb5_warnx(context, "user lacks get-keys privilege for %s",
86 unparsed);
87 goto out;
88 }
89 if (kadm5_some_keys_are_bogus(princ.n_key_data, princ.key_data)) {
90 krb5_warnx(context, "some keys for %s are corrupted in the HDB",
91 unparsed);
92 }
93 keys = calloc(sizeof(*keys), princ.n_key_data);
94 if (keys == NULL) {
95 ret = krb5_enomem(context);
96 goto out;
97 }
98 for (i = 0; i < princ.n_key_data; i++) {
99 krb5_key_data *kd = &princ.key_data[i];
100
101 /* Don't extract bogus keys */
102 if (kadm5_all_keys_are_bogus(1, kd))
103 continue;
104
105 keys[i].principal = princ.principal;
106 keys[i].vno = kd->key_data_kvno;
107 keys[i].keyblock.keytype = kd->key_data_type[0];
108 keys[i].keyblock.keyvalue.length = kd->key_data_length[0];
109 keys[i].keyblock.keyvalue.data = kd->key_data_contents[0];
110 keys[i].timestamp = time(NULL);
111 n_k++;
112 }
113 } else if (e->random_key_flag) {
114 ret = kadm5_randkey_principal(kadm_handle, principal, &k, &n_k);
115 if (ret)
116 goto out;
117
118 keys = calloc(sizeof(*keys), n_k);
119 if (keys == NULL) {
120 ret = krb5_enomem(context);
121 goto out;
122 }
123 for (i = 0; i < n_k; i++) {
124 keys[i].principal = principal;
125 keys[i].vno = princ.kvno + 1; /* XXX get entry again */
126 keys[i].keyblock = k[i];
127 keys[i].timestamp = time(NULL);
128 }
129 }
130
131 if (n_k == 0)
132 krb5_warn(context, ret, "no keys written to keytab for %s", unparsed);
133
134 for (i = 0; i < n_k; i++) {
135 ret = krb5_kt_add_entry(context, e->keytab, &keys[i]);
136 if (ret)
137 krb5_warn(context, ret, "krb5_kt_add_entry(%lu)", (unsigned long)i);
138 }
139
140 out:
141 kadm5_free_principal_ent(kadm_handle, &princ);
142 if (k) {
143 for (i = 0; i < n_k; i++)
144 memset(k[i].keyvalue.data, 0, k[i].keyvalue.length);
145 free(k);
146 }
147 free(unparsed);
148 free(keys);
149 return ret;
150 }
151
152 int
ext_keytab(struct ext_keytab_options * opt,int argc,char ** argv)153 ext_keytab(struct ext_keytab_options *opt, int argc, char **argv)
154 {
155 krb5_error_code ret;
156 int i;
157 struct ext_keytab_data data;
158
159 if (opt->keytab_string == NULL)
160 ret = krb5_kt_default(context, &data.keytab);
161 else
162 ret = krb5_kt_resolve(context, opt->keytab_string, &data.keytab);
163
164 if(ret){
165 krb5_warn(context, ret, "krb5_kt_resolve");
166 return 1;
167 }
168
169 data.random_key_flag = opt->random_key_flag;
170
171 for(i = 0; i < argc; i++) {
172 ret = foreach_principal(argv[i], do_ext_keytab, "ext", &data);
173 if (ret)
174 break;
175 }
176
177 krb5_kt_close(context, data.keytab);
178
179 return ret != 0;
180 }
181