xref: /onnv-gate/usr/src/cmd/krb5/kadmin/dbutil/kadm5_create.c (revision 2881:ea6360e7e1c5)
10Sstevel@tonic-gate /*
21508Smp153739  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
70Sstevel@tonic-gate /*
80Sstevel@tonic-gate  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
90Sstevel@tonic-gate  *
100Sstevel@tonic-gate  * $Id: kadm5_create.c,v 1.6 1998/10/30 02:52:37 marc Exp $
110Sstevel@tonic-gate  * $Source: /cvs/krbdev/krb5/src/kadmin/dbutil/kadm5_create.c,v $
120Sstevel@tonic-gate  */
130Sstevel@tonic-gate 
140Sstevel@tonic-gate /*
150Sstevel@tonic-gate  * Copyright (C) 1998 by the FundsXpress, INC.
160Sstevel@tonic-gate  *
170Sstevel@tonic-gate  * All rights reserved.
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * Export of this software from the United States of America may require
200Sstevel@tonic-gate  * a specific license from the United States Government.  It is the
210Sstevel@tonic-gate  * responsibility of any person or organization contemplating export to
220Sstevel@tonic-gate  * obtain such a license before exporting.
230Sstevel@tonic-gate  *
240Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
250Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
260Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
270Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
280Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
290Sstevel@tonic-gate  * the name of FundsXpress. not be used in advertising or publicity pertaining
300Sstevel@tonic-gate  * to distribution of the software without specific, written prior
310Sstevel@tonic-gate  * permission.  FundsXpress makes no representations about the suitability of
320Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
330Sstevel@tonic-gate  * or implied warranty.
340Sstevel@tonic-gate  *
350Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
360Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
370Sstevel@tonic-gate  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #include "string_table.h"
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #include <stdio.h>
430Sstevel@tonic-gate #include <stdlib.h>
440Sstevel@tonic-gate #include <string.h>
450Sstevel@tonic-gate #include <kadm5/adb.h>
460Sstevel@tonic-gate #include <kadm5/admin.h>
47*2881Smp153739 #include <krb5/adm_proto.h>
48*2881Smp153739 
490Sstevel@tonic-gate 
500Sstevel@tonic-gate #include <krb5.h>
510Sstevel@tonic-gate #include <krb5/kdb.h>
520Sstevel@tonic-gate #include <libintl.h>
530Sstevel@tonic-gate 
540Sstevel@tonic-gate int
550Sstevel@tonic-gate add_admin_old_princ(void *handle, krb5_context context,
560Sstevel@tonic-gate 		    char *name, char *realm, int attrs, int lifetime);
570Sstevel@tonic-gate int
580Sstevel@tonic-gate add_admin_sname_princ(void *handle, krb5_context context,
590Sstevel@tonic-gate     char *sname, int attrs, int lifetime);
600Sstevel@tonic-gate int
610Sstevel@tonic-gate add_admin_princ(void *handle, krb5_context context,
620Sstevel@tonic-gate     krb5_principal principal, int attrs, int lifetime);
630Sstevel@tonic-gate 
64*2881Smp153739 static int add_admin_princs(void *handle, krb5_context context, char *realm);
65*2881Smp153739 
66*2881Smp153739 #define ERR 1
67*2881Smp153739 #define OK 0
680Sstevel@tonic-gate 
690Sstevel@tonic-gate #define ADMIN_LIFETIME 60*60*3 /* 3 hours */
700Sstevel@tonic-gate #define CHANGEPW_LIFETIME 60*5 /* 5 minutes */
710Sstevel@tonic-gate 
720Sstevel@tonic-gate extern char *progname;
730Sstevel@tonic-gate 
740Sstevel@tonic-gate /*
750Sstevel@tonic-gate  * Function: kadm5_create
760Sstevel@tonic-gate  *
770Sstevel@tonic-gate  * Purpose: create admin principals in KDC database
780Sstevel@tonic-gate  *
790Sstevel@tonic-gate  * Arguments:	params	(r) configuration parameters to use
800Sstevel@tonic-gate  *
810Sstevel@tonic-gate  * Effects:  Creates KADM5_ADMIN_SERVICE and KADM5_CHANGEPW_SERVICE
820Sstevel@tonic-gate  * principals in the KDC database and sets their attributes
830Sstevel@tonic-gate  * appropriately.
840Sstevel@tonic-gate  */
85*2881Smp153739 int kadm5_create(kadm5_config_params *params)
860Sstevel@tonic-gate {
870Sstevel@tonic-gate      int retval;
880Sstevel@tonic-gate      krb5_context context;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate      kadm5_config_params lparams;
910Sstevel@tonic-gate 
92*2881Smp153739      if ((retval = krb5_init_context(&context)))
93*2881Smp153739 	  exit(ERR);
940Sstevel@tonic-gate 
950Sstevel@tonic-gate      (void) memset(&lparams, 0, sizeof (kadm5_config_params));
960Sstevel@tonic-gate 
970Sstevel@tonic-gate      /*
980Sstevel@tonic-gate       * The lock file has to exist before calling kadm5_init, but
990Sstevel@tonic-gate       * params->admin_lockfile may not be set yet...
1000Sstevel@tonic-gate       */
101*2881Smp153739      if ((retval = kadm5_get_config_params(context, NULL, NULL,
102*2881Smp153739 					   params, &lparams))) {
103*2881Smp153739 	com_err(progname, retval, gettext("while looking up the Kerberos configuration"));
104*2881Smp153739 	  return 1;
1050Sstevel@tonic-gate      }
106*2881Smp153739 
107*2881Smp153739      if ((retval = osa_adb_create_policy_db(&lparams))) {
1080Sstevel@tonic-gate 	com_err(progname, retval, gettext(str_CREATING_POLICY_DB));
109*2881Smp153739 	  return 1;
1100Sstevel@tonic-gate      }
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate      retval = kadm5_create_magic_princs(&lparams, context);
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate      kadm5_free_config_params(context, &lparams);
1150Sstevel@tonic-gate      krb5_free_context(context);
1160Sstevel@tonic-gate 
117*2881Smp153739      return retval;
1180Sstevel@tonic-gate }
1190Sstevel@tonic-gate 
120*2881Smp153739 int kadm5_create_magic_princs(kadm5_config_params *params,
121*2881Smp153739 			      krb5_context context)
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate      int retval;
1240Sstevel@tonic-gate      void *handle;
1250Sstevel@tonic-gate 
126*2881Smp153739      retval = krb5_klog_init(context, "admin_server", progname, 0);
127*2881Smp153739      if (retval)
128*2881Smp153739 	  return retval;
1290Sstevel@tonic-gate      if ((retval = kadm5_init(progname, NULL, NULL, params,
1300Sstevel@tonic-gate 			      KADM5_STRUCT_VERSION,
1310Sstevel@tonic-gate 			      KADM5_API_VERSION_2,
1320Sstevel@tonic-gate 			      &handle))) {
133*2881Smp153739 	com_err(progname, retval,  gettext("while initializing the Kerberos admin interface"));
134*2881Smp153739 	  return retval;
1350Sstevel@tonic-gate      }
136*2881Smp153739 
1370Sstevel@tonic-gate      retval = add_admin_princs(handle, context, params->realm);
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate      kadm5_destroy(handle);
1400Sstevel@tonic-gate 
141*2881Smp153739      krb5_klog_close(context);
142*2881Smp153739 
143*2881Smp153739      return retval;
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate /*
1470Sstevel@tonic-gate  * Function: build_name_with_realm
1480Sstevel@tonic-gate  *
1490Sstevel@tonic-gate  * Purpose: concatenate a name and a realm to form a krb5 name
1500Sstevel@tonic-gate  *
1510Sstevel@tonic-gate  * Arguments:
1520Sstevel@tonic-gate  *
1530Sstevel@tonic-gate  * 	name	(input) the name
1540Sstevel@tonic-gate  * 	realm	(input) the realm
1550Sstevel@tonic-gate  *
1560Sstevel@tonic-gate  * Returns:
1570Sstevel@tonic-gate  *
1580Sstevel@tonic-gate  * 	pointer to name@realm, in allocated memory, or NULL if it
1590Sstevel@tonic-gate  * 	cannot be allocated
1600Sstevel@tonic-gate  *
1610Sstevel@tonic-gate  * Requires: both strings are null-terminated
1620Sstevel@tonic-gate  */
163*2881Smp153739 static char *build_name_with_realm(char *name, char *realm)
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate      char *n;
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate      n = (char *) malloc(strlen(name) + strlen(realm) + 2);
1680Sstevel@tonic-gate      sprintf(n, "%s@%s", name, realm);
169*2881Smp153739      return n;
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate  * Function: add_admin_princs
1740Sstevel@tonic-gate  *
1750Sstevel@tonic-gate  * Purpose: create admin principals
1760Sstevel@tonic-gate  *
1770Sstevel@tonic-gate  * Arguments:
1780Sstevel@tonic-gate  *
1790Sstevel@tonic-gate  * 	rseed		(input) random seed
1800Sstevel@tonic-gate  * 	realm		(input) realm, or NULL for default realm
1810Sstevel@tonic-gate  *      <return value>  (output) status, 0 for success, 1 for serious error
1820Sstevel@tonic-gate  *
1830Sstevel@tonic-gate  * Requires:
1840Sstevel@tonic-gate  *
1850Sstevel@tonic-gate  * Effects:
1860Sstevel@tonic-gate  *
1870Sstevel@tonic-gate  * add_admin_princs creates KADM5_ADMIN_SERVICE,
1880Sstevel@tonic-gate  * KADM5_CHANGEPW_SERVICE.  If any of these exist a message is
1890Sstevel@tonic-gate  * printed.  If any of these existing principal do not have the proper
1900Sstevel@tonic-gate  * attributes, a warning message is printed.
1910Sstevel@tonic-gate  */
192*2881Smp153739 static int add_admin_princs(void *handle, krb5_context context, char *realm)
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate   krb5_error_code ret = 0;
1951508Smp153739 
1961508Smp153739 /*
1971508Smp153739  * Solaris Kerberos:
1981508Smp153739  * The kadmin/admin principal is unused on Solaris. This principal is used
1991508Smp153739  * in AUTH_GSSAPI but Solaris doesn't support AUTH_GSSAPI. RPCSEC_GSS can only
2001508Smp153739  * be used with host-based principals.
2011508Smp153739  *
2021508Smp153739  */
2031508Smp153739 
2041508Smp153739 #if 0
2051508Smp153739   if ((ret = add_admin_old_princ(handle, context,
2061508Smp153739   		     KADM5_ADMIN_SERVICE, realm,
2071508Smp153739   		     KRB5_KDB_DISALLOW_TGT_BASED,
2081508Smp153739   		     ADMIN_LIFETIME)))
2091508Smp153739      goto clean_and_exit;
2101508Smp153739 #endif
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	if ((ret = add_admin_old_princ(handle, context,
2130Sstevel@tonic-gate 			     KADM5_CHANGEPW_SERVICE, realm,
2140Sstevel@tonic-gate 			     KRB5_KDB_DISALLOW_TGT_BASED |
2150Sstevel@tonic-gate 			     KRB5_KDB_PWCHANGE_SERVICE,
2160Sstevel@tonic-gate 			     CHANGEPW_LIFETIME)))
2170Sstevel@tonic-gate        goto clean_and_exit;
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 	if ((ret = add_admin_sname_princ(handle, context,
2200Sstevel@tonic-gate 		    KADM5_ADMIN_HOST_SERVICE,
2210Sstevel@tonic-gate 		    KRB5_KDB_DISALLOW_TGT_BASED,
2220Sstevel@tonic-gate 		    ADMIN_LIFETIME)))
2230Sstevel@tonic-gate 		goto clean_and_exit;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	if ((ret = add_admin_sname_princ(handle, context,
2260Sstevel@tonic-gate 		    KADM5_CHANGEPW_HOST_SERVICE,
2270Sstevel@tonic-gate 		    KRB5_KDB_DISALLOW_TGT_BASED |
2280Sstevel@tonic-gate 		    KRB5_KDB_PWCHANGE_SERVICE,
2290Sstevel@tonic-gate 		    ADMIN_LIFETIME)))
2300Sstevel@tonic-gate 		goto clean_and_exit;
2310Sstevel@tonic-gate 
2321508Smp153739 	if ((ret = add_admin_sname_princ(handle, context,
2331508Smp153739 		    KADM5_KIPROP_HOST_SERVICE,
2341508Smp153739 		    KRB5_KDB_DISALLOW_TGT_BASED,
2351508Smp153739 		    ADMIN_LIFETIME)))
2361508Smp153739 		goto clean_and_exit;
2371508Smp153739 
2380Sstevel@tonic-gate clean_and_exit:
2390Sstevel@tonic-gate 
240*2881Smp153739   return ret;
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate /*
2440Sstevel@tonic-gate  * Function: add_admin_princ
2450Sstevel@tonic-gate  *
2460Sstevel@tonic-gate  * Arguments:
2470Sstevel@tonic-gate  *
2480Sstevel@tonic-gate  * 	creator		(r) principal to use as "mod_by"
2490Sstevel@tonic-gate  * 	rseed		(r) seed for random key generator
2500Sstevel@tonic-gate  *	principal	(r) kerberos principal to add
2510Sstevel@tonic-gate  * 	attrs		(r) principal's attributes
2520Sstevel@tonic-gate  * 	lifetime	(r) principal's max life, or 0
2530Sstevel@tonic-gate  * 	not_unique	(r) error message for multiple entries, never used
2540Sstevel@tonic-gate  * 	exists		(r) warning message for principal exists
2550Sstevel@tonic-gate  * 	wrong_attrs	(r) warning message for wrong attributes
2560Sstevel@tonic-gate  *
2570Sstevel@tonic-gate  * Returns:
2580Sstevel@tonic-gate  *
259*2881Smp153739  * 	OK on success
260*2881Smp153739  * 	ERR on serious errors
2610Sstevel@tonic-gate  *
2620Sstevel@tonic-gate  * Effects:
2630Sstevel@tonic-gate  *
2640Sstevel@tonic-gate  * If the principal is not unique, not_unique is printed (but this
2650Sstevel@tonic-gate  * never happens).  If the principal exists, then exists is printed
2660Sstevel@tonic-gate  * and if the principals attributes != attrs, wrong_attrs is printed.
2670Sstevel@tonic-gate  * Otherwise, the principal is created with mod_by creator and
2680Sstevel@tonic-gate  * attributes attrs and max life of lifetime (if not zero).
2690Sstevel@tonic-gate  */
2700Sstevel@tonic-gate 
271*2881Smp153739 int add_admin_princ(void *handle, krb5_context context,
2720Sstevel@tonic-gate     krb5_principal principal, int attrs, int lifetime)
2730Sstevel@tonic-gate {
2740Sstevel@tonic-gate      char *fullname;
2750Sstevel@tonic-gate      krb5_error_code ret;
2760Sstevel@tonic-gate      kadm5_principal_ent_rec ent;
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate      memset(&ent, 0, sizeof(ent));
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	if (krb5_unparse_name(context, principal, &fullname))
281*2881Smp153739 		return ERR;
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate      ent.principal = principal;
2840Sstevel@tonic-gate      ent.max_life = lifetime;
2850Sstevel@tonic-gate      ent.attributes = attrs | KRB5_KDB_DISALLOW_ALL_TIX;
2860Sstevel@tonic-gate 
287*2881Smp153739      ret = kadm5_create_principal(handle, &ent,
288*2881Smp153739 				  (KADM5_PRINCIPAL | KADM5_MAX_LIFE |
289*2881Smp153739 				   KADM5_ATTRIBUTES),
290*2881Smp153739 				  "to-be-random");
291*2881Smp153739      if (ret) {
2920Sstevel@tonic-gate 	  if (ret != KADM5_DUP) {
2930Sstevel@tonic-gate 		com_err(progname, ret,
2940Sstevel@tonic-gate 			gettext(str_PUT_PRINC), fullname);
2950Sstevel@tonic-gate 	       krb5_free_principal(context, ent.principal);
2960Sstevel@tonic-gate 	       free(fullname);
297*2881Smp153739 	       return ERR;
2980Sstevel@tonic-gate 	  }
2990Sstevel@tonic-gate      } else {
3000Sstevel@tonic-gate 	  /* only randomize key if we created the principal */
3010Sstevel@tonic-gate 	ret = kadm5_randkey_principal(handle, ent.principal, NULL, NULL);
3020Sstevel@tonic-gate 	if (ret) {
3030Sstevel@tonic-gate 		com_err(progname, ret,
3040Sstevel@tonic-gate 			gettext(str_RANDOM_KEY), fullname);
305*2881Smp153739 	       krb5_free_principal(context, ent.principal);
306*2881Smp153739 	       free(fullname);
307*2881Smp153739 	       return ERR;
308*2881Smp153739 	  }
309*2881Smp153739 
310*2881Smp153739 	  ent.attributes = attrs;
311*2881Smp153739 	  ret = kadm5_modify_principal(handle, &ent, KADM5_ATTRIBUTES);
312*2881Smp153739 	  if (ret) {
313*2881Smp153739 	      com_err(progname, ret,
314*2881Smp153739 	       gettext(str_PUT_PRINC), fullname);
315*2881Smp153739 	       krb5_free_principal(context, ent.principal);
316*2881Smp153739 	       free(fullname);
317*2881Smp153739 	       return ERR;
318*2881Smp153739 	  }
319*2881Smp153739      }
3200Sstevel@tonic-gate 
321*2881Smp153739      krb5_free_principal(context, ent.principal);
322*2881Smp153739      free(fullname);
3230Sstevel@tonic-gate 
324*2881Smp153739      return OK;
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate int
3280Sstevel@tonic-gate add_admin_old_princ(void *handle, krb5_context context,
3290Sstevel@tonic-gate     char *name, char *realm, int attrs, int lifetime)
3300Sstevel@tonic-gate {
3310Sstevel@tonic-gate 	char *fullname;
3320Sstevel@tonic-gate 	krb5_error_code ret;
3330Sstevel@tonic-gate 	krb5_principal principal;
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 	fullname = build_name_with_realm(name, realm);
3360Sstevel@tonic-gate 	if (ret = krb5_parse_name(context, fullname, &principal)) {
3370Sstevel@tonic-gate 		com_err(progname, ret, gettext(str_PARSE_NAME));
338*2881Smp153739 		return (ERR);
3390Sstevel@tonic-gate 	}
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	return (add_admin_princ(handle, context, principal, attrs, lifetime));
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate int
3450Sstevel@tonic-gate add_admin_sname_princ(void *handle, krb5_context context,
3460Sstevel@tonic-gate 	     char *sname, int attrs, int lifetime)
3470Sstevel@tonic-gate {
3480Sstevel@tonic-gate 	krb5_error_code ret;
3490Sstevel@tonic-gate 	krb5_principal principal;
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	if (ret = krb5_sname_to_principal(context, NULL, sname,
3520Sstevel@tonic-gate 					  KRB5_NT_SRV_HST, &principal)) {
3530Sstevel@tonic-gate 		com_err(progname, ret,
3540Sstevel@tonic-gate 			gettext("Could not get host based "
3550Sstevel@tonic-gate 				"service name for %s principal\n"), sname);
356*2881Smp153739 		return (ERR);
3570Sstevel@tonic-gate 	}
3580Sstevel@tonic-gate 	return (add_admin_princ(handle, context, principal, attrs, lifetime));
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 
363