int LASIpGetter(NSErr_t *errp, PList_t subject, PList_t resource, PList_t auth_info, PList_t global_auth, void *arg) { Session *sn=NULL; int rv; IPAddr_t ip; int retcode, tmpip, netmask; char * tmp; rv = PListGetValue(subject, ACL_ATTR_SESSION_INDEX, (void **)&sn, NULL); if (rv < 0) { ereport(LOG_SECURITY, XP_GetAdminStr(DBT_aclFrameLASIpGetter1), rv); return LAS_EVAL_FAIL; } tmp = inet_ntoa(sn->iaddr); retcode =dotdecimal(tmp, "255.255.255.255", &tmpip, &netmask); if (retcode) return (retcode); ip = tmpip; rv = PListInitProp(subject, ACL_ATTR_IP_INDEX, ACL_ATTR_IP, (void *)ip, NULL); if (rv < 0) { ereport(LOG_SECURITY, XP_GetAdminStr(DBT_aclFrameLASIpGetter2), rv); return LAS_EVAL_FAIL; } return LAS_EVAL_TRUE; }
NSAPI_PUBLIC int ACL_ListPostParseForAuth(NSErr_t *errp, ACLListHandle_t *acl_list ) { ACLHandle_t *acl; ACLWrapper_t *wrap; ACLExprHandle_t *expr; char *method; char *database; int rv; ACLDbType_t *dbtype; ACLMethod_t *methodtype; if ( acl_list == NULL ) return(0); // for all ACLs for ( wrap = acl_list->acl_list_head; wrap; wrap = wrap->wrap_next ) { acl = wrap->acl; if ( acl == NULL ) continue; // for all expressions with the ACL for ( expr = acl->expr_list_head; expr; expr = expr->expr_next ) { if ( expr->expr_type != ACL_EXPR_TYPE_AUTH || expr->expr_auth == NULL) continue; // get method attribute - this is a name now rv = PListGetValue(expr->expr_auth, ACL_ATTR_METHOD_INDEX, (void **) &method, NULL); if ( rv >= 0 ) { methodtype = (ACLMethod_t *)PERM_MALLOC(sizeof(ACLMethod_t)); rv = ACL_MethodFind(errp, method, methodtype); if (rv < 0) { nserrGenerate(errp, ACLERRUNDEF, ACLERR3800, ACL_Program, 3, acl->tag, "method", method); PERM_FREE(methodtype); return(ACLERRUNDEF); } // replace it with a method type rv = PListSetValue(expr->expr_auth, ACL_ATTR_METHOD_INDEX, methodtype, NULL); if ( rv < 0 ) { nserrGenerate(errp, ACLERRNOMEM, ACLERR3810, ACL_Program, 0); return(ACLERRNOMEM); } PERM_FREE(method); } } } return(0); }
/* acl_get_req_time -- * If the REQ_TIME is available on the 'resource' plist, return it. * Otherwise, make a system call to get the time and insert the time on the * 'resource' PList. Allocate the time_t structure using the 'resource' * PList's pool. */ time_t *acl_get_req_time (PList_t resource) { time_t *req_time = 0; int rv = PListGetValue(resource, ACL_ATTR_TIME_INDEX, (void **)&req_time, NULL); if (rv < 0) { req_time = (time_t *)pool_malloc(PListGetPool(resource), sizeof(time_t)); if (NULL == req_time) { return NULL; } time(req_time); PListInitProp(resource, ACL_ATTR_TIME_INDEX, ACL_ATTR_TIME, (void *)req_time, NULL); } return req_time; }
/* * LASIpv6Getter * This is the Attribute Getter function for IPv6 Addresses. * LAS_EVAL_FAIL on failure of LAS_EVAL_TRUE on success. */ int LASIpv6Getter(NSErr_t *errp, PList_t subject, PList_t resource, PList_t auth_info, PList_t global_auth, void *arg) { Request *rq = 0; int rv = PListGetValue(resource, ACL_ATTR_REQUEST_INDEX, (void **)&rq, NULL); if (rv < 0) { ereport(LOG_VERBOSE, "Unable to get request object", rv); return LAS_EVAL_FAIL; } HttpRequest *hrq = GetHrq(rq); DaemonSession &dsn = hrq->GetDaemonSession(); PRNetAddr *ip = dsn.GetRemoteAddress(); rv = PListInitProp(subject, ACL_ATTR_IP_INDEX, ACL_ATTR_IP, (void *)ip, NULL); if (rv < 0) { ereport(LOG_SECURITY, XP_GetAdminStr(DBT_aclFrameLASIpGetter2), rv); return LAS_EVAL_FAIL; } return LAS_EVAL_TRUE; }
NSAPI_PUBLIC int ACL_ListPostParseForAuth(NSErr_t *errp, ACLListHandle_t *acl_list ) { ACLHandle_t *acl; ACLWrapper_t *wrap; ACLExprHandle_t *expr; char *method; char *database; int rv; ACLDbType_t *dbtype; ACLMethod_t *methodtype; if ( acl_list == NULL ) return(0); for ( wrap = acl_list->acl_list_head; wrap; wrap = wrap->wrap_next ) { acl = wrap->acl; if ( acl == NULL ) continue; for ( expr = acl->expr_list_head; expr; expr = expr->expr_next ) { if ( expr->expr_type != ACL_EXPR_TYPE_AUTH || expr->expr_auth == NULL) continue; rv = PListGetValue(expr->expr_auth, ACL_ATTR_METHOD_INDEX, (void **) &method, NULL); if ( rv >= 0 ) { methodtype = (ACLMethod_t *)PERM_MALLOC(sizeof(ACLMethod_t)); rv = ACL_MethodFind(errp, method, methodtype); if (rv) { nserrGenerate(errp, ACLERRUNDEF, ACLERR3800, ACL_Program, 3, acl->tag, "method", method); PERM_FREE(methodtype); return(ACLERRUNDEF); } rv = PListSetValue(expr->expr_auth, ACL_ATTR_METHOD_INDEX, methodtype, NULL); if ( rv < 0 ) { nserrGenerate(errp, ACLERRNOMEM, ACLERR3810, ACL_Program, 0); return(ACLERRNOMEM); } PERM_FREE(method); } rv = PListGetValue(expr->expr_auth, ACL_ATTR_DATABASE_INDEX, (void **) &database, NULL); if (rv < 0) continue; /* The following function lets user use databases which are * not registered by their administrators. This also fixes * the backward compatibility. */ dbtype = (ACLDbType_t *)PERM_MALLOC(sizeof(ACLDbType_t)); rv = ACL_RegisterDbFromACL(errp, (const char *) database, dbtype); if (rv < 0) { nserrGenerate(errp, ACLERRUNDEF, ACLERR3800, ACL_Program, 3, acl->tag, "database", database); PERM_FREE(dbtype); return(ACLERRUNDEF); } rv = PListInitProp(expr->expr_auth, ACL_ATTR_DBTYPE_INDEX, ACL_ATTR_DBTYPE, dbtype, NULL); if ( rv < 0 ) { nserrGenerate(errp, ACLERRNOMEM, ACLERR3810, ACL_Program, 0); return(ACLERRNOMEM); } } } return(0); }
/* 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; }
// // ACL_GetAttribute - find and call one or more matching attribute getter functions // NSAPI_PUBLIC int ACL_GetAttribute(NSErr_t *errp, const char *attr, void **val, PList_t subject, PList_t resource, PList_t auth_info, PList_t global_auth) { int rv; void *attrval; ACLAttrGetterFn_t func; ACLAttrGetterList_t getters; ACLAttrGetter_t *getter; ACLMethod_t method; char *dbname; ACLDbType_t dbtype; /* If subject PList is NULL, we will fail anyway */ if (!subject) return LAS_EVAL_FAIL; /* Is the attribute already present in the subject property list? */ rv = PListFindValue(subject, attr, &attrval, NULL); if (rv >= 0) { /* Yes, take it from there */ *val = attrval; return LAS_EVAL_TRUE; } /* Get the authentication method and database type */ // XXX umm... for ACLs that do not depend on user databases and authentication // methods (like cipher, dns, ip, tod!), we do not need method and database type. // so there's no reason to fail if we don't find anything here. // I think setting method to ACL_METHOD_ANY and dbtype to ACL_DBTYPE_ANY would // do the job in attr_getter_is_matching - this way, we would find only attr // getters that do not care about method and dbtype. if (ACL_AuthInfoGetMethod(errp, auth_info, &method) < 0) { nserrGenerate(errp, ACLERRFAIL, ACLERR4300, ACL_Program, 2, XP_GetAdminStr(DBT_GetAttributeCouldntDetermineMethod), attr); return LAS_EVAL_FAIL; } // dbtype is cached by our friendly ACLEvalAce caller (it's constant for the ACE) // XXX what if we don't get called by ACLEvalAce? if (PListGetValue(resource, ACL_ATTR_DBTYPE_INDEX, &dbtype, NULL) < 0) { dbtype = ACL_DBTYPE_INVALID; } /* Get the list of attribute getters */ if ((ACL_AttrGetterFind(errp, attr, &getters) < 0) || (getters == 0)) { nserrGenerate(errp, ACLERRFAIL, ACLERR4310, ACL_Program, 2, XP_GetAdminStr(DBT_GetAttributeCouldntLocateGetter), attr); return LAS_EVAL_DECLINE; } // Iterate over each getter and see if it should be called // Call each matching getter until a getter which doesn't decline is // found. char * method_name = NULL; char * dbtype_name = NULL; for (getter = ACL_AttrGetterFirst(&getters); getter != 0; getter = ACL_AttrGetterNext(&getters, getter)) { /* Require matching method and database type */ if (!attr_getter_is_matching(errp, getter, method, dbtype)) continue; if (ereport_can_log(LOG_VERBOSE)) { method_name = acl_get_name(ACLMethodHash, method); dbtype_name = acl_get_name(ACLDbTypeHash, dbtype); ereport(LOG_VERBOSE, "acl: calling getter for (attr=%s; " "method=%s, dbtype=%s)", attr, method_name, dbtype_name); } /* Call the getter function */ func = getter->fn; rv = (*func)(errp, subject, resource, auth_info, global_auth, getter->arg); if (method_name) { ereport(LOG_VERBOSE, "acl: getter for (attr=%s; " "method=%s, dbtype=%s) returns %d", attr, method_name, dbtype_name, rv); FREE(method_name); FREE(dbtype_name); } // if the getter declined, let's try to find another one if (rv == LAS_EVAL_DECLINE) continue; /* Did the getter succeed? */ if (rv == LAS_EVAL_TRUE) { /* * Yes, it should leave the attribute on the subject * property list. */ if (PListFindValue(subject, attr, (void **)&attrval, NULL) < 0) { nserrGenerate(errp, ACLERRFAIL, ACLERR4320, ACL_Program, 2, XP_GetAdminStr(DBT_GetAttributeDidntSetAttr), attr); return LAS_EVAL_FAIL; } /* Got it */ *val = attrval; return LAS_EVAL_TRUE; } else { /* No, did it fail to get the attribute */ if (rv == LAS_EVAL_FAIL || rv == LAS_EVAL_INVALID) { nserrGenerate(errp, ACLERRFAIL, ACLERR4330, ACL_Program, 2, XP_GetAdminStr(DBT_GetAttributeDidntGetAttr), attr); } return rv; } } // If we fall out of the loop, all the getters declined if (ereport_can_log(LOG_VERBOSE)) { method_name = acl_get_name(ACLMethodHash, method); dbtype_name = acl_get_name(ACLDbTypeHash, dbtype); ereport(LOG_VERBOSE, "acl: unable to obtain an attribute getter for " "[%s] with method [%s] (%d), dbtype [%s] (%d)", attr, method_name, method, dbtype_name, dbtype); FREE(method_name); FREE(dbtype_name); } nserrGenerate(errp, ACLERRFAIL, ACLERR4340, ACL_Program, 2, XP_GetAdminStr(DBT_GetAttributeAllGettersDeclined), attr); return LAS_EVAL_DECLINE; }