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 * 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 * 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 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 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 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 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 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 * 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 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 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 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 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 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