init.c revision 1.1.1.1
1/* $NetBSD: init.c,v 1.1.1.1 2011/04/13 18:14:35 elric 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 42static kadm5_ret_t 43create_random_entry(krb5_principal princ, 44 unsigned max_life, 45 unsigned max_rlife, 46 uint32_t attributes) 47{ 48 kadm5_principal_ent_rec ent; 49 kadm5_ret_t ret; 50 int mask = 0; 51 krb5_keyblock *keys; 52 int n_keys, i; 53 char *name; 54 const char *password; 55 char pwbuf[512]; 56 57 random_password(pwbuf, sizeof(pwbuf)); 58 password = pwbuf; 59 60 ret = krb5_unparse_name(context, princ, &name); 61 if (ret) { 62 krb5_warn(context, ret, "failed to unparse principal name"); 63 return ret; 64 } 65 66 memset(&ent, 0, sizeof(ent)); 67 ent.principal = princ; 68 mask |= KADM5_PRINCIPAL; 69 if (max_life) { 70 ent.max_life = max_life; 71 mask |= KADM5_MAX_LIFE; 72 } 73 if (max_rlife) { 74 ent.max_renewable_life = max_rlife; 75 mask |= KADM5_MAX_RLIFE; 76 } 77 ent.attributes |= attributes | KRB5_KDB_DISALLOW_ALL_TIX; 78 mask |= KADM5_ATTRIBUTES; 79 80 /* Create the entry with a random password */ 81 ret = kadm5_create_principal(kadm_handle, &ent, mask, password); 82 if(ret) { 83 krb5_warn(context, ret, "create_random_entry(%s): randkey failed", 84 name); 85 goto out; 86 } 87 88 /* Replace the string2key based keys with real random bytes */ 89 ret = kadm5_randkey_principal(kadm_handle, princ, &keys, &n_keys); 90 if(ret) { 91 krb5_warn(context, ret, "create_random_entry(%s): randkey failed", 92 name); 93 goto out; 94 } 95 for(i = 0; i < n_keys; i++) 96 krb5_free_keyblock_contents(context, &keys[i]); 97 free(keys); 98 ret = kadm5_get_principal(kadm_handle, princ, &ent, 99 KADM5_PRINCIPAL | KADM5_ATTRIBUTES); 100 if(ret) { 101 krb5_warn(context, ret, "create_random_entry(%s): " 102 "unable to get principal", name); 103 goto out; 104 } 105 ent.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX); 106 ent.kvno = 1; 107 ret = kadm5_modify_principal(kadm_handle, &ent, 108 KADM5_ATTRIBUTES|KADM5_KVNO); 109 kadm5_free_principal_ent (kadm_handle, &ent); 110 if(ret) { 111 krb5_warn(context, ret, "create_random_entry(%s): " 112 "unable to modify principal", name); 113 goto out; 114 } 115 out: 116 free(name); 117 return ret; 118} 119 120extern int local_flag; 121 122int 123init(struct init_options *opt, int argc, char **argv) 124{ 125 kadm5_ret_t ret; 126 int i; 127 HDB *db; 128 krb5_deltat max_life = 0, max_rlife = 0; 129 130 if (!local_flag) { 131 krb5_warnx(context, "init is only available in local (-l) mode"); 132 return 0; 133 } 134 135 if (opt->realm_max_ticket_life_string) { 136 if (str2deltat (opt->realm_max_ticket_life_string, &max_life) != 0) { 137 krb5_warnx (context, "unable to parse \"%s\"", 138 opt->realm_max_ticket_life_string); 139 return 0; 140 } 141 } 142 if (opt->realm_max_renewable_life_string) { 143 if (str2deltat (opt->realm_max_renewable_life_string, &max_rlife) != 0) { 144 krb5_warnx (context, "unable to parse \"%s\"", 145 opt->realm_max_renewable_life_string); 146 return 0; 147 } 148 } 149 150 db = _kadm5_s_get_db(kadm_handle); 151 152 ret = db->hdb_open(context, db, O_RDWR | O_CREAT, 0600); 153 if(ret){ 154 krb5_warn(context, ret, "hdb_open"); 155 return 0; 156 } 157 db->hdb_close(context, db); 158 for(i = 0; i < argc; i++){ 159 krb5_principal princ; 160 const char *realm = argv[i]; 161 162 if (opt->realm_max_ticket_life_string == NULL) { 163 max_life = 0; 164 if(edit_deltat ("Realm max ticket life", &max_life, NULL, 0)) { 165 return 0; 166 } 167 } 168 if (opt->realm_max_renewable_life_string == NULL) { 169 max_rlife = 0; 170 if(edit_deltat("Realm max renewable ticket life", &max_rlife, 171 NULL, 0)) { 172 return 0; 173 } 174 } 175 176 /* Create `krbtgt/REALM' */ 177 ret = krb5_make_principal(context, &princ, realm, 178 KRB5_TGS_NAME, realm, NULL); 179 if(ret) 180 return 0; 181 182 create_random_entry(princ, max_life, max_rlife, 0); 183 krb5_free_principal(context, princ); 184 185 if (opt->bare_flag) 186 continue; 187 188 /* Create `kadmin/changepw' */ 189 krb5_make_principal(context, &princ, realm, 190 "kadmin", "changepw", NULL); 191 /* 192 * The Windows XP (at least) password changing protocol 193 * request the `kadmin/changepw' ticket with `renewable_ok, 194 * renewable, forwardable' and so fails if we disallow 195 * forwardable here. 196 */ 197 create_random_entry(princ, 5*60, 5*60, 198 KRB5_KDB_DISALLOW_TGT_BASED| 199 KRB5_KDB_PWCHANGE_SERVICE| 200 KRB5_KDB_DISALLOW_POSTDATED| 201 KRB5_KDB_DISALLOW_RENEWABLE| 202 KRB5_KDB_DISALLOW_PROXIABLE| 203 KRB5_KDB_REQUIRES_PRE_AUTH); 204 krb5_free_principal(context, princ); 205 206 /* Create `kadmin/admin' */ 207 krb5_make_principal(context, &princ, realm, 208 "kadmin", "admin", NULL); 209 create_random_entry(princ, 60*60, 60*60, KRB5_KDB_REQUIRES_PRE_AUTH); 210 krb5_free_principal(context, princ); 211 212 /* Create `changepw/kerberos' (for v4 compat) */ 213 krb5_make_principal(context, &princ, realm, 214 "changepw", "kerberos", NULL); 215 create_random_entry(princ, 60*60, 60*60, 216 KRB5_KDB_DISALLOW_TGT_BASED| 217 KRB5_KDB_PWCHANGE_SERVICE); 218 219 krb5_free_principal(context, princ); 220 221 /* Create `kadmin/hprop' for database propagation */ 222 krb5_make_principal(context, &princ, realm, 223 "kadmin", "hprop", NULL); 224 create_random_entry(princ, 60*60, 60*60, 225 KRB5_KDB_REQUIRES_PRE_AUTH| 226 KRB5_KDB_DISALLOW_TGT_BASED); 227 krb5_free_principal(context, princ); 228 229 /* Create `WELLKNOWN/ANONYMOUS' for anonymous as-req */ 230 krb5_make_principal(context, &princ, realm, 231 KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL); 232 create_random_entry(princ, 60*60, 60*60, 233 KRB5_KDB_REQUIRES_PRE_AUTH); 234 krb5_free_principal(context, princ); 235 236 237 /* Create `default' */ 238 { 239 kadm5_principal_ent_rec ent; 240 int mask = 0; 241 242 memset (&ent, 0, sizeof(ent)); 243 mask |= KADM5_PRINCIPAL; 244 krb5_make_principal(context, &ent.principal, realm, 245 "default", NULL); 246 mask |= KADM5_MAX_LIFE; 247 ent.max_life = 24 * 60 * 60; 248 mask |= KADM5_MAX_RLIFE; 249 ent.max_renewable_life = 7 * ent.max_life; 250 ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX; 251 mask |= KADM5_ATTRIBUTES; 252 253 ret = kadm5_create_principal(kadm_handle, &ent, mask, ""); 254 if (ret) 255 krb5_err (context, 1, ret, "kadm5_create_principal"); 256 257 krb5_free_principal(context, ent.principal); 258 } 259 } 260 return 0; 261} 262