]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - crypto/heimdal/admin/get.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / crypto / heimdal / admin / get.c
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: get.c 15583 2005-07-07 21:44:37Z lha $");
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_string(context, "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     int i, j;
94     unsigned int failed = 0;
95     
96     if((keytab = ktutil_open_keytab()) == NULL)
97         return 1;
98
99     if(opt->realm_string)
100         krb5_set_default_realm(context, opt->realm_string);
101
102     if (opt->enctypes_strings.num_strings != 0) {
103
104         etypes = malloc (opt->enctypes_strings.num_strings * sizeof(*etypes));
105         if (etypes == NULL) {
106             krb5_warnx(context, "malloc failed");
107             goto out;
108         }
109         netypes = opt->enctypes_strings.num_strings;
110         for(i = 0; i < netypes; i++) {
111             ret = krb5_string_to_enctype(context, 
112                                          opt->enctypes_strings.strings[i], 
113                                          &etypes[i]);
114             if(ret) {
115                 krb5_warnx(context, "unrecognized enctype: %s",
116                            opt->enctypes_strings.strings[i]);
117                 goto out;
118             }
119         }
120     }
121
122     
123     for(i = 0; i < argc; i++){
124         krb5_principal princ_ent;
125         kadm5_principal_ent_rec princ;
126         int mask = 0;
127         krb5_keyblock *keys;
128         int n_keys;
129         int created = 0;
130         krb5_keytab_entry entry;
131
132         ret = krb5_parse_name(context, argv[i], &princ_ent);
133         if (ret) {
134             krb5_warn(context, ret, "can't parse principal %s", argv[i]);
135             failed++;
136             continue;
137         }
138         memset(&princ, 0, sizeof(princ));
139         princ.principal = princ_ent;
140         mask |= KADM5_PRINCIPAL;
141         princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
142         mask |= KADM5_ATTRIBUTES;
143         princ.princ_expire_time = 0;
144         mask |= KADM5_PRINC_EXPIRE_TIME;
145
146         if(kadm_handle == NULL) {
147             const char *r;
148             if(opt->realm_string != NULL)
149                 r = opt->realm_string;
150             else
151                 r = krb5_principal_get_realm(context, princ_ent);
152             kadm_handle = open_kadmin_connection(opt->principal_string, 
153                                                  r, 
154                                                  opt->admin_server_string, 
155                                                  opt->server_port_integer);
156             if(kadm_handle == NULL)
157                 break;
158         }
159         
160         ret = kadm5_create_principal(kadm_handle, &princ, mask, "x");
161         if(ret == 0)
162             created = 1;
163         else if(ret != KADM5_DUP) {
164             krb5_warn(context, ret, "kadm5_create_principal(%s)", argv[i]);
165             krb5_free_principal(context, princ_ent);
166             failed++;
167             continue;
168         }
169         ret = kadm5_randkey_principal(kadm_handle, princ_ent, &keys, &n_keys);
170         if (ret) {
171             krb5_warn(context, ret, "kadm5_randkey_principal(%s)", argv[i]);
172             krb5_free_principal(context, princ_ent);
173             failed++;
174             continue;
175         }
176         
177         ret = kadm5_get_principal(kadm_handle, princ_ent, &princ, 
178                               KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
179         if (ret) {
180             krb5_warn(context, ret, "kadm5_get_principal(%s)", argv[i]);
181             for (j = 0; j < n_keys; j++)
182                 krb5_free_keyblock_contents(context, &keys[j]);
183             krb5_free_principal(context, princ_ent);
184             failed++;
185             continue;
186         }
187         if(!created && (princ.attributes & KRB5_KDB_DISALLOW_ALL_TIX))
188             krb5_warnx(context, "%s: disallow-all-tix flag set - clearing", argv[i]);
189         princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
190         mask = KADM5_ATTRIBUTES;
191         if(created) {
192             princ.kvno = 1;
193             mask |= KADM5_KVNO;
194         }
195         ret = kadm5_modify_principal(kadm_handle, &princ, mask);
196         if (ret) {
197             krb5_warn(context, ret, "kadm5_modify_principal(%s)", argv[i]);
198             for (j = 0; j < n_keys; j++)
199                 krb5_free_keyblock_contents(context, &keys[j]);
200             krb5_free_principal(context, princ_ent);
201             failed++;
202             continue;
203         }
204         for(j = 0; j < n_keys; j++) {
205             int do_add = TRUE;
206
207             if (netypes) {
208                 int k;
209
210                 do_add = FALSE;
211                 for (k = 0; k < netypes; ++k)
212                     if (keys[j].keytype == etypes[k]) {
213                         do_add = TRUE;
214                         break;
215                     }
216             }
217             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 }