155682Smarkm/* 2233294Sstas * Copyright (c) 1997-2004 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 755682Smarkm * 8233294Sstas * Redistribution and use in source and binary forms, with or without 9233294Sstas * modification, are permitted provided that the following conditions 10233294Sstas * are met: 1155682Smarkm * 12233294Sstas * 1. Redistributions of source code must retain the above copyright 13233294Sstas * notice, this list of conditions and the following disclaimer. 1455682Smarkm * 15233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 16233294Sstas * notice, this list of conditions and the following disclaimer in the 17233294Sstas * documentation and/or other materials provided with the distribution. 1855682Smarkm * 19233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 20233294Sstas * may be used to endorse or promote products derived from this software 21233294Sstas * without specific prior written permission. 22233294Sstas * 23233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33233294Sstas * SUCH DAMAGE. 3455682Smarkm */ 3555682Smarkm 3655682Smarkm#include "kadmin_locl.h" 37178825Sdfr#include "kadmin-commands.h" 3855682Smarkm#include <kadm5/private.h> 3955682Smarkm 4055682Smarkmstatic kadm5_ret_t 4155682Smarkmcreate_random_entry(krb5_principal princ, 4255682Smarkm unsigned max_life, 4355682Smarkm unsigned max_rlife, 44178825Sdfr uint32_t attributes) 4555682Smarkm{ 4655682Smarkm kadm5_principal_ent_rec ent; 4755682Smarkm kadm5_ret_t ret; 4855682Smarkm int mask = 0; 4955682Smarkm krb5_keyblock *keys; 5055682Smarkm int n_keys, i; 51178825Sdfr char *name; 52178825Sdfr const char *password; 53178825Sdfr char pwbuf[512]; 5455682Smarkm 55178825Sdfr random_password(pwbuf, sizeof(pwbuf)); 56178825Sdfr password = pwbuf; 57178825Sdfr 58178825Sdfr ret = krb5_unparse_name(context, princ, &name); 59178825Sdfr if (ret) { 60178825Sdfr krb5_warn(context, ret, "failed to unparse principal name"); 61178825Sdfr return ret; 62178825Sdfr } 63178825Sdfr 6455682Smarkm memset(&ent, 0, sizeof(ent)); 6555682Smarkm ent.principal = princ; 6655682Smarkm mask |= KADM5_PRINCIPAL; 6755682Smarkm if (max_life) { 6855682Smarkm ent.max_life = max_life; 6955682Smarkm mask |= KADM5_MAX_LIFE; 7055682Smarkm } 7155682Smarkm if (max_rlife) { 7255682Smarkm ent.max_renewable_life = max_rlife; 7355682Smarkm mask |= KADM5_MAX_RLIFE; 7455682Smarkm } 7555682Smarkm ent.attributes |= attributes | KRB5_KDB_DISALLOW_ALL_TIX; 7655682Smarkm mask |= KADM5_ATTRIBUTES; 7755682Smarkm 78178825Sdfr /* Create the entry with a random password */ 79178825Sdfr ret = kadm5_create_principal(kadm_handle, &ent, mask, password); 80178825Sdfr if(ret) { 81233294Sstas krb5_warn(context, ret, "create_random_entry(%s): randkey failed", 82178825Sdfr name); 83178825Sdfr goto out; 84178825Sdfr } 85233294Sstas 86178825Sdfr /* Replace the string2key based keys with real random bytes */ 8755682Smarkm ret = kadm5_randkey_principal(kadm_handle, princ, &keys, &n_keys); 88178825Sdfr if(ret) { 89233294Sstas krb5_warn(context, ret, "create_random_entry(%s): randkey failed", 90178825Sdfr name); 91178825Sdfr goto out; 92178825Sdfr } 9355682Smarkm for(i = 0; i < n_keys; i++) 9455682Smarkm krb5_free_keyblock_contents(context, &keys[i]); 9555682Smarkm free(keys); 96233294Sstas ret = kadm5_get_principal(kadm_handle, princ, &ent, 9755682Smarkm KADM5_PRINCIPAL | KADM5_ATTRIBUTES); 98178825Sdfr if(ret) { 99178825Sdfr krb5_warn(context, ret, "create_random_entry(%s): " 100178825Sdfr "unable to get principal", name); 101178825Sdfr goto out; 102178825Sdfr } 10355682Smarkm ent.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX); 10455682Smarkm ent.kvno = 1; 105233294Sstas ret = kadm5_modify_principal(kadm_handle, &ent, 10655682Smarkm KADM5_ATTRIBUTES|KADM5_KVNO); 10755682Smarkm kadm5_free_principal_ent (kadm_handle, &ent); 108178825Sdfr if(ret) { 109178825Sdfr krb5_warn(context, ret, "create_random_entry(%s): " 110178825Sdfr "unable to modify principal", name); 111178825Sdfr goto out; 112178825Sdfr } 113178825Sdfr out: 114178825Sdfr free(name); 115178825Sdfr return ret; 11655682Smarkm} 11755682Smarkm 118178825Sdfrextern int local_flag; 11955682Smarkm 12055682Smarkmint 121178825Sdfrinit(struct init_options *opt, int argc, char **argv) 12255682Smarkm{ 12355682Smarkm kadm5_ret_t ret; 12455682Smarkm int i; 12555682Smarkm HDB *db; 126233294Sstas krb5_deltat max_life = 0, max_rlife = 0; 12755682Smarkm 128233294Sstas if (!local_flag) { 129178825Sdfr krb5_warnx(context, "init is only available in local (-l) mode"); 13055682Smarkm return 0; 13155682Smarkm } 13255682Smarkm 133178825Sdfr if (opt->realm_max_ticket_life_string) { 134178825Sdfr if (str2deltat (opt->realm_max_ticket_life_string, &max_life) != 0) { 135233294Sstas krb5_warnx (context, "unable to parse \"%s\"", 136178825Sdfr opt->realm_max_ticket_life_string); 13755682Smarkm return 0; 13855682Smarkm } 13955682Smarkm } 140178825Sdfr if (opt->realm_max_renewable_life_string) { 141178825Sdfr if (str2deltat (opt->realm_max_renewable_life_string, &max_rlife) != 0) { 142233294Sstas krb5_warnx (context, "unable to parse \"%s\"", 143178825Sdfr opt->realm_max_renewable_life_string); 14455682Smarkm return 0; 14555682Smarkm } 14655682Smarkm } 14755682Smarkm 14855682Smarkm db = _kadm5_s_get_db(kadm_handle); 14955682Smarkm 150178825Sdfr ret = db->hdb_open(context, db, O_RDWR | O_CREAT, 0600); 15155682Smarkm if(ret){ 15255682Smarkm krb5_warn(context, ret, "hdb_open"); 15355682Smarkm return 0; 15455682Smarkm } 155178825Sdfr db->hdb_close(context, db); 156178825Sdfr for(i = 0; i < argc; i++){ 15755682Smarkm krb5_principal princ; 15855682Smarkm const char *realm = argv[i]; 15955682Smarkm 160178825Sdfr if (opt->realm_max_ticket_life_string == NULL) { 16155682Smarkm max_life = 0; 162120945Snectar if(edit_deltat ("Realm max ticket life", &max_life, NULL, 0)) { 163120945Snectar return 0; 164120945Snectar } 16555682Smarkm } 166178825Sdfr if (opt->realm_max_renewable_life_string == NULL) { 16755682Smarkm max_rlife = 0; 168120945Snectar if(edit_deltat("Realm max renewable ticket life", &max_rlife, 169120945Snectar NULL, 0)) { 170120945Snectar return 0; 171120945Snectar } 17255682Smarkm } 173233294Sstas 174233294Sstas /* Create `krbtgt/REALM' */ 175233294Sstas ret = krb5_make_principal(context, &princ, realm, 176233294Sstas KRB5_TGS_NAME, realm, NULL); 177233294Sstas if(ret) 178233294Sstas return 0; 179233294Sstas 18055682Smarkm create_random_entry(princ, max_life, max_rlife, 0); 18155682Smarkm krb5_free_principal(context, princ); 18255682Smarkm 183233294Sstas if (opt->bare_flag) 184233294Sstas continue; 185233294Sstas 18655682Smarkm /* Create `kadmin/changepw' */ 187233294Sstas krb5_make_principal(context, &princ, realm, 18855682Smarkm "kadmin", "changepw", NULL); 189178825Sdfr /* 190178825Sdfr * The Windows XP (at least) password changing protocol 191178825Sdfr * request the `kadmin/changepw' ticket with `renewable_ok, 192178825Sdfr * renewable, forwardable' and so fails if we disallow 193178825Sdfr * forwardable here. 194178825Sdfr */ 195233294Sstas create_random_entry(princ, 5*60, 5*60, 19655682Smarkm KRB5_KDB_DISALLOW_TGT_BASED| 19755682Smarkm KRB5_KDB_PWCHANGE_SERVICE| 19855682Smarkm KRB5_KDB_DISALLOW_POSTDATED| 19955682Smarkm KRB5_KDB_DISALLOW_RENEWABLE| 20055682Smarkm KRB5_KDB_DISALLOW_PROXIABLE| 20155682Smarkm KRB5_KDB_REQUIRES_PRE_AUTH); 20255682Smarkm krb5_free_principal(context, princ); 20355682Smarkm 20455682Smarkm /* Create `kadmin/admin' */ 205233294Sstas krb5_make_principal(context, &princ, realm, 20655682Smarkm "kadmin", "admin", NULL); 20755682Smarkm create_random_entry(princ, 60*60, 60*60, KRB5_KDB_REQUIRES_PRE_AUTH); 20855682Smarkm krb5_free_principal(context, princ); 20955682Smarkm 21055682Smarkm /* Create `changepw/kerberos' (for v4 compat) */ 21155682Smarkm krb5_make_principal(context, &princ, realm, 21255682Smarkm "changepw", "kerberos", NULL); 21372445Sassar create_random_entry(princ, 60*60, 60*60, 21472445Sassar KRB5_KDB_DISALLOW_TGT_BASED| 21572445Sassar KRB5_KDB_PWCHANGE_SERVICE); 21672445Sassar 21755682Smarkm krb5_free_principal(context, princ); 21855682Smarkm 21972445Sassar /* Create `kadmin/hprop' for database propagation */ 22072445Sassar krb5_make_principal(context, &princ, realm, 22172445Sassar "kadmin", "hprop", NULL); 22272445Sassar create_random_entry(princ, 60*60, 60*60, 22372445Sassar KRB5_KDB_REQUIRES_PRE_AUTH| 22472445Sassar KRB5_KDB_DISALLOW_TGT_BASED); 22572445Sassar krb5_free_principal(context, princ); 22672445Sassar 227233294Sstas /* Create `WELLKNOWN/ANONYMOUS' for anonymous as-req */ 228233294Sstas krb5_make_principal(context, &princ, realm, 229233294Sstas KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL); 230233294Sstas create_random_entry(princ, 60*60, 60*60, 231233294Sstas KRB5_KDB_REQUIRES_PRE_AUTH); 232233294Sstas krb5_free_principal(context, princ); 233233294Sstas 234233294Sstas 23555682Smarkm /* Create `default' */ 23655682Smarkm { 23755682Smarkm kadm5_principal_ent_rec ent; 23855682Smarkm int mask = 0; 23955682Smarkm 24055682Smarkm memset (&ent, 0, sizeof(ent)); 24155682Smarkm mask |= KADM5_PRINCIPAL; 24255682Smarkm krb5_make_principal(context, &ent.principal, realm, 24355682Smarkm "default", NULL); 24455682Smarkm mask |= KADM5_MAX_LIFE; 24555682Smarkm ent.max_life = 24 * 60 * 60; 24655682Smarkm mask |= KADM5_MAX_RLIFE; 24755682Smarkm ent.max_renewable_life = 7 * ent.max_life; 24855682Smarkm ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX; 24955682Smarkm mask |= KADM5_ATTRIBUTES; 25055682Smarkm 25155682Smarkm ret = kadm5_create_principal(kadm_handle, &ent, mask, ""); 25255682Smarkm if (ret) 25355682Smarkm krb5_err (context, 1, ret, "kadm5_create_principal"); 25455682Smarkm 25555682Smarkm krb5_free_principal(context, ent.principal); 25655682Smarkm } 25755682Smarkm } 25855682Smarkm return 0; 25955682Smarkm} 260