init.c revision 1.2
1/*	$NetBSD: init.c,v 1.2 2017/01/28 21:31:44 christos Exp $	*/
2
3/*
4 * Copyright (c) 1997-2004 Kungliga Tekniska H��gskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 *
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 *
21 * 3. Neither the name of the Institute nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38#include "kadmin_locl.h"
39#include "kadmin-commands.h"
40#include <kadm5/private.h>
41
42#define CRE_DUP_OK	1
43
44static kadm5_ret_t
45create_random_entry(krb5_principal princ,
46		    unsigned max_life,
47		    unsigned max_rlife,
48		    uint32_t attributes,
49		    unsigned flags)
50{
51    kadm5_principal_ent_rec ent;
52    kadm5_ret_t ret;
53    int mask = 0;
54    krb5_keyblock *keys;
55    int n_keys, i;
56    char *name;
57    const char *password;
58    char pwbuf[512];
59
60    random_password(pwbuf, sizeof(pwbuf));
61    password = pwbuf;
62
63    ret = krb5_unparse_name(context, princ, &name);
64    if (ret) {
65	krb5_warn(context, ret, "failed to unparse principal name");
66	return ret;
67    }
68
69    memset(&ent, 0, sizeof(ent));
70    ent.principal = princ;
71    mask |= KADM5_PRINCIPAL;
72    if (max_life) {
73	ent.max_life = max_life;
74	mask |= KADM5_MAX_LIFE;
75    }
76    if (max_rlife) {
77	ent.max_renewable_life = max_rlife;
78	mask |= KADM5_MAX_RLIFE;
79    }
80    ent.attributes |= attributes | KRB5_KDB_DISALLOW_ALL_TIX;
81    mask |= KADM5_ATTRIBUTES;
82
83    /* Create the entry with a random password */
84    ret = kadm5_create_principal(kadm_handle, &ent, mask, password);
85    if(ret) {
86	if (ret == KADM5_DUP && (flags & CRE_DUP_OK))
87	    goto out;
88	krb5_warn(context, ret, "create_random_entry(%s): randkey failed",
89		  name);
90	goto out;
91    }
92
93    /* Replace the string2key based keys with real random bytes */
94    ret = kadm5_randkey_principal(kadm_handle, princ, &keys, &n_keys);
95    if(ret) {
96	krb5_warn(context, ret, "create_random_entry(%s): randkey failed",
97		  name);
98	goto out;
99    }
100    for(i = 0; i < n_keys; i++)
101	krb5_free_keyblock_contents(context, &keys[i]);
102    free(keys);
103    ret = kadm5_get_principal(kadm_handle, princ, &ent,
104			      KADM5_PRINCIPAL | KADM5_ATTRIBUTES);
105    if(ret) {
106	krb5_warn(context, ret, "create_random_entry(%s): "
107		  "unable to get principal", name);
108	goto out;
109    }
110    ent.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
111    ent.kvno = 1;
112    ret = kadm5_modify_principal(kadm_handle, &ent,
113				 KADM5_ATTRIBUTES|KADM5_KVNO);
114    kadm5_free_principal_ent (kadm_handle, &ent);
115    if(ret) {
116	krb5_warn(context, ret, "create_random_entry(%s): "
117		  "unable to modify principal", name);
118	goto out;
119    }
120 out:
121    free(name);
122    return ret;
123}
124
125extern int local_flag;
126
127int
128init(struct init_options *opt, int argc, char **argv)
129{
130    kadm5_ret_t ret;
131    int i;
132    HDB *db;
133    krb5_deltat max_life = 0, max_rlife = 0;
134
135    if (!local_flag) {
136	krb5_warnx(context, "init is only available in local (-l) mode");
137	return 0;
138    }
139
140    if (opt->realm_max_ticket_life_string) {
141	if (str2deltat (opt->realm_max_ticket_life_string, &max_life) != 0) {
142	    krb5_warnx (context, "unable to parse \"%s\"",
143			opt->realm_max_ticket_life_string);
144	    return 0;
145	}
146    }
147    if (opt->realm_max_renewable_life_string) {
148	if (str2deltat (opt->realm_max_renewable_life_string, &max_rlife) != 0) {
149	    krb5_warnx (context, "unable to parse \"%s\"",
150			opt->realm_max_renewable_life_string);
151	    return 0;
152	}
153    }
154
155    db = _kadm5_s_get_db(kadm_handle);
156
157    ret = db->hdb_open(context, db, O_RDWR | O_CREAT, 0600);
158    if(ret){
159	krb5_warn(context, ret, "hdb_open");
160	return 0;
161    }
162    ret = kadm5_log_reinit(kadm_handle, 0);
163    if (ret)
164        krb5_err(context, 1, ret, "Failed iprop log initialization");
165    kadm5_log_end(kadm_handle);
166    db->hdb_close(context, db);
167    for(i = 0; i < argc; i++){
168	krb5_principal princ;
169	const char *realm = argv[i];
170
171	if (opt->realm_max_ticket_life_string == NULL) {
172	    max_life = 0;
173	    if(edit_deltat ("Realm max ticket life", &max_life, NULL, 0)) {
174		return 0;
175	    }
176	}
177	if (opt->realm_max_renewable_life_string == NULL) {
178	    max_rlife = 0;
179	    if(edit_deltat("Realm max renewable ticket life", &max_rlife,
180			   NULL, 0)) {
181		return 0;
182	    }
183	}
184
185	/* Create `krbtgt/REALM' */
186	ret = krb5_make_principal(context, &princ, realm,
187				  KRB5_TGS_NAME, realm, NULL);
188	if(ret)
189	    return 0;
190
191	create_random_entry(princ, max_life, max_rlife, 0, 0);
192	krb5_free_principal(context, princ);
193
194	if (opt->bare_flag)
195	    continue;
196
197	/* Create `kadmin/changepw' */
198	krb5_make_principal(context, &princ, realm,
199			    "kadmin", "changepw", NULL);
200	/*
201	 * The Windows XP (at least) password changing protocol
202	 * request the `kadmin/changepw' ticket with `renewable_ok,
203	 * renewable, forwardable' and so fails if we disallow
204	 * forwardable here.
205	 */
206	create_random_entry(princ, 5*60, 5*60,
207			    KRB5_KDB_DISALLOW_TGT_BASED|
208			    KRB5_KDB_PWCHANGE_SERVICE|
209			    KRB5_KDB_DISALLOW_POSTDATED|
210			    KRB5_KDB_DISALLOW_RENEWABLE|
211			    KRB5_KDB_DISALLOW_PROXIABLE|
212			    KRB5_KDB_REQUIRES_PRE_AUTH,
213			    0);
214	krb5_free_principal(context, princ);
215
216	/* Create `kadmin/admin' */
217	krb5_make_principal(context, &princ, realm,
218			    "kadmin", "admin", NULL);
219	create_random_entry(princ, 60*60, 60*60, KRB5_KDB_REQUIRES_PRE_AUTH, 0);
220	krb5_free_principal(context, princ);
221
222	/* Create `changepw/kerberos' (for v4 compat) */
223	krb5_make_principal(context, &princ, realm,
224			    "changepw", "kerberos", NULL);
225	create_random_entry(princ, 60*60, 60*60,
226			    KRB5_KDB_DISALLOW_TGT_BASED|
227			    KRB5_KDB_PWCHANGE_SERVICE, 0);
228
229	krb5_free_principal(context, princ);
230
231	/* Create `kadmin/hprop' for database propagation */
232	krb5_make_principal(context, &princ, realm,
233			    "kadmin", "hprop", NULL);
234	create_random_entry(princ, 60*60, 60*60,
235			    KRB5_KDB_REQUIRES_PRE_AUTH|
236			    KRB5_KDB_DISALLOW_TGT_BASED, 0);
237	krb5_free_principal(context, princ);
238
239	/* Create `WELLKNOWN/ANONYMOUS' for anonymous as-req */
240	krb5_make_principal(context, &princ, realm,
241			    KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL);
242	create_random_entry(princ, 60*60, 60*60,
243			    KRB5_KDB_REQUIRES_PRE_AUTH, 0);
244	krb5_free_principal(context, princ);
245
246
247	/* Create `WELLKNONW/org.h5l.fast-cookie@WELLKNOWN:ORG.H5L' for FAST cookie */
248	krb5_make_principal(context, &princ, KRB5_WELLKNOWN_ORG_H5L_REALM,
249			    KRB5_WELLKNOWN_NAME, "org.h5l.fast-cookie", NULL);
250	create_random_entry(princ, 60*60, 60*60,
251			    KRB5_KDB_REQUIRES_PRE_AUTH|
252			    KRB5_KDB_DISALLOW_TGT_BASED|
253			    KRB5_KDB_DISALLOW_ALL_TIX, CRE_DUP_OK);
254	krb5_free_principal(context, princ);
255
256	/* Create `default' */
257	{
258	    kadm5_principal_ent_rec ent;
259	    int mask = 0;
260
261	    memset (&ent, 0, sizeof(ent));
262	    mask |= KADM5_PRINCIPAL;
263	    krb5_make_principal(context, &ent.principal, realm,
264				"default", NULL);
265	    mask |= KADM5_MAX_LIFE;
266	    ent.max_life = 24 * 60 * 60;
267	    mask |= KADM5_MAX_RLIFE;
268	    ent.max_renewable_life = 7 * ent.max_life;
269	    ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX;
270	    mask |= KADM5_ATTRIBUTES;
271
272	    ret = kadm5_create_principal(kadm_handle, &ent, mask, "");
273	    if (ret)
274		krb5_err (context, 1, ret, "kadm5_create_principal");
275
276	    krb5_free_principal(context, ent.principal);
277	}
278    }
279    return 0;
280}
281