1178825Sdfr/*
2233294Sstas * Copyright (c) 2005 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
5178825Sdfr *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
9178825Sdfr *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
20178825Sdfr *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34178825Sdfr/*
35178825Sdfr * Check database for strange configurations on default principals
36178825Sdfr */
37178825Sdfr
38178825Sdfr#include "kadmin_locl.h"
39178825Sdfr#include "kadmin-commands.h"
40178825Sdfr
41178825Sdfrstatic int
42178825Sdfrget_check_entry(const char *name, kadm5_principal_ent_rec *ent)
43178825Sdfr{
44178825Sdfr    krb5_error_code ret;
45178825Sdfr    krb5_principal principal;
46178825Sdfr
47178825Sdfr    ret = krb5_parse_name(context, name, &principal);
48178825Sdfr    if (ret) {
49178825Sdfr	krb5_warn(context, ret, "krb5_unparse_name: %s", name);
50178825Sdfr	return 1;
51178825Sdfr    }
52178825Sdfr
53178825Sdfr    memset(ent, 0, sizeof(*ent));
54178825Sdfr    ret = kadm5_get_principal(kadm_handle, principal, ent, 0);
55178825Sdfr    krb5_free_principal(context, principal);
56178825Sdfr    if(ret)
57178825Sdfr	return 1;
58178825Sdfr
59178825Sdfr    return 0;
60178825Sdfr}
61178825Sdfr
62178825Sdfr
63178825Sdfrstatic int
64178825Sdfrdo_check_entry(krb5_principal principal, void *data)
65178825Sdfr{
66178825Sdfr    krb5_error_code ret;
67178825Sdfr    kadm5_principal_ent_rec princ;
68178825Sdfr    char *name;
69178825Sdfr    int i;
70233294Sstas
71178825Sdfr    ret = krb5_unparse_name(context, principal, &name);
72178825Sdfr    if (ret)
73178825Sdfr	return 1;
74178825Sdfr
75178825Sdfr    memset (&princ, 0, sizeof(princ));
76178825Sdfr    ret = kadm5_get_principal(kadm_handle, principal, &princ,
77178825Sdfr			      KADM5_PRINCIPAL | KADM5_KEY_DATA);
78178825Sdfr    if(ret) {
79178825Sdfr	krb5_warn(context, ret, "Failed to get principal: %s", name);
80178825Sdfr	free(name);
81178825Sdfr	return 0;
82178825Sdfr    }
83178825Sdfr
84178825Sdfr    for (i = 0; i < princ.n_key_data; i++) {
85178825Sdfr	size_t keysize;
86233294Sstas	ret = krb5_enctype_keysize(context,
87178825Sdfr				   princ.key_data[i].key_data_type[0],
88178825Sdfr				   &keysize);
89233294Sstas	if (ret == 0 && keysize != (size_t)princ.key_data[i].key_data_length[0]) {
90178825Sdfr	    krb5_warnx(context,
91178825Sdfr		       "Principal %s enctype %d, wrong length: %lu\n",
92178825Sdfr		       name, princ.key_data[i].key_data_type[0],
93178825Sdfr		       (unsigned long)princ.key_data[i].key_data_length);
94178825Sdfr	}
95178825Sdfr    }
96178825Sdfr
97178825Sdfr    free(name);
98178825Sdfr    kadm5_free_principal_ent(kadm_handle, &princ);
99178825Sdfr
100178825Sdfr    return 0;
101178825Sdfr}
102178825Sdfr
103178825Sdfrint
104178825Sdfrcheck(void *opt, int argc, char **argv)
105178825Sdfr{
106178825Sdfr    kadm5_principal_ent_rec ent;
107178825Sdfr    krb5_error_code ret;
108178825Sdfr    char *realm = NULL, *p, *p2;
109178825Sdfr    int found;
110178825Sdfr
111178825Sdfr    if (argc == 0) {
112178825Sdfr	ret = krb5_get_default_realm(context, &realm);
113178825Sdfr	if (ret) {
114178825Sdfr	    krb5_warn(context, ret, "krb5_get_default_realm");
115178825Sdfr	    goto fail;
116178825Sdfr	}
117178825Sdfr    } else {
118178825Sdfr	realm = strdup(argv[0]);
119178825Sdfr	if (realm == NULL) {
120178825Sdfr	    krb5_warnx(context, "malloc");
121178825Sdfr	    goto fail;
122178825Sdfr	}
123178825Sdfr    }
124178825Sdfr
125178825Sdfr    /*
126178825Sdfr     * Check krbtgt/REALM@REALM
127178825Sdfr     *
128178825Sdfr     * For now, just check existance
129178825Sdfr     */
130178825Sdfr
131178825Sdfr    if (asprintf(&p, "%s/%s@%s", KRB5_TGS_NAME, realm, realm) == -1) {
132178825Sdfr	krb5_warn(context, errno, "asprintf");
133178825Sdfr	goto fail;
134178825Sdfr    }
135178825Sdfr
136178825Sdfr    ret = get_check_entry(p, &ent);
137178825Sdfr    if (ret) {
138178825Sdfr	printf("%s doesn't exist, are you sure %s is a realm in your database",
139178825Sdfr	       p, realm);
140178825Sdfr	free(p);
141178825Sdfr	goto fail;
142178825Sdfr    }
143233294Sstas    free(p);
144178825Sdfr
145178825Sdfr    kadm5_free_principal_ent(kadm_handle, &ent);
146178825Sdfr
147178825Sdfr    /*
148178825Sdfr     * Check kadmin/admin@REALM
149178825Sdfr     */
150178825Sdfr
151178825Sdfr    if (asprintf(&p, "kadmin/admin@%s", realm) == -1) {
152178825Sdfr	krb5_warn(context, errno, "asprintf");
153178825Sdfr	goto fail;
154178825Sdfr    }
155178825Sdfr
156178825Sdfr    ret = get_check_entry(p, &ent);
157178825Sdfr    if (ret) {
158178825Sdfr	printf("%s doesn't exist, "
159178825Sdfr	       "there is no way to do remote administration", p);
160178825Sdfr	free(p);
161178825Sdfr	goto fail;
162178825Sdfr    }
163178825Sdfr    free(p);
164178825Sdfr
165178825Sdfr    kadm5_free_principal_ent(kadm_handle, &ent);
166178825Sdfr
167178825Sdfr    /*
168178825Sdfr     * Check kadmin/changepw@REALM
169178825Sdfr     */
170178825Sdfr
171178825Sdfr    if (asprintf(&p, "kadmin/changepw@%s", realm) == -1) {
172178825Sdfr	krb5_warn(context, errno, "asprintf");
173178825Sdfr	goto fail;
174178825Sdfr    }
175178825Sdfr
176178825Sdfr    ret = get_check_entry(p, &ent);
177178825Sdfr    if (ret) {
178178825Sdfr	printf("%s doesn't exist, "
179178825Sdfr	       "there is no way to do change password", p);
180178825Sdfr	free(p);
181178825Sdfr	goto fail;
182178825Sdfr    }
183178825Sdfr    free(p);
184178825Sdfr
185178825Sdfr    kadm5_free_principal_ent(kadm_handle, &ent);
186178825Sdfr
187178825Sdfr    /*
188233294Sstas     * Check for duplicate afs keys
189178825Sdfr     */
190178825Sdfr
191178825Sdfr    p2 = strdup(realm);
192178825Sdfr    if (p2 == NULL) {
193178825Sdfr	krb5_warn(context, errno, "malloc");
194178825Sdfr	goto fail;
195178825Sdfr    }
196178825Sdfr    strlwr(p2);
197178825Sdfr
198178825Sdfr    if (asprintf(&p, "afs/%s@%s", p2, realm) == -1) {
199178825Sdfr	krb5_warn(context, errno, "asprintf");
200178825Sdfr	free(p2);
201178825Sdfr	goto fail;
202178825Sdfr    }
203178825Sdfr    free(p2);
204178825Sdfr
205178825Sdfr    ret = get_check_entry(p, &ent);
206178825Sdfr    free(p);
207178825Sdfr    if (ret == 0) {
208178825Sdfr	kadm5_free_principal_ent(kadm_handle, &ent);
209178825Sdfr	found = 1;
210178825Sdfr    } else
211178825Sdfr	found = 0;
212178825Sdfr
213178825Sdfr    if (asprintf(&p, "afs@%s", realm) == -1) {
214178825Sdfr	krb5_warn(context, errno, "asprintf");
215178825Sdfr	goto fail;
216178825Sdfr    }
217178825Sdfr
218178825Sdfr    ret = get_check_entry(p, &ent);
219178825Sdfr    free(p);
220178825Sdfr    if (ret == 0) {
221178825Sdfr	kadm5_free_principal_ent(kadm_handle, &ent);
222178825Sdfr	if (found) {
223178825Sdfr	    krb5_warnx(context, "afs@REALM and afs/cellname@REALM both exists");
224178825Sdfr	    goto fail;
225178825Sdfr	}
226178825Sdfr    }
227178825Sdfr
228178825Sdfr    foreach_principal("*", do_check_entry, "check", NULL);
229178825Sdfr
230178825Sdfr    free(realm);
231178825Sdfr    return 0;
232178825Sdfrfail:
233178825Sdfr    free(realm);
234178825Sdfr    return 1;
235178825Sdfr}
236