1 /*
2 * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Portions Copyright (c) 2009 Apple Inc. 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 #include <kadm5/private.h>
39
40 static kadm5_ret_t
create_random_entry(krb5_principal princ,unsigned max_life,unsigned max_rlife,uint32_t attributes)41 create_random_entry(krb5_principal princ,
42 unsigned max_life,
43 unsigned max_rlife,
44 uint32_t attributes)
45 {
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];
54
55 random_password(pwbuf, sizeof(pwbuf));
56 password = pwbuf;
57
58 ret = krb5_unparse_name(context, princ, &name);
59 if (ret) {
60 krb5_warn(context, ret, "failed to unparse principal name");
61 return ret;
62 }
63
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;
70 }
71 if (max_rlife) {
72 ent.max_renewable_life = max_rlife;
73 mask |= KADM5_MAX_RLIFE;
74 }
75 ent.attributes |= attributes | KRB5_KDB_DISALLOW_ALL_TIX;
76 mask |= KADM5_ATTRIBUTES;
77
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;
84 }
85
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;
92 }
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;
102 }
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;
112 }
113 out:
114 free(name);
115 return ret;
116 }
117
118 extern int local_flag;
119
120 int
init(struct init_options * opt,int argc,char ** argv)121 init(struct init_options *opt, int argc, char **argv)
122 {
123 kadm5_ret_t ret;
124 int i;
125 HDB *db;
126 krb5_deltat max_life = 0, max_rlife = 0;
127
128 if (!local_flag) {
129 krb5_warnx(context, "init is only available in local (-l) mode");
130 return 0;
131 }
132
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;
138 }
139 }
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;
145 }
146 }
147
148 db = _kadm5_s_get_db(kadm_handle);
149
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;
154 }
155 db->hdb_close(context, db);
156 for(i = 0; i < argc; i++){
157 krb5_principal princ;
158 const char *realm = argv[i];
159
160 if (opt->realm_max_ticket_life_string == NULL) {
161 max_life = 0;
162 if(edit_deltat ("Realm max ticket life", &max_life, NULL, 0)) {
163 return 0;
164 }
165 }
166 if (opt->realm_max_renewable_life_string == NULL) {
167 max_rlife = 0;
168 if(edit_deltat("Realm max renewable ticket life", &max_rlife,
169 NULL, 0)) {
170 return 0;
171 }
172 }
173
174 /* Create `krbtgt/REALM' */
175 ret = krb5_make_principal(context, &princ, realm,
176 KRB5_TGS_NAME, realm, NULL);
177 if(ret)
178 return 0;
179
180 create_random_entry(princ, max_life, max_rlife, 0);
181 krb5_free_principal(context, princ);
182
183 if (opt->bare_flag)
184 continue;
185
186 /* Create `kadmin/changepw' */
187 krb5_make_principal(context, &princ, realm,
188 "kadmin", "changepw", NULL);
189 /*
190 * The Windows XP (at least) password changing protocol
191 * request the `kadmin/changepw' ticket with `renewable_ok,
192 * renewable, forwardable' and so fails if we disallow
193 * forwardable here.
194 */
195 create_random_entry(princ, 5*60, 5*60,
196 KRB5_KDB_DISALLOW_TGT_BASED|
197 KRB5_KDB_PWCHANGE_SERVICE|
198 KRB5_KDB_DISALLOW_POSTDATED|
199 KRB5_KDB_DISALLOW_RENEWABLE|
200 KRB5_KDB_DISALLOW_PROXIABLE|
201 KRB5_KDB_REQUIRES_PRE_AUTH);
202 krb5_free_principal(context, princ);
203
204 /* Create `kadmin/admin' */
205 krb5_make_principal(context, &princ, realm,
206 "kadmin", "admin", NULL);
207 create_random_entry(princ, 60*60, 60*60, KRB5_KDB_REQUIRES_PRE_AUTH);
208 krb5_free_principal(context, princ);
209
210 /* Create `changepw/kerberos' (for v4 compat) */
211 krb5_make_principal(context, &princ, realm,
212 "changepw", "kerberos", NULL);
213 create_random_entry(princ, 60*60, 60*60,
214 KRB5_KDB_DISALLOW_TGT_BASED|
215 KRB5_KDB_PWCHANGE_SERVICE);
216
217 krb5_free_principal(context, princ);
218
219 /* Create `kadmin/hprop' for database propagation */
220 krb5_make_principal(context, &princ, realm,
221 "kadmin", "hprop", NULL);
222 create_random_entry(princ, 60*60, 60*60,
223 KRB5_KDB_REQUIRES_PRE_AUTH|
224 KRB5_KDB_DISALLOW_TGT_BASED);
225 krb5_free_principal(context, princ);
226
227 /* Create `WELLKNOWN/ANONYMOUS' for anonymous as-req */
228 krb5_make_principal(context, &princ, realm,
229 KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL);
230 create_random_entry(princ, 60*60, 60*60,
231 KRB5_KDB_REQUIRES_PRE_AUTH);
232 krb5_free_principal(context, princ);
233
234
235 /* Create `default' */
236 {
237 kadm5_principal_ent_rec ent;
238 int mask = 0;
239
240 memset (&ent, 0, sizeof(ent));
241 mask |= KADM5_PRINCIPAL;
242 krb5_make_principal(context, &ent.principal, realm,
243 "default", NULL);
244 mask |= KADM5_MAX_LIFE;
245 ent.max_life = 24 * 60 * 60;
246 mask |= KADM5_MAX_RLIFE;
247 ent.max_renewable_life = 7 * ent.max_life;
248 ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX;
249 mask |= KADM5_ATTRIBUTES;
250
251 ret = kadm5_create_principal(kadm_handle, &ent, mask, "");
252 if (ret)
253 krb5_err (context, 1, ret, "kadm5_create_principal");
254
255 krb5_free_principal(context, ent.principal);
256 }
257 }
258 return 0;
259 }
260