get.c revision 178826
11590Srgrimes/*
21590Srgrimes * Copyright (c) 1997-2004 Kungliga Tekniska H�gskolan
31590Srgrimes * (Royal Institute of Technology, Stockholm, Sweden).
41590Srgrimes * All rights reserved.
51590Srgrimes *
61590Srgrimes * Redistribution and use in source and binary forms, with or without
71590Srgrimes * modification, are permitted provided that the following conditions
81590Srgrimes * are met:
91590Srgrimes *
101590Srgrimes * 1. Redistributions of source code must retain the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer.
121590Srgrimes *
131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141590Srgrimes *    notice, this list of conditions and the following disclaimer in the
151590Srgrimes *    documentation and/or other materials provided with the distribution.
161590Srgrimes *
171590Srgrimes * 3. Neither the name of the Institute nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#include "ktutil_locl.h"
351590Srgrimes
361590SrgrimesRCSID("$Id: get.c 15583 2005-07-07 21:44:37Z lha $");
371590Srgrimes
3898552Smarkmstatic void*
391590Srgrimesopen_kadmin_connection(char *principal,
401590Srgrimes		       const char *realm,
411590Srgrimes		       char *admin_server,
4298552Smarkm		       int server_port)
431590Srgrimes{
4498552Smarkm    static kadm5_config_params conf;
4598552Smarkm    krb5_error_code ret;
4698552Smarkm    void *kadm_handle;
471590Srgrimes    memset(&conf, 0, sizeof(conf));
481590Srgrimes
491590Srgrimes    if(realm) {
501590Srgrimes	conf.realm = strdup(realm);
51204359Sed	if (conf.realm == NULL) {
52204359Sed	    krb5_set_error_string(context, "malloc: out of memory");
531590Srgrimes	    return NULL;
541590Srgrimes	}
551590Srgrimes	conf.mask |= KADM5_CONFIG_REALM;
561590Srgrimes    }
571590Srgrimes
581590Srgrimes    if (admin_server) {
591590Srgrimes	conf.admin_server = admin_server;
601590Srgrimes	conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
611590Srgrimes    }
621590Srgrimes
631590Srgrimes    if (server_port) {
641590Srgrimes	conf.kadmind_port = htons(server_port);
651590Srgrimes	conf.mask |= KADM5_CONFIG_KADMIND_PORT;
661590Srgrimes    }
671590Srgrimes
681590Srgrimes    /* should get realm from each principal, instead of doing
691590Srgrimes       everything with the same (local) realm */
701590Srgrimes
711590Srgrimes    ret = kadm5_init_with_password_ctx(context,
7298552Smarkm				       principal,
7398552Smarkm				       NULL,
741590Srgrimes				       KADM5_ADMIN_SERVICE,
7598552Smarkm				       &conf, 0, 0,
761590Srgrimes				       &kadm_handle);
7798552Smarkm    free(conf.realm);
7898552Smarkm    if(ret) {
791590Srgrimes	krb5_warn(context, ret, "kadm5_init_with_password");
8098552Smarkm	return NULL;
811590Srgrimes    }
821590Srgrimes    return kadm_handle;
831590Srgrimes}
841590Srgrimes
851590Srgrimesint
861590Srgrimeskt_get(struct get_options *opt, int argc, char **argv)
871590Srgrimes{
881590Srgrimes    krb5_error_code ret = 0;
891590Srgrimes    krb5_keytab keytab;
901590Srgrimes    void *kadm_handle = NULL;
911590Srgrimes    krb5_enctype *etypes = NULL;
921590Srgrimes    size_t netypes = 0;
931590Srgrimes    int i, j;
9498552Smarkm    unsigned int failed = 0;
9598698Scharnier
961590Srgrimes    if((keytab = ktutil_open_keytab()) == NULL)
971590Srgrimes	return 1;
981590Srgrimes
991590Srgrimes    if(opt->realm_string)
1001590Srgrimes	krb5_set_default_realm(context, opt->realm_string);
1011590Srgrimes
1021590Srgrimes    if (opt->enctypes_strings.num_strings != 0) {
1031590Srgrimes
10498552Smarkm	etypes = malloc (opt->enctypes_strings.num_strings * sizeof(*etypes));
10598698Scharnier	if (etypes == NULL) {
1061590Srgrimes	    krb5_warnx(context, "malloc failed");
1071590Srgrimes	    goto out;
1081590Srgrimes	}
1091590Srgrimes	netypes = opt->enctypes_strings.num_strings;
1101590Srgrimes	for(i = 0; i < netypes; i++) {
1111590Srgrimes	    ret = krb5_string_to_enctype(context,
1121590Srgrimes					 opt->enctypes_strings.strings[i],
1131590Srgrimes					 &etypes[i]);
1141590Srgrimes	    if(ret) {
1151590Srgrimes		krb5_warnx(context, "unrecognized enctype: %s",
11698698Scharnier			   opt->enctypes_strings.strings[i]);
1171590Srgrimes		goto out;
1181590Srgrimes	    }
11998698Scharnier	}
1201590Srgrimes    }
1211590Srgrimes
1221590Srgrimes
1231590Srgrimes    for(i = 0; i < argc; i++){
1241590Srgrimes	krb5_principal princ_ent;
1251590Srgrimes	kadm5_principal_ent_rec princ;
1261590Srgrimes	int mask = 0;
1271590Srgrimes	krb5_keyblock *keys;
1281590Srgrimes	int n_keys;
1291590Srgrimes	int created = 0;
1301590Srgrimes	krb5_keytab_entry entry;
1311590Srgrimes
1321590Srgrimes	ret = krb5_parse_name(context, argv[i], &princ_ent);
13398552Smarkm	if (ret) {
1341590Srgrimes	    krb5_warn(context, ret, "can't parse principal %s", argv[i]);
1351590Srgrimes	    failed++;
1361590Srgrimes	    continue;
1371590Srgrimes	}
1381590Srgrimes	memset(&princ, 0, sizeof(princ));
1391590Srgrimes	princ.principal = princ_ent;
1401590Srgrimes	mask |= KADM5_PRINCIPAL;
1411590Srgrimes	princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
1421590Srgrimes	mask |= KADM5_ATTRIBUTES;
1431590Srgrimes	princ.princ_expire_time = 0;
1441590Srgrimes	mask |= KADM5_PRINC_EXPIRE_TIME;
1451590Srgrimes
1461590Srgrimes	if(kadm_handle == NULL) {
1471590Srgrimes	    const char *r;
1481590Srgrimes	    if(opt->realm_string != NULL)
1491590Srgrimes		r = opt->realm_string;
1501590Srgrimes	    else
1511590Srgrimes		r = krb5_principal_get_realm(context, princ_ent);
1521590Srgrimes	    kadm_handle = open_kadmin_connection(opt->principal_string,
1531590Srgrimes						 r,
1541590Srgrimes						 opt->admin_server_string,
1551590Srgrimes						 opt->server_port_integer);
1561590Srgrimes	    if(kadm_handle == NULL)
1571590Srgrimes		break;
1581590Srgrimes	}
1591590Srgrimes
1601590Srgrimes	ret = kadm5_create_principal(kadm_handle, &princ, mask, "x");
1611590Srgrimes	if(ret == 0)
1621590Srgrimes	    created = 1;
1631590Srgrimes	else if(ret != KADM5_DUP) {
1641590Srgrimes	    krb5_warn(context, ret, "kadm5_create_principal(%s)", argv[i]);
1651590Srgrimes	    krb5_free_principal(context, princ_ent);
1661590Srgrimes	    failed++;
1671590Srgrimes	    continue;
1681590Srgrimes	}
1691590Srgrimes	ret = kadm5_randkey_principal(kadm_handle, princ_ent, &keys, &n_keys);
1701590Srgrimes	if (ret) {
1711590Srgrimes	    krb5_warn(context, ret, "kadm5_randkey_principal(%s)", argv[i]);
1721590Srgrimes	    krb5_free_principal(context, princ_ent);
1731590Srgrimes	    failed++;
1741590Srgrimes	    continue;
1751590Srgrimes	}
1761590Srgrimes
1771590Srgrimes	ret = kadm5_get_principal(kadm_handle, princ_ent, &princ,
1781590Srgrimes			      KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
1791590Srgrimes	if (ret) {
1801590Srgrimes	    krb5_warn(context, ret, "kadm5_get_principal(%s)", argv[i]);
1811590Srgrimes	    for (j = 0; j < n_keys; j++)
1821590Srgrimes		krb5_free_keyblock_contents(context, &keys[j]);
1831590Srgrimes	    krb5_free_principal(context, princ_ent);
1841590Srgrimes	    failed++;
1851590Srgrimes	    continue;
1861590Srgrimes	}
1871590Srgrimes	if(!created && (princ.attributes & KRB5_KDB_DISALLOW_ALL_TIX))
1881590Srgrimes	    krb5_warnx(context, "%s: disallow-all-tix flag set - clearing", argv[i]);
1891590Srgrimes	princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
1901590Srgrimes	mask = KADM5_ATTRIBUTES;
1911590Srgrimes	if(created) {
1921590Srgrimes	    princ.kvno = 1;
1931590Srgrimes	    mask |= KADM5_KVNO;
1941590Srgrimes	}
1951590Srgrimes	ret = kadm5_modify_principal(kadm_handle, &princ, mask);
1961590Srgrimes	if (ret) {
19798552Smarkm	    krb5_warn(context, ret, "kadm5_modify_principal(%s)", argv[i]);
1981590Srgrimes	    for (j = 0; j < n_keys; j++)
1991590Srgrimes		krb5_free_keyblock_contents(context, &keys[j]);
2001590Srgrimes	    krb5_free_principal(context, princ_ent);
2011590Srgrimes	    failed++;
2021590Srgrimes	    continue;
2031590Srgrimes	}
2041590Srgrimes	for(j = 0; j < n_keys; j++) {
2051590Srgrimes	    int do_add = TRUE;
2061590Srgrimes
2071590Srgrimes	    if (netypes) {
2081590Srgrimes		int k;
2091590Srgrimes
2101590Srgrimes		do_add = FALSE;
2111590Srgrimes		for (k = 0; k < netypes; ++k)
2121590Srgrimes		    if (keys[j].keytype == etypes[k]) {
2131590Srgrimes			do_add = TRUE;
21498552Smarkm			break;
2151590Srgrimes		    }
2161590Srgrimes	    }
2171590Srgrimes	    if (do_add) {
218		entry.principal = princ_ent;
219		entry.vno = princ.kvno;
220		entry.keyblock = keys[j];
221		entry.timestamp = time (NULL);
222		ret = krb5_kt_add_entry(context, keytab, &entry);
223		if (ret)
224		    krb5_warn(context, ret, "krb5_kt_add_entry");
225	    }
226	    krb5_free_keyblock_contents(context, &keys[j]);
227	}
228
229	kadm5_free_principal_ent(kadm_handle, &princ);
230	krb5_free_principal(context, princ_ent);
231    }
232 out:
233    free(etypes);
234    if (kadm_handle)
235	kadm5_destroy(kadm_handle);
236    krb5_kt_close(context, keytab);
237    return ret != 0 || failed > 0;
238}
239