10Sstevel@tonic-gate /*
2*7934SMark.Phalan@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate
70Sstevel@tonic-gate /*
80Sstevel@tonic-gate * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
90Sstevel@tonic-gate *
100Sstevel@tonic-gate * Openvision retains the copyright to derivative works of
110Sstevel@tonic-gate * this source code. Do *NOT* create a derivative of this
120Sstevel@tonic-gate * source code before consulting with your legal department.
130Sstevel@tonic-gate * Do *NOT* integrate *ANY* of this source code into another
140Sstevel@tonic-gate * product before consulting with your legal department.
150Sstevel@tonic-gate *
160Sstevel@tonic-gate * For further information, read the top-level Openvision
170Sstevel@tonic-gate * copyright which is contained in the top-level MIT Kerberos
180Sstevel@tonic-gate * copyright.
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
210Sstevel@tonic-gate *
220Sstevel@tonic-gate */
230Sstevel@tonic-gate
240Sstevel@tonic-gate
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate * kadmin/v5server/srv_acl.c
270Sstevel@tonic-gate *
280Sstevel@tonic-gate * Copyright 1995 by the Massachusetts Institute of Technology.
290Sstevel@tonic-gate * All Rights Reserved.
300Sstevel@tonic-gate *
310Sstevel@tonic-gate * Export of this software from the United States of America may
320Sstevel@tonic-gate * require a specific license from the United States Government.
330Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating
340Sstevel@tonic-gate * export to obtain such a license before exporting.
350Sstevel@tonic-gate *
360Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
370Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
380Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
390Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
400Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
410Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining
420Sstevel@tonic-gate * to distribution of the software without specific, written prior
430Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label
440Sstevel@tonic-gate * your software as modified software and not distribute it in such a
450Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software.
460Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of
470Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
480Sstevel@tonic-gate * or implied warranty.
490Sstevel@tonic-gate *
500Sstevel@tonic-gate */
510Sstevel@tonic-gate
520Sstevel@tonic-gate /*
530Sstevel@tonic-gate * srv_acl.c - Handle Kerberos ACL related functions.
540Sstevel@tonic-gate */
550Sstevel@tonic-gate #include <stdio.h>
560Sstevel@tonic-gate #include <syslog.h>
570Sstevel@tonic-gate #include <sys/param.h>
58*7934SMark.Phalan@Sun.COM #include "k5-int.h"
590Sstevel@tonic-gate #include <gssapi_krb5.h>
600Sstevel@tonic-gate #include <kadm5/server_internal.h>
610Sstevel@tonic-gate #include <kadm5/admin.h>
620Sstevel@tonic-gate #include <adm_proto.h> /* SUNWresync121 XXX */
630Sstevel@tonic-gate #include "server_acl.h"
640Sstevel@tonic-gate #include <ctype.h>
650Sstevel@tonic-gate #include <libintl.h> /* SUNWresync121 XXX */
660Sstevel@tonic-gate
670Sstevel@tonic-gate typedef struct _acl_op_table {
680Sstevel@tonic-gate char ao_op;
690Sstevel@tonic-gate krb5_int32 ao_mask;
700Sstevel@tonic-gate } aop_t;
710Sstevel@tonic-gate
720Sstevel@tonic-gate typedef struct _acl_entry {
730Sstevel@tonic-gate struct _acl_entry *ae_next;
740Sstevel@tonic-gate char *ae_name;
750Sstevel@tonic-gate krb5_boolean ae_name_bad;
760Sstevel@tonic-gate krb5_principal ae_principal;
770Sstevel@tonic-gate krb5_int32 ae_op_allowed;
780Sstevel@tonic-gate char *ae_target;
790Sstevel@tonic-gate krb5_boolean ae_target_bad;
800Sstevel@tonic-gate krb5_principal ae_target_princ;
810Sstevel@tonic-gate char *ae_restriction_string;
820Sstevel@tonic-gate /* eg: "-maxlife 3h -service +proxiable" */
830Sstevel@tonic-gate krb5_boolean ae_restriction_bad;
840Sstevel@tonic-gate restriction_t *ae_restrictions;
850Sstevel@tonic-gate } aent_t;
860Sstevel@tonic-gate
870Sstevel@tonic-gate static const aop_t acl_op_table[] = {
880Sstevel@tonic-gate { 'a', ACL_ADD },
890Sstevel@tonic-gate { 'd', ACL_DELETE },
900Sstevel@tonic-gate { 'm', ACL_MODIFY },
910Sstevel@tonic-gate { 'c', ACL_CHANGEPW },
920Sstevel@tonic-gate { 'i', ACL_INQUIRE },
930Sstevel@tonic-gate { 'l', ACL_LIST },
940Sstevel@tonic-gate { 'p', ACL_IPROP }, /* SUNW IProp */
950Sstevel@tonic-gate { 's', ACL_SETKEY },
960Sstevel@tonic-gate { 'u', ACL_MIGRATE }, /* pam_krb5_migrate */
970Sstevel@tonic-gate { 'x', ACL_ALL_MASK },
980Sstevel@tonic-gate { '*', ACL_ALL_MASK },
990Sstevel@tonic-gate { '\0', 0 }
1000Sstevel@tonic-gate };
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate typedef struct _wildstate {
1030Sstevel@tonic-gate int nwild;
1040Sstevel@tonic-gate krb5_data *backref[9];
1050Sstevel@tonic-gate } wildstate_t;
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate static aent_t *acl_list_head = (aent_t *) NULL;
1080Sstevel@tonic-gate static aent_t *acl_list_tail = (aent_t *) NULL;
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate static const char *acl_acl_file = (char *) NULL;
1110Sstevel@tonic-gate static int acl_inited = 0;
1120Sstevel@tonic-gate static int acl_debug_level = 0;
1130Sstevel@tonic-gate /*
1140Sstevel@tonic-gate * This is the catchall entry. If nothing else appropriate is found, or in
1150Sstevel@tonic-gate * the case where the ACL file is not present, this entry controls what can
1160Sstevel@tonic-gate * be done.
1170Sstevel@tonic-gate */
1180Sstevel@tonic-gate static const char *acl_catchall_entry = NULL;
1190Sstevel@tonic-gate
120*7934SMark.Phalan@Sun.COM /* Solaris Kerberos */
1210Sstevel@tonic-gate #define ACL_LINE2LONG_MSG dgettext(TEXT_DOMAIN, \
1220Sstevel@tonic-gate "%s: line %d too long, truncated\n")
1230Sstevel@tonic-gate #define ACL_OP_BAD_MSG dgettext(TEXT_DOMAIN, \
1240Sstevel@tonic-gate "Unrecognized ACL operation '%c' in %s\n")
1250Sstevel@tonic-gate #define ACL_SYN_ERR_MSG dgettext(TEXT_DOMAIN, \
1260Sstevel@tonic-gate "%s: syntax error at line %d <%10s...>\n")
1270Sstevel@tonic-gate #define ACL_CANTOPEN_MSG dgettext(TEXT_DOMAIN, \
1280Sstevel@tonic-gate "\007cannot open ACL file")
1290Sstevel@tonic-gate
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate /*
1322881Smp153739 * kadm5int_acl_get_line() - Get a line from the ACL file.
1330Sstevel@tonic-gate * Lines ending with \ are continued on the next line
1340Sstevel@tonic-gate */
1350Sstevel@tonic-gate static char *
kadm5int_acl_get_line(fp,lnp)1362881Smp153739 kadm5int_acl_get_line(fp, lnp)
1370Sstevel@tonic-gate FILE *fp;
1380Sstevel@tonic-gate int *lnp; /* caller should set to 1 before first call */
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate int i, domore;
1410Sstevel@tonic-gate static int line_incr = 0;
1420Sstevel@tonic-gate static char acl_buf[BUFSIZ];
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate *lnp += line_incr;
1450Sstevel@tonic-gate line_incr = 0;
1460Sstevel@tonic-gate for (domore = 1; domore && !feof(fp); ) {
1470Sstevel@tonic-gate /* Copy in the line, with continuations */
1480Sstevel@tonic-gate for (i=0; ((i < sizeof acl_buf) && !feof(fp)); i++ ) {
1490Sstevel@tonic-gate acl_buf[i] = fgetc(fp);
1500Sstevel@tonic-gate if (acl_buf[i] == (char)EOF) {
1510Sstevel@tonic-gate if (i > 0 && acl_buf[i-1] == '\\')
1520Sstevel@tonic-gate i--;
1530Sstevel@tonic-gate break; /* it gets nulled-out below */
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate else if (acl_buf[i] == '\n') {
1560Sstevel@tonic-gate if (i == 0 || acl_buf[i-1] != '\\')
1570Sstevel@tonic-gate break; /* empty line or normal end of line */
1580Sstevel@tonic-gate else {
1590Sstevel@tonic-gate i -= 2; /* back up over "\\\n" and continue */
1600Sstevel@tonic-gate line_incr++;
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate /* Check if we exceeded our buffer size */
1650Sstevel@tonic-gate if (i == sizeof acl_buf && (i--, !feof(fp))) {
1660Sstevel@tonic-gate int c1 = acl_buf[i], c2;
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR, ACL_LINE2LONG_MSG, acl_acl_file, *lnp);
1690Sstevel@tonic-gate while ((c2 = fgetc(fp)) != EOF) {
1700Sstevel@tonic-gate if (c2 == '\n') {
1710Sstevel@tonic-gate if (c1 != '\\')
1720Sstevel@tonic-gate break;
1730Sstevel@tonic-gate line_incr++;
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate c1 = c2;
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate acl_buf[i] = '\0';
1790Sstevel@tonic-gate if (acl_buf[0] == (char) EOF) /* ptooey */
1800Sstevel@tonic-gate acl_buf[0] = '\0';
1810Sstevel@tonic-gate else
1820Sstevel@tonic-gate line_incr++;
1830Sstevel@tonic-gate if ((acl_buf[0] != '#') && (acl_buf[0] != '\0'))
1840Sstevel@tonic-gate domore = 0;
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate if (domore || (strlen(acl_buf) == 0))
1870Sstevel@tonic-gate return((char *) NULL);
1880Sstevel@tonic-gate else
1890Sstevel@tonic-gate return(acl_buf);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate /*
1932881Smp153739 * kadm5int_acl_parse_line() - Parse the contents of an ACL line.
1940Sstevel@tonic-gate */
1950Sstevel@tonic-gate static aent_t *
kadm5int_acl_parse_line(lp)1962881Smp153739 kadm5int_acl_parse_line(lp)
1970Sstevel@tonic-gate const char *lp;
1980Sstevel@tonic-gate {
1990Sstevel@tonic-gate static char acle_principal[BUFSIZ];
2000Sstevel@tonic-gate static char acle_ops[BUFSIZ];
2010Sstevel@tonic-gate static char acle_object[BUFSIZ];
2020Sstevel@tonic-gate static char acle_restrictions[BUFSIZ];
2030Sstevel@tonic-gate aent_t *acle;
2040Sstevel@tonic-gate char *op;
2050Sstevel@tonic-gate int t, found, opok, nmatch;
2060Sstevel@tonic-gate
2070Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level,
2082881Smp153739 ("* kadm5int_acl_parse_line(line=%20s)\n", lp));
2090Sstevel@tonic-gate /*
2100Sstevel@tonic-gate * Format is still simple:
2110Sstevel@tonic-gate * entry ::= [<whitespace>] <principal> <whitespace> <opstring>
2120Sstevel@tonic-gate * [<whitespace> <target> [<whitespace> <restrictions>
2130Sstevel@tonic-gate * [<whitespace>]]]
2140Sstevel@tonic-gate */
2150Sstevel@tonic-gate acle = (aent_t *) NULL;
2160Sstevel@tonic-gate acle_object[0] = '\0';
2170Sstevel@tonic-gate nmatch = sscanf(lp, "%s %s %s %[^\n]", acle_principal, acle_ops,
2180Sstevel@tonic-gate acle_object, acle_restrictions);
2190Sstevel@tonic-gate if (nmatch >= 2) {
2200Sstevel@tonic-gate acle = (aent_t *) malloc(sizeof(aent_t));
2210Sstevel@tonic-gate if (acle) {
2220Sstevel@tonic-gate acle->ae_next = (aent_t *) NULL;
2230Sstevel@tonic-gate acle->ae_op_allowed = (krb5_int32) 0;
2240Sstevel@tonic-gate acle->ae_target =
2250Sstevel@tonic-gate (nmatch >= 3) ? strdup(acle_object) : (char *) NULL;
2260Sstevel@tonic-gate acle->ae_target_bad = 0;
2270Sstevel@tonic-gate acle->ae_target_princ = (krb5_principal) NULL;
2280Sstevel@tonic-gate opok = 1;
2290Sstevel@tonic-gate for (op=acle_ops; *op; op++) {
2300Sstevel@tonic-gate char rop;
2310Sstevel@tonic-gate
232*7934SMark.Phalan@Sun.COM rop = (isupper((unsigned char) *op)) ? tolower((unsigned char) *op) : *op;
2330Sstevel@tonic-gate found = 0;
2340Sstevel@tonic-gate for (t=0; acl_op_table[t].ao_op; t++) {
2350Sstevel@tonic-gate if (rop == acl_op_table[t].ao_op) {
2360Sstevel@tonic-gate found = 1;
2370Sstevel@tonic-gate if (rop == *op)
2380Sstevel@tonic-gate acle->ae_op_allowed |= acl_op_table[t].ao_mask;
2390Sstevel@tonic-gate else
2400Sstevel@tonic-gate acle->ae_op_allowed &= ~acl_op_table[t].ao_mask;
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate if (!found) {
2440Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR, ACL_OP_BAD_MSG, *op, lp);
2450Sstevel@tonic-gate opok = 0;
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate }
2480Sstevel@tonic-gate if (opok) {
2490Sstevel@tonic-gate acle->ae_name = (char *) malloc(strlen(acle_principal)+1);
2500Sstevel@tonic-gate if (acle->ae_name) {
2510Sstevel@tonic-gate strcpy(acle->ae_name, acle_principal);
2520Sstevel@tonic-gate acle->ae_principal = (krb5_principal) NULL;
2530Sstevel@tonic-gate acle->ae_name_bad = 0;
2540Sstevel@tonic-gate DPRINT(DEBUG_ACL, acl_debug_level,
2550Sstevel@tonic-gate ("A ACL entry %s -> opmask %x\n",
2560Sstevel@tonic-gate acle->ae_name, acle->ae_op_allowed));
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate else {
2590Sstevel@tonic-gate if (acle->ae_target)
2600Sstevel@tonic-gate free(acle->ae_target);
2610Sstevel@tonic-gate free(acle);
2620Sstevel@tonic-gate acle = (aent_t *) NULL;
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate else {
2660Sstevel@tonic-gate if (acle->ae_target)
2670Sstevel@tonic-gate free(acle->ae_target);
2680Sstevel@tonic-gate free(acle);
2690Sstevel@tonic-gate acle = (aent_t *) NULL;
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate if ( nmatch >= 4 ) {
2720Sstevel@tonic-gate char *trailing;
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate trailing = &acle_restrictions[strlen(acle_restrictions)-1];
2752881Smp153739 while ( isspace((int) *trailing) )
2760Sstevel@tonic-gate trailing--;
2770Sstevel@tonic-gate trailing[1] = '\0';
2780Sstevel@tonic-gate acle->ae_restriction_string = strdup(acle_restrictions);
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate else {
2810Sstevel@tonic-gate acle->ae_restriction_string = (char *) NULL;
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate acle->ae_restriction_bad = 0;
2840Sstevel@tonic-gate acle->ae_restrictions = (restriction_t *) NULL;
2850Sstevel@tonic-gate }
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level,
2882881Smp153739 ("X kadm5int_acl_parse_line() = %x\n", (long) acle));
2890Sstevel@tonic-gate return(acle);
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate /*
2932881Smp153739 * kadm5int_acl_parse_restrictions() - Parse optional restrictions field
2940Sstevel@tonic-gate *
2950Sstevel@tonic-gate * Allowed restrictions are:
2960Sstevel@tonic-gate * [+-]flagname (recognized by krb5_string_to_flags)
2970Sstevel@tonic-gate * flag is forced to indicated value
2980Sstevel@tonic-gate * -clearpolicy policy is forced clear
2990Sstevel@tonic-gate * -policy pol policy is forced to be "pol"
3000Sstevel@tonic-gate * -{expire,pwexpire,maxlife,maxrenewlife} deltat
3010Sstevel@tonic-gate * associated value will be forced to
3020Sstevel@tonic-gate * MIN(deltat, requested value)
3030Sstevel@tonic-gate *
3040Sstevel@tonic-gate * Returns: 0 on success, or system errors
3050Sstevel@tonic-gate */
3060Sstevel@tonic-gate static krb5_error_code
kadm5int_acl_parse_restrictions(s,rpp)3072881Smp153739 kadm5int_acl_parse_restrictions(s, rpp)
3080Sstevel@tonic-gate char *s;
3090Sstevel@tonic-gate restriction_t **rpp;
3100Sstevel@tonic-gate {
3110Sstevel@tonic-gate char *sp, *tp, *ap;
3120Sstevel@tonic-gate static const char *delims = "\t\n\f\v\r ,";
3130Sstevel@tonic-gate krb5_deltat dt;
3140Sstevel@tonic-gate krb5_flags flag;
3150Sstevel@tonic-gate krb5_error_code code;
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level,
3182881Smp153739 ("* kadm5int_acl_parse_restrictions(s=%20s, rpp=0x%08x)\n", s, (long)rpp));
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate *rpp = (restriction_t *) NULL;
3210Sstevel@tonic-gate code = 0;
3222881Smp153739 if (s) {
3230Sstevel@tonic-gate if (!(sp = strdup(s)) /* Don't munge the original */
3240Sstevel@tonic-gate || !(*rpp = (restriction_t *) malloc(sizeof(restriction_t)))) {
3250Sstevel@tonic-gate code = ENOMEM;
3260Sstevel@tonic-gate } else {
3270Sstevel@tonic-gate memset(*rpp, 0, sizeof(**rpp));
3280Sstevel@tonic-gate for (tp=strtok(sp, delims); tp; tp=strtok((char *)NULL, delims)) {
3290Sstevel@tonic-gate flag = 0;
3300Sstevel@tonic-gate if (!krb5_string_to_flags(tp, "+", "-", &flag)) {
3310Sstevel@tonic-gate /* OK, but was it in the positive or negative sense? */
3320Sstevel@tonic-gate if (flag) {
3330Sstevel@tonic-gate (*rpp)->require_attrs |= flag;
3340Sstevel@tonic-gate } else {
3350Sstevel@tonic-gate flag = ~0;
3360Sstevel@tonic-gate (void) krb5_string_to_flags(tp, "+", "-", &flag);
3370Sstevel@tonic-gate (*rpp)->forbid_attrs |= ~flag;
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate (*rpp)->mask |= KADM5_ATTRIBUTES;
3400Sstevel@tonic-gate } else if (!strcmp(tp, "-clearpolicy")) {
3410Sstevel@tonic-gate (*rpp)->mask |= KADM5_POLICY_CLR;
3420Sstevel@tonic-gate } else {
3430Sstevel@tonic-gate /* everything else needs an argument ... */
3440Sstevel@tonic-gate if (!(ap = strtok((char *)NULL, delims))) {
3450Sstevel@tonic-gate code = EINVAL;
3460Sstevel@tonic-gate break;
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate if (!strcmp(tp, "-policy")) {
3490Sstevel@tonic-gate if (!((*rpp)->policy = strdup(ap))) {
3500Sstevel@tonic-gate code = ENOMEM;
3510Sstevel@tonic-gate break;
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate (*rpp)->mask |= KADM5_POLICY;
3540Sstevel@tonic-gate } else {
3550Sstevel@tonic-gate /* all other arguments must be a deltat ... */
3560Sstevel@tonic-gate if (krb5_string_to_deltat(ap, &dt)) {
3570Sstevel@tonic-gate code = EINVAL;
3580Sstevel@tonic-gate break;
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate if (!strcmp(tp, "-expire")) {
3610Sstevel@tonic-gate (*rpp)->princ_lifetime = dt;
3620Sstevel@tonic-gate (*rpp)->mask |= KADM5_PRINC_EXPIRE_TIME;
3630Sstevel@tonic-gate } else if (!strcmp(tp, "-pwexpire")) {
3640Sstevel@tonic-gate (*rpp)->pw_lifetime = dt;
3650Sstevel@tonic-gate (*rpp)->mask |= KADM5_PW_EXPIRATION;
3660Sstevel@tonic-gate } else if (!strcmp(tp, "-maxlife")) {
3670Sstevel@tonic-gate (*rpp)->max_life = dt;
3680Sstevel@tonic-gate (*rpp)->mask |= KADM5_MAX_LIFE;
3690Sstevel@tonic-gate } else if (!strcmp(tp, "-maxrenewlife")) {
3700Sstevel@tonic-gate (*rpp)->max_renewable_life = dt;
3710Sstevel@tonic-gate (*rpp)->mask |= KADM5_MAX_RLIFE;
3720Sstevel@tonic-gate } else {
3730Sstevel@tonic-gate code = EINVAL;
3740Sstevel@tonic-gate break;
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate }
3802881Smp153739 }
3810Sstevel@tonic-gate if (sp)
3820Sstevel@tonic-gate free(sp);
3830Sstevel@tonic-gate if (*rpp && code) {
3840Sstevel@tonic-gate if ((*rpp)->policy)
3850Sstevel@tonic-gate free((*rpp)->policy);
3860Sstevel@tonic-gate free(*rpp);
3870Sstevel@tonic-gate *rpp = (restriction_t *) NULL;
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level,
3902881Smp153739 ("X kadm5int_acl_parse_restrictions() = %d, mask=0x%08x\n",
3910Sstevel@tonic-gate code, (*rpp) ? (*rpp)->mask : 0));
3920Sstevel@tonic-gate return code;
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate /*
3962881Smp153739 * kadm5int_acl_impose_restrictions() - impose restrictions, modifying *recp, *maskp
3970Sstevel@tonic-gate *
3980Sstevel@tonic-gate * Returns: 0 on success;
3990Sstevel@tonic-gate * malloc or timeofday errors
4000Sstevel@tonic-gate */
4010Sstevel@tonic-gate krb5_error_code
kadm5int_acl_impose_restrictions(kcontext,recp,maskp,rp)4022881Smp153739 kadm5int_acl_impose_restrictions(kcontext, recp, maskp, rp)
4030Sstevel@tonic-gate krb5_context kcontext;
4040Sstevel@tonic-gate kadm5_principal_ent_rec *recp;
4050Sstevel@tonic-gate long *maskp;
4060Sstevel@tonic-gate restriction_t *rp;
4070Sstevel@tonic-gate {
4080Sstevel@tonic-gate krb5_error_code code;
4090Sstevel@tonic-gate krb5_int32 now;
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level,
4122881Smp153739 ("* kadm5int_acl_impose_restrictions(..., *maskp=0x%08x, rp=0x%08x)\n",
4130Sstevel@tonic-gate *maskp, (long)rp));
4140Sstevel@tonic-gate if (!rp)
4150Sstevel@tonic-gate return 0;
4160Sstevel@tonic-gate if (rp->mask & (KADM5_PRINC_EXPIRE_TIME|KADM5_PW_EXPIRATION))
4170Sstevel@tonic-gate if ((code = krb5_timeofday(kcontext, &now)))
4180Sstevel@tonic-gate return code;
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate if (rp->mask & KADM5_ATTRIBUTES) {
4210Sstevel@tonic-gate recp->attributes |= rp->require_attrs;
4220Sstevel@tonic-gate recp->attributes &= ~(rp->forbid_attrs);
4230Sstevel@tonic-gate *maskp |= KADM5_ATTRIBUTES;
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate if (rp->mask & KADM5_POLICY_CLR) {
4260Sstevel@tonic-gate *maskp &= ~KADM5_POLICY;
4270Sstevel@tonic-gate *maskp |= KADM5_POLICY_CLR;
4280Sstevel@tonic-gate } else if (rp->mask & KADM5_POLICY) {
4290Sstevel@tonic-gate if (recp->policy && strcmp(recp->policy, rp->policy)) {
4300Sstevel@tonic-gate free(recp->policy);
4310Sstevel@tonic-gate recp->policy = (char *) NULL;
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate if (!recp->policy) {
4340Sstevel@tonic-gate recp->policy = strdup(rp->policy); /* XDR will free it */
4350Sstevel@tonic-gate if (!recp->policy)
4360Sstevel@tonic-gate return ENOMEM;
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate *maskp |= KADM5_POLICY;
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate if (rp->mask & KADM5_PRINC_EXPIRE_TIME) {
4410Sstevel@tonic-gate if (!(*maskp & KADM5_PRINC_EXPIRE_TIME)
4420Sstevel@tonic-gate || (recp->princ_expire_time > (now + rp->princ_lifetime)))
4430Sstevel@tonic-gate recp->princ_expire_time = now + rp->princ_lifetime;
4440Sstevel@tonic-gate *maskp |= KADM5_PRINC_EXPIRE_TIME;
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate if (rp->mask & KADM5_PW_EXPIRATION) {
4470Sstevel@tonic-gate if (!(*maskp & KADM5_PW_EXPIRATION)
4480Sstevel@tonic-gate || (recp->pw_expiration > (now + rp->pw_lifetime)))
4490Sstevel@tonic-gate recp->pw_expiration = now + rp->pw_lifetime;
4500Sstevel@tonic-gate *maskp |= KADM5_PW_EXPIRATION;
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate if (rp->mask & KADM5_MAX_LIFE) {
4530Sstevel@tonic-gate if (!(*maskp & KADM5_MAX_LIFE)
4540Sstevel@tonic-gate || (recp->max_life > rp->max_life))
4550Sstevel@tonic-gate recp->max_life = rp->max_life;
4560Sstevel@tonic-gate *maskp |= KADM5_MAX_LIFE;
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate if (rp->mask & KADM5_MAX_RLIFE) {
4590Sstevel@tonic-gate if (!(*maskp & KADM5_MAX_RLIFE)
4600Sstevel@tonic-gate || (recp->max_renewable_life > rp->max_renewable_life))
4610Sstevel@tonic-gate recp->max_renewable_life = rp->max_renewable_life;
4620Sstevel@tonic-gate *maskp |= KADM5_MAX_RLIFE;
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level,
4652881Smp153739 ("X kadm5int_acl_impose_restrictions() = 0, *maskp=0x%08x\n", *maskp));
4660Sstevel@tonic-gate return 0;
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate /*
4702881Smp153739 * kadm5int_acl_free_entries() - Free all ACL entries.
4710Sstevel@tonic-gate */
4720Sstevel@tonic-gate static void
kadm5int_acl_free_entries()4732881Smp153739 kadm5int_acl_free_entries()
4740Sstevel@tonic-gate {
4750Sstevel@tonic-gate aent_t *ap;
4760Sstevel@tonic-gate aent_t *np;
4770Sstevel@tonic-gate
4782881Smp153739 DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_free_entries()\n"));
4790Sstevel@tonic-gate for (ap=acl_list_head; ap; ap = np) {
4800Sstevel@tonic-gate if (ap->ae_name)
4810Sstevel@tonic-gate free(ap->ae_name);
4820Sstevel@tonic-gate if (ap->ae_principal)
4830Sstevel@tonic-gate krb5_free_principal((krb5_context) NULL, ap->ae_principal);
4840Sstevel@tonic-gate if (ap->ae_target)
4850Sstevel@tonic-gate free(ap->ae_target);
4860Sstevel@tonic-gate if (ap->ae_target_princ)
4870Sstevel@tonic-gate krb5_free_principal((krb5_context) NULL, ap->ae_target_princ);
4880Sstevel@tonic-gate if (ap->ae_restriction_string)
4890Sstevel@tonic-gate free(ap->ae_restriction_string);
4900Sstevel@tonic-gate if (ap->ae_restrictions) {
4910Sstevel@tonic-gate if (ap->ae_restrictions->policy)
4920Sstevel@tonic-gate free(ap->ae_restrictions->policy);
4930Sstevel@tonic-gate free(ap->ae_restrictions);
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate np = ap->ae_next;
4960Sstevel@tonic-gate free(ap);
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate acl_list_head = acl_list_tail = (aent_t *) NULL;
4990Sstevel@tonic-gate acl_inited = 0;
5002881Smp153739 DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_free_entries()\n"));
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate /*
5042881Smp153739 * kadm5int_acl_load_acl_file() - Open and parse the ACL file.
5050Sstevel@tonic-gate */
5060Sstevel@tonic-gate static int
kadm5int_acl_load_acl_file()5072881Smp153739 kadm5int_acl_load_acl_file()
5080Sstevel@tonic-gate {
5090Sstevel@tonic-gate FILE *afp;
5100Sstevel@tonic-gate char *alinep;
5110Sstevel@tonic-gate aent_t **aentpp;
5120Sstevel@tonic-gate int alineno;
5130Sstevel@tonic-gate int retval = 1;
5140Sstevel@tonic-gate
5152881Smp153739 DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_load_acl_file()\n"));
5160Sstevel@tonic-gate /* Open the ACL file for read */
517*7934SMark.Phalan@Sun.COM afp = fopen(acl_acl_file, "rF"); /* Solaris Kerberos */
5182881Smp153739 if (afp) {
5190Sstevel@tonic-gate alineno = 1;
5200Sstevel@tonic-gate aentpp = &acl_list_head;
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate /* Get a non-comment line */
5232881Smp153739 while ((alinep = kadm5int_acl_get_line(afp, &alineno))) {
5240Sstevel@tonic-gate /* Parse it */
5252881Smp153739 *aentpp = kadm5int_acl_parse_line(alinep);
5260Sstevel@tonic-gate /* If syntax error, then fall out */
5270Sstevel@tonic-gate if (!*aentpp) {
5280Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR, ACL_SYN_ERR_MSG,
5290Sstevel@tonic-gate acl_acl_file, alineno, alinep);
5300Sstevel@tonic-gate retval = 0;
5310Sstevel@tonic-gate break;
5320Sstevel@tonic-gate }
5330Sstevel@tonic-gate acl_list_tail = *aentpp;
5340Sstevel@tonic-gate aentpp = &(*aentpp)->ae_next;
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate fclose(afp);
5380Sstevel@tonic-gate
5390Sstevel@tonic-gate if (acl_catchall_entry) {
5402881Smp153739 *aentpp = kadm5int_acl_parse_line(acl_catchall_entry);
5412881Smp153739 if (*aentpp) {
5420Sstevel@tonic-gate acl_list_tail = *aentpp;
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate else {
5450Sstevel@tonic-gate retval = 0;
5460Sstevel@tonic-gate DPRINT(DEBUG_OPERATION, acl_debug_level,
5470Sstevel@tonic-gate ("> catchall acl entry (%s) load failed\n",
5480Sstevel@tonic-gate acl_catchall_entry));
5490Sstevel@tonic-gate }
5500Sstevel@tonic-gate }
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate else {
5530Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR, ACL_CANTOPEN_MSG,
5540Sstevel@tonic-gate error_message(errno), acl_acl_file);
5550Sstevel@tonic-gate if (acl_catchall_entry &&
5562881Smp153739 (acl_list_head = kadm5int_acl_parse_line((char *)acl_catchall_entry))) {
5570Sstevel@tonic-gate acl_list_tail = acl_list_head;
5580Sstevel@tonic-gate }
5590Sstevel@tonic-gate else {
5600Sstevel@tonic-gate retval = 0;
5610Sstevel@tonic-gate DPRINT(DEBUG_OPERATION, acl_debug_level,
5620Sstevel@tonic-gate ("> catchall acl entry (%s) load failed\n",
5630Sstevel@tonic-gate acl_catchall_entry));
5640Sstevel@tonic-gate }
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate if (!retval) {
5682881Smp153739 kadm5int_acl_free_entries();
5690Sstevel@tonic-gate }
5700Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level,
5712881Smp153739 ("X kadm5int_acl_load_acl_file() = %d\n", retval));
5720Sstevel@tonic-gate return(retval);
5730Sstevel@tonic-gate }
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate /*
5762881Smp153739 * kadm5int_acl_match_data() - See if two data entries match.
5770Sstevel@tonic-gate *
5780Sstevel@tonic-gate * Wildcarding is only supported for a whole component.
5790Sstevel@tonic-gate */
5800Sstevel@tonic-gate static krb5_boolean
kadm5int_acl_match_data(e1,e2,targetflag,ws)5812881Smp153739 kadm5int_acl_match_data(e1, e2, targetflag, ws)
5820Sstevel@tonic-gate krb5_data *e1, *e2;
5830Sstevel@tonic-gate int targetflag;
5840Sstevel@tonic-gate wildstate_t *ws;
5850Sstevel@tonic-gate {
5860Sstevel@tonic-gate krb5_boolean retval;
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level,
5890Sstevel@tonic-gate ("* acl_match_entry(%s, %s)\n", e1->data, e2->data));
5900Sstevel@tonic-gate retval = 0;
5910Sstevel@tonic-gate if (!strncmp(e1->data, "*", e1->length)) {
5920Sstevel@tonic-gate retval = 1;
5930Sstevel@tonic-gate if (ws && !targetflag) {
5940Sstevel@tonic-gate if (ws->nwild >= 9) {
595*7934SMark.Phalan@Sun.COM /* Solaris Kerberos */
5960Sstevel@tonic-gate DPRINT(DEBUG_ACL, acl_debug_level,
5972881Smp153739 ("Too many wildcards in ACL entry %s\n", e1->data));
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate else
6000Sstevel@tonic-gate ws->backref[ws->nwild++] = e2;
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate }
6030Sstevel@tonic-gate else if (ws && targetflag && (e1->length == 2) && (e1->data[0] == '*') &&
6040Sstevel@tonic-gate (e1->data[1] >= '1') && (e1->data[1] <= '9')) {
6050Sstevel@tonic-gate int n = e1->data[1] - '1';
6060Sstevel@tonic-gate if (n >= ws->nwild) {
607*7934SMark.Phalan@Sun.COM /* Solaris Kerberos */
6080Sstevel@tonic-gate DPRINT(DEBUG_ACL, acl_debug_level,
6092881Smp153739 ("Too many backrefs in ACL entry %s\n", e1->data));
6100Sstevel@tonic-gate }
6110Sstevel@tonic-gate else if ((ws->backref[n]->length == e2->length) &&
6120Sstevel@tonic-gate (!strncmp(ws->backref[n]->data, e2->data, e2->length)))
6130Sstevel@tonic-gate retval = 1;
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate else {
6170Sstevel@tonic-gate if ((e1->length == e2->length) &&
6180Sstevel@tonic-gate (!strncmp(e1->data, e2->data, e1->length)))
6190Sstevel@tonic-gate retval = 1;
6200Sstevel@tonic-gate }
6210Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_match_entry()=%d\n",retval));
6220Sstevel@tonic-gate return(retval);
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate /*
6262881Smp153739 * kadm5int_acl_find_entry() - Find a matching entry.
6270Sstevel@tonic-gate */
6280Sstevel@tonic-gate static aent_t *
kadm5int_acl_find_entry(kcontext,principal,dest_princ)6292881Smp153739 kadm5int_acl_find_entry(kcontext, principal, dest_princ)
6300Sstevel@tonic-gate krb5_context kcontext;
6310Sstevel@tonic-gate krb5_principal principal;
6320Sstevel@tonic-gate krb5_principal dest_princ;
6330Sstevel@tonic-gate {
6340Sstevel@tonic-gate aent_t *entry;
6350Sstevel@tonic-gate krb5_error_code kret;
6360Sstevel@tonic-gate int i;
6370Sstevel@tonic-gate int matchgood;
6380Sstevel@tonic-gate wildstate_t state;
6390Sstevel@tonic-gate
6402881Smp153739 DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_find_entry()\n"));
6410Sstevel@tonic-gate memset((char *)&state, 0, sizeof state);
6420Sstevel@tonic-gate for (entry=acl_list_head; entry; entry = entry->ae_next) {
6430Sstevel@tonic-gate if (entry->ae_name_bad)
6440Sstevel@tonic-gate continue;
6450Sstevel@tonic-gate if (!strcmp(entry->ae_name, "*")) {
6460Sstevel@tonic-gate DPRINT(DEBUG_ACL, acl_debug_level, ("A wildcard ACL match\n"));
6470Sstevel@tonic-gate matchgood = 1;
6480Sstevel@tonic-gate }
6490Sstevel@tonic-gate else {
6500Sstevel@tonic-gate if (!entry->ae_principal && !entry->ae_name_bad) {
6510Sstevel@tonic-gate kret = krb5_parse_name(kcontext,
6520Sstevel@tonic-gate entry->ae_name,
6530Sstevel@tonic-gate &entry->ae_principal);
6540Sstevel@tonic-gate if (kret)
6550Sstevel@tonic-gate entry->ae_name_bad = 1;
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate if (entry->ae_name_bad) {
6580Sstevel@tonic-gate DPRINT(DEBUG_ACL, acl_debug_level,
6590Sstevel@tonic-gate ("Bad ACL entry %s\n", entry->ae_name));
6600Sstevel@tonic-gate continue;
6610Sstevel@tonic-gate }
6620Sstevel@tonic-gate matchgood = 0;
6632881Smp153739 if (kadm5int_acl_match_data(&entry->ae_principal->realm,
6640Sstevel@tonic-gate &principal->realm, 0, (wildstate_t *)0) &&
6650Sstevel@tonic-gate (entry->ae_principal->length == principal->length)) {
6660Sstevel@tonic-gate matchgood = 1;
6670Sstevel@tonic-gate for (i=0; i<principal->length; i++) {
6682881Smp153739 if (!kadm5int_acl_match_data(&entry->ae_principal->data[i],
6690Sstevel@tonic-gate &principal->data[i], 0, &state)) {
6700Sstevel@tonic-gate matchgood = 0;
6710Sstevel@tonic-gate break;
6720Sstevel@tonic-gate }
6730Sstevel@tonic-gate }
6740Sstevel@tonic-gate }
6750Sstevel@tonic-gate }
6760Sstevel@tonic-gate if (!matchgood)
6770Sstevel@tonic-gate continue;
6780Sstevel@tonic-gate
6790Sstevel@tonic-gate /* We've matched the principal. If we have a target, then try it */
6802881Smp153739 if (entry->ae_target && strcmp(entry->ae_target, "*")) {
6810Sstevel@tonic-gate if (!entry->ae_target_princ && !entry->ae_target_bad) {
6820Sstevel@tonic-gate kret = krb5_parse_name(kcontext, entry->ae_target,
6830Sstevel@tonic-gate &entry->ae_target_princ);
6840Sstevel@tonic-gate if (kret)
6850Sstevel@tonic-gate entry->ae_target_bad = 1;
6860Sstevel@tonic-gate }
6872881Smp153739 if (entry->ae_target_bad) {
6882881Smp153739 DPRINT(DEBUG_ACL, acl_debug_level,
6892881Smp153739 ("Bad target in ACL entry for %s\n", entry->ae_name));
6902881Smp153739 entry->ae_name_bad = 1;
6912881Smp153739 continue;
6922881Smp153739 }
6932881Smp153739 if (!dest_princ)
6942881Smp153739 matchgood = 0;
6952881Smp153739 else if (entry->ae_target_princ && dest_princ) {
6962881Smp153739 if (kadm5int_acl_match_data(&entry->ae_target_princ->realm,
6972881Smp153739 &dest_princ->realm, 1, (wildstate_t *)0) &&
6982881Smp153739 (entry->ae_target_princ->length == dest_princ->length)) {
6992881Smp153739 for (i=0; i<dest_princ->length; i++) {
7002881Smp153739 if (!kadm5int_acl_match_data(&entry->ae_target_princ->data[i],
7012881Smp153739 &dest_princ->data[i], 1, &state)) {
7022881Smp153739 matchgood = 0;
7032881Smp153739 break;
7042881Smp153739 }
7050Sstevel@tonic-gate }
7062881Smp153739 }
7072881Smp153739 else
7082881Smp153739 matchgood = 0;
7090Sstevel@tonic-gate }
7102881Smp153739 }
7110Sstevel@tonic-gate if (!matchgood)
7120Sstevel@tonic-gate continue;
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate if (entry->ae_restriction_string
7150Sstevel@tonic-gate && !entry->ae_restriction_bad
7160Sstevel@tonic-gate && !entry->ae_restrictions
7172881Smp153739 && kadm5int_acl_parse_restrictions(entry->ae_restriction_string,
7180Sstevel@tonic-gate &entry->ae_restrictions)) {
7190Sstevel@tonic-gate DPRINT(DEBUG_ACL, acl_debug_level,
7200Sstevel@tonic-gate ("Bad restrictions in ACL entry for %s\n", entry->ae_name));
7210Sstevel@tonic-gate entry->ae_restriction_bad = 1;
7220Sstevel@tonic-gate }
7230Sstevel@tonic-gate if (entry->ae_restriction_bad) {
7240Sstevel@tonic-gate entry->ae_name_bad = 1;
7250Sstevel@tonic-gate continue;
7260Sstevel@tonic-gate }
7270Sstevel@tonic-gate break;
7280Sstevel@tonic-gate }
7292881Smp153739 DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_find_entry()=%x\n",entry));
7300Sstevel@tonic-gate return(entry);
7310Sstevel@tonic-gate }
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate /*
7342881Smp153739 * kadm5int_acl_init() - Initialize ACL context.
7350Sstevel@tonic-gate */
7360Sstevel@tonic-gate krb5_error_code
kadm5int_acl_init(kcontext,debug_level,acl_file)7372881Smp153739 kadm5int_acl_init(kcontext, debug_level, acl_file)
7380Sstevel@tonic-gate krb5_context kcontext;
7390Sstevel@tonic-gate int debug_level;
7400Sstevel@tonic-gate char *acl_file;
7410Sstevel@tonic-gate {
7420Sstevel@tonic-gate krb5_error_code kret;
7430Sstevel@tonic-gate
7440Sstevel@tonic-gate kret = 0;
7450Sstevel@tonic-gate acl_debug_level = debug_level;
7460Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level,
7472881Smp153739 ("* kadm5int_acl_init(afile=%s)\n",
7480Sstevel@tonic-gate ((acl_file) ? acl_file : "(null)")));
7490Sstevel@tonic-gate acl_acl_file = (acl_file) ? acl_file : (char *) KRB5_DEFAULT_ADMIN_ACL;
7502881Smp153739 acl_inited = kadm5int_acl_load_acl_file();
7510Sstevel@tonic-gate
7522881Smp153739 DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_init() = %d\n", kret));
7530Sstevel@tonic-gate return(kret);
7540Sstevel@tonic-gate }
7550Sstevel@tonic-gate
7560Sstevel@tonic-gate /*
7572881Smp153739 * kadm5int_acl_finish - Terminate ACL context.
7580Sstevel@tonic-gate */
7590Sstevel@tonic-gate void
kadm5int_acl_finish(kcontext,debug_level)7602881Smp153739 kadm5int_acl_finish(kcontext, debug_level)
7610Sstevel@tonic-gate krb5_context kcontext;
7620Sstevel@tonic-gate int debug_level;
7630Sstevel@tonic-gate {
7642881Smp153739 DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_finish()\n"));
7652881Smp153739 kadm5int_acl_free_entries();
7662881Smp153739 DPRINT(DEBUG_CALLS, acl_debug_level, ("X kadm5int_acl_finish()\n"));
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate /*
7702881Smp153739 * kadm5int_acl_check() - Is this operation permitted for this principal?
7710Sstevel@tonic-gate * this code used not to be based on gssapi. In order
7720Sstevel@tonic-gate * to minimize porting hassles, I've put all the
7730Sstevel@tonic-gate * gssapi hair in this function. This might not be
7740Sstevel@tonic-gate * the best medium-term solution. (The best long-term
7750Sstevel@tonic-gate * solution is, of course, a real authorization service.)
7760Sstevel@tonic-gate */
7770Sstevel@tonic-gate krb5_boolean
kadm5int_acl_check(kcontext,caller,opmask,principal,restrictions)7782881Smp153739 kadm5int_acl_check(kcontext, caller, opmask, principal, restrictions)
7790Sstevel@tonic-gate krb5_context kcontext;
7800Sstevel@tonic-gate gss_name_t caller;
7810Sstevel@tonic-gate krb5_int32 opmask;
7820Sstevel@tonic-gate krb5_principal principal;
7830Sstevel@tonic-gate restriction_t **restrictions;
7840Sstevel@tonic-gate {
7850Sstevel@tonic-gate krb5_boolean retval;
7860Sstevel@tonic-gate aent_t *aentry;
7870Sstevel@tonic-gate gss_buffer_desc caller_buf;
7880Sstevel@tonic-gate gss_OID caller_oid;
7890Sstevel@tonic-gate OM_uint32 emaj, emin;
7900Sstevel@tonic-gate krb5_error_code code;
7910Sstevel@tonic-gate krb5_principal caller_princ;
7920Sstevel@tonic-gate
7930Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level, ("* acl_op_permitted()\n"));
7940Sstevel@tonic-gate
795*7934SMark.Phalan@Sun.COM /* Solaris Kerberos */
7960Sstevel@tonic-gate if (restrictions)
7970Sstevel@tonic-gate *restrictions = NULL;
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate if (GSS_ERROR(emaj = gss_display_name(&emin, caller, &caller_buf,
8000Sstevel@tonic-gate &caller_oid)))
8010Sstevel@tonic-gate return(1);
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate code = krb5_parse_name(kcontext, (char *) caller_buf.value,
8040Sstevel@tonic-gate &caller_princ);
8050Sstevel@tonic-gate
8060Sstevel@tonic-gate gss_release_buffer(&emin, &caller_buf);
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate if (code)
8090Sstevel@tonic-gate return(code);
8100Sstevel@tonic-gate
8110Sstevel@tonic-gate retval = 0;
8122881Smp153739
8132881Smp153739 aentry = kadm5int_acl_find_entry(kcontext, caller_princ, principal);
8142881Smp153739 if (aentry) {
8150Sstevel@tonic-gate if ((aentry->ae_op_allowed & opmask) == opmask) {
8160Sstevel@tonic-gate retval = 1;
8170Sstevel@tonic-gate if (restrictions) {
8180Sstevel@tonic-gate *restrictions =
8190Sstevel@tonic-gate (aentry->ae_restrictions && aentry->ae_restrictions->mask)
8200Sstevel@tonic-gate ? aentry->ae_restrictions
8210Sstevel@tonic-gate : (restriction_t *) NULL;
8220Sstevel@tonic-gate }
8230Sstevel@tonic-gate }
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate krb5_free_principal(kcontext, caller_princ);
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_op_permitted()=%d\n",
8290Sstevel@tonic-gate retval));
8300Sstevel@tonic-gate return(retval);
8310Sstevel@tonic-gate }
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate kadm5_ret_t
kadm5_get_privs(void * server_handle,long * privs)8340Sstevel@tonic-gate kadm5_get_privs(void *server_handle, long *privs)
8350Sstevel@tonic-gate {
8360Sstevel@tonic-gate CHECK_HANDLE(server_handle);
8370Sstevel@tonic-gate
8380Sstevel@tonic-gate /* this is impossible to do with the current interface. For now,
8390Sstevel@tonic-gate return all privs, which will confuse some clients, but not
8400Sstevel@tonic-gate deny any access to users of "smart" clients which try to cache */
8410Sstevel@tonic-gate
8420Sstevel@tonic-gate *privs = ~0;
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate return KADM5_OK;
8450Sstevel@tonic-gate }
8460Sstevel@tonic-gate
8470Sstevel@tonic-gate /* SUNWresync121 (SEAM1.0) XXX */
8480Sstevel@tonic-gate kadm5_ret_t
__kadm5_get_priv(void * server_handle,long * privs,gss_name_t client)8490Sstevel@tonic-gate __kadm5_get_priv(void *server_handle, long *privs, gss_name_t client)
8500Sstevel@tonic-gate {
8510Sstevel@tonic-gate
8520Sstevel@tonic-gate aent_t *aentry;
8530Sstevel@tonic-gate gss_buffer_desc caller_buff;
8540Sstevel@tonic-gate gss_OID caller_oid;
8550Sstevel@tonic-gate krb5_principal caller_principal;
8560Sstevel@tonic-gate OM_uint32 minor, major;
8570Sstevel@tonic-gate krb5_error_code k_error;
8580Sstevel@tonic-gate kadm5_ret_t retval = KADM5_FAILURE;
8590Sstevel@tonic-gate
8600Sstevel@tonic-gate kadm5_server_handle_t handle = server_handle;
8610Sstevel@tonic-gate
8620Sstevel@tonic-gate CHECK_HANDLE(server_handle);
8630Sstevel@tonic-gate
8640Sstevel@tonic-gate if (GSS_ERROR(major = gss_display_name(&minor, client, &caller_buff,
8650Sstevel@tonic-gate &caller_oid)))
8660Sstevel@tonic-gate return(retval);
8670Sstevel@tonic-gate k_error = krb5_parse_name(handle->context,
8680Sstevel@tonic-gate (char *) caller_buff.value,
8690Sstevel@tonic-gate &caller_principal);
8700Sstevel@tonic-gate gss_release_buffer(&minor, &caller_buff);
8710Sstevel@tonic-gate
8720Sstevel@tonic-gate if (k_error)
8730Sstevel@tonic-gate return(retval);
8740Sstevel@tonic-gate
8752881Smp153739 if (aentry = kadm5int_acl_find_entry(handle->context, caller_principal,
8760Sstevel@tonic-gate (krb5_principal)NULL))
8770Sstevel@tonic-gate *privs = aentry->ae_op_allowed;
8780Sstevel@tonic-gate krb5_free_principal(handle->context, caller_principal);
8790Sstevel@tonic-gate
8800Sstevel@tonic-gate return (KADM5_OK);
8810Sstevel@tonic-gate }
882