1 /*	$NetBSD: check.c,v 1.1.1.2 2014/04/24 12:45:27 pettai Exp $	*/
2 
3 /*
4  * Copyright (c) 2005 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 /*
37  * Check database for strange configurations on default principals
38  */
39 
40 #include "kadmin_locl.h"
41 #include "kadmin-commands.h"
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 != (size_t)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 	goto fail;
197     }
198     strlwr(p2);
199 
200     if (asprintf(&p, "afs/%s@%s", p2, realm) == -1) {
201 	krb5_warn(context, errno, "asprintf");
202 	free(p2);
203 	goto fail;
204     }
205     free(p2);
206 
207     ret = get_check_entry(p, &ent);
208     free(p);
209     if (ret == 0) {
210 	kadm5_free_principal_ent(kadm_handle, &ent);
211 	found = 1;
212     } else
213 	found = 0;
214 
215     if (asprintf(&p, "afs@%s", realm) == -1) {
216 	krb5_warn(context, errno, "asprintf");
217 	goto fail;
218     }
219 
220     ret = get_check_entry(p, &ent);
221     free(p);
222     if (ret == 0) {
223 	kadm5_free_principal_ent(kadm_handle, &ent);
224 	if (found) {
225 	    krb5_warnx(context, "afs@REALM and afs/cellname@REALM both exists");
226 	    goto fail;
227 	}
228     }
229 
230     foreach_principal("*", do_check_entry, "check", NULL);
231 
232     free(realm);
233     return 0;
234 fail:
235     free(realm);
236     return 1;
237 }
238