/* * LASIpEval * INPUT * attr_name The string "ip" - in lower case. * comparator CMP_OP_EQ or CMP_OP_NE only * attr_pattern A comma-separated list of IP addresses and netmasks * in dotted-decimal form. Netmasks are optionally * prepended to the IP address using a plus sign. E.g. * 255.255.255.0+123.45.67.89. Any byte in the IP address * (but not the netmask) can be wildcarded using "*" * *cachable Always set to ACL_INDEF_CACHABLE * subject Subject property list * resource Resource property list * auth_info The authentication info if any * RETURNS * ret code The usual LAS return codes. */ int LASIpEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, char *attr_pattern, ACLCachable_t *cachable, void **LAS_cookie, PList_t subject, PList_t resource, PList_t auth_info, PList_t global_auth) { void *pip; int retcode; LASIpContext_t *context; int rv; #ifndef UTEST *cachable = ACL_INDEF_CACHABLE; #endif if (strcmp(attr_name, "ip") != 0) { nserrGenerate(errp, ACLERRINVAL, ACLERR5200, ACL_Program, 2, XP_GetAdminStr(DBT_lasIpBuildReceivedRequestForAttr_), attr_name); return LAS_EVAL_INVALID; } if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) { nserrGenerate(errp, ACLERRINVAL, ACLERR5210, ACL_Program, 2, XP_GetAdminStr(DBT_lasipevalIllegalComparatorDN_), comparator_string(comparator)); return LAS_EVAL_INVALID; } /* GET THE IP ADDR FROM THE SESSION CONTEXT AND STORE IT IN THE * VARIABLE ip. */ #ifndef UTEST rv = ACL_GetAttribute(errp, ACL_ATTR_IP, &pip, subject, resource, auth_info, global_auth); PRNetAddr *ip_addr = (PRNetAddr *)pip; if (rv != LAS_EVAL_TRUE) { if (subject || resource) { /* Don't ereport if called from ACL_CachableAclList */ char rv_str[16]; sprintf(rv_str, "%d", rv); nserrGenerate(errp, ACLERRINVAL, ACLERR5220, ACL_Program, 2, XP_GetAdminStr(DBT_lasipevalUnableToGetSessionAddre_), rv_str); } ereport(LOG_VERBOSE, "ERROR Attribute Getter for ACL_ATTR_IP returned error %d.", rv); return LAS_EVAL_FAIL; } #else PRNetAddr *ip_addr = LASIpGetIpv6(); if (ip_addr == NULL) { ereport(LOG_VERBOSE, "ERROR IP Address returned from LASIpGetIpv6() is NULL."); return LAS_EVAL_FAIL; } #endif int ipVersion = PR_AF_INET; if (ip_addr->ipv6.family == PR_AF_INET6) { ipVersion = PR_AF_INET6; } else if (ip_addr->inet.family != PR_AF_INET) { PR_ASSERT(0); } /* If this is the first time through, build the pattern tree first. */ if (*LAS_cookie == NULL) { if (strcspn(attr_pattern, "0123456789.*ABCDEF:abcdef,+ \t")) { nserrGenerate(errp,ACLERRINVAL,ACLERR5120,ACL_Program,2, XP_GetAdminStr(DBT_lasIpIncorrentIPPattern),attr_pattern); return LAS_EVAL_INVALID; } ACL_CritEnter(); context = (LASIpContext *) *LAS_cookie; if (*LAS_cookie == NULL) { /* must check again */ *LAS_cookie = context = (LASIpContext_t *)PERM_MALLOC(sizeof(LASIpContext_t)); if (context == NULL) { nserrGenerate(errp, ACLERRNOMEM, ACLERR5230, ACL_Program, 1, XP_GetAdminStr(DBT_lasipevalUnableToAllocateContext_)); ACL_CritExit(); return LAS_EVAL_FAIL; } context->treetop = NULL; retcode = LASIpBuild(errp, attr_pattern, &context->treetop, ipVersion); if ((retcode == PR_AF_INET6) || (retcode == PR_AF_INET) || (retcode == (PR_AF_INET6+PR_AF_INET))) context->ipVersion = retcode; else { ACL_CritExit(); return (retcode); } } ACL_CritExit(); } else context = (LASIpContext *) *LAS_cookie; return traverseTreeAndCompareIPs(errp, ip_addr, context, attr_pattern, ipVersion, (comparator == CMP_OP_EQ)?1:0); }
/* * LASIsLockOwnerEval * INPUT * attr_name The string "is-lock-owner" - in lower case. * comparator CMP_OP_EQ or CMP_OP_NE only * attr_pattern "on", "off", "yes", "no", "true", "false", "1", "0" * cachable Always set to ACL_NOT_CACHABLE. * subject Subject property list * resource Resource property list * auth_info Authentication info, if any * RETURNS * retcode The usual LAS return codes. */ int LASIsLockOwnerEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, char *attr_pattern, ACLCachable_t *cachable, void **LAS_cookie, PList_t subject, PList_t resource, PList_t auth_info, PList_t global_auth) { int retcode=0; int matched=0; char *lock_owner=NULL; char *user=NULL; PRBool pattern=PR_TRUE; int rv=0; *cachable = ACL_NOT_CACHABLE; *LAS_cookie = (void *)0; if (strcmp(attr_name, ACL_ATTR_IS_LOCK_OWNER)) { nserrGenerate(errp, ACLERRINVAL, ACLERR6700, ACL_Program, 2, XP_GetAdminStr(DBT_lasIsLockOwnerEvalReceivedRequestForAtt_), attr_name); return LAS_EVAL_INVALID; } if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) { nserrGenerate(errp, ACLERRINVAL, ACLERR6710, ACL_Program, 2, XP_GetAdminStr(DBT_lasIsLockOwnerEvalIllegalComparatorDN_), comparator_string(comparator)); return LAS_EVAL_INVALID; } if (PL_strcasecmp(attr_pattern, "on") == 0 || PL_strcasecmp(attr_pattern, "true") == 0 || PL_strcasecmp(attr_pattern, "yes") == 0 || PL_strcasecmp(attr_pattern, "1") == 0) { pattern = PR_TRUE; } else if (PL_strcasecmp(attr_pattern, "off") == 0 || PL_strcasecmp(attr_pattern, "false") == 0 || PL_strcasecmp(attr_pattern, "no") == 0 || PL_strcasecmp(attr_pattern, "0") == 0) { pattern = PR_FALSE; } else { nserrGenerate(errp, ACLERRINVAL, ACLERR6720, ACL_Program, 2, XP_GetAdminStr(DBT_lasIsLockOwnerEvalIllegalAttrPattern_), attr_pattern); return LAS_EVAL_INVALID; } // get the lock owner // assuming lock owner has been set in plist before ACL_Evaluate is called rv = ACL_GetAttribute(errp, ACL_ATTR_LOCK_OWNER, (void **)&lock_owner, subject, resource, auth_info, global_auth); if (rv != LAS_EVAL_TRUE) { return rv; } if (lock_owner) { // get the authenticated user name rv = ACL_GetAttribute(errp, ACL_ATTR_USER, (void **)&user, subject, resource, auth_info, global_auth); if (rv != LAS_EVAL_TRUE) { return rv; } if (user) { // if user is the lock owner matched = !strcmp(user, lock_owner); } else // user has not been authenticated yet matched=0; } else // lock owner is null means does not match matched=0; if (pattern == PR_FALSE) matched = !matched; if (comparator == CMP_OP_EQ) { retcode = (matched ? LAS_EVAL_TRUE : LAS_EVAL_FALSE); } else { retcode = (matched ? LAS_EVAL_FALSE : LAS_EVAL_TRUE); } ereport(LOG_VERBOSE, "acl is-lock-owner : user [%s] %s is lock owner [%s] %s (%s)", user?user:"", (retcode == LAS_EVAL_FALSE) ? "does not match" : (retcode == LAS_EVAL_TRUE) ? "matched" : "error in", lock_owner?lock_owner:"", (comparator == CMP_OP_EQ) ? "=" : "!=", attr_pattern); return retcode; }
/* * LASUserEval * INPUT * attr_name The string "user" - in lower case. * comparator CMP_OP_EQ or CMP_OP_NE only * attr_pattern A comma-separated list of users * *cachable Always set to ACL_NOT_CACHABLE. * subject Subject property list * resource Resource property list * auth_info Authentication info, if any * RETURNS * retcode The usual LAS return codes. */ int LASUserEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, char *attr_pattern, ACLCachable_t *cachable, void **LAS_cookie, PList_t subject, PList_t resource, PList_t auth_info, PList_t global_auth) { char *uid; char *users; char *user; char *comma; int retcode; int matched; int is_owner; int rv; *cachable = ACL_NOT_CACHABLE; *LAS_cookie = (void *)0; if (strcmp(attr_name, ACL_ATTR_USER) != 0) { nserrGenerate(errp, ACLERRINVAL, ACLERR5700, ACL_Program, 2, XP_GetAdminStr(DBT_lasUserEvalReceivedRequestForAtt_), attr_name); return LAS_EVAL_INVALID; } if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) { nserrGenerate(errp, ACLERRINVAL, ACLERR5710, ACL_Program, 2, XP_GetAdminStr(DBT_lasuserevalIllegalComparatorDN_), comparator_string(comparator)); return LAS_EVAL_INVALID; } if (!strcmp(attr_pattern, "anyone")) { *cachable = ACL_INDEF_CACHABLE; return comparator == CMP_OP_EQ ? LAS_EVAL_TRUE : LAS_EVAL_FALSE; } /* get the authenticated user name */ #ifndef UTEST rv = ACL_GetAttribute(errp, ACL_ATTR_USER, (void **)&uid, subject, resource, auth_info, global_auth); if (rv != LAS_EVAL_TRUE) { return rv; } #else uid = (char *)LASUserGetUser(); #endif /* We have an authenticated user */ if (!strcmp(attr_pattern, "all")) { return comparator == CMP_OP_EQ ? LAS_EVAL_TRUE : LAS_EVAL_FALSE; } users = STRDUP(attr_pattern); if (!users) { nserrGenerate(errp, ACLERRNOMEM, ACLERR5720, ACL_Program, 1, XP_GetAdminStr(DBT_lasuserevalRanOutOfMemoryN_)); return LAS_EVAL_FAIL; } user = users; matched = 0; /* check if the uid is one of the users */ while(user != 0 && *user != 0 && !matched) { if ((comma = strchr(user, ',')) != NULL) { *comma++ = 0; } /* ignore leading whitespace */ while(*user == ' ' || *user == '\t') user++; if (*user) { /* ignore trailing whitespace */ int len = strlen(user); char *ptr = user+len-1; while(*ptr == ' ' || *ptr == '\t') *ptr-- = 0; } if (!strcasecmp(user, ACL_ATTR_OWNER)) { rv = ACL_GetAttribute(errp, ACL_ATTR_IS_OWNER, (void **)&is_owner, subject, resource, auth_info, global_auth); if (rv == LAS_EVAL_TRUE) matched = 1; else /* continue checking for next user */ user = comma; } else if (!WILDPAT_CASECMP(uid, user)) { /* uid is one of the users */ matched = 1; } else { /* continue checking for next user */ user = comma; } } if (comparator == CMP_OP_EQ) { retcode = (matched ? LAS_EVAL_TRUE : LAS_EVAL_FALSE); } else { retcode = (matched ? LAS_EVAL_FALSE : LAS_EVAL_TRUE); } FREE(users); return retcode; }
/* * LASDnsEval * INPUT * attr_name The string "dns" - in lower case. * comparator CMP_OP_EQ or CMP_OP_NE only * attr_pattern A comma-separated list of DNS names * Any segment(s) in a DNS name can be wildcarded using * "*". Note that this is not a true Regular Expression * form. * *cachable Always set to ACL_INDEF_CACHE * subject Subject property list * resource Resource property list * auth_info Authentication info, if any * RETURNS * ret code The usual LAS return codes. */ int LASDnsEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator, char *attr_pattern, ACLCachable_t *cachable, void **LAS_cookie, PList_t subject, PList_t resource, PList_t auth_info, PList_t global_auth) { int result; int aliasflg; char *my_dns; LASDnsContext_t *context = NULL; int rv; *cachable = ACL_INDEF_CACHABLE; if (strcmp(attr_name, "dns") == 0) { /* Enable aliasflg for "dns", which allows "dns" hostname to look up * DSN hash table using the primary hostname. */ aliasflg = 1; } else if (strcmp(attr_name, "dnsalias") == 0) { aliasflg = 1; } else { nserrGenerate(errp, ACLERRINVAL, ACLERR4800, ACL_Program, 2, XP_GetAdminStr(DBT_lasDnsBuildReceivedRequestForAtt_), attr_name); return LAS_EVAL_INVALID; } if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) { nserrGenerate(errp, ACLERRINVAL, ACLERR4810, ACL_Program, 2, XP_GetAdminStr(DBT_lasdnsevalIllegalComparatorDN_), comparator_string(comparator)); return LAS_EVAL_INVALID; } /* If this is the first time through, build the pattern tree first. */ if (*LAS_cookie == NULL) { ACL_CritEnter(); if (*LAS_cookie == NULL) { /* Must check again */ *LAS_cookie = context = (LASDnsContext_t *)PERM_MALLOC(sizeof(LASDnsContext_t)); if (context == NULL) { nserrGenerate(errp, ACLERRNOMEM, ACLERR4820, ACL_Program, 1, XP_GetAdminStr(DBT_lasdnsevalUnableToAllocateContex_)); ACL_CritExit(); return LAS_EVAL_FAIL; } context->Table = NULL; if (LASDnsBuild(errp, attr_pattern, context, aliasflg) == LAS_EVAL_INVALID) { /* Error is already printed in LASDnsBuild */ ACL_CritExit(); return LAS_EVAL_FAIL; } /* After this line, it is assured context->Table is not NULL. */ } else { context = (LASDnsContext *) *LAS_cookie; } ACL_CritExit(); } else { ACL_CritEnter(); context = (LASDnsContext *) *LAS_cookie; ACL_CritExit(); } /* Call the DNS attribute getter */ #ifdef UTEST LASDnsGetDns(&my_dns); /* gets stuffed on return */ #else rv = ACL_GetAttribute(errp, ACL_ATTR_DNS, (void **)&my_dns, subject, resource, auth_info, global_auth); if (rv != LAS_EVAL_TRUE) { if (subject || resource) { char rv_str[16]; /* Don't ereport if called from ACL_CachableAclList */ sprintf(rv_str, "%d", rv); nserrGenerate(errp, ACLERRINVAL, ACLERR4830, ACL_Program, 2, XP_GetAdminStr(DBT_lasdnsevalUnableToGetDnsErrorDN_), rv_str); } return LAS_EVAL_FAIL; } #endif result = LASDnsMatch(my_dns, context); if (comparator == CMP_OP_NE) { if (result == LAS_EVAL_FALSE) return LAS_EVAL_TRUE; else if (result == LAS_EVAL_TRUE) return LAS_EVAL_FALSE; } return (result); }
/* SSL LAS driver * Note that everything is case-insensitive. * INPUT * attr must be the string "ssl". * comparator can only be "=" or "!=". * pattern "on", "off", "yes", "no", "true", "false", "1", "0" * OUTPUT * cachable Will be set to ACL_NOT_CACHABLE. * return code set to LAS_EVAL_* */ int LASSSLEval(NSErr_t *errp, char *attr, CmpOp_t comparator, char *pattern, ACLCachable_t *cachable, void **las_cookie, PList_t subject, PList_t resource, PList_t auth_info, PList_t global_auth) { Session *sn = NULL; PRBool sslrequired, sslstate; int rv; /* Sanity checking */ if (strcmp(attr, "ssl") != 0) { nserrGenerate(errp, ACLERRINVAL, ACLERR6300, ACL_Program, 2, XP_GetAdminStr(DBT_sslLasUnexpectedAttribute), attr); return LAS_EVAL_INVALID; } if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) { nserrGenerate(errp, ACLERRINVAL, ACLERR6310, ACL_Program, 2, XP_GetAdminStr(DBT_sslLasIllegalComparator), comparator_string(comparator)); return LAS_EVAL_INVALID; } *cachable = ACL_NOT_CACHABLE; // ???? if (PL_strcasecmp(pattern, "on") == 0 || PL_strcasecmp(pattern, "true") == 0 || PL_strcasecmp(pattern, "yes") == 0 || PL_strcasecmp(pattern, "1") == 0) { sslrequired = PR_TRUE; } else if (PL_strcasecmp(pattern, "off") == 0 || PL_strcasecmp(pattern, "false") == 0 || PL_strcasecmp(pattern, "no") == 0 || PL_strcasecmp(pattern, "0") == 0) { sslrequired = PR_FALSE; } else { nserrGenerate(errp, ACLERRINVAL, ACLERR6320, ACL_Program, 2, XP_GetAdminStr(DBT_sslLasIllegalValue), pattern); return LAS_EVAL_INVALID; } // Now look whether our session is over SSL if (PListGetValue(subject, ACL_ATTR_SESSION_INDEX, (void **)&sn, NULL) < 0) { nserrGenerate(errp, ACLERRINVAL, ACLERR6330, ACL_Program, 2, XP_GetAdminStr(DBT_sslLasUnableToGetSessionAddr)); return LAS_EVAL_FAIL; } sslstate = GetSecurity(sn); if ((sslstate == sslrequired) && (comparator == CMP_OP_EQ)) { rv = LAS_EVAL_TRUE; } else if ((sslstate != sslrequired) && (comparator == CMP_OP_NE)) { rv = LAS_EVAL_TRUE; } else { rv = LAS_EVAL_FALSE; } ereport(LOG_VERBOSE, "acl ssl: %s on ssl %s (%s)", (rv == LAS_EVAL_FALSE) ? "no match" : "match", (comparator == CMP_OP_EQ) ? "=" : "!=", pattern); return rv; }