xref: /freebsd/crypto/heimdal/kadmin/check.c (revision aa0a1e58)
1 /*
2  * Copyright (c) 2005 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 /*
35  * Check database for strange configurations on default principals
36  */
37 
38 #include "kadmin_locl.h"
39 #include "kadmin-commands.h"
40 
41 RCSID("$Id: check.c 20962 2007-06-07 05:09:24Z lha $");
42 
43 static int
44 get_check_entry(const char *name, kadm5_principal_ent_rec *ent)
45 {
46     krb5_error_code ret;
47     krb5_principal principal;
48 
49     ret = krb5_parse_name(context, name, &principal);
50     if (ret) {
51 	krb5_warn(context, ret, "krb5_unparse_name: %s", name);
52 	return 1;
53     }
54 
55     memset(ent, 0, sizeof(*ent));
56     ret = kadm5_get_principal(kadm_handle, principal, ent, 0);
57     krb5_free_principal(context, principal);
58     if(ret)
59 	return 1;
60 
61     return 0;
62 }
63 
64 
65 static int
66 do_check_entry(krb5_principal principal, void *data)
67 {
68     krb5_error_code ret;
69     kadm5_principal_ent_rec princ;
70     char *name;
71     int i;
72 
73     ret = krb5_unparse_name(context, principal, &name);
74     if (ret)
75 	return 1;
76 
77     memset (&princ, 0, sizeof(princ));
78     ret = kadm5_get_principal(kadm_handle, principal, &princ,
79 			      KADM5_PRINCIPAL | KADM5_KEY_DATA);
80     if(ret) {
81 	krb5_warn(context, ret, "Failed to get principal: %s", name);
82 	free(name);
83 	return 0;
84     }
85 
86     for (i = 0; i < princ.n_key_data; i++) {
87 	size_t keysize;
88 	ret = krb5_enctype_keysize(context,
89 				   princ.key_data[i].key_data_type[0],
90 				   &keysize);
91 	if (ret == 0 && keysize != princ.key_data[i].key_data_length[0]) {
92 	    krb5_warnx(context,
93 		       "Principal %s enctype %d, wrong length: %lu\n",
94 		       name, princ.key_data[i].key_data_type[0],
95 		       (unsigned long)princ.key_data[i].key_data_length);
96 	}
97     }
98 
99     free(name);
100     kadm5_free_principal_ent(kadm_handle, &princ);
101 
102     return 0;
103 }
104 
105 int
106 check(void *opt, int argc, char **argv)
107 {
108     kadm5_principal_ent_rec ent;
109     krb5_error_code ret;
110     char *realm = NULL, *p, *p2;
111     int found;
112 
113     if (argc == 0) {
114 	ret = krb5_get_default_realm(context, &realm);
115 	if (ret) {
116 	    krb5_warn(context, ret, "krb5_get_default_realm");
117 	    goto fail;
118 	}
119     } else {
120 	realm = strdup(argv[0]);
121 	if (realm == NULL) {
122 	    krb5_warnx(context, "malloc");
123 	    goto fail;
124 	}
125     }
126 
127     /*
128      * Check krbtgt/REALM@REALM
129      *
130      * For now, just check existance
131      */
132 
133     if (asprintf(&p, "%s/%s@%s", KRB5_TGS_NAME, realm, realm) == -1) {
134 	krb5_warn(context, errno, "asprintf");
135 	goto fail;
136     }
137 
138     ret = get_check_entry(p, &ent);
139     if (ret) {
140 	printf("%s doesn't exist, are you sure %s is a realm in your database",
141 	       p, realm);
142 	free(p);
143 	goto fail;
144     }
145     free(p);
146 
147     kadm5_free_principal_ent(kadm_handle, &ent);
148 
149     /*
150      * Check kadmin/admin@REALM
151      */
152 
153     if (asprintf(&p, "kadmin/admin@%s", realm) == -1) {
154 	krb5_warn(context, errno, "asprintf");
155 	goto fail;
156     }
157 
158     ret = get_check_entry(p, &ent);
159     if (ret) {
160 	printf("%s doesn't exist, "
161 	       "there is no way to do remote administration", p);
162 	free(p);
163 	goto fail;
164     }
165     free(p);
166 
167     kadm5_free_principal_ent(kadm_handle, &ent);
168 
169     /*
170      * Check kadmin/changepw@REALM
171      */
172 
173     if (asprintf(&p, "kadmin/changepw@%s", realm) == -1) {
174 	krb5_warn(context, errno, "asprintf");
175 	goto fail;
176     }
177 
178     ret = get_check_entry(p, &ent);
179     if (ret) {
180 	printf("%s doesn't exist, "
181 	       "there is no way to do change password", p);
182 	free(p);
183 	goto fail;
184     }
185     free(p);
186 
187     kadm5_free_principal_ent(kadm_handle, &ent);
188 
189     /*
190      * Check for duplicate afs keys
191      */
192 
193     p2 = strdup(realm);
194     if (p2 == NULL) {
195 	krb5_warn(context, errno, "malloc");
196 	free(p);
197 	goto fail;
198     }
199     strlwr(p2);
200 
201     if (asprintf(&p, "afs/%s@%s", p2, realm) == -1) {
202 	krb5_warn(context, errno, "asprintf");
203 	free(p2);
204 	goto fail;
205     }
206     free(p2);
207 
208     ret = get_check_entry(p, &ent);
209     free(p);
210     if (ret == 0) {
211 	kadm5_free_principal_ent(kadm_handle, &ent);
212 	found = 1;
213     } else
214 	found = 0;
215 
216     if (asprintf(&p, "afs@%s", realm) == -1) {
217 	krb5_warn(context, errno, "asprintf");
218 	goto fail;
219     }
220 
221     ret = get_check_entry(p, &ent);
222     free(p);
223     if (ret == 0) {
224 	kadm5_free_principal_ent(kadm_handle, &ent);
225 	if (found) {
226 	    krb5_warnx(context, "afs@REALM and afs/cellname@REALM both exists");
227 	    goto fail;
228 	}
229     }
230 
231     foreach_principal("*", do_check_entry, "check", NULL);
232 
233     free(realm);
234     return 0;
235 fail:
236     free(realm);
237     return 1;
238 }
239