/* * Copyright (c) 1991 by the University of Washington * Copyright (c) 1993 by the University of Southern California * * For copying and distribution information, please see the files * and . */ #include #include #include #include /* for decl. of inet_ntoa() */ #include /* for decl. of inet_ntoa() */ #include /* for decl. of inet_ntoa() */ #include /* for decl. of inet_ntoa() */ #include #include #include #include #include #include #include #ifndef IPPORT_RESERVED #define IPPORT_RESERVED 1024 #endif /* used to initialize ACLs */ struct aclinit { int acetype; char *atype; char *rights; char *prin_1; /* principals list */ char *prin_2; /* principals list */ char *prin_3; /* principals list */ char *prin_4; /* principals list */ char *prin_5; /* principals list */ char *prin_6; /* principals list */ char *prin_7; /* principals list */ char *prin_8; /* principals list */ char *prin_9; /* principals list */ char *prin_10; /* principals list */ char *prin_11; /* principals list */ char *prin_12; /* principals list */ char *prin_13; /* principals list */ char *prin_14; /* principals list */ char *prin_15; /* principals list */ char *prin_16; /* principals list */ char *prin_17; /* principals list */ char *prin_18; /* principals list */ char *prin_19; /* principals list */ char *prin_20; /* principals list */ char *prin_21; /* principals list */ char *prin_22; /* principals list */ char *prin_23; /* principals list */ char *prin_24; /* principals list */ char *prin_25; /* principals list */ char *prin_26; /* principals list */ }; static ACL_ST default_iacl = {ACL_DEFAULT, NULL}; static ACL_ST system_iacl = {ACL_SYSTEM, NULL}; static ACL_ST container_iacl = {ACL_CONTAINER, NULL}; static ACL_ST directory_iacl = {ACL_DIRECTORY, NULL}; static struct aclinit default_aclinit[] = DEFAULT_ACL; static struct aclinit system_aclinit[] = SYSTEM_ACL; static struct aclinit override_aclinit[] = OVERRIDE_ACL; static struct aclinit maint_aclinit[] = MAINT_ACL; /* Only modified in p_srv_check_acl_initialize_defaults(), which is called before we go multi-threaded. */ ACL default_acl = NULL; ACL system_acl = NULL; ACL override_acl = NULL; ACL nulldir_acl = NULL; ACL nullobj_acl = NULL; ACL nullcont_acl = NULL; ACL nulllink_acl = NULL; ACL maint_acl = NULL; static checkl_acl_r(); static check_permissions(); static check_asserted_principal(); ACL get_container_acl(); static ACL aclinit2acl(struct aclinit init[], int nelems); static int checkl_acl_r(ACL acl, ACL dacl, RREQ req, char *op, int depth, int ld,char *objid,char *itemid); /* Called before things start to run in psrv. */ void p_srv_check_acl_initialize_defaults(void) { default_acl = aclinit2acl(default_aclinit, sizeof default_aclinit / sizeof default_aclinit[0]); system_acl = aclinit2acl(system_aclinit, sizeof system_aclinit / sizeof system_aclinit[0]); override_acl = aclinit2acl(override_aclinit, sizeof override_aclinit / sizeof override_aclinit[0]); maint_acl = aclinit2acl(maint_aclinit, sizeof maint_aclinit / sizeof maint_aclinit[0]); default_iacl.next = &system_iacl; system_iacl.previous = &default_iacl; nulldir_acl = &default_iacl; nulllink_acl = &directory_iacl; nullobj_acl = &container_iacl; nullcont_acl = nulldir_acl; } static ACL aclentryinit2aclentry(struct aclinit *init); /* constructs a real list of ACL entries out of an array of aclinit structures. */ static ACL aclinit2acl(struct aclinit init[], int nelems) { ACL rethead = NULL; /* head of list of AC entries being returned */ int i; for (i = 0; i < nelems; ++i) { ACL tmp = aclentryinit2aclentry(&init[i]); APPEND_ITEM(tmp, rethead); } return rethead; } static ACL aclentryinit2aclentry(struct aclinit *init) { ACL retval; retval = acalloc(); if (!retval) out_of_memory(); retval->acetype = init->acetype; retval->atype = init->atype; retval->rights = init->rights; retval->principals = NULL; if (init->prin_1) retval->principals = tkappend(init->prin_1, retval->principals); if (init->prin_2) retval->principals = tkappend(init->prin_2, retval->principals); if (init->prin_3) retval->principals = tkappend(init->prin_3, retval->principals); if (init->prin_4) retval->principals = tkappend(init->prin_4, retval->principals); if (init->prin_5) retval->principals = tkappend(init->prin_5, retval->principals); if (init->prin_6) retval->principals = tkappend(init->prin_6, retval->principals); if (init->prin_7) retval->principals = tkappend(init->prin_8, retval->principals); if (init->prin_9) retval->principals = tkappend(init->prin_9, retval->principals); if (init->prin_10) retval->principals = tkappend(init->prin_10, retval->principals); if (init->prin_11) retval->principals = tkappend(init->prin_11, retval->principals); if (init->prin_12) retval->principals = tkappend(init->prin_12, retval->principals); if (init->prin_13) retval->principals = tkappend(init->prin_13, retval->principals); if (init->prin_14) retval->principals = tkappend(init->prin_14, retval->principals); if (init->prin_15) retval->principals = tkappend(init->prin_15, retval->principals); if (init->prin_16) retval->principals = tkappend(init->prin_16, retval->principals); if (init->prin_17) retval->principals = tkappend(init->prin_17, retval->principals); if (init->prin_18) retval->principals = tkappend(init->prin_18, retval->principals); if (init->prin_19) retval->principals = tkappend(init->prin_19, retval->principals); if (init->prin_20) retval->principals = tkappend(init->prin_20, retval->principals); if (init->prin_21) retval->principals = tkappend(init->prin_21, retval->principals); if (init->prin_22) retval->principals = tkappend(init->prin_22, retval->principals); if (init->prin_23) retval->principals = tkappend(init->prin_23, retval->principals); if (init->prin_24) retval->principals = tkappend(init->prin_24, retval->principals); if (init->prin_25) retval->principals = tkappend(init->prin_25, retval->principals); if (init->prin_26) retval->principals = tkappend(init->prin_26, retval->principals); return retval; } /* * srv_check_acl - check access control list * * SRV_CHECK_ACL checks an access control list to see if a particular * user is authorized to perform a particular operation. It returns * a positive number if the operation is authorized, and zero if * not authorized. SRV_CHECK_ACL actually checks up to three access * control lists. First, the access control list associated with * a link is checked (if specified). If the operation would not * be authorized, the secondary ACL may be checked if present, and * depending on the type of ACL check specified in the flags field, * to see if it applies to or overrides the individual entry. If sill * not authorized, an override ACL is checked to see if the operation * is performed. * * NOTE on negative rights: Negative rights apply within * a particular access control list only. Thus, a negative * entry in the link ACL can override other entries in the * link ACL, but it will not prevent access if the user * is authorized to perform the operation by the directory * or override ACL's. */ int srv_check_acl(ACL pacl, /* Primary ACL */ ACL sacl, /* Secondary ACL */ RREQ req, /* Request; used for client identification */ char *op, /* Operation */ int flags, /* Type of ACL check */ char *objid, /* hsoname of object to which ACL applies */ char *itemid) /* Name of item to be manipulated */ { int answer = 0; /* Now called from dirsrv */ #if 0 if(!initialized) initialize_defaults(); #endif if(flags == SCA_LINK) { if(!pacl) pacl = nulllink_acl; if(!sacl) sacl = nulldir_acl; answer = checkl_acl_r(pacl,sacl,req,op,ACL_NESTING, SCA_LINK,objid,itemid); if(!answer) answer = checkl_acl_r(sacl,sacl,req,op,ACL_NESTING, SCA_DIRECTORY,objid,itemid); } else if(flags == SCA_LINKDIR) { if(!pacl) pacl = nulllink_acl; if(!sacl) sacl = nulldir_acl; answer = checkl_acl_r(pacl,sacl,req,op,ACL_NESTING, SCA_LINK,objid,itemid); if(!answer) answer = checkl_acl_r(sacl,sacl,req,op,ACL_NESTING, SCA_DIRECTORY,objid,itemid); } else if(flags == SCA_DIRECTORY) { if(!pacl) pacl = nulldir_acl; answer = checkl_acl_r(pacl,pacl,req,op,ACL_NESTING, SCA_DIRECTORY,objid,itemid); } else if (flags == SCA_OBJECT) { ACL cacl = NULL; if(!pacl) pacl = nullobj_acl; if(!sacl) { if(objid && (cacl = get_container_acl(objid))) { answer = checkl_acl_r(pacl,cacl,req,op,ACL_NESTING, SCA_OBJECT,objid,itemid); aclfree(cacl); } else answer = checkl_acl_r(pacl,nullcont_acl,req,op,ACL_NESTING, SCA_OBJECT,objid,itemid); } else answer = checkl_acl_r(pacl,sacl,req,op,ACL_NESTING,SCA_OBJECT, objid,itemid); } else if (flags == SCA_MISC) { if(!pacl) pacl = maint_acl; answer = checkl_acl_r(pacl,NULL,req,op,ACL_NESTING, SCA_MISC,objid,itemid); } if(answer) return(answer); /* Check to see if absolute override applies */ return(checkl_acl_r(override_acl,NULL,req,op,ACL_NESTING, SCA_MISC, objid,itemid)); } static int checkl_acl_r(acl,sacl,req,op,depth,ld,objid,itemid) ACL acl; /* Access control list */ ACL sacl; /* Secondary access control list */ char *op; /* Operation */ RREQ req; /* Client identification */ int depth; /* Maximum nesting */ int ld; /* 0 = link, 1 = dir, 2 = both, 4=misc */ char *objid; /* Object associated with ACL */ char *itemid; /* Name of item to manipulate */ { int retval = 0; /* Would this entry authorize op */ int answer = 1; /* How to answer if match */ if(depth == 0) return(NOT_AUTHORIZED); while(acl) { retval = check_permissions(op,acl->rights,ld); if(retval||((acl->rights==NULL)&&((acl->acetype == ACL_DEFAULT) ||(acl->acetype == ACL_SYSTEM) ||(acl->acetype == ACL_DIRECTORY) ||(acl->acetype == ACL_CONTAINER) ||(acl->acetype == ACL_IETF_AAC)))) { if(retval == NEG_AUTHORIZED) answer = NOT_AUTHORIZED; else answer = AUTHORIZED; switch(acl->acetype) { case ACL_NONE: break; case ACL_DEFAULT: retval = checkl_acl_r(default_acl,sacl,req,op,depth-1,ld,objid,itemid); if(retval) return(answer); break; case ACL_SYSTEM: retval = checkl_acl_r(system_acl,sacl,req,op,depth-1,ld,objid,itemid); if(retval) return(answer); break; case ACL_OWNER: /* Check if user is the owner of the dirtectory */ #if 0 /* We need to find the owner of the file/directory */ /* for which this ACL applies and check whether it */ /* is the current principal. For now, we don't */ /* know the name of the file or directory. When */ /* the interface is changed so we do know it, we */ /* will check against the current host address and */ /* the TRSTHOST authentication type. Alternatively */ /* we will use an OBJECT-OWNER attribute from the */ /* object attribute list which will be in the form */ /* of an ACL entry, but without a rights field */ #endif break; case ACL_DIRECTORY: if(ld == SCA_LINK) { retval = checkl_acl_r(sacl,sacl,req,op,depth-1, SCA_LINKDIR,objid,itemid); if(retval) return(answer); } break; case ACL_CONTAINER: if(ld == SCA_OBJECT) { retval = checkl_acl_r(sacl,sacl,req,op,depth-1, SCA_CONTAINER,objid,itemid); if(retval) return(answer); } break; case ACL_ANY: return(answer); case ACL_AUTHENT: if (acl->atype && strequal(acl->atype, "KERBEROS")) { PAUTH pap; /* Iteration variable for PAUTH. */ TOKEN prin; /* principals */ /* Loop through all of the Kerberos authenticated principals. (This is upward-compatible with future versions of Kerberos that will allow one to be registered as multiple principals simultaneously.) */ for (pap = req->auth_info; pap; pap = pap->next) { if (pap->ainfo_type == PFSA_KERBEROS) { for (prin = pap->principals; prin; prin = prin->next) { if (member(prin->token, acl->principals)) return answer; } } } } else if (acl->atype && strequal(acl->atype, "P_PASSWORD")) { PAUTH pap; /* Iteration variable for PAUTH. */ TOKEN prin; /* principals */ /* Loop through all of the principals. */ for (pap = req->auth_info; pap; pap = pap->next) { if (pap->ainfo_type == PFSA_P_PASSWORD) { for (prin = pap->principals; prin; prin = prin->next) { if (member(prin->token, acl->principals)) return answer; } } } } break; case ACL_LGROUP: /* Not yet implemented */ break; case ACL_GROUP: /* Not yet implemented */ break; case ACL_TRSTHOST: /* Check host and userid */ if (!check_prvport(req)) break; /* DELIBERATE FALLTHROUGH */ case ACL_ASRTHOST: /* Check host and asserted userid */ { PAUTH pap; TOKEN prin; /* principals */ /* Loop through all of the asserted principals. */ for (pap = req->auth_info; pap; pap = pap->next) { if (pap->ainfo_type == PFSA_UNAUTHENTICATED) { for (prin = pap->principals; prin; prin = prin->next) { if (check_asserted_principal(prin->token, acl->principals, req->peer_addr)) return answer; } } } } break; case ACL_IETF_AAC: /* This ACL entry type is not yet implemented */ break; default: /* Not implemented */ break; } } acl = acl->next; } return(NOT_AUTHORIZED); } /* * check_permissions - Check if operation is authorized * * CHECK_PERMISIONS takes a string with letters representing * the permissions required for the current opration, and * a string listing operating authorized by the current ACL * entry. It returns a 1 if the operation would be * authorized by the current entry, a 0 if not, and a -1 * if the ACL entry would have authorized the operation, * but began with a "-" indicating negative authorization. * * ARGS: op - String with operations to be performed * p - Permissions from ACL entry * ld - Whther ACL entry is for directory or link (or both) * * RETURNS: 1 if authorized * 0 if not authorized * -1 if negative authorization * * Protections * * The more common entry appears first if multiple rights allow an * operation. The operation identifier appears second. * * Object File Directory Link* Meaning * AB AB AB Aa Administer ACL * VYAB VYAB VYAB VvAa View ACL * - - L Ll List link * Rg RG RQ RrQ Read link, get attribute or file * Wu Ww WM WmM Modify attribute, data, links * EiWu EeWw EIWM - Insert attributes links, append (extend) * DzWu - DKWM DdKWMm Delete link or attribute * * The following will eventually be replaced by restricted forms of * Administer (A or B). * * > > > ] Add rights * < < < [ Remove rights * ) ) ) - Add rights * ( ( ( - Remove rights * * The following only appear on the server maintenance ACL * * S Restart server * T Terminate server * U Update system information * P Administer passwords * p Add new password entry * * A - sign in an ACL means that the specified rights are explicitly * denied. In the table, it means not applicable. * * * A capital letter on a link ACL means that this right exists in the * direcory ACL for the directory containing the link. * * ** When restrictions are supported, they can be used to restrict the * specific attributes to which a right applies, or to restrict the * interpretation of an ACL entry to only the Object, File, or Directory, * or link. * * When a small letter is associated with a directory, it is the default * used for those links in the directory which do not otherwise specify * protections. The large letter for a directory indicates that the * right applies to ALL entries in the directory, regardless of the ACLs * associated with the individual link. * * These rights apply to the directory and individual links. The ability * to read a link does not grant any rights to read the file that the * link points to. Instead, it grants the right to read the binding * of the link. The protection mechanisms for the objects themselves * depend on the underlying access mechanism. * * The Administer right is required to change the ACL. "A" allows one * to change the ACLs for the directory as a whole, as well as those * for individual links. It does not, however, grant any rights to * the object pointed to by those links (e.g. it doesn't allow one * to change the permissions on subdirectories. * * List allows one to list an entry in a wildcarded search. Read allows * one to learn the binding of a link. If one can read a link, but * not list it, then it can only be seen when the user specifies the * exact name of the link in a query. * * Modify allows one to change the binding of a link. It does not * allow one to create a new link or delete an existing one. Insert * or delete access are necessary for that. * * View allows one to view the contents of the ACL. Administer implies view. * Add rights and remove rights, ><][)(, allow one to add or remove the * other rights that are specified as part of the same ACL entry. It is * a limited form of administer. The other rights included in the * same ACL entry do not apply, but only restrict which rights may be * added or removed. The add or remove indicators must appear in the * first one or two positions in the rights field, and can not themselves * be added or removed unless they also appear later in the rights field. * * If the permission string begins with a "-" and if the specified operation * would otherwise be authorized, check_permissions returns -1 indicating * that an applicable negative right has been found, and that the operation * should be denied even if subsequent ACL entries authorizing it are found. * If an ACL entry preceding this one has already authorized the operation, * the operation will be performed. * * BUGS: For now, only the first character in ><][])( means add or * delete the following rights, and all rights included in the * entry including the first ><][)( may be added or deleted. * Eventually, we will check the first two positions to see * if adding and deleting is allowed, and the matching * characters in those positions will be removed before * checking subsequent characters. */ int static check_permissions(op,p,ld) char *op; /* Operation */ char *p; /* Permissions */ int ld; /* 0 =link, 1 =directory, 2=both, 4=misc */ { char *tp = p; int polarity = 1; /* -1 = neg authorization */ if(!p || !(*p)) return(NOT_AUTHORIZED); if(*p == '-') polarity = -1; /* Reject if ACL entry for insert or delete rights, but not operation */ if(index("><][)(",*p) && !index("><][",*op)) return(NOT_AUTHORIZED); /* Insert or delete rights must be first in ACL permissions */ while(*(++tp)) if(index("><][)(",*tp)) return(NOT_AUTHORIZED); while(*op) { switch(*(op++)) { case 'a': if((ld != 1) && index(p,'a')) continue; if((ld != 0) && index(p,'A')) continue; else return(NOT_AUTHORIZED); case 'A': case 'B': if((ld != 0) && index(p,'A')) continue; if((ld != 0) && index(p,'B')) continue; else return(NOT_AUTHORIZED); case 'v': if((ld != 1) && index(p,'v')) continue; if((ld != 0) && index(p,'V')) continue; if((ld != 1) && index(p,'a')) continue; if((ld != 0) && index(p,'A')) continue; else return(NOT_AUTHORIZED); case 'V': case 'Y': if((ld != 0) && index(p,'V')) continue; if((ld != 0) && index(p,'Y')) continue; if((ld != 0) && index(p,'A')) continue; if((ld != 0) && index(p,'B')) continue; else return(NOT_AUTHORIZED); case 'l': if((ld != 1) && index(p,'l')) continue; case 'L': /* and fall through */ if((ld != 0) && index(p,'L')) continue; else return(NOT_AUTHORIZED); case 'r': if((ld != 1) && index(p,'r')) continue; case 'R': /* and fall through */ case 'Q': /* and fall through */ if((ld != 0) && index(p,'R')) continue; if((ld != 0) && index(p,'Q')) continue; else return(NOT_AUTHORIZED); case 'G': if((ld != 0) && index(p,'G')) continue; if((ld != 0) && index(p,'R')) continue; else return(NOT_AUTHORIZED); case 'g': if((ld != 0) && index(p,'g')) continue; if((ld != 0) && index(p,'R')) continue; else return(NOT_AUTHORIZED); case 'm': if((ld != 1) && index(p,'m')) continue; case 'M': /* and fall through */ if((ld != 0) && index(p,'M')) continue; if((ld != 0) && index(p,'W')) continue; else return(NOT_AUTHORIZED); case 'w': /* and fall through */ if((ld != 0) && index(p,'w')) continue; if((ld != 0) && index(p,'W')) continue; else return(NOT_AUTHORIZED); case 'u': /* and fall through */ if((ld != 0) && index(p,'u')) continue; if((ld != 0) && index(p,'W')) continue; else return(NOT_AUTHORIZED); case 'I': if((ld != 0) && index(p,'I')) continue; if((ld != 0) && index(p,'E')) continue; if((ld != 0) && index(p,'W')) continue; if((ld != 0) && index(p,'M')) continue; else return(NOT_AUTHORIZED); case 'e': if((ld != 0) && index(p,'e')) continue; if((ld != 0) && index(p,'E')) continue; if((ld != 0) && index(p,'W')) continue; if((ld != 0) && index(p,'w')) continue; else return(NOT_AUTHORIZED); case 'i': if((ld != 0) && index(p,'i')) continue; if((ld != 0) && index(p,'E')) continue; if((ld != 0) && index(p,'W')) continue; if((ld != 0) && index(p,'u')) continue; else return(NOT_AUTHORIZED); case 'd': if((ld != 1) && index(p,'d')) continue; if((ld != 1) && index(p,'m')) continue; case 'D': /* and fall through */ if((ld != 0) && index(p,'D')) continue; if((ld != 0) && index(p,'K')) continue; if((ld != 0) && index(p,'W')) continue; if((ld != 0) && index(p,'M')) continue; else return(NOT_AUTHORIZED); case 'z': /* and fall through */ if((ld != 0) && index(p,'D')) continue; if((ld != 0) && index(p,'z')) continue; if((ld != 0) && index(p,'W')) continue; if((ld != 0) && index(p,'u')) continue; else return(NOT_AUTHORIZED); case ']': if((ld != 1) && index(p,']')) continue; if((ld != 0) && index(p,'>')) continue; else return(NOT_AUTHORIZED); case '>': if((ld != 0) && index(p,'>')) continue; if((ld != 0) && index(p,')')) continue; else return(NOT_AUTHORIZED); case '[': if((ld != 1) && index(p,'[')) continue; if((ld != 0) && index(p,'<')) continue; else return(NOT_AUTHORIZED); case '<': if((ld != 0) && index(p,'<')) continue; if((ld != 0) && index(p,'(')) continue; else return(NOT_AUTHORIZED); /* Maintenance operations. */ case 'S': if (index(p, 'S')) continue; else return NOT_AUTHORIZED; case 'T': if (index(p, 'T')) continue; else return NOT_AUTHORIZED; case 'U': if (index(p, 'U')) continue; else return NOT_AUTHORIZED; case 'P': if (index(p, 'P')) continue; else return NOT_AUTHORIZED; case 'p': if (index(p, 'p')) continue; if (index(p, 'P')) continue; else return NOT_AUTHORIZED; default: return(NOT_AUTHORIZED); } } return(polarity); } #ifdef NOTDEF /* Unused. Make this thread-safe before commenting it out. */ static char *inet_ntoa(a) struct in_addr a; { static char astring[20]; #if BYTE_ORDER == BIG_ENDIAN sprintf(astring,"%d.%d.%d.%d",(a.s_addr >> 24) & 0xff, (a.s_addr >> 16) & 0xff,(a.s_addr >> 8) & 0xff, a.s_addr & 0xff); #else sprintf(astring,"%d.%d.%d.%d", a.s_addr & 0xff, (a.s_addr >> 8) & 0xff,(a.s_addr >> 16) & 0xff, (a.s_addr >> 24) & 0xff); #endif return(astring); } #endif NOTDEF /* Only used locally in a context where it returns static data overwritten by each call. */ static char * inet_def_local(char *s) { AUTOSTAT_CHARPP(adstringp); static long myaddr = 0; /* look below to see how this is mutexed */ char intstring[10]; static long o[4]; /* look below to see how this is mutexed */ char *ads; long *octet; if (!*adstringp) *adstringp = stalloc(50); /* effectively, an array of size 50. */ if (!myaddr) { p_th_mutex_lock(p_th_mutexPSRV_CHECK_ACL_INET_DEF_LOCAL); /* Now that we have a mutex, check adstring again, since it might have changed since we tested it. This tests whether another initialization successfully completed since we called this. */ if (!myaddr) { long local_myaddr = myaddress(); #if BYTE_ORDER == BIG_ENDIAN o[0] = (local_myaddr >> 24) & 0xff; o[1] = (local_myaddr >> 16) & 0xff; o[2] = (local_myaddr >> 8) & 0xff; o[3] = local_myaddr & 0xff; #else o[0] = local_myaddr & 0xff; o[1] = (local_myaddr >> 8) & 0xff; o[2] = (local_myaddr >> 16) & 0xff; o[3] = (local_myaddr >> 24) & 0xff; #endif myaddr = local_myaddr; /* change done; commit. */ } p_th_mutex_unlock(p_th_mutexPSRV_CHECK_ACL_INET_DEF_LOCAL); } octet = o; ads = *adstringp; while(*s && ((ads - *adstringp) < 40) ) { switch(*s) { case '.': octet++; *ads++ = *s; break; case '%': qsprintf(intstring,sizeof intstring, "%d",*octet); bcopy(intstring,ads,strlen(intstring)); ads += strlen(intstring); break; default: *ads++ = *s; break; } s++; } *ads++ = '\0'; return(*adstringp); } /* Are we logged into a privileged port? 1 if yes, zero if no. */ int check_prvport(req) RREQ req; { return PEER_PORT(req) <= IPPORT_RESERVED; } /* * check_asserted_principal - check for membership in list of principals * and check optional host ID. The principals have the format used by ASRTHOST * and TRSTHOST. */ static int check_asserted_principal(username,principals, hostaddr) char username[]; struct in_addr hostaddr; TOKEN principals; { for(; principals; principals = principals->next) { char *host; /* principal specified in the ACL entry. We copy it because we can't modify the principals structure, since the principals structure might contain strings that are in readonly memory. */ AUTOSTAT_CHARPP(aclprinp); *aclprinp = stcopyr(principals->token, *aclprinp); host = strchr(*aclprinp,'@'); if(host == NULL) { if(wcmatch(username,*aclprinp)) return(TRUE); else continue; } *(host++) = '\0'; if(!wcmatch(username,*aclprinp)) continue; if(index("%123456789.",*host)) { /* Host address */ if(wcmatch(inet_ntoa(hostaddr),inet_def_local(host))) return(TRUE); continue; } else if(*host == '0') { /* Host address with leading 0 */ if(wcmatch(inet_ntoa(hostaddr),inet_def_local(host+1))) return(TRUE); continue; } else { /* Host name - not implemented */ continue; } } return(FALSE); } ACL get_container_acl(char *path) { PFILE container; ACL cont_acl = NULL; ACL tacl = NULL; ACL tacl2 = NULL; char cpath[MAXPATHLEN]; char *slash; strcpy(cpath,path); slash = strrchr(cpath,'/'); if(slash) { *slash = '\0'; container = pfalloc(); dsrfinfo(cpath,0,container); cont_acl = container->oacl; container->oacl = NULL; pffree(container); tacl = cont_acl; while(tacl) { if(tacl->acetype == ACL_CONTAINER) { tacl2 = tacl; tacl = tacl->next; EXTRACT_ITEM(tacl2,cont_acl); acfree(tacl2); } else tacl = tacl->next; } return(cont_acl); } return(NULL); }