heimdal kerberos - fix memory leak (free the plugin list always - not only in error...
[heimdal.git] / kadmin / init.c
blob62ff55dedfbab31370defa580aa73fd7bf008a5b
1 /*
2 * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 #include "kadmin_locl.h"
35 #include "kadmin-commands.h"
36 #include <kadm5/private.h>
38 RCSID("$Id$");
40 static kadm5_ret_t
41 create_random_entry(krb5_principal princ,
42 unsigned max_life,
43 unsigned max_rlife,
44 uint32_t attributes)
46 kadm5_principal_ent_rec ent;
47 kadm5_ret_t ret;
48 int mask = 0;
49 krb5_keyblock *keys;
50 int n_keys, i;
51 char *name;
52 const char *password;
53 char pwbuf[512];
55 random_password(pwbuf, sizeof(pwbuf));
56 password = pwbuf;
58 ret = krb5_unparse_name(context, princ, &name);
59 if (ret) {
60 krb5_warn(context, ret, "failed to unparse principal name");
61 return ret;
64 memset(&ent, 0, sizeof(ent));
65 ent.principal = princ;
66 mask |= KADM5_PRINCIPAL;
67 if (max_life) {
68 ent.max_life = max_life;
69 mask |= KADM5_MAX_LIFE;
71 if (max_rlife) {
72 ent.max_renewable_life = max_rlife;
73 mask |= KADM5_MAX_RLIFE;
75 ent.attributes |= attributes | KRB5_KDB_DISALLOW_ALL_TIX;
76 mask |= KADM5_ATTRIBUTES;
78 /* Create the entry with a random password */
79 ret = kadm5_create_principal(kadm_handle, &ent, mask, password);
80 if(ret) {
81 krb5_warn(context, ret, "create_random_entry(%s): randkey failed",
82 name);
83 goto out;
86 /* Replace the string2key based keys with real random bytes */
87 ret = kadm5_randkey_principal(kadm_handle, princ, &keys, &n_keys);
88 if(ret) {
89 krb5_warn(context, ret, "create_random_entry(%s): randkey failed",
90 name);
91 goto out;
93 for(i = 0; i < n_keys; i++)
94 krb5_free_keyblock_contents(context, &keys[i]);
95 free(keys);
96 ret = kadm5_get_principal(kadm_handle, princ, &ent,
97 KADM5_PRINCIPAL | KADM5_ATTRIBUTES);
98 if(ret) {
99 krb5_warn(context, ret, "create_random_entry(%s): "
100 "unable to get principal", name);
101 goto out;
103 ent.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
104 ent.kvno = 1;
105 ret = kadm5_modify_principal(kadm_handle, &ent,
106 KADM5_ATTRIBUTES|KADM5_KVNO);
107 kadm5_free_principal_ent (kadm_handle, &ent);
108 if(ret) {
109 krb5_warn(context, ret, "create_random_entry(%s): "
110 "unable to modify principal", name);
111 goto out;
113 out:
114 free(name);
115 return ret;
118 extern int local_flag;
121 init(struct init_options *opt, int argc, char **argv)
123 kadm5_ret_t ret;
124 int i;
125 HDB *db;
126 krb5_deltat max_life, max_rlife;
128 if(!local_flag) {
129 krb5_warnx(context, "init is only available in local (-l) mode");
130 return 0;
133 if (opt->realm_max_ticket_life_string) {
134 if (str2deltat (opt->realm_max_ticket_life_string, &max_life) != 0) {
135 krb5_warnx (context, "unable to parse \"%s\"",
136 opt->realm_max_ticket_life_string);
137 return 0;
140 if (opt->realm_max_renewable_life_string) {
141 if (str2deltat (opt->realm_max_renewable_life_string, &max_rlife) != 0) {
142 krb5_warnx (context, "unable to parse \"%s\"",
143 opt->realm_max_renewable_life_string);
144 return 0;
148 db = _kadm5_s_get_db(kadm_handle);
150 ret = db->hdb_open(context, db, O_RDWR | O_CREAT, 0600);
151 if(ret){
152 krb5_warn(context, ret, "hdb_open");
153 return 0;
155 db->hdb_close(context, db);
156 for(i = 0; i < argc; i++){
157 krb5_principal princ;
158 const char *realm = argv[i];
160 /* Create `krbtgt/REALM' */
161 ret = krb5_make_principal(context, &princ, realm,
162 KRB5_TGS_NAME, realm, NULL);
163 if(ret)
164 return 0;
165 if (opt->realm_max_ticket_life_string == NULL) {
166 max_life = 0;
167 if(edit_deltat ("Realm max ticket life", &max_life, NULL, 0)) {
168 krb5_free_principal(context, princ);
169 return 0;
172 if (opt->realm_max_renewable_life_string == NULL) {
173 max_rlife = 0;
174 if(edit_deltat("Realm max renewable ticket life", &max_rlife,
175 NULL, 0)) {
176 krb5_free_principal(context, princ);
177 return 0;
180 create_random_entry(princ, max_life, max_rlife, 0);
181 krb5_free_principal(context, princ);
183 /* Create `kadmin/changepw' */
184 krb5_make_principal(context, &princ, realm,
185 "kadmin", "changepw", NULL);
187 * The Windows XP (at least) password changing protocol
188 * request the `kadmin/changepw' ticket with `renewable_ok,
189 * renewable, forwardable' and so fails if we disallow
190 * forwardable here.
192 create_random_entry(princ, 5*60, 5*60,
193 KRB5_KDB_DISALLOW_TGT_BASED|
194 KRB5_KDB_PWCHANGE_SERVICE|
195 KRB5_KDB_DISALLOW_POSTDATED|
196 KRB5_KDB_DISALLOW_RENEWABLE|
197 KRB5_KDB_DISALLOW_PROXIABLE|
198 KRB5_KDB_REQUIRES_PRE_AUTH);
199 krb5_free_principal(context, princ);
201 /* Create `kadmin/admin' */
202 krb5_make_principal(context, &princ, realm,
203 "kadmin", "admin", NULL);
204 create_random_entry(princ, 60*60, 60*60, KRB5_KDB_REQUIRES_PRE_AUTH);
205 krb5_free_principal(context, princ);
207 /* Create `changepw/kerberos' (for v4 compat) */
208 krb5_make_principal(context, &princ, realm,
209 "changepw", "kerberos", NULL);
210 create_random_entry(princ, 60*60, 60*60,
211 KRB5_KDB_DISALLOW_TGT_BASED|
212 KRB5_KDB_PWCHANGE_SERVICE);
214 krb5_free_principal(context, princ);
216 /* Create `kadmin/hprop' for database propagation */
217 krb5_make_principal(context, &princ, realm,
218 "kadmin", "hprop", NULL);
219 create_random_entry(princ, 60*60, 60*60,
220 KRB5_KDB_REQUIRES_PRE_AUTH|
221 KRB5_KDB_DISALLOW_TGT_BASED);
222 krb5_free_principal(context, princ);
224 /* Create `WELLKNOWN/ANONYMOUS' for anonymous as-req */
225 krb5_make_principal(context, &princ, realm,
226 KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL);
227 create_random_entry(princ, 60*60, 60*60,
228 KRB5_KDB_REQUIRES_PRE_AUTH);
229 krb5_free_principal(context, princ);
232 /* Create `default' */
234 kadm5_principal_ent_rec ent;
235 int mask = 0;
237 memset (&ent, 0, sizeof(ent));
238 mask |= KADM5_PRINCIPAL;
239 krb5_make_principal(context, &ent.principal, realm,
240 "default", NULL);
241 mask |= KADM5_MAX_LIFE;
242 ent.max_life = 24 * 60 * 60;
243 mask |= KADM5_MAX_RLIFE;
244 ent.max_renewable_life = 7 * ent.max_life;
245 ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX;
246 mask |= KADM5_ATTRIBUTES;
248 ret = kadm5_create_principal(kadm_handle, &ent, mask, "");
249 if (ret)
250 krb5_err (context, 1, ret, "kadm5_create_principal");
252 krb5_free_principal(context, ent.principal);
255 return 0;