155682Smarkm/*
2233294Sstas * Copyright (c) 1997-2004 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
955682Smarkm *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
2055682Smarkm *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "ktutil_locl.h"
3555682Smarkm
36233294SstasRCSID("$Id$");
3755682Smarkm
3890926Snectarstatic void*
3990926Snectaropen_kadmin_connection(char *principal,
40233294Sstas		       const char *realm,
41233294Sstas		       char *admin_server,
4290926Snectar		       int server_port)
4390926Snectar{
4490926Snectar    static kadm5_config_params conf;
4590926Snectar    krb5_error_code ret;
4690926Snectar    void *kadm_handle;
4790926Snectar    memset(&conf, 0, sizeof(conf));
4890926Snectar
4990926Snectar    if(realm) {
50178825Sdfr	conf.realm = strdup(realm);
51178825Sdfr	if (conf.realm == NULL) {
52233294Sstas	    krb5_set_error_message(context, 0, "malloc: out of memory");
53178825Sdfr	    return NULL;
54178825Sdfr	}
5590926Snectar	conf.mask |= KADM5_CONFIG_REALM;
5690926Snectar    }
57233294Sstas
5890926Snectar    if (admin_server) {
5990926Snectar	conf.admin_server = admin_server;
6090926Snectar	conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
6190926Snectar    }
6290926Snectar
6390926Snectar    if (server_port) {
6490926Snectar	conf.kadmind_port = htons(server_port);
6590926Snectar	conf.mask |= KADM5_CONFIG_KADMIND_PORT;
6690926Snectar    }
6790926Snectar
6890926Snectar    /* should get realm from each principal, instead of doing
6990926Snectar       everything with the same (local) realm */
7090926Snectar
71233294Sstas    ret = kadm5_init_with_password_ctx(context,
7290926Snectar				       principal,
7390926Snectar				       NULL,
7490926Snectar				       KADM5_ADMIN_SERVICE,
75233294Sstas				       &conf, 0, 0,
7690926Snectar				       &kadm_handle);
77178825Sdfr    free(conf.realm);
7890926Snectar    if(ret) {
7990926Snectar	krb5_warn(context, ret, "kadm5_init_with_password");
8090926Snectar	return NULL;
8190926Snectar    }
8290926Snectar    return kadm_handle;
8390926Snectar}
8490926Snectar
8555682Smarkmint
86178825Sdfrkt_get(struct get_options *opt, int argc, char **argv)
8755682Smarkm{
8878527Sassar    krb5_error_code ret = 0;
8978527Sassar    krb5_keytab keytab;
9078527Sassar    void *kadm_handle = NULL;
9178527Sassar    krb5_enctype *etypes = NULL;
9278527Sassar    size_t netypes = 0;
93233294Sstas    size_t i;
94233294Sstas    int a, j;
95178825Sdfr    unsigned int failed = 0;
96233294Sstas
9790926Snectar    if((keytab = ktutil_open_keytab()) == NULL)
9878527Sassar	return 1;
9978527Sassar
100178825Sdfr    if(opt->realm_string)
101178825Sdfr	krb5_set_default_realm(context, opt->realm_string);
10290926Snectar
103178825Sdfr    if (opt->enctypes_strings.num_strings != 0) {
10478527Sassar
105178825Sdfr	etypes = malloc (opt->enctypes_strings.num_strings * sizeof(*etypes));
10678527Sassar	if (etypes == NULL) {
10778527Sassar	    krb5_warnx(context, "malloc failed");
10878527Sassar	    goto out;
10978527Sassar	}
110178825Sdfr	netypes = opt->enctypes_strings.num_strings;
11178527Sassar	for(i = 0; i < netypes; i++) {
112233294Sstas	    ret = krb5_string_to_enctype(context,
113233294Sstas					 opt->enctypes_strings.strings[i],
11478527Sassar					 &etypes[i]);
11578527Sassar	    if(ret) {
11678527Sassar		krb5_warnx(context, "unrecognized enctype: %s",
117178825Sdfr			   opt->enctypes_strings.strings[i]);
11878527Sassar		goto out;
11978527Sassar	    }
12078527Sassar	}
12178527Sassar    }
12278527Sassar
123233294Sstas
124233294Sstas    for(a = 0; a < argc; a++){
12555682Smarkm	krb5_principal princ_ent;
12655682Smarkm	kadm5_principal_ent_rec princ;
12755682Smarkm	int mask = 0;
12855682Smarkm	krb5_keyblock *keys;
12955682Smarkm	int n_keys;
13055682Smarkm	int created = 0;
13155682Smarkm	krb5_keytab_entry entry;
13255682Smarkm
133233294Sstas	ret = krb5_parse_name(context, argv[a], &princ_ent);
134142403Snectar	if (ret) {
135233294Sstas	    krb5_warn(context, ret, "can't parse principal %s", argv[a]);
136178825Sdfr	    failed++;
137142403Snectar	    continue;
138142403Snectar	}
13955682Smarkm	memset(&princ, 0, sizeof(princ));
14055682Smarkm	princ.principal = princ_ent;
14155682Smarkm	mask |= KADM5_PRINCIPAL;
14255682Smarkm	princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
14355682Smarkm	mask |= KADM5_ATTRIBUTES;
14455682Smarkm	princ.princ_expire_time = 0;
14555682Smarkm	mask |= KADM5_PRINC_EXPIRE_TIME;
14690926Snectar
14790926Snectar	if(kadm_handle == NULL) {
14890926Snectar	    const char *r;
149178825Sdfr	    if(opt->realm_string != NULL)
150178825Sdfr		r = opt->realm_string;
15190926Snectar	    else
15290926Snectar		r = krb5_principal_get_realm(context, princ_ent);
153233294Sstas	    kadm_handle = open_kadmin_connection(opt->principal_string,
154233294Sstas						 r,
155233294Sstas						 opt->admin_server_string,
156178825Sdfr						 opt->server_port_integer);
157178825Sdfr	    if(kadm_handle == NULL)
15890926Snectar		break;
15990926Snectar	}
160233294Sstas
16155682Smarkm	ret = kadm5_create_principal(kadm_handle, &princ, mask, "x");
16255682Smarkm	if(ret == 0)
163178825Sdfr	    created = 1;
16455682Smarkm	else if(ret != KADM5_DUP) {
165233294Sstas	    krb5_warn(context, ret, "kadm5_create_principal(%s)", argv[a]);
16655682Smarkm	    krb5_free_principal(context, princ_ent);
167178825Sdfr	    failed++;
16855682Smarkm	    continue;
16955682Smarkm	}
17055682Smarkm	ret = kadm5_randkey_principal(kadm_handle, princ_ent, &keys, &n_keys);
17172445Sassar	if (ret) {
172233294Sstas	    krb5_warn(context, ret, "kadm5_randkey_principal(%s)", argv[a]);
17372445Sassar	    krb5_free_principal(context, princ_ent);
174178825Sdfr	    failed++;
17572445Sassar	    continue;
17672445Sassar	}
177233294Sstas
178233294Sstas	ret = kadm5_get_principal(kadm_handle, princ_ent, &princ,
17955682Smarkm			      KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
18072445Sassar	if (ret) {
181233294Sstas	    krb5_warn(context, ret, "kadm5_get_principal(%s)", argv[a]);
18272445Sassar	    for (j = 0; j < n_keys; j++)
18372445Sassar		krb5_free_keyblock_contents(context, &keys[j]);
18472445Sassar	    krb5_free_principal(context, princ_ent);
185178825Sdfr	    failed++;
18672445Sassar	    continue;
18772445Sassar	}
188178825Sdfr	if(!created && (princ.attributes & KRB5_KDB_DISALLOW_ALL_TIX))
189233294Sstas	    krb5_warnx(context, "%s: disallow-all-tix flag set - clearing", argv[a]);
19055682Smarkm	princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
19155682Smarkm	mask = KADM5_ATTRIBUTES;
19255682Smarkm	if(created) {
19355682Smarkm	    princ.kvno = 1;
19455682Smarkm	    mask |= KADM5_KVNO;
19555682Smarkm	}
19655682Smarkm	ret = kadm5_modify_principal(kadm_handle, &princ, mask);
19772445Sassar	if (ret) {
198233294Sstas	    krb5_warn(context, ret, "kadm5_modify_principal(%s)", argv[a]);
19972445Sassar	    for (j = 0; j < n_keys; j++)
20072445Sassar		krb5_free_keyblock_contents(context, &keys[j]);
20172445Sassar	    krb5_free_principal(context, princ_ent);
202178825Sdfr	    failed++;
20372445Sassar	    continue;
20472445Sassar	}
20555682Smarkm	for(j = 0; j < n_keys; j++) {
20678527Sassar	    int do_add = TRUE;
20778527Sassar
20878527Sassar	    if (netypes) {
209233294Sstas		size_t k;
21078527Sassar
21178527Sassar		do_add = FALSE;
212178825Sdfr		for (k = 0; k < netypes; ++k)
213178825Sdfr		    if (keys[j].keytype == etypes[k]) {
21478527Sassar			do_add = TRUE;
21578527Sassar			break;
21678527Sassar		    }
21778527Sassar	    }
21878527Sassar	    if (do_add) {
21978527Sassar		entry.principal = princ_ent;
22078527Sassar		entry.vno = princ.kvno;
22178527Sassar		entry.keyblock = keys[j];
22278527Sassar		entry.timestamp = time (NULL);
22378527Sassar		ret = krb5_kt_add_entry(context, keytab, &entry);
22478527Sassar		if (ret)
22578527Sassar		    krb5_warn(context, ret, "krb5_kt_add_entry");
22678527Sassar	    }
22755682Smarkm	    krb5_free_keyblock_contents(context, &keys[j]);
22855682Smarkm	}
229233294Sstas
23055682Smarkm	kadm5_free_principal_ent(kadm_handle, &princ);
23155682Smarkm	krb5_free_principal(context, princ_ent);
23255682Smarkm    }
23378527Sassar out:
23478527Sassar    free(etypes);
23578527Sassar    if (kadm_handle)
23678527Sassar	kadm5_destroy(kadm_handle);
23778527Sassar    krb5_kt_close(context, keytab);
238178825Sdfr    return ret != 0 || failed > 0;
23955682Smarkm}
240