Merge from vendor branch BIND:
[dragonfly.git] / crypto / heimdal / admin / get.c
1 /*
2  * Copyright (c) 1997 - 2001 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: get.c,v 1.21 2001/10/29 12:53:52 nectar Exp $");
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 = (char*)realm;
51         conf.mask |= KADM5_CONFIG_REALM;
52     }
53     
54     if (admin_server) {
55         conf.admin_server = admin_server;
56         conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
57     }
58
59     if (server_port) {
60         conf.kadmind_port = htons(server_port);
61         conf.mask |= KADM5_CONFIG_KADMIND_PORT;
62     }
63
64     /* should get realm from each principal, instead of doing
65        everything with the same (local) realm */
66
67     ret = kadm5_init_with_password_ctx(context, 
68                                        principal,
69                                        NULL,
70                                        KADM5_ADMIN_SERVICE,
71                                        &conf, 0, 0, 
72                                        &kadm_handle);
73     if(ret) {
74         krb5_warn(context, ret, "kadm5_init_with_password");
75         return NULL;
76     }
77     return kadm_handle;
78 }
79
80 int
81 kt_get(int argc, char **argv)
82 {
83     krb5_error_code ret = 0;
84     krb5_keytab keytab;
85     void *kadm_handle = NULL;
86     char *principal = NULL;
87     char *realm = NULL;
88     char *admin_server = NULL;
89     int server_port = 0;
90     int help_flag = 0;
91     int optind = 0;
92     int i, j;
93     struct getarg_strings etype_strs = {0, NULL};
94     krb5_enctype *etypes = NULL;
95     size_t netypes = 0;
96     
97     struct getargs args[] = {
98         { "principal",  'p',    arg_string,   NULL, 
99           "admin principal", "principal" 
100         },
101         { "enctypes",   'e',    arg_strings,    NULL,
102           "encryption types to use", "enctypes" },
103         { "realm",      'r',    arg_string,   NULL, 
104           "realm to use", "realm" 
105         },
106         { "admin-server",       'a',    arg_string, NULL,
107           "server to contact", "host" 
108         },
109         { "server-port",        's',    arg_integer, NULL,
110           "port to contact", "port number" 
111         },
112         { "help",               'h',    arg_flag,    NULL }
113     };
114
115     args[0].value = &principal;
116     args[1].value = &etype_strs;
117     args[2].value = &realm;
118     args[3].value = &admin_server;
119     args[4].value = &server_port;
120     args[5].value = &help_flag;
121
122     if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind)
123        || help_flag) {
124         arg_printusage(args, sizeof(args) / sizeof(args[0]), 
125                        "ktutil get", "principal...");
126         return 1;
127     }
128     if(optind == argc) {
129         krb5_warnx(context, "no principals specified");
130         arg_printusage(args, sizeof(args) / sizeof(args[0]), 
131                        "ktutil get", "principal...");
132         return 1;
133     }
134     
135     if((keytab = ktutil_open_keytab()) == NULL)
136         return 1;
137
138     if(realm)
139         krb5_set_default_realm(context, realm);
140
141     if (etype_strs.num_strings) {
142         int i;
143
144         etypes = malloc (etype_strs.num_strings * sizeof(*etypes));
145         if (etypes == NULL) {
146             krb5_warnx(context, "malloc failed");
147             goto out;
148         }
149         netypes = etype_strs.num_strings;
150         for(i = 0; i < netypes; i++) {
151             ret = krb5_string_to_enctype(context, 
152                                          etype_strs.strings[i], 
153                                          &etypes[i]);
154             if(ret) {
155                 krb5_warnx(context, "unrecognized enctype: %s",
156                            etype_strs.strings[i]);
157                 goto out;
158             }
159         }
160     }
161
162     
163     for(i = optind; i < argc; i++){
164         krb5_principal princ_ent;
165         kadm5_principal_ent_rec princ;
166         int mask = 0;
167         krb5_keyblock *keys;
168         int n_keys;
169         int created = 0;
170         krb5_keytab_entry entry;
171
172         ret = krb5_parse_name(context, argv[i], &princ_ent);
173         memset(&princ, 0, sizeof(princ));
174         princ.principal = princ_ent;
175         mask |= KADM5_PRINCIPAL;
176         princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
177         mask |= KADM5_ATTRIBUTES;
178         princ.princ_expire_time = 0;
179         mask |= KADM5_PRINC_EXPIRE_TIME;
180
181         if(kadm_handle == NULL) {
182             const char *r;
183             if(realm != NULL)
184                 r = realm;
185             else
186                 r = krb5_principal_get_realm(context, princ_ent);
187             kadm_handle = open_kadmin_connection(principal, 
188                                                  r, 
189                                                  admin_server, 
190                                                  server_port);
191             if(kadm_handle == NULL) {
192                 break;
193             }
194         }
195         
196         ret = kadm5_create_principal(kadm_handle, &princ, mask, "x");
197         if(ret == 0)
198             created++;
199         else if(ret != KADM5_DUP) {
200             krb5_warn(context, ret, "kadm5_create_principal(%s)", argv[i]);
201             krb5_free_principal(context, princ_ent);
202             continue;
203         }
204         ret = kadm5_randkey_principal(kadm_handle, princ_ent, &keys, &n_keys);
205         if (ret) {
206             krb5_warn(context, ret, "kadm5_randkey_principal(%s)", argv[i]);
207             krb5_free_principal(context, princ_ent);
208             continue;
209         }
210         
211         ret = kadm5_get_principal(kadm_handle, princ_ent, &princ, 
212                               KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
213         if (ret) {
214             krb5_warn(context, ret, "kadm5_get_principal(%s)", argv[i]);
215             for (j = 0; j < n_keys; j++)
216                 krb5_free_keyblock_contents(context, &keys[j]);
217             krb5_free_principal(context, princ_ent);
218             continue;
219         }
220         princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
221         mask = KADM5_ATTRIBUTES;
222         if(created) {
223             princ.kvno = 1;
224             mask |= KADM5_KVNO;
225         }
226         ret = kadm5_modify_principal(kadm_handle, &princ, mask);
227         if (ret) {
228             krb5_warn(context, ret, "kadm5_modify_principal(%s)", argv[i]);
229             for (j = 0; j < n_keys; j++)
230                 krb5_free_keyblock_contents(context, &keys[j]);
231             krb5_free_principal(context, princ_ent);
232             continue;
233         }
234         for(j = 0; j < n_keys; j++) {
235             int do_add = TRUE;
236
237             if (netypes) {
238                 int i;
239
240                 do_add = FALSE;
241                 for (i = 0; i < netypes; ++i)
242                     if (keys[j].keytype == etypes[i]) {
243                         do_add = TRUE;
244                         break;
245                     }
246             }
247             if (do_add) {
248                 entry.principal = princ_ent;
249                 entry.vno = princ.kvno;
250                 entry.keyblock = keys[j];
251                 entry.timestamp = time (NULL);
252                 ret = krb5_kt_add_entry(context, keytab, &entry);
253                 if (ret)
254                     krb5_warn(context, ret, "krb5_kt_add_entry");
255             }
256             krb5_free_keyblock_contents(context, &keys[j]);
257         }
258         
259         kadm5_free_principal_ent(kadm_handle, &princ);
260         krb5_free_principal(context, princ_ent);
261     }
262  out:
263     free_getarg_strings(&etype_strs);
264     free(etypes);
265     if (kadm_handle)
266         kadm5_destroy(kadm_handle);
267     krb5_kt_close(context, keytab);
268     return ret != 0;
269 }