1 /* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. 8 * 9 * $Id: kadm5_create.c,v 1.6 1998/10/30 02:52:37 marc Exp $ 10 * $Source: /cvs/krbdev/krb5/src/kadmin/dbutil/kadm5_create.c,v $ 11 */ 12 13 /* 14 * Copyright (C) 1998 by the FundsXpress, INC. 15 * 16 * All rights reserved. 17 * 18 * Export of this software from the United States of America may require 19 * a specific license from the United States Government. It is the 20 * responsibility of any person or organization contemplating export to 21 * obtain such a license before exporting. 22 * 23 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 24 * distribute this software and its documentation for any purpose and 25 * without fee is hereby granted, provided that the above copyright 26 * notice appear in all copies and that both that copyright notice and 27 * this permission notice appear in supporting documentation, and that 28 * the name of FundsXpress. not be used in advertising or publicity pertaining 29 * to distribution of the software without specific, written prior 30 * permission. FundsXpress makes no representations about the suitability of 31 * this software for any purpose. It is provided "as is" without express 32 * or implied warranty. 33 * 34 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 35 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 36 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 37 */ 38 39 #include "string_table.h" 40 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <k5-int.h> 45 #include <kdb.h> 46 #include <kadm5/admin.h> 47 #include <krb5/adm_proto.h> 48 49 #include <krb5.h> 50 #include <krb5/kdb.h> 51 #include "kdb5_util.h" 52 #include <libintl.h> 53 54 int 55 add_admin_old_princ(void *handle, krb5_context context, 56 char *name, char *realm, int attrs, int lifetime); 57 int 58 add_admin_sname_princ(void *handle, krb5_context context, 59 char *sname, int attrs, int lifetime); 60 static int 61 add_admin_princ(void *handle, krb5_context context, 62 krb5_principal principal, int attrs, int lifetime); 63 64 static int add_admin_princs(void *handle, krb5_context context, char *realm); 65 66 #define ERR 1 67 #define OK 0 68 69 #define ADMIN_LIFETIME 60*60*3 /* 3 hours */ 70 #define CHANGEPW_LIFETIME 60*5 /* 5 minutes */ 71 72 extern char *progname; 73 74 /* 75 * Function: kadm5_create 76 * 77 * Purpose: create admin principals in KDC database 78 * 79 * Arguments: params (r) configuration parameters to use 80 * 81 * Effects: Creates KADM5_ADMIN_SERVICE and KADM5_CHANGEPW_SERVICE 82 * principals in the KDC database and sets their attributes 83 * appropriately. 84 */ 85 int kadm5_create(kadm5_config_params *params) 86 { 87 int retval; 88 krb5_context context; 89 90 kadm5_config_params lparams; 91 92 if ((retval = kadm5_init_krb5_context(&context))) 93 exit(ERR); 94 95 (void) memset(&lparams, 0, sizeof (kadm5_config_params)); 96 97 /* 98 * The lock file has to exist before calling kadm5_init, but 99 * params->admin_lockfile may not be set yet... 100 */ 101 if ((retval = kadm5_get_config_params(context, 1, 102 params, &lparams))) { 103 com_err(progname, retval, gettext("while looking up the Kerberos configuration")); 104 return 1; 105 } 106 107 retval = kadm5_create_magic_princs(&lparams, context); 108 109 kadm5_free_config_params(context, &lparams); 110 krb5_free_context(context); 111 112 return retval; 113 } 114 115 int kadm5_create_magic_princs(kadm5_config_params *params, 116 krb5_context context) 117 { 118 int retval; 119 void *handle; 120 121 retval = krb5_klog_init(context, "admin_server", progname, 0); 122 if (retval) 123 return retval; 124 if ((retval = kadm5_init(progname, NULL, NULL, params, 125 KADM5_STRUCT_VERSION, 126 KADM5_API_VERSION_2, 127 db5util_db_args, 128 &handle))) { 129 com_err(progname, retval, gettext("while initializing the Kerberos admin interface")); 130 return retval; 131 } 132 133 retval = add_admin_princs(handle, context, params->realm); 134 135 kadm5_destroy(handle); 136 137 krb5_klog_close(context); 138 139 return retval; 140 } 141 142 /* 143 * Function: build_name_with_realm 144 * 145 * Purpose: concatenate a name and a realm to form a krb5 name 146 * 147 * Arguments: 148 * 149 * name (input) the name 150 * realm (input) the realm 151 * 152 * Returns: 153 * 154 * pointer to name@realm, in allocated memory, or NULL if it 155 * cannot be allocated 156 * 157 * Requires: both strings are null-terminated 158 */ 159 static char *build_name_with_realm(char *name, char *realm) 160 { 161 char *n; 162 163 n = (char *) malloc(strlen(name) + strlen(realm) + 2); 164 sprintf(n, "%s@%s", name, realm); 165 return n; 166 } 167 168 /* 169 * Function: add_admin_princs 170 * 171 * Purpose: create admin principals 172 * 173 * Arguments: 174 * 175 * rseed (input) random seed 176 * realm (input) realm, or NULL for default realm 177 * <return value> (output) status, 0 for success, 1 for serious error 178 * 179 * Requires: 180 * 181 * Effects: 182 * 183 * add_admin_princs creates KADM5_ADMIN_SERVICE, 184 * KADM5_CHANGEPW_SERVICE. If any of these exist a message is 185 * printed. If any of these existing principal do not have the proper 186 * attributes, a warning message is printed. 187 */ 188 static int add_admin_princs(void *handle, krb5_context context, char *realm) 189 { 190 krb5_error_code ret = 0; 191 192 /* 193 * Solaris Kerberos: 194 * The kadmin/admin principal is unused on Solaris. This principal is used 195 * in AUTH_GSSAPI but Solaris doesn't support AUTH_GSSAPI. RPCSEC_GSS can only 196 * be used with host-based principals. 197 * 198 */ 199 200 #if 0 201 if ((ret = add_admin_old_princ(handle, context, 202 KADM5_ADMIN_SERVICE, realm, 203 KRB5_KDB_DISALLOW_TGT_BASED, 204 ADMIN_LIFETIME))) 205 goto clean_and_exit; 206 #endif 207 208 if ((ret = add_admin_old_princ(handle, context, 209 KADM5_CHANGEPW_SERVICE, realm, 210 KRB5_KDB_DISALLOW_TGT_BASED | 211 KRB5_KDB_PWCHANGE_SERVICE, 212 CHANGEPW_LIFETIME))) 213 goto clean_and_exit; 214 215 if ((ret = add_admin_sname_princ(handle, context, 216 KADM5_ADMIN_HOST_SERVICE, 217 KRB5_KDB_DISALLOW_TGT_BASED, 218 ADMIN_LIFETIME))) 219 goto clean_and_exit; 220 221 if ((ret = add_admin_sname_princ(handle, context, 222 KADM5_CHANGEPW_HOST_SERVICE, 223 KRB5_KDB_DISALLOW_TGT_BASED | 224 KRB5_KDB_PWCHANGE_SERVICE, 225 ADMIN_LIFETIME))) 226 goto clean_and_exit; 227 228 if ((ret = add_admin_sname_princ(handle, context, 229 KADM5_KIPROP_HOST_SERVICE, 230 KRB5_KDB_DISALLOW_TGT_BASED, 231 ADMIN_LIFETIME))) 232 goto clean_and_exit; 233 234 clean_and_exit: 235 236 return ret; 237 } 238 239 /* 240 * Function: add_admin_princ 241 * 242 * Arguments: 243 * 244 * creator (r) principal to use as "mod_by" 245 * rseed (r) seed for random key generator 246 * principal (r) kerberos principal to add 247 * attrs (r) principal's attributes 248 * lifetime (r) principal's max life, or 0 249 * not_unique (r) error message for multiple entries, never used 250 * exists (r) warning message for principal exists 251 * wrong_attrs (r) warning message for wrong attributes 252 * 253 * Returns: 254 * 255 * OK on success 256 * ERR on serious errors 257 * 258 * Effects: 259 * 260 * If the principal is not unique, not_unique is printed (but this 261 * never happens). If the principal exists, then exists is printed 262 * and if the principals attributes != attrs, wrong_attrs is printed. 263 * Otherwise, the principal is created with mod_by creator and 264 * attributes attrs and max life of lifetime (if not zero). 265 */ 266 267 static int add_admin_princ(void *handle, krb5_context context, 268 krb5_principal principal, int attrs, int lifetime) 269 { 270 char *fullname; 271 krb5_error_code ret; 272 kadm5_principal_ent_rec ent; 273 274 memset(&ent, 0, sizeof(ent)); 275 276 if (krb5_unparse_name(context, principal, &fullname)) 277 return ERR; 278 279 ent.principal = principal; 280 ent.max_life = lifetime; 281 ent.attributes = attrs | KRB5_KDB_DISALLOW_ALL_TIX; 282 283 ret = kadm5_create_principal(handle, &ent, 284 (KADM5_PRINCIPAL | KADM5_MAX_LIFE | 285 KADM5_ATTRIBUTES), 286 "to-be-random"); 287 if (ret) { 288 if (ret != KADM5_DUP) { 289 com_err(progname, ret, 290 gettext(str_PUT_PRINC), fullname); 291 krb5_free_principal(context, ent.principal); 292 free(fullname); 293 return ERR; 294 } 295 } else { 296 /* only randomize key if we created the principal */ 297 298 /* 299 * Solaris Kerberos: 300 * Create kadmind principals with keys for all supported encryption types. 301 * Follows a similar pattern to add_principal() in keytab.c. 302 */ 303 krb5_enctype *tmpenc, *enctype = NULL; 304 krb5_key_salt_tuple *keysalt; 305 int num_ks, i; 306 krb5_int32 normalsalttype; 307 308 ret = krb5_get_permitted_enctypes(context, &enctype); 309 if (ret || *enctype == NULL) { 310 com_err(progname, ret, 311 gettext("while getting list of permitted encryption types")); 312 krb5_free_principal(context, ent.principal); 313 free(fullname); 314 return ERR; 315 } 316 317 /* Count the number of enc types */ 318 for (tmpenc = enctype, num_ks = 0; *tmpenc; tmpenc++) 319 num_ks++; 320 321 keysalt = malloc (sizeof (krb5_key_salt_tuple) * num_ks); 322 if (keysalt == NULL) { 323 com_err(progname, ENOMEM, 324 gettext("while generating list of key salt tuples")); 325 krb5_free_ktypes(context, enctype); 326 krb5_free_principal(context, ent.principal); 327 free(fullname); 328 return ERR; 329 } 330 331 ret = krb5_string_to_salttype("normal", &normalsalttype); 332 if (ret) { 333 com_err(progname, ret, 334 gettext("while converting \"normal\" to a salttype")); 335 free(keysalt); 336 krb5_free_ktypes(context, enctype); 337 krb5_free_principal(context, ent.principal); 338 free(fullname); 339 return ERR; 340 } 341 342 /* Only create keys with "normal" salttype */ 343 for (i = 0; i < num_ks; i++) { 344 keysalt[i].ks_enctype = enctype[i]; 345 keysalt[i].ks_salttype = normalsalttype; 346 } 347 348 ret = kadm5_randkey_principal_3(handle, ent.principal, FALSE, num_ks, 349 keysalt, NULL, NULL); 350 free(keysalt); 351 krb5_free_ktypes (context, enctype); 352 353 354 if (ret) { 355 com_err(progname, ret, 356 gettext(str_RANDOM_KEY), fullname); 357 krb5_free_principal(context, ent.principal); 358 free(fullname); 359 return ERR; 360 } 361 362 ent.attributes = attrs; 363 ret = kadm5_modify_principal(handle, &ent, KADM5_ATTRIBUTES); 364 if (ret) { 365 com_err(progname, ret, 366 gettext(str_PUT_PRINC), fullname); 367 krb5_free_principal(context, ent.principal); 368 free(fullname); 369 return ERR; 370 } 371 } 372 373 krb5_free_principal(context, ent.principal); 374 free(fullname); 375 376 return OK; 377 } 378 379 int 380 add_admin_old_princ(void *handle, krb5_context context, 381 char *name, char *realm, int attrs, int lifetime) 382 { 383 char *fullname; 384 krb5_error_code ret; 385 krb5_principal principal; 386 387 fullname = build_name_with_realm(name, realm); 388 if (ret = krb5_parse_name(context, fullname, &principal)) { 389 com_err(progname, ret, gettext(str_PARSE_NAME)); 390 return (ERR); 391 } 392 393 return (add_admin_princ(handle, context, principal, attrs, lifetime)); 394 } 395 396 int 397 add_admin_sname_princ(void *handle, krb5_context context, 398 char *sname, int attrs, int lifetime) 399 { 400 krb5_error_code ret; 401 krb5_principal principal; 402 403 if (ret = krb5_sname_to_principal(context, NULL, sname, 404 KRB5_NT_SRV_HST, &principal)) { 405 com_err(progname, ret, 406 gettext("Could not get host based " 407 "service name for %s principal\n"), sname); 408 return (ERR); 409 } 410 return (add_admin_princ(handle, context, principal, attrs, lifetime)); 411 } 412 413 414 415