| 1 | /*
|
|---|
| 2 | * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
|
|---|
| 3 | * (Royal Institute of Technology, Stockholm, Sweden).
|
|---|
| 4 | * All rights reserved.
|
|---|
| 5 | *
|
|---|
| 6 | * Redistribution and use in source and binary forms, with or without
|
|---|
| 7 | * modification, are permitted provided that the following conditions
|
|---|
| 8 | * are met:
|
|---|
| 9 | *
|
|---|
| 10 | * 1. Redistributions of source code must retain the above copyright
|
|---|
| 11 | * notice, this list of conditions and the following disclaimer.
|
|---|
| 12 | *
|
|---|
| 13 | * 2. Redistributions in binary form must reproduce the above copyright
|
|---|
| 14 | * notice, this list of conditions and the following disclaimer in the
|
|---|
| 15 | * documentation and/or other materials provided with the distribution.
|
|---|
| 16 | *
|
|---|
| 17 | * 3. Neither the name of the Institute nor the names of its contributors
|
|---|
| 18 | * may be used to endorse or promote products derived from this software
|
|---|
| 19 | * without specific prior written permission.
|
|---|
| 20 | *
|
|---|
| 21 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|---|
| 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|---|
| 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|---|
| 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|---|
| 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|---|
| 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|---|
| 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|---|
| 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|---|
| 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|---|
| 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|---|
| 31 | * SUCH DAMAGE.
|
|---|
| 32 | */
|
|---|
| 33 |
|
|---|
| 34 | #include "ktutil_locl.h"
|
|---|
| 35 |
|
|---|
| 36 | RCSID("$Id$");
|
|---|
| 37 |
|
|---|
| 38 | static void*
|
|---|
| 39 | open_kadmin_connection(char *principal,
|
|---|
| 40 | const char *realm,
|
|---|
| 41 | char *admin_server,
|
|---|
| 42 | int server_port)
|
|---|
| 43 | {
|
|---|
| 44 | static kadm5_config_params conf;
|
|---|
| 45 | krb5_error_code ret;
|
|---|
| 46 | void *kadm_handle;
|
|---|
| 47 | memset(&conf, 0, sizeof(conf));
|
|---|
| 48 |
|
|---|
| 49 | if(realm) {
|
|---|
| 50 | conf.realm = strdup(realm);
|
|---|
| 51 | if (conf.realm == NULL) {
|
|---|
| 52 | krb5_set_error_message(context, 0, "malloc: out of memory");
|
|---|
| 53 | return NULL;
|
|---|
| 54 | }
|
|---|
| 55 | conf.mask |= KADM5_CONFIG_REALM;
|
|---|
| 56 | }
|
|---|
| 57 |
|
|---|
| 58 | if (admin_server) {
|
|---|
| 59 | conf.admin_server = admin_server;
|
|---|
| 60 | conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
|
|---|
| 61 | }
|
|---|
| 62 |
|
|---|
| 63 | if (server_port) {
|
|---|
| 64 | conf.kadmind_port = htons(server_port);
|
|---|
| 65 | conf.mask |= KADM5_CONFIG_KADMIND_PORT;
|
|---|
| 66 | }
|
|---|
| 67 |
|
|---|
| 68 | /* should get realm from each principal, instead of doing
|
|---|
| 69 | everything with the same (local) realm */
|
|---|
| 70 |
|
|---|
| 71 | ret = kadm5_init_with_password_ctx(context,
|
|---|
| 72 | principal,
|
|---|
| 73 | NULL,
|
|---|
| 74 | KADM5_ADMIN_SERVICE,
|
|---|
| 75 | &conf, 0, 0,
|
|---|
| 76 | &kadm_handle);
|
|---|
| 77 | free(conf.realm);
|
|---|
| 78 | if(ret) {
|
|---|
| 79 | krb5_warn(context, ret, "kadm5_init_with_password");
|
|---|
| 80 | return NULL;
|
|---|
| 81 | }
|
|---|
| 82 | return kadm_handle;
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | int
|
|---|
| 86 | kt_get(struct get_options *opt, int argc, char **argv)
|
|---|
| 87 | {
|
|---|
| 88 | krb5_error_code ret = 0;
|
|---|
| 89 | krb5_keytab keytab;
|
|---|
| 90 | void *kadm_handle = NULL;
|
|---|
| 91 | krb5_enctype *etypes = NULL;
|
|---|
| 92 | size_t netypes = 0;
|
|---|
| 93 | size_t i;
|
|---|
| 94 | int a, j;
|
|---|
| 95 | unsigned int failed = 0;
|
|---|
| 96 |
|
|---|
| 97 | if((keytab = ktutil_open_keytab()) == NULL)
|
|---|
| 98 | return 1;
|
|---|
| 99 |
|
|---|
| 100 | if(opt->realm_string)
|
|---|
| 101 | krb5_set_default_realm(context, opt->realm_string);
|
|---|
| 102 |
|
|---|
| 103 | if (opt->enctypes_strings.num_strings != 0) {
|
|---|
| 104 |
|
|---|
| 105 | etypes = malloc (opt->enctypes_strings.num_strings * sizeof(*etypes));
|
|---|
| 106 | if (etypes == NULL) {
|
|---|
| 107 | krb5_warnx(context, "malloc failed");
|
|---|
| 108 | goto out;
|
|---|
| 109 | }
|
|---|
| 110 | netypes = opt->enctypes_strings.num_strings;
|
|---|
| 111 | for(i = 0; i < netypes; i++) {
|
|---|
| 112 | ret = krb5_string_to_enctype(context,
|
|---|
| 113 | opt->enctypes_strings.strings[i],
|
|---|
| 114 | &etypes[i]);
|
|---|
| 115 | if(ret) {
|
|---|
| 116 | krb5_warnx(context, "unrecognized enctype: %s",
|
|---|
| 117 | opt->enctypes_strings.strings[i]);
|
|---|
| 118 | goto out;
|
|---|
| 119 | }
|
|---|
| 120 | }
|
|---|
| 121 | }
|
|---|
| 122 |
|
|---|
| 123 |
|
|---|
| 124 | for(a = 0; a < argc; a++){
|
|---|
| 125 | krb5_principal princ_ent;
|
|---|
| 126 | kadm5_principal_ent_rec princ;
|
|---|
| 127 | int mask = 0;
|
|---|
| 128 | krb5_keyblock *keys;
|
|---|
| 129 | int n_keys;
|
|---|
| 130 | int created = 0;
|
|---|
| 131 | krb5_keytab_entry entry;
|
|---|
| 132 |
|
|---|
| 133 | ret = krb5_parse_name(context, argv[a], &princ_ent);
|
|---|
| 134 | if (ret) {
|
|---|
| 135 | krb5_warn(context, ret, "can't parse principal %s", argv[a]);
|
|---|
| 136 | failed++;
|
|---|
| 137 | continue;
|
|---|
| 138 | }
|
|---|
| 139 | memset(&princ, 0, sizeof(princ));
|
|---|
| 140 | princ.principal = princ_ent;
|
|---|
| 141 | mask |= KADM5_PRINCIPAL;
|
|---|
| 142 | princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
|
|---|
| 143 | mask |= KADM5_ATTRIBUTES;
|
|---|
| 144 | princ.princ_expire_time = 0;
|
|---|
| 145 | mask |= KADM5_PRINC_EXPIRE_TIME;
|
|---|
| 146 |
|
|---|
| 147 | if(kadm_handle == NULL) {
|
|---|
| 148 | const char *r;
|
|---|
| 149 | if(opt->realm_string != NULL)
|
|---|
| 150 | r = opt->realm_string;
|
|---|
| 151 | else
|
|---|
| 152 | r = krb5_principal_get_realm(context, princ_ent);
|
|---|
| 153 | kadm_handle = open_kadmin_connection(opt->principal_string,
|
|---|
| 154 | r,
|
|---|
| 155 | opt->admin_server_string,
|
|---|
| 156 | opt->server_port_integer);
|
|---|
| 157 | if(kadm_handle == NULL)
|
|---|
| 158 | break;
|
|---|
| 159 | }
|
|---|
| 160 |
|
|---|
| 161 | ret = kadm5_create_principal(kadm_handle, &princ, mask, "x");
|
|---|
| 162 | if(ret == 0)
|
|---|
| 163 | created = 1;
|
|---|
| 164 | else if(ret != KADM5_DUP) {
|
|---|
| 165 | krb5_warn(context, ret, "kadm5_create_principal(%s)", argv[a]);
|
|---|
| 166 | krb5_free_principal(context, princ_ent);
|
|---|
| 167 | failed++;
|
|---|
| 168 | continue;
|
|---|
| 169 | }
|
|---|
| 170 | ret = kadm5_randkey_principal(kadm_handle, princ_ent, &keys, &n_keys);
|
|---|
| 171 | if (ret) {
|
|---|
| 172 | krb5_warn(context, ret, "kadm5_randkey_principal(%s)", argv[a]);
|
|---|
| 173 | krb5_free_principal(context, princ_ent);
|
|---|
| 174 | failed++;
|
|---|
| 175 | continue;
|
|---|
| 176 | }
|
|---|
| 177 |
|
|---|
| 178 | ret = kadm5_get_principal(kadm_handle, princ_ent, &princ,
|
|---|
| 179 | KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
|
|---|
| 180 | if (ret) {
|
|---|
| 181 | krb5_warn(context, ret, "kadm5_get_principal(%s)", argv[a]);
|
|---|
| 182 | for (j = 0; j < n_keys; j++)
|
|---|
| 183 | krb5_free_keyblock_contents(context, &keys[j]);
|
|---|
| 184 | krb5_free_principal(context, princ_ent);
|
|---|
| 185 | failed++;
|
|---|
| 186 | continue;
|
|---|
| 187 | }
|
|---|
| 188 | if(!created && (princ.attributes & KRB5_KDB_DISALLOW_ALL_TIX))
|
|---|
| 189 | krb5_warnx(context, "%s: disallow-all-tix flag set - clearing", argv[a]);
|
|---|
| 190 | princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
|
|---|
| 191 | mask = KADM5_ATTRIBUTES;
|
|---|
| 192 | if(created) {
|
|---|
| 193 | princ.kvno = 1;
|
|---|
| 194 | mask |= KADM5_KVNO;
|
|---|
| 195 | }
|
|---|
| 196 | ret = kadm5_modify_principal(kadm_handle, &princ, mask);
|
|---|
| 197 | if (ret) {
|
|---|
| 198 | krb5_warn(context, ret, "kadm5_modify_principal(%s)", argv[a]);
|
|---|
| 199 | for (j = 0; j < n_keys; j++)
|
|---|
| 200 | krb5_free_keyblock_contents(context, &keys[j]);
|
|---|
| 201 | krb5_free_principal(context, princ_ent);
|
|---|
| 202 | failed++;
|
|---|
| 203 | continue;
|
|---|
| 204 | }
|
|---|
| 205 | for(j = 0; j < n_keys; j++) {
|
|---|
| 206 | int do_add = TRUE;
|
|---|
| 207 |
|
|---|
| 208 | if (netypes) {
|
|---|
| 209 | size_t k;
|
|---|
| 210 |
|
|---|
| 211 | do_add = FALSE;
|
|---|
| 212 | for (k = 0; k < netypes; ++k)
|
|---|
| 213 | if (keys[j].keytype == etypes[k]) {
|
|---|
| 214 | do_add = TRUE;
|
|---|
| 215 | break;
|
|---|
| 216 | }
|
|---|
| 217 | }
|
|---|
| 218 | if (do_add) {
|
|---|
| 219 | entry.principal = princ_ent;
|
|---|
| 220 | entry.vno = princ.kvno;
|
|---|
| 221 | entry.keyblock = keys[j];
|
|---|
| 222 | entry.timestamp = time (NULL);
|
|---|
| 223 | ret = krb5_kt_add_entry(context, keytab, &entry);
|
|---|
| 224 | if (ret)
|
|---|
| 225 | krb5_warn(context, ret, "krb5_kt_add_entry");
|
|---|
| 226 | }
|
|---|
| 227 | krb5_free_keyblock_contents(context, &keys[j]);
|
|---|
| 228 | }
|
|---|
| 229 |
|
|---|
| 230 | kadm5_free_principal_ent(kadm_handle, &princ);
|
|---|
| 231 | krb5_free_principal(context, princ_ent);
|
|---|
| 232 | }
|
|---|
| 233 | out:
|
|---|
| 234 | free(etypes);
|
|---|
| 235 | if (kadm_handle)
|
|---|
| 236 | kadm5_destroy(kadm_handle);
|
|---|
| 237 | krb5_kt_close(context, keytab);
|
|---|
| 238 | return ret != 0 || failed > 0;
|
|---|
| 239 | }
|
|---|