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