xref: /titanic_44/usr/src/lib/krb5/kadm5/srv/server_acl.c (revision 159d09a20817016f09b3ea28d1bdada4a336bb91)
17c478bd9Sstevel@tonic-gate /*
2*159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  *	Openvision retains the copyright to derivative works of
117c478bd9Sstevel@tonic-gate  *	this source code.  Do *NOT* create a derivative of this
127c478bd9Sstevel@tonic-gate  *	source code before consulting with your legal department.
137c478bd9Sstevel@tonic-gate  *	Do *NOT* integrate *ANY* of this source code into another
147c478bd9Sstevel@tonic-gate  *	product before consulting with your legal department.
157c478bd9Sstevel@tonic-gate  *
167c478bd9Sstevel@tonic-gate  *	For further information, read the top-level Openvision
177c478bd9Sstevel@tonic-gate  *	copyright which is contained in the top-level MIT Kerberos
187c478bd9Sstevel@tonic-gate  *	copyright.
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
217c478bd9Sstevel@tonic-gate  *
227c478bd9Sstevel@tonic-gate  */
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate  * kadmin/v5server/srv_acl.c
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  * Copyright 1995 by the Massachusetts Institute of Technology.
297c478bd9Sstevel@tonic-gate  * All Rights Reserved.
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
327c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
337c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
347c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
377c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
387c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
397c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
407c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
417c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
427c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
437c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
447c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
457c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
467c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
477c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
487c478bd9Sstevel@tonic-gate  * or implied warranty.
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  * srv_acl.c - Handle Kerberos ACL related functions.
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate #include <stdio.h>
567c478bd9Sstevel@tonic-gate #include <syslog.h>
577c478bd9Sstevel@tonic-gate #include <sys/param.h>
587c478bd9Sstevel@tonic-gate #include "k5-int.h"
59*159d09a2SMark Phalan #include <gssapi_krb5.h>
607c478bd9Sstevel@tonic-gate #include <kadm5/server_internal.h>
617c478bd9Sstevel@tonic-gate #include <kadm5/admin.h>
627c478bd9Sstevel@tonic-gate #include <adm_proto.h> /* SUNWresync121 XXX */
637c478bd9Sstevel@tonic-gate #include "server_acl.h"
647c478bd9Sstevel@tonic-gate #include <ctype.h>
657c478bd9Sstevel@tonic-gate #include <libintl.h> /* SUNWresync121 XXX */
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate typedef struct _acl_op_table {
687c478bd9Sstevel@tonic-gate     char	ao_op;
697c478bd9Sstevel@tonic-gate     krb5_int32	ao_mask;
707c478bd9Sstevel@tonic-gate } aop_t;
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate typedef struct _acl_entry {
737c478bd9Sstevel@tonic-gate     struct _acl_entry	*ae_next;
747c478bd9Sstevel@tonic-gate     char		*ae_name;
757c478bd9Sstevel@tonic-gate     krb5_boolean	ae_name_bad;
767c478bd9Sstevel@tonic-gate     krb5_principal	ae_principal;
777c478bd9Sstevel@tonic-gate     krb5_int32		ae_op_allowed;
787c478bd9Sstevel@tonic-gate     char		*ae_target;
797c478bd9Sstevel@tonic-gate     krb5_boolean	ae_target_bad;
807c478bd9Sstevel@tonic-gate     krb5_principal	ae_target_princ;
817c478bd9Sstevel@tonic-gate     char		*ae_restriction_string;
827c478bd9Sstevel@tonic-gate 			/* eg: "-maxlife 3h -service +proxiable" */
837c478bd9Sstevel@tonic-gate     krb5_boolean	ae_restriction_bad;
847c478bd9Sstevel@tonic-gate     restriction_t	*ae_restrictions;
857c478bd9Sstevel@tonic-gate } aent_t;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate static const aop_t acl_op_table[] = {
887c478bd9Sstevel@tonic-gate     { 'a',	ACL_ADD },
897c478bd9Sstevel@tonic-gate     { 'd',	ACL_DELETE },
907c478bd9Sstevel@tonic-gate     { 'm',	ACL_MODIFY },
917c478bd9Sstevel@tonic-gate     { 'c',	ACL_CHANGEPW },
927c478bd9Sstevel@tonic-gate     { 'i',	ACL_INQUIRE },
937c478bd9Sstevel@tonic-gate     { 'l',	ACL_LIST },
947c478bd9Sstevel@tonic-gate     { 'p',	ACL_IPROP },		/* SUNW IProp */
957c478bd9Sstevel@tonic-gate     { 's',	ACL_SETKEY },
967c478bd9Sstevel@tonic-gate     { 'u',	ACL_MIGRATE },		/* pam_krb5_migrate */
977c478bd9Sstevel@tonic-gate     { 'x',	ACL_ALL_MASK },
987c478bd9Sstevel@tonic-gate     { '*',	ACL_ALL_MASK },
997c478bd9Sstevel@tonic-gate     { '\0',	0 }
1007c478bd9Sstevel@tonic-gate };
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate typedef struct _wildstate {
1037c478bd9Sstevel@tonic-gate     int		nwild;
1047c478bd9Sstevel@tonic-gate     krb5_data	*backref[9];
1057c478bd9Sstevel@tonic-gate } wildstate_t;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate static aent_t	*acl_list_head = (aent_t *) NULL;
1087c478bd9Sstevel@tonic-gate static aent_t	*acl_list_tail = (aent_t *) NULL;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate static const char *acl_acl_file = (char *) NULL;
1117c478bd9Sstevel@tonic-gate static int acl_inited = 0;
1127c478bd9Sstevel@tonic-gate static int acl_debug_level = 0;
1137c478bd9Sstevel@tonic-gate /*
1147c478bd9Sstevel@tonic-gate  * This is the catchall entry.  If nothing else appropriate is found, or in
1157c478bd9Sstevel@tonic-gate  * the case where the ACL file is not present, this entry controls what can
1167c478bd9Sstevel@tonic-gate  * be done.
1177c478bd9Sstevel@tonic-gate  */
1187c478bd9Sstevel@tonic-gate static const char *acl_catchall_entry = NULL;
1197c478bd9Sstevel@tonic-gate 
120*159d09a2SMark Phalan /* Solaris Kerberos */
1217c478bd9Sstevel@tonic-gate #define ACL_LINE2LONG_MSG dgettext(TEXT_DOMAIN, \
1227c478bd9Sstevel@tonic-gate 			"%s: line %d too long, truncated\n")
1237c478bd9Sstevel@tonic-gate #define ACL_OP_BAD_MSG dgettext(TEXT_DOMAIN, \
1247c478bd9Sstevel@tonic-gate 			"Unrecognized ACL operation '%c' in %s\n")
1257c478bd9Sstevel@tonic-gate #define ACL_SYN_ERR_MSG dgettext(TEXT_DOMAIN, \
1267c478bd9Sstevel@tonic-gate 			"%s: syntax error at line %d <%10s...>\n")
1277c478bd9Sstevel@tonic-gate #define ACL_CANTOPEN_MSG dgettext(TEXT_DOMAIN, \
1287c478bd9Sstevel@tonic-gate 			"\007cannot open ACL file")
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate /*
13256a424ccSmp153739  * kadm5int_acl_get_line() - Get a line from the ACL file.
1337c478bd9Sstevel@tonic-gate  *			Lines ending with \ are continued on the next line
1347c478bd9Sstevel@tonic-gate  */
1357c478bd9Sstevel@tonic-gate static char *
kadm5int_acl_get_line(fp,lnp)13656a424ccSmp153739 kadm5int_acl_get_line(fp, lnp)
1377c478bd9Sstevel@tonic-gate     FILE	*fp;
1387c478bd9Sstevel@tonic-gate     int		*lnp;		/* caller should set to 1 before first call */
1397c478bd9Sstevel@tonic-gate {
1407c478bd9Sstevel@tonic-gate     int		i, domore;
1417c478bd9Sstevel@tonic-gate     static int	line_incr = 0;
1427c478bd9Sstevel@tonic-gate     static char acl_buf[BUFSIZ];
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate     *lnp += line_incr;
1457c478bd9Sstevel@tonic-gate     line_incr = 0;
1467c478bd9Sstevel@tonic-gate     for (domore = 1; domore && !feof(fp); ) {
1477c478bd9Sstevel@tonic-gate 	/* Copy in the line, with continuations */
1487c478bd9Sstevel@tonic-gate 	for (i=0; ((i < sizeof acl_buf) && !feof(fp)); i++ ) {
1497c478bd9Sstevel@tonic-gate 	    acl_buf[i] = fgetc(fp);
1507c478bd9Sstevel@tonic-gate 	    if (acl_buf[i] == (char)EOF) {
1517c478bd9Sstevel@tonic-gate 		if (i > 0 && acl_buf[i-1] == '\\')
1527c478bd9Sstevel@tonic-gate 		    i--;
1537c478bd9Sstevel@tonic-gate 		break;		/* it gets nulled-out below */
1547c478bd9Sstevel@tonic-gate 	    }
1557c478bd9Sstevel@tonic-gate 	    else if (acl_buf[i] == '\n') {
1567c478bd9Sstevel@tonic-gate 		if (i == 0 || acl_buf[i-1] != '\\')
1577c478bd9Sstevel@tonic-gate 		    break;	/* empty line or normal end of line */
1587c478bd9Sstevel@tonic-gate 		else {
1597c478bd9Sstevel@tonic-gate 		    i -= 2;	/* back up over "\\\n" and continue */
1607c478bd9Sstevel@tonic-gate 		    line_incr++;
1617c478bd9Sstevel@tonic-gate 		}
1627c478bd9Sstevel@tonic-gate 	    }
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 	/* Check if we exceeded our buffer size */
1657c478bd9Sstevel@tonic-gate 	if (i == sizeof acl_buf && (i--, !feof(fp))) {
1667c478bd9Sstevel@tonic-gate 	    int	c1 = acl_buf[i], c2;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	    krb5_klog_syslog(LOG_ERR, ACL_LINE2LONG_MSG, acl_acl_file, *lnp);
1697c478bd9Sstevel@tonic-gate 	    while ((c2 = fgetc(fp)) != EOF) {
1707c478bd9Sstevel@tonic-gate 		if (c2 == '\n') {
1717c478bd9Sstevel@tonic-gate 		    if (c1 != '\\')
1727c478bd9Sstevel@tonic-gate 			break;
1737c478bd9Sstevel@tonic-gate 		    line_incr++;
1747c478bd9Sstevel@tonic-gate 		}
1757c478bd9Sstevel@tonic-gate 		c1 = c2;
1767c478bd9Sstevel@tonic-gate 	    }
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 	acl_buf[i] = '\0';
1797c478bd9Sstevel@tonic-gate 	if (acl_buf[0] == (char) EOF)	/* ptooey */
1807c478bd9Sstevel@tonic-gate 	    acl_buf[0] = '\0';
1817c478bd9Sstevel@tonic-gate 	else
1827c478bd9Sstevel@tonic-gate 	    line_incr++;
1837c478bd9Sstevel@tonic-gate 	if ((acl_buf[0] != '#') && (acl_buf[0] != '\0'))
1847c478bd9Sstevel@tonic-gate 	    domore = 0;
1857c478bd9Sstevel@tonic-gate     }
1867c478bd9Sstevel@tonic-gate     if (domore || (strlen(acl_buf) == 0))
1877c478bd9Sstevel@tonic-gate 	return((char *) NULL);
1887c478bd9Sstevel@tonic-gate     else
1897c478bd9Sstevel@tonic-gate 	return(acl_buf);
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate /*
19356a424ccSmp153739  * kadm5int_acl_parse_line() - Parse the contents of an ACL line.
1947c478bd9Sstevel@tonic-gate  */
1957c478bd9Sstevel@tonic-gate static aent_t *
kadm5int_acl_parse_line(lp)19656a424ccSmp153739 kadm5int_acl_parse_line(lp)
1977c478bd9Sstevel@tonic-gate     const char *lp;
1987c478bd9Sstevel@tonic-gate {
1997c478bd9Sstevel@tonic-gate     static char acle_principal[BUFSIZ];
2007c478bd9Sstevel@tonic-gate     static char acle_ops[BUFSIZ];
2017c478bd9Sstevel@tonic-gate     static char acle_object[BUFSIZ];
2027c478bd9Sstevel@tonic-gate     static char acle_restrictions[BUFSIZ];
2037c478bd9Sstevel@tonic-gate     aent_t	*acle;
2047c478bd9Sstevel@tonic-gate     char	*op;
2057c478bd9Sstevel@tonic-gate     int		t, found, opok, nmatch;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate     DPRINT(DEBUG_CALLS, acl_debug_level,
20856a424ccSmp153739 	   ("* kadm5int_acl_parse_line(line=%20s)\n", lp));
2097c478bd9Sstevel@tonic-gate     /*
2107c478bd9Sstevel@tonic-gate      * Format is still simple:
2117c478bd9Sstevel@tonic-gate      *  entry ::= [<whitespace>] <principal> <whitespace> <opstring>
2127c478bd9Sstevel@tonic-gate      *		  [<whitespace> <target> [<whitespace> <restrictions>
2137c478bd9Sstevel@tonic-gate      *					  [<whitespace>]]]
2147c478bd9Sstevel@tonic-gate      */
2157c478bd9Sstevel@tonic-gate     acle = (aent_t *) NULL;
2167c478bd9Sstevel@tonic-gate     acle_object[0] = '\0';
2177c478bd9Sstevel@tonic-gate     nmatch = sscanf(lp, "%s %s %s %[^\n]", acle_principal, acle_ops,
2187c478bd9Sstevel@tonic-gate 		    acle_object, acle_restrictions);
2197c478bd9Sstevel@tonic-gate     if (nmatch >= 2) {
2207c478bd9Sstevel@tonic-gate 	acle = (aent_t *) malloc(sizeof(aent_t));
2217c478bd9Sstevel@tonic-gate 	if (acle) {
2227c478bd9Sstevel@tonic-gate 	    acle->ae_next = (aent_t *) NULL;
2237c478bd9Sstevel@tonic-gate 	    acle->ae_op_allowed = (krb5_int32) 0;
2247c478bd9Sstevel@tonic-gate 	    acle->ae_target =
2257c478bd9Sstevel@tonic-gate 		(nmatch >= 3) ? strdup(acle_object) : (char *) NULL;
2267c478bd9Sstevel@tonic-gate 	    acle->ae_target_bad = 0;
2277c478bd9Sstevel@tonic-gate 	    acle->ae_target_princ = (krb5_principal) NULL;
2287c478bd9Sstevel@tonic-gate 	    opok = 1;
2297c478bd9Sstevel@tonic-gate 	    for (op=acle_ops; *op; op++) {
2307c478bd9Sstevel@tonic-gate 		char rop;
2317c478bd9Sstevel@tonic-gate 
232*159d09a2SMark Phalan 		rop = (isupper((unsigned char) *op)) ? tolower((unsigned char) *op) : *op;
2337c478bd9Sstevel@tonic-gate 		found = 0;
2347c478bd9Sstevel@tonic-gate 		for (t=0; acl_op_table[t].ao_op; t++) {
2357c478bd9Sstevel@tonic-gate 		    if (rop == acl_op_table[t].ao_op) {
2367c478bd9Sstevel@tonic-gate 			found = 1;
2377c478bd9Sstevel@tonic-gate 			if (rop == *op)
2387c478bd9Sstevel@tonic-gate 			    acle->ae_op_allowed |= acl_op_table[t].ao_mask;
2397c478bd9Sstevel@tonic-gate 			else
2407c478bd9Sstevel@tonic-gate 			    acle->ae_op_allowed &= ~acl_op_table[t].ao_mask;
2417c478bd9Sstevel@tonic-gate 		    }
2427c478bd9Sstevel@tonic-gate 		}
2437c478bd9Sstevel@tonic-gate 		if (!found) {
2447c478bd9Sstevel@tonic-gate 		    krb5_klog_syslog(LOG_ERR, ACL_OP_BAD_MSG, *op, lp);
2457c478bd9Sstevel@tonic-gate 		    opok = 0;
2467c478bd9Sstevel@tonic-gate 		}
2477c478bd9Sstevel@tonic-gate 	    }
2487c478bd9Sstevel@tonic-gate 	    if (opok) {
2497c478bd9Sstevel@tonic-gate 		acle->ae_name = (char *) malloc(strlen(acle_principal)+1);
2507c478bd9Sstevel@tonic-gate 		if (acle->ae_name) {
2517c478bd9Sstevel@tonic-gate 		    strcpy(acle->ae_name, acle_principal);
2527c478bd9Sstevel@tonic-gate 		    acle->ae_principal = (krb5_principal) NULL;
2537c478bd9Sstevel@tonic-gate 		    acle->ae_name_bad = 0;
2547c478bd9Sstevel@tonic-gate 		    DPRINT(DEBUG_ACL, acl_debug_level,
2557c478bd9Sstevel@tonic-gate 			   ("A ACL entry %s -> opmask %x\n",
2567c478bd9Sstevel@tonic-gate 			    acle->ae_name, acle->ae_op_allowed));
2577c478bd9Sstevel@tonic-gate 		}
2587c478bd9Sstevel@tonic-gate 		else {
2597c478bd9Sstevel@tonic-gate 		    if (acle->ae_target)
2607c478bd9Sstevel@tonic-gate 			free(acle->ae_target);
2617c478bd9Sstevel@tonic-gate 		    free(acle);
2627c478bd9Sstevel@tonic-gate 		    acle = (aent_t *) NULL;
2637c478bd9Sstevel@tonic-gate 		}
2647c478bd9Sstevel@tonic-gate 	    }
2657c478bd9Sstevel@tonic-gate 	    else {
2667c478bd9Sstevel@tonic-gate 		if (acle->ae_target)
2677c478bd9Sstevel@tonic-gate 		    free(acle->ae_target);
2687c478bd9Sstevel@tonic-gate 		free(acle);
2697c478bd9Sstevel@tonic-gate 		acle = (aent_t *) NULL;
2707c478bd9Sstevel@tonic-gate 	    }
2717c478bd9Sstevel@tonic-gate 	    if ( nmatch >= 4 ) {
2727c478bd9Sstevel@tonic-gate 		char	*trailing;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 		trailing = &acle_restrictions[strlen(acle_restrictions)-1];
27556a424ccSmp153739 		while ( isspace((int) *trailing) )
2767c478bd9Sstevel@tonic-gate 		    trailing--;
2777c478bd9Sstevel@tonic-gate 		trailing[1] = '\0';
2787c478bd9Sstevel@tonic-gate 		acle->ae_restriction_string = strdup(acle_restrictions);
2797c478bd9Sstevel@tonic-gate 	    }
2807c478bd9Sstevel@tonic-gate 	    else {
2817c478bd9Sstevel@tonic-gate 		acle->ae_restriction_string = (char *) NULL;
2827c478bd9Sstevel@tonic-gate 	    }
2837c478bd9Sstevel@tonic-gate 	    acle->ae_restriction_bad = 0;
2847c478bd9Sstevel@tonic-gate 	    acle->ae_restrictions = (restriction_t *) NULL;
2857c478bd9Sstevel@tonic-gate 	}
2867c478bd9Sstevel@tonic-gate     }
2877c478bd9Sstevel@tonic-gate     DPRINT(DEBUG_CALLS, acl_debug_level,
28856a424ccSmp153739 	   ("X kadm5int_acl_parse_line() = %x\n", (long) acle));
2897c478bd9Sstevel@tonic-gate     return(acle);
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate /*
29356a424ccSmp153739  * kadm5int_acl_parse_restrictions() - Parse optional restrictions field
2947c478bd9Sstevel@tonic-gate  *
2957c478bd9Sstevel@tonic-gate  * Allowed restrictions are:
2967c478bd9Sstevel@tonic-gate  *	[+-]flagname		(recognized by krb5_string_to_flags)
2977c478bd9Sstevel@tonic-gate  *				flag is forced to indicated value
2987c478bd9Sstevel@tonic-gate  *	-clearpolicy		policy is forced clear
2997c478bd9Sstevel@tonic-gate  *	-policy pol		policy is forced to be "pol"
3007c478bd9Sstevel@tonic-gate  *	-{expire,pwexpire,maxlife,maxrenewlife} deltat
3017c478bd9Sstevel@tonic-gate  *				associated value will be forced to
3027c478bd9Sstevel@tonic-gate  *				MIN(deltat, requested value)
3037c478bd9Sstevel@tonic-gate  *
3047c478bd9Sstevel@tonic-gate  * Returns: 0 on success, or system errors
3057c478bd9Sstevel@tonic-gate  */
3067c478bd9Sstevel@tonic-gate static krb5_error_code
kadm5int_acl_parse_restrictions(s,rpp)30756a424ccSmp153739 kadm5int_acl_parse_restrictions(s, rpp)
3087c478bd9Sstevel@tonic-gate     char		*s;
3097c478bd9Sstevel@tonic-gate     restriction_t	**rpp;
3107c478bd9Sstevel@tonic-gate {
3117c478bd9Sstevel@tonic-gate     char		*sp, *tp, *ap;
3127c478bd9Sstevel@tonic-gate     static const char	*delims = "\t\n\f\v\r ,";
3137c478bd9Sstevel@tonic-gate     krb5_deltat		dt;
3147c478bd9Sstevel@tonic-gate     krb5_flags		flag;
3157c478bd9Sstevel@tonic-gate     krb5_error_code	code;
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate    DPRINT(DEBUG_CALLS, acl_debug_level,
31856a424ccSmp153739 	   ("* kadm5int_acl_parse_restrictions(s=%20s, rpp=0x%08x)\n", s, (long)rpp));
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate     *rpp = (restriction_t *) NULL;
3217c478bd9Sstevel@tonic-gate     code = 0;
32256a424ccSmp153739     if (s) {
3237c478bd9Sstevel@tonic-gate 	if (!(sp = strdup(s))	/* Don't munge the original */
3247c478bd9Sstevel@tonic-gate 	    || !(*rpp = (restriction_t *) malloc(sizeof(restriction_t)))) {
3257c478bd9Sstevel@tonic-gate 	    code = ENOMEM;
3267c478bd9Sstevel@tonic-gate 	} else {
3277c478bd9Sstevel@tonic-gate 	    memset(*rpp, 0, sizeof(**rpp));
3287c478bd9Sstevel@tonic-gate 	    for (tp=strtok(sp, delims); tp; tp=strtok((char *)NULL, delims)) {
3297c478bd9Sstevel@tonic-gate 		flag = 0;
3307c478bd9Sstevel@tonic-gate 		if (!krb5_string_to_flags(tp, "+", "-", &flag)) {
3317c478bd9Sstevel@tonic-gate 		    /* OK, but was it in the positive or negative sense? */
3327c478bd9Sstevel@tonic-gate 		    if (flag) {
3337c478bd9Sstevel@tonic-gate 			(*rpp)->require_attrs |= flag;
3347c478bd9Sstevel@tonic-gate 		    } else {
3357c478bd9Sstevel@tonic-gate 			flag = ~0;
3367c478bd9Sstevel@tonic-gate 			(void) krb5_string_to_flags(tp, "+", "-", &flag);
3377c478bd9Sstevel@tonic-gate 			(*rpp)->forbid_attrs |= ~flag;
3387c478bd9Sstevel@tonic-gate 		    }
3397c478bd9Sstevel@tonic-gate 		    (*rpp)->mask |= KADM5_ATTRIBUTES;
3407c478bd9Sstevel@tonic-gate 		} else if (!strcmp(tp, "-clearpolicy")) {
3417c478bd9Sstevel@tonic-gate 		    (*rpp)->mask |= KADM5_POLICY_CLR;
3427c478bd9Sstevel@tonic-gate 		} else {
3437c478bd9Sstevel@tonic-gate 		    /* everything else needs an argument ... */
3447c478bd9Sstevel@tonic-gate 		    if (!(ap = strtok((char *)NULL, delims))) {
3457c478bd9Sstevel@tonic-gate 			code = EINVAL;
3467c478bd9Sstevel@tonic-gate 			break;
3477c478bd9Sstevel@tonic-gate 		    }
3487c478bd9Sstevel@tonic-gate 		    if (!strcmp(tp, "-policy")) {
3497c478bd9Sstevel@tonic-gate 			if (!((*rpp)->policy = strdup(ap))) {
3507c478bd9Sstevel@tonic-gate 			    code = ENOMEM;
3517c478bd9Sstevel@tonic-gate 			    break;
3527c478bd9Sstevel@tonic-gate 			}
3537c478bd9Sstevel@tonic-gate 			(*rpp)->mask |= KADM5_POLICY;
3547c478bd9Sstevel@tonic-gate 		    } else {
3557c478bd9Sstevel@tonic-gate 			/* all other arguments must be a deltat ... */
3567c478bd9Sstevel@tonic-gate 			if (krb5_string_to_deltat(ap, &dt)) {
3577c478bd9Sstevel@tonic-gate 			    code = EINVAL;
3587c478bd9Sstevel@tonic-gate 			    break;
3597c478bd9Sstevel@tonic-gate 			}
3607c478bd9Sstevel@tonic-gate 			if (!strcmp(tp, "-expire")) {
3617c478bd9Sstevel@tonic-gate 			    (*rpp)->princ_lifetime = dt;
3627c478bd9Sstevel@tonic-gate 			    (*rpp)->mask |= KADM5_PRINC_EXPIRE_TIME;
3637c478bd9Sstevel@tonic-gate 			} else if (!strcmp(tp, "-pwexpire")) {
3647c478bd9Sstevel@tonic-gate 			    (*rpp)->pw_lifetime = dt;
3657c478bd9Sstevel@tonic-gate 			    (*rpp)->mask |= KADM5_PW_EXPIRATION;
3667c478bd9Sstevel@tonic-gate 			} else if (!strcmp(tp, "-maxlife")) {
3677c478bd9Sstevel@tonic-gate 			    (*rpp)->max_life = dt;
3687c478bd9Sstevel@tonic-gate 			    (*rpp)->mask |= KADM5_MAX_LIFE;
3697c478bd9Sstevel@tonic-gate 			} else if (!strcmp(tp, "-maxrenewlife")) {
3707c478bd9Sstevel@tonic-gate 			    (*rpp)->max_renewable_life = dt;
3717c478bd9Sstevel@tonic-gate 			    (*rpp)->mask |= KADM5_MAX_RLIFE;
3727c478bd9Sstevel@tonic-gate 			} else {
3737c478bd9Sstevel@tonic-gate 			    code = EINVAL;
3747c478bd9Sstevel@tonic-gate 			    break;
3757c478bd9Sstevel@tonic-gate 			}
3767c478bd9Sstevel@tonic-gate 		    }
3777c478bd9Sstevel@tonic-gate 		}
3787c478bd9Sstevel@tonic-gate 	    }
3797c478bd9Sstevel@tonic-gate 	}
38056a424ccSmp153739     }
3817c478bd9Sstevel@tonic-gate     if (sp)
3827c478bd9Sstevel@tonic-gate 	free(sp);
3837c478bd9Sstevel@tonic-gate     if (*rpp && code) {
3847c478bd9Sstevel@tonic-gate 	if ((*rpp)->policy)
3857c478bd9Sstevel@tonic-gate 	    free((*rpp)->policy);
3867c478bd9Sstevel@tonic-gate 	free(*rpp);
3877c478bd9Sstevel@tonic-gate 	*rpp = (restriction_t *) NULL;
3887c478bd9Sstevel@tonic-gate     }
3897c478bd9Sstevel@tonic-gate     DPRINT(DEBUG_CALLS, acl_debug_level,
39056a424ccSmp153739 	   ("X kadm5int_acl_parse_restrictions() = %d, mask=0x%08x\n",
3917c478bd9Sstevel@tonic-gate 	    code, (*rpp) ? (*rpp)->mask : 0));
3927c478bd9Sstevel@tonic-gate     return code;
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate /*
39656a424ccSmp153739  * kadm5int_acl_impose_restrictions()	- impose restrictions, modifying *recp, *maskp
3977c478bd9Sstevel@tonic-gate  *
3987c478bd9Sstevel@tonic-gate  * Returns: 0 on success;
3997c478bd9Sstevel@tonic-gate  *	    malloc or timeofday errors
4007c478bd9Sstevel@tonic-gate  */
4017c478bd9Sstevel@tonic-gate krb5_error_code
kadm5int_acl_impose_restrictions(kcontext,recp,maskp,rp)40256a424ccSmp153739 kadm5int_acl_impose_restrictions(kcontext, recp, maskp, rp)
4037c478bd9Sstevel@tonic-gate      krb5_context		kcontext;
4047c478bd9Sstevel@tonic-gate      kadm5_principal_ent_rec	*recp;
4057c478bd9Sstevel@tonic-gate      long			*maskp;
4067c478bd9Sstevel@tonic-gate      restriction_t		*rp;
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate     krb5_error_code	code;
4097c478bd9Sstevel@tonic-gate     krb5_int32		now;
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate     DPRINT(DEBUG_CALLS, acl_debug_level,
41256a424ccSmp153739 	   ("* kadm5int_acl_impose_restrictions(..., *maskp=0x%08x, rp=0x%08x)\n",
4137c478bd9Sstevel@tonic-gate 	    *maskp, (long)rp));
4147c478bd9Sstevel@tonic-gate     if (!rp)
4157c478bd9Sstevel@tonic-gate 	return 0;
4167c478bd9Sstevel@tonic-gate     if (rp->mask & (KADM5_PRINC_EXPIRE_TIME|KADM5_PW_EXPIRATION))
4177c478bd9Sstevel@tonic-gate 	if ((code = krb5_timeofday(kcontext, &now)))
4187c478bd9Sstevel@tonic-gate 	    return code;
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate     if (rp->mask & KADM5_ATTRIBUTES) {
4217c478bd9Sstevel@tonic-gate 	recp->attributes |= rp->require_attrs;
4227c478bd9Sstevel@tonic-gate 	recp->attributes &= ~(rp->forbid_attrs);
4237c478bd9Sstevel@tonic-gate 	*maskp |= KADM5_ATTRIBUTES;
4247c478bd9Sstevel@tonic-gate     }
4257c478bd9Sstevel@tonic-gate     if (rp->mask & KADM5_POLICY_CLR) {
4267c478bd9Sstevel@tonic-gate 	*maskp &= ~KADM5_POLICY;
4277c478bd9Sstevel@tonic-gate 	*maskp |= KADM5_POLICY_CLR;
4287c478bd9Sstevel@tonic-gate     } else if (rp->mask & KADM5_POLICY) {
4297c478bd9Sstevel@tonic-gate 	if (recp->policy && strcmp(recp->policy, rp->policy)) {
4307c478bd9Sstevel@tonic-gate 		free(recp->policy);
4317c478bd9Sstevel@tonic-gate 		recp->policy = (char *) NULL;
4327c478bd9Sstevel@tonic-gate 	}
4337c478bd9Sstevel@tonic-gate 	if (!recp->policy) {
4347c478bd9Sstevel@tonic-gate 	    recp->policy = strdup(rp->policy);  /* XDR will free it */
4357c478bd9Sstevel@tonic-gate 	    if (!recp->policy)
4367c478bd9Sstevel@tonic-gate 		return ENOMEM;
4377c478bd9Sstevel@tonic-gate 	}
4387c478bd9Sstevel@tonic-gate 	*maskp |= KADM5_POLICY;
4397c478bd9Sstevel@tonic-gate     }
4407c478bd9Sstevel@tonic-gate     if (rp->mask & KADM5_PRINC_EXPIRE_TIME) {
4417c478bd9Sstevel@tonic-gate 	if (!(*maskp & KADM5_PRINC_EXPIRE_TIME)
4427c478bd9Sstevel@tonic-gate 	    || (recp->princ_expire_time > (now + rp->princ_lifetime)))
4437c478bd9Sstevel@tonic-gate 	    recp->princ_expire_time = now + rp->princ_lifetime;
4447c478bd9Sstevel@tonic-gate 	*maskp |= KADM5_PRINC_EXPIRE_TIME;
4457c478bd9Sstevel@tonic-gate     }
4467c478bd9Sstevel@tonic-gate     if (rp->mask & KADM5_PW_EXPIRATION) {
4477c478bd9Sstevel@tonic-gate 	if (!(*maskp & KADM5_PW_EXPIRATION)
4487c478bd9Sstevel@tonic-gate 	    || (recp->pw_expiration > (now + rp->pw_lifetime)))
4497c478bd9Sstevel@tonic-gate 	    recp->pw_expiration = now + rp->pw_lifetime;
4507c478bd9Sstevel@tonic-gate 	*maskp |= KADM5_PW_EXPIRATION;
4517c478bd9Sstevel@tonic-gate     }
4527c478bd9Sstevel@tonic-gate     if (rp->mask & KADM5_MAX_LIFE) {
4537c478bd9Sstevel@tonic-gate 	if (!(*maskp & KADM5_MAX_LIFE)
4547c478bd9Sstevel@tonic-gate 	    || (recp->max_life > rp->max_life))
4557c478bd9Sstevel@tonic-gate 	    recp->max_life = rp->max_life;
4567c478bd9Sstevel@tonic-gate 	*maskp |= KADM5_MAX_LIFE;
4577c478bd9Sstevel@tonic-gate     }
4587c478bd9Sstevel@tonic-gate     if (rp->mask & KADM5_MAX_RLIFE) {
4597c478bd9Sstevel@tonic-gate 	if (!(*maskp & KADM5_MAX_RLIFE)
4607c478bd9Sstevel@tonic-gate 	    || (recp->max_renewable_life > rp->max_renewable_life))
4617c478bd9Sstevel@tonic-gate 	    recp->max_renewable_life = rp->max_renewable_life;
4627c478bd9Sstevel@tonic-gate 	*maskp |= KADM5_MAX_RLIFE;
4637c478bd9Sstevel@tonic-gate     }
4647c478bd9Sstevel@tonic-gate     DPRINT(DEBUG_CALLS, acl_debug_level,
46556a424ccSmp153739 	   ("X kadm5int_acl_impose_restrictions() = 0, *maskp=0x%08x\n", *maskp));
4667c478bd9Sstevel@tonic-gate     return 0;
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate /*
47056a424ccSmp153739  * kadm5int_acl_free_entries() - Free all ACL entries.
4717c478bd9Sstevel@tonic-gate  */
4727c478bd9Sstevel@tonic-gate static void
kadm5int_acl_free_entries()47356a424ccSmp153739 kadm5int_acl_free_entries()
4747c478bd9Sstevel@tonic-gate {
4757c478bd9Sstevel@tonic-gate     aent_t	*ap;
4767c478bd9Sstevel@tonic-gate     aent_t	*np;
4777c478bd9Sstevel@tonic-gate 
47856a424ccSmp153739     DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_free_entries()\n"));
4797c478bd9Sstevel@tonic-gate     for (ap=acl_list_head; ap; ap = np) {
4807c478bd9Sstevel@tonic-gate 	if (ap->ae_name)
4817c478bd9Sstevel@tonic-gate 	    free(ap->ae_name);
4827c478bd9Sstevel@tonic-gate 	if (ap->ae_principal)
4837c478bd9Sstevel@tonic-gate 	    krb5_free_principal((krb5_context) NULL, ap->ae_principal);
4847c478bd9Sstevel@tonic-gate 	if (ap->ae_target)
4857c478bd9Sstevel@tonic-gate 	    free(ap->ae_target);
4867c478bd9Sstevel@tonic-gate 	if (ap->ae_target_princ)
4877c478bd9Sstevel@tonic-gate 	    krb5_free_principal((krb5_context) NULL, ap->ae_target_princ);
4887c478bd9Sstevel@tonic-gate 	if (ap->ae_restriction_string)
4897c478bd9Sstevel@tonic-gate 	    free(ap->ae_restriction_string);
4907c478bd9Sstevel@tonic-gate 	if (ap->ae_restrictions) {
4917c478bd9Sstevel@tonic-gate 	    if (ap->ae_restrictions->policy)
4927c478bd9Sstevel@tonic-gate 		free(ap->ae_restrictions->policy);
4937c478bd9Sstevel@tonic-gate 	    free(ap->ae_restrictions);
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate 	np = ap->ae_next;
4967c478bd9Sstevel@tonic-gate 	free(ap);
4977c478bd9Sstevel@tonic-gate     }
4987c478bd9Sstevel@tonic-gate     acl_list_head = acl_list_tail = (aent_t *) NULL;
4997c478bd9Sstevel@tonic-gate     acl_inited = 0;
50056a424ccSmp153739     DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_free_entries()\n"));
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate /*
50456a424ccSmp153739  * kadm5int_acl_load_acl_file()	- Open and parse the ACL file.
5057c478bd9Sstevel@tonic-gate  */
5067c478bd9Sstevel@tonic-gate static int
kadm5int_acl_load_acl_file()50756a424ccSmp153739 kadm5int_acl_load_acl_file()
5087c478bd9Sstevel@tonic-gate {
5097c478bd9Sstevel@tonic-gate     FILE 	*afp;
5107c478bd9Sstevel@tonic-gate     char 	*alinep;
5117c478bd9Sstevel@tonic-gate     aent_t	**aentpp;
5127c478bd9Sstevel@tonic-gate     int		alineno;
5137c478bd9Sstevel@tonic-gate     int		retval = 1;
5147c478bd9Sstevel@tonic-gate 
51556a424ccSmp153739     DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_load_acl_file()\n"));
5167c478bd9Sstevel@tonic-gate     /* Open the ACL file for read */
517*159d09a2SMark Phalan     afp = fopen(acl_acl_file, "rF"); /* Solaris Kerberos */
51856a424ccSmp153739     if (afp) {
5197c478bd9Sstevel@tonic-gate 	alineno = 1;
5207c478bd9Sstevel@tonic-gate 	aentpp = &acl_list_head;
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	/* Get a non-comment line */
52356a424ccSmp153739 	while ((alinep = kadm5int_acl_get_line(afp, &alineno))) {
5247c478bd9Sstevel@tonic-gate 	    /* Parse it */
52556a424ccSmp153739 	    *aentpp = kadm5int_acl_parse_line(alinep);
5267c478bd9Sstevel@tonic-gate 	    /* If syntax error, then fall out */
5277c478bd9Sstevel@tonic-gate 	    if (!*aentpp) {
5287c478bd9Sstevel@tonic-gate 		krb5_klog_syslog(LOG_ERR, ACL_SYN_ERR_MSG,
5297c478bd9Sstevel@tonic-gate 			acl_acl_file, alineno, alinep);
5307c478bd9Sstevel@tonic-gate 		retval = 0;
5317c478bd9Sstevel@tonic-gate 		break;
5327c478bd9Sstevel@tonic-gate 	    }
5337c478bd9Sstevel@tonic-gate 	    acl_list_tail = *aentpp;
5347c478bd9Sstevel@tonic-gate 	    aentpp = &(*aentpp)->ae_next;
5357c478bd9Sstevel@tonic-gate 	}
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	fclose(afp);
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	if (acl_catchall_entry) {
54056a424ccSmp153739 	     *aentpp = kadm5int_acl_parse_line(acl_catchall_entry);
54156a424ccSmp153739 	     if (*aentpp) {
5427c478bd9Sstevel@tonic-gate 		  acl_list_tail = *aentpp;
5437c478bd9Sstevel@tonic-gate 	     }
5447c478bd9Sstevel@tonic-gate 	     else {
5457c478bd9Sstevel@tonic-gate 		  retval = 0;
5467c478bd9Sstevel@tonic-gate 		  DPRINT(DEBUG_OPERATION, acl_debug_level,
5477c478bd9Sstevel@tonic-gate 			 ("> catchall acl entry (%s) load failed\n",
5487c478bd9Sstevel@tonic-gate 			  acl_catchall_entry));
5497c478bd9Sstevel@tonic-gate 	     }
5507c478bd9Sstevel@tonic-gate 	}
5517c478bd9Sstevel@tonic-gate     }
5527c478bd9Sstevel@tonic-gate     else {
5537c478bd9Sstevel@tonic-gate 	krb5_klog_syslog(LOG_ERR,  ACL_CANTOPEN_MSG,
5547c478bd9Sstevel@tonic-gate 			 error_message(errno), acl_acl_file);
5557c478bd9Sstevel@tonic-gate 	if (acl_catchall_entry &&
55656a424ccSmp153739 	    (acl_list_head = kadm5int_acl_parse_line((char *)acl_catchall_entry))) {
5577c478bd9Sstevel@tonic-gate 	    acl_list_tail = acl_list_head;
5587c478bd9Sstevel@tonic-gate 	}
5597c478bd9Sstevel@tonic-gate 	else {
5607c478bd9Sstevel@tonic-gate 	    retval = 0;
5617c478bd9Sstevel@tonic-gate 	    DPRINT(DEBUG_OPERATION, acl_debug_level,
5627c478bd9Sstevel@tonic-gate 		   ("> catchall acl entry (%s) load failed\n",
5637c478bd9Sstevel@tonic-gate 		    acl_catchall_entry));
5647c478bd9Sstevel@tonic-gate 	}
5657c478bd9Sstevel@tonic-gate     }
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate     if (!retval) {
56856a424ccSmp153739 	kadm5int_acl_free_entries();
5697c478bd9Sstevel@tonic-gate     }
5707c478bd9Sstevel@tonic-gate     DPRINT(DEBUG_CALLS, acl_debug_level,
57156a424ccSmp153739 	   ("X kadm5int_acl_load_acl_file() = %d\n", retval));
5727c478bd9Sstevel@tonic-gate     return(retval);
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate /*
57656a424ccSmp153739  * kadm5int_acl_match_data()	- See if two data entries match.
5777c478bd9Sstevel@tonic-gate  *
5787c478bd9Sstevel@tonic-gate  * Wildcarding is only supported for a whole component.
5797c478bd9Sstevel@tonic-gate  */
5807c478bd9Sstevel@tonic-gate static krb5_boolean
kadm5int_acl_match_data(e1,e2,targetflag,ws)58156a424ccSmp153739 kadm5int_acl_match_data(e1, e2, targetflag, ws)
5827c478bd9Sstevel@tonic-gate     krb5_data	*e1, *e2;
5837c478bd9Sstevel@tonic-gate     int		targetflag;
5847c478bd9Sstevel@tonic-gate     wildstate_t	*ws;
5857c478bd9Sstevel@tonic-gate {
5867c478bd9Sstevel@tonic-gate     krb5_boolean	retval;
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate     DPRINT(DEBUG_CALLS, acl_debug_level,
5897c478bd9Sstevel@tonic-gate 	   ("* acl_match_entry(%s, %s)\n", e1->data, e2->data));
5907c478bd9Sstevel@tonic-gate     retval = 0;
5917c478bd9Sstevel@tonic-gate     if (!strncmp(e1->data, "*", e1->length)) {
5927c478bd9Sstevel@tonic-gate 	retval = 1;
5937c478bd9Sstevel@tonic-gate 	if (ws && !targetflag) {
5947c478bd9Sstevel@tonic-gate 	    if (ws->nwild >= 9) {
595*159d09a2SMark Phalan 		/* Solaris Kerberos */
5967c478bd9Sstevel@tonic-gate 		DPRINT(DEBUG_ACL, acl_debug_level,
5977c478bd9Sstevel@tonic-gate 		    ("Too many wildcards in ACL entry %s\n", e1->data));
5987c478bd9Sstevel@tonic-gate 	    }
5997c478bd9Sstevel@tonic-gate 	    else
6007c478bd9Sstevel@tonic-gate 		ws->backref[ws->nwild++] = e2;
6017c478bd9Sstevel@tonic-gate 	}
6027c478bd9Sstevel@tonic-gate     }
6037c478bd9Sstevel@tonic-gate     else if (ws && targetflag && (e1->length == 2) && (e1->data[0] == '*') &&
6047c478bd9Sstevel@tonic-gate 	     (e1->data[1] >= '1') && (e1->data[1] <= '9')) {
6057c478bd9Sstevel@tonic-gate 	int	n = e1->data[1] - '1';
6067c478bd9Sstevel@tonic-gate 	if (n >= ws->nwild) {
607*159d09a2SMark Phalan 	    /* Solaris Kerberos */
6087c478bd9Sstevel@tonic-gate 	    DPRINT(DEBUG_ACL, acl_debug_level,
6097c478bd9Sstevel@tonic-gate 		   ("Too many backrefs in ACL entry %s\n", e1->data));
6107c478bd9Sstevel@tonic-gate 	}
6117c478bd9Sstevel@tonic-gate 	else if ((ws->backref[n]->length == e2->length) &&
6127c478bd9Sstevel@tonic-gate 		 (!strncmp(ws->backref[n]->data, e2->data, e2->length)))
6137c478bd9Sstevel@tonic-gate 	    retval = 1;
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate     }
6167c478bd9Sstevel@tonic-gate     else {
6177c478bd9Sstevel@tonic-gate 	if ((e1->length == e2->length) &&
6187c478bd9Sstevel@tonic-gate 	    (!strncmp(e1->data, e2->data, e1->length)))
6197c478bd9Sstevel@tonic-gate 	    retval = 1;
6207c478bd9Sstevel@tonic-gate     }
6217c478bd9Sstevel@tonic-gate     DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_match_entry()=%d\n",retval));
6227c478bd9Sstevel@tonic-gate     return(retval);
6237c478bd9Sstevel@tonic-gate }
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate /*
62656a424ccSmp153739  * kadm5int_acl_find_entry()	- Find a matching entry.
6277c478bd9Sstevel@tonic-gate  */
6287c478bd9Sstevel@tonic-gate static aent_t *
kadm5int_acl_find_entry(kcontext,principal,dest_princ)62956a424ccSmp153739 kadm5int_acl_find_entry(kcontext, principal, dest_princ)
6307c478bd9Sstevel@tonic-gate     krb5_context	kcontext;
6317c478bd9Sstevel@tonic-gate     krb5_principal	principal;
6327c478bd9Sstevel@tonic-gate     krb5_principal	dest_princ;
6337c478bd9Sstevel@tonic-gate {
6347c478bd9Sstevel@tonic-gate     aent_t		*entry;
6357c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
6367c478bd9Sstevel@tonic-gate     int			i;
6377c478bd9Sstevel@tonic-gate     int			matchgood;
6387c478bd9Sstevel@tonic-gate     wildstate_t		state;
6397c478bd9Sstevel@tonic-gate 
64056a424ccSmp153739     DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_find_entry()\n"));
6417c478bd9Sstevel@tonic-gate     memset((char *)&state, 0, sizeof state);
6427c478bd9Sstevel@tonic-gate     for (entry=acl_list_head; entry; entry = entry->ae_next) {
6437c478bd9Sstevel@tonic-gate 	if (entry->ae_name_bad)
6447c478bd9Sstevel@tonic-gate 	    continue;
6457c478bd9Sstevel@tonic-gate 	if (!strcmp(entry->ae_name, "*")) {
6467c478bd9Sstevel@tonic-gate 	    DPRINT(DEBUG_ACL, acl_debug_level, ("A wildcard ACL match\n"));
6477c478bd9Sstevel@tonic-gate 	    matchgood = 1;
6487c478bd9Sstevel@tonic-gate 	}
6497c478bd9Sstevel@tonic-gate 	else {
6507c478bd9Sstevel@tonic-gate 	    if (!entry->ae_principal && !entry->ae_name_bad) {
6517c478bd9Sstevel@tonic-gate 		kret = krb5_parse_name(kcontext,
6527c478bd9Sstevel@tonic-gate 				       entry->ae_name,
6537c478bd9Sstevel@tonic-gate 				       &entry->ae_principal);
6547c478bd9Sstevel@tonic-gate 		if (kret)
6557c478bd9Sstevel@tonic-gate 		    entry->ae_name_bad = 1;
6567c478bd9Sstevel@tonic-gate 	    }
6577c478bd9Sstevel@tonic-gate 	    if (entry->ae_name_bad) {
6587c478bd9Sstevel@tonic-gate 		DPRINT(DEBUG_ACL, acl_debug_level,
6597c478bd9Sstevel@tonic-gate 		       ("Bad ACL entry %s\n", entry->ae_name));
6607c478bd9Sstevel@tonic-gate 		continue;
6617c478bd9Sstevel@tonic-gate 	    }
6627c478bd9Sstevel@tonic-gate 	    matchgood = 0;
66356a424ccSmp153739 	    if (kadm5int_acl_match_data(&entry->ae_principal->realm,
6647c478bd9Sstevel@tonic-gate 			       &principal->realm, 0, (wildstate_t *)0) &&
6657c478bd9Sstevel@tonic-gate 		(entry->ae_principal->length == principal->length)) {
6667c478bd9Sstevel@tonic-gate 		matchgood = 1;
6677c478bd9Sstevel@tonic-gate 		for (i=0; i<principal->length; i++) {
66856a424ccSmp153739 		    if (!kadm5int_acl_match_data(&entry->ae_principal->data[i],
6697c478bd9Sstevel@tonic-gate 					&principal->data[i], 0, &state)) {
6707c478bd9Sstevel@tonic-gate 			matchgood = 0;
6717c478bd9Sstevel@tonic-gate 			break;
6727c478bd9Sstevel@tonic-gate 		    }
6737c478bd9Sstevel@tonic-gate 		}
6747c478bd9Sstevel@tonic-gate 	    }
6757c478bd9Sstevel@tonic-gate 	}
6767c478bd9Sstevel@tonic-gate 	if (!matchgood)
6777c478bd9Sstevel@tonic-gate 	    continue;
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 	/* We've matched the principal.  If we have a target, then try it */
68056a424ccSmp153739 	if (entry->ae_target && strcmp(entry->ae_target, "*")) {
6817c478bd9Sstevel@tonic-gate 	    if (!entry->ae_target_princ && !entry->ae_target_bad) {
6827c478bd9Sstevel@tonic-gate 		kret = krb5_parse_name(kcontext, entry->ae_target,
6837c478bd9Sstevel@tonic-gate 				       &entry->ae_target_princ);
6847c478bd9Sstevel@tonic-gate 		if (kret)
6857c478bd9Sstevel@tonic-gate 		    entry->ae_target_bad = 1;
6867c478bd9Sstevel@tonic-gate 	    }
6877c478bd9Sstevel@tonic-gate 	    if (entry->ae_target_bad) {
6887c478bd9Sstevel@tonic-gate 	        DPRINT(DEBUG_ACL, acl_debug_level,
6897c478bd9Sstevel@tonic-gate 		       ("Bad target in ACL entry for %s\n", entry->ae_name));
6907c478bd9Sstevel@tonic-gate 	        entry->ae_name_bad = 1;
6917c478bd9Sstevel@tonic-gate 	        continue;
6927c478bd9Sstevel@tonic-gate 	    }
69356a424ccSmp153739 	    if (!dest_princ)
6947c478bd9Sstevel@tonic-gate 	        matchgood = 0;
69556a424ccSmp153739 	    else if (entry->ae_target_princ && dest_princ) {
69656a424ccSmp153739 	        if (kadm5int_acl_match_data(&entry->ae_target_princ->realm,
6977c478bd9Sstevel@tonic-gate 			           &dest_princ->realm, 1, (wildstate_t *)0) &&
6987c478bd9Sstevel@tonic-gate 		    (entry->ae_target_princ->length == dest_princ->length)) {
6997c478bd9Sstevel@tonic-gate 		    for (i=0; i<dest_princ->length; i++) {
70056a424ccSmp153739 		        if (!kadm5int_acl_match_data(&entry->ae_target_princ->data[i],
7017c478bd9Sstevel@tonic-gate 			  		    &dest_princ->data[i], 1, &state)) {
7027c478bd9Sstevel@tonic-gate 			    matchgood = 0;
7037c478bd9Sstevel@tonic-gate 			    break;
7047c478bd9Sstevel@tonic-gate 		        }
7057c478bd9Sstevel@tonic-gate 		    }
7067c478bd9Sstevel@tonic-gate 	        }
7077c478bd9Sstevel@tonic-gate 	        else
7087c478bd9Sstevel@tonic-gate 		    matchgood = 0;
7097c478bd9Sstevel@tonic-gate 	    }
71056a424ccSmp153739         }
7117c478bd9Sstevel@tonic-gate 	if (!matchgood)
7127c478bd9Sstevel@tonic-gate 	    continue;
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	if (entry->ae_restriction_string
7157c478bd9Sstevel@tonic-gate 	    && !entry->ae_restriction_bad
7167c478bd9Sstevel@tonic-gate 	    && !entry->ae_restrictions
71756a424ccSmp153739 	    && kadm5int_acl_parse_restrictions(entry->ae_restriction_string,
7187c478bd9Sstevel@tonic-gate 				      &entry->ae_restrictions)) {
7197c478bd9Sstevel@tonic-gate 	    DPRINT(DEBUG_ACL, acl_debug_level,
7207c478bd9Sstevel@tonic-gate 		   ("Bad restrictions in ACL entry for %s\n", entry->ae_name));
7217c478bd9Sstevel@tonic-gate 	    entry->ae_restriction_bad = 1;
7227c478bd9Sstevel@tonic-gate 	}
7237c478bd9Sstevel@tonic-gate 	if (entry->ae_restriction_bad) {
7247c478bd9Sstevel@tonic-gate 	    entry->ae_name_bad = 1;
7257c478bd9Sstevel@tonic-gate 	    continue;
7267c478bd9Sstevel@tonic-gate 	}
7277c478bd9Sstevel@tonic-gate 	break;
7287c478bd9Sstevel@tonic-gate     }
72956a424ccSmp153739     DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_find_entry()=%x\n",entry));
7307c478bd9Sstevel@tonic-gate     return(entry);
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate /*
73456a424ccSmp153739  * kadm5int_acl_init()	- Initialize ACL context.
7357c478bd9Sstevel@tonic-gate  */
7367c478bd9Sstevel@tonic-gate krb5_error_code
kadm5int_acl_init(kcontext,debug_level,acl_file)73756a424ccSmp153739 kadm5int_acl_init(kcontext, debug_level, acl_file)
7387c478bd9Sstevel@tonic-gate     krb5_context	kcontext;
7397c478bd9Sstevel@tonic-gate     int			debug_level;
7407c478bd9Sstevel@tonic-gate     char		*acl_file;
7417c478bd9Sstevel@tonic-gate {
7427c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate     kret = 0;
7457c478bd9Sstevel@tonic-gate     acl_debug_level = debug_level;
7467c478bd9Sstevel@tonic-gate     DPRINT(DEBUG_CALLS, acl_debug_level,
74756a424ccSmp153739 	   ("* kadm5int_acl_init(afile=%s)\n",
7487c478bd9Sstevel@tonic-gate 	    ((acl_file) ? acl_file : "(null)")));
7497c478bd9Sstevel@tonic-gate     acl_acl_file = (acl_file) ? acl_file : (char *) KRB5_DEFAULT_ADMIN_ACL;
75056a424ccSmp153739     acl_inited = kadm5int_acl_load_acl_file();
7517c478bd9Sstevel@tonic-gate 
75256a424ccSmp153739     DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_init() = %d\n", kret));
7537c478bd9Sstevel@tonic-gate     return(kret);
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate /*
75756a424ccSmp153739  * kadm5int_acl_finish	- Terminate ACL context.
7587c478bd9Sstevel@tonic-gate  */
7597c478bd9Sstevel@tonic-gate void
kadm5int_acl_finish(kcontext,debug_level)76056a424ccSmp153739 kadm5int_acl_finish(kcontext, debug_level)
7617c478bd9Sstevel@tonic-gate     krb5_context	kcontext;
7627c478bd9Sstevel@tonic-gate     int			debug_level;
7637c478bd9Sstevel@tonic-gate {
76456a424ccSmp153739     DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_finish()\n"));
76556a424ccSmp153739     kadm5int_acl_free_entries();
76656a424ccSmp153739     DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_finish()\n"));
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate /*
77056a424ccSmp153739  * kadm5int_acl_check()	- Is this operation permitted for this principal?
7717c478bd9Sstevel@tonic-gate  *			this code used not to be based on gssapi.  In order
7727c478bd9Sstevel@tonic-gate  *			to minimize porting hassles, I've put all the
7737c478bd9Sstevel@tonic-gate  *			gssapi hair in this function.  This might not be
7747c478bd9Sstevel@tonic-gate  *			the best medium-term solution.  (The best long-term
7757c478bd9Sstevel@tonic-gate  *			solution is, of course, a real authorization service.)
7767c478bd9Sstevel@tonic-gate  */
7777c478bd9Sstevel@tonic-gate krb5_boolean
kadm5int_acl_check(kcontext,caller,opmask,principal,restrictions)77856a424ccSmp153739 kadm5int_acl_check(kcontext, caller, opmask, principal, restrictions)
7797c478bd9Sstevel@tonic-gate     krb5_context	kcontext;
7807c478bd9Sstevel@tonic-gate     gss_name_t		caller;
7817c478bd9Sstevel@tonic-gate     krb5_int32		opmask;
7827c478bd9Sstevel@tonic-gate     krb5_principal	principal;
7837c478bd9Sstevel@tonic-gate     restriction_t	**restrictions;
7847c478bd9Sstevel@tonic-gate {
7857c478bd9Sstevel@tonic-gate     krb5_boolean	retval;
7867c478bd9Sstevel@tonic-gate     aent_t		*aentry;
7877c478bd9Sstevel@tonic-gate     gss_buffer_desc	caller_buf;
7887c478bd9Sstevel@tonic-gate     gss_OID		caller_oid;
7897c478bd9Sstevel@tonic-gate     OM_uint32		emaj, emin;
7907c478bd9Sstevel@tonic-gate     krb5_error_code	code;
7917c478bd9Sstevel@tonic-gate     krb5_principal	caller_princ;
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate     DPRINT(DEBUG_CALLS, acl_debug_level, ("* acl_op_permitted()\n"));
7947c478bd9Sstevel@tonic-gate 
795*159d09a2SMark Phalan     /* Solaris Kerberos */
7967c478bd9Sstevel@tonic-gate     if (restrictions)
7977c478bd9Sstevel@tonic-gate         *restrictions = NULL;
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate     if (GSS_ERROR(emaj = gss_display_name(&emin, caller, &caller_buf,
8007c478bd9Sstevel@tonic-gate 					  &caller_oid)))
8017c478bd9Sstevel@tonic-gate        return(1);
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate     code = krb5_parse_name(kcontext, (char *) caller_buf.value,
8047c478bd9Sstevel@tonic-gate 			   &caller_princ);
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate     gss_release_buffer(&emin, &caller_buf);
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate     if (code)
8097c478bd9Sstevel@tonic-gate        return(code);
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate     retval = 0;
81256a424ccSmp153739 
81356a424ccSmp153739     aentry = kadm5int_acl_find_entry(kcontext, caller_princ, principal);
81456a424ccSmp153739     if (aentry) {
8157c478bd9Sstevel@tonic-gate 	if ((aentry->ae_op_allowed & opmask) == opmask) {
8167c478bd9Sstevel@tonic-gate 	    retval = 1;
8177c478bd9Sstevel@tonic-gate 	    if (restrictions) {
8187c478bd9Sstevel@tonic-gate 		*restrictions =
8197c478bd9Sstevel@tonic-gate 		    (aentry->ae_restrictions && aentry->ae_restrictions->mask)
8207c478bd9Sstevel@tonic-gate 		    ? aentry->ae_restrictions
8217c478bd9Sstevel@tonic-gate 		    : (restriction_t *) NULL;
8227c478bd9Sstevel@tonic-gate 	    }
8237c478bd9Sstevel@tonic-gate 	}
8247c478bd9Sstevel@tonic-gate     }
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate     krb5_free_principal(kcontext, caller_princ);
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate     DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_op_permitted()=%d\n",
8297c478bd9Sstevel@tonic-gate 					  retval));
8307c478bd9Sstevel@tonic-gate     return(retval);
8317c478bd9Sstevel@tonic-gate }
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate kadm5_ret_t
kadm5_get_privs(void * server_handle,long * privs)8347c478bd9Sstevel@tonic-gate kadm5_get_privs(void *server_handle, long *privs)
8357c478bd9Sstevel@tonic-gate {
8367c478bd9Sstevel@tonic-gate      CHECK_HANDLE(server_handle);
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate      /* this is impossible to do with the current interface.  For now,
8397c478bd9Sstevel@tonic-gate 	return all privs, which will confuse some clients, but not
8407c478bd9Sstevel@tonic-gate 	deny any access to users of "smart" clients which try to cache */
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate      *privs = ~0;
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate      return KADM5_OK;
8457c478bd9Sstevel@tonic-gate }
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate /* SUNWresync121 (SEAM1.0) XXX */
8487c478bd9Sstevel@tonic-gate kadm5_ret_t
__kadm5_get_priv(void * server_handle,long * privs,gss_name_t client)8497c478bd9Sstevel@tonic-gate __kadm5_get_priv(void *server_handle, long *privs, gss_name_t client)
8507c478bd9Sstevel@tonic-gate {
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 	aent_t		*aentry;
8537c478bd9Sstevel@tonic-gate 	gss_buffer_desc	caller_buff;
8547c478bd9Sstevel@tonic-gate 	gss_OID		caller_oid;
8557c478bd9Sstevel@tonic-gate 	krb5_principal	caller_principal;
8567c478bd9Sstevel@tonic-gate 	OM_uint32	minor, major;
8577c478bd9Sstevel@tonic-gate 	krb5_error_code	k_error;
8587c478bd9Sstevel@tonic-gate 	kadm5_ret_t	retval = KADM5_FAILURE;
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate      kadm5_server_handle_t handle = server_handle;
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate      CHECK_HANDLE(server_handle);
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(major = gss_display_name(&minor, client, &caller_buff,
8657c478bd9Sstevel@tonic-gate 						&caller_oid)))
8667c478bd9Sstevel@tonic-gate 		return(retval);
8677c478bd9Sstevel@tonic-gate 	k_error = krb5_parse_name(handle->context,
8687c478bd9Sstevel@tonic-gate 					(char *) caller_buff.value,
8697c478bd9Sstevel@tonic-gate 					&caller_principal);
8707c478bd9Sstevel@tonic-gate 	gss_release_buffer(&minor, &caller_buff);
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 	if (k_error)
8737c478bd9Sstevel@tonic-gate 		return(retval);
8747c478bd9Sstevel@tonic-gate 
87556a424ccSmp153739 	if (aentry = kadm5int_acl_find_entry(handle->context, caller_principal,
8767c478bd9Sstevel@tonic-gate 					(krb5_principal)NULL))
8777c478bd9Sstevel@tonic-gate 		*privs = aentry->ae_op_allowed;
8787c478bd9Sstevel@tonic-gate 	krb5_free_principal(handle->context, caller_principal);
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 	return (KADM5_OK);
8817c478bd9Sstevel@tonic-gate }
882