Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/admin/change.c
34865 views
1
/*
2
* Copyright (c) 1997-2005 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 krb5_error_code
39
change_entry (krb5_keytab keytab,
40
krb5_principal principal, krb5_kvno kvno,
41
const char *realm, const char *admin_server, int server_port)
42
{
43
krb5_error_code ret;
44
kadm5_config_params conf;
45
void *kadm_handle;
46
char *client_name;
47
krb5_keyblock *keys;
48
int num_keys;
49
int i;
50
51
ret = krb5_unparse_name (context, principal, &client_name);
52
if (ret) {
53
krb5_warn (context, ret, "krb5_unparse_name");
54
return ret;
55
}
56
57
memset (&conf, 0, sizeof(conf));
58
59
if(realm == NULL)
60
realm = krb5_principal_get_realm(context, principal);
61
conf.realm = strdup(realm);
62
if (conf.realm == NULL) {
63
free (client_name);
64
krb5_set_error_message(context, ENOMEM, "malloc failed");
65
return ENOMEM;
66
}
67
conf.mask |= KADM5_CONFIG_REALM;
68
69
if (admin_server) {
70
conf.admin_server = strdup(admin_server);
71
if (conf.admin_server == NULL) {
72
free(client_name);
73
free(conf.realm);
74
krb5_set_error_message(context, ENOMEM, "malloc failed");
75
return ENOMEM;
76
}
77
conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
78
}
79
80
if (server_port) {
81
conf.kadmind_port = htons(server_port);
82
conf.mask |= KADM5_CONFIG_KADMIND_PORT;
83
}
84
85
ret = kadm5_init_with_skey_ctx (context,
86
client_name,
87
keytab_string,
88
KADM5_ADMIN_SERVICE,
89
&conf, 0, 0,
90
&kadm_handle);
91
free(conf.admin_server);
92
free(conf.realm);
93
if (ret) {
94
krb5_warn (context, ret,
95
"kadm5_c_init_with_skey_ctx: %s:", client_name);
96
free (client_name);
97
return ret;
98
}
99
ret = kadm5_randkey_principal (kadm_handle, principal, &keys, &num_keys);
100
kadm5_destroy (kadm_handle);
101
if (ret) {
102
krb5_warn(context, ret, "kadm5_randkey_principal: %s:", client_name);
103
free (client_name);
104
return ret;
105
}
106
free (client_name);
107
for (i = 0; i < num_keys; ++i) {
108
krb5_keytab_entry new_entry;
109
110
new_entry.principal = principal;
111
new_entry.timestamp = time (NULL);
112
new_entry.vno = kvno + 1;
113
new_entry.keyblock = keys[i];
114
115
ret = krb5_kt_add_entry (context, keytab, &new_entry);
116
if (ret)
117
krb5_warn (context, ret, "krb5_kt_add_entry");
118
krb5_free_keyblock_contents (context, &keys[i]);
119
}
120
return ret;
121
}
122
123
/*
124
* loop over all the entries in the keytab (or those given) and change
125
* their keys, writing the new keys
126
*/
127
128
struct change_set {
129
krb5_principal principal;
130
krb5_kvno kvno;
131
};
132
133
int
134
kt_change (struct change_options *opt, int argc, char **argv)
135
{
136
krb5_error_code ret;
137
krb5_keytab keytab;
138
krb5_kt_cursor cursor;
139
krb5_keytab_entry entry;
140
int i, j, max;
141
struct change_set *changeset;
142
int errors = 0;
143
144
if((keytab = ktutil_open_keytab()) == NULL)
145
return 1;
146
147
j = 0;
148
max = 0;
149
changeset = NULL;
150
151
ret = krb5_kt_start_seq_get(context, keytab, &cursor);
152
if(ret){
153
krb5_warn(context, ret, "%s", keytab_string);
154
goto out;
155
}
156
157
while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
158
int add = 0;
159
160
for (i = 0; i < j; ++i) {
161
if (krb5_principal_compare (context, changeset[i].principal,
162
entry.principal)) {
163
if (changeset[i].kvno < entry.vno)
164
changeset[i].kvno = entry.vno;
165
break;
166
}
167
}
168
if (i < j) {
169
krb5_kt_free_entry (context, &entry);
170
continue;
171
}
172
173
if (argc == 0) {
174
add = 1;
175
} else {
176
for (i = 0; i < argc; ++i) {
177
krb5_principal princ;
178
179
ret = krb5_parse_name (context, argv[i], &princ);
180
if (ret) {
181
krb5_warn (context, ret, "%s", argv[i]);
182
continue;
183
}
184
if (krb5_principal_compare (context, princ, entry.principal))
185
add = 1;
186
187
krb5_free_principal (context, princ);
188
}
189
}
190
191
if (add) {
192
if (j >= max) {
193
void *tmp;
194
195
max = max(max * 2, 1);
196
tmp = realloc (changeset, max * sizeof(*changeset));
197
if (tmp == NULL) {
198
krb5_kt_free_entry (context, &entry);
199
krb5_warnx (context, "realloc: out of memory");
200
ret = ENOMEM;
201
break;
202
}
203
changeset = tmp;
204
}
205
ret = krb5_copy_principal (context, entry.principal,
206
&changeset[j].principal);
207
if (ret) {
208
krb5_warn (context, ret, "krb5_copy_principal");
209
krb5_kt_free_entry (context, &entry);
210
break;
211
}
212
changeset[j].kvno = entry.vno;
213
++j;
214
}
215
krb5_kt_free_entry (context, &entry);
216
}
217
krb5_kt_end_seq_get(context, keytab, &cursor);
218
219
if (ret == KRB5_KT_END) {
220
for (i = 0; i < j; i++) {
221
if (verbose_flag) {
222
char *client_name;
223
224
ret = krb5_unparse_name (context, changeset[i].principal,
225
&client_name);
226
if (ret) {
227
krb5_warn (context, ret, "krb5_unparse_name");
228
} else {
229
printf("Changing %s kvno %d\n",
230
client_name, changeset[i].kvno);
231
free(client_name);
232
}
233
}
234
ret = change_entry (keytab,
235
changeset[i].principal, changeset[i].kvno,
236
opt->realm_string,
237
opt->admin_server_string,
238
opt->server_port_integer);
239
if (ret != 0)
240
errors = 1;
241
}
242
} else
243
errors = 1;
244
for (i = 0; i < j; i++)
245
krb5_free_principal (context, changeset[i].principal);
246
free (changeset);
247
248
out:
249
krb5_kt_close(context, keytab);
250
return errors;
251
}
252
253