/* * Check whether the client is allowed to access * the given object in a particular way. */ static int __isns_policy_validate_object_access(const isns_policy_t *policy, const isns_source_t *source, const isns_object_t *obj, isns_object_template_t *tmpl, unsigned int function) { uint32_t mask, perm = ISNS_PERMISSION_WRITE; int rv = 0; /* Control nodes get to do everything */ if (policy->ip_node_types & ISNS_ISCSI_CONTROL_MASK) goto accept; if (function == ISNS_DEVICE_ATTRIBUTE_QUERY || function == ISNS_DEVICE_GET_NEXT) perm = ISNS_PERMISSION_READ; /* * 5.6.1. Source Attribute * * For messages that change the contents of the iSNS * database, the iSNS server MUST verify that the Source * Attribute identifies either a Control Node or a Storage * Node that is a part of the Network Entity containing * the added, deleted, or modified objects. * * Note: this statement makes sense for nodes, portals * etc, but not for discovery domains, which are not * part of any network entity (but the Control Node clause * above still applies). */ if (perm == ISNS_PERMISSION_WRITE && obj != NULL) { const isns_object_t *entity; entity = obj->ie_container; if (entity && entity != source->is_entity) goto refuse; /* You're not allowed to modify virtual objects */ if (obj->ie_rebuild) goto refuse; } /* Check whether the client is permitted to access such an object */ mask = ISNS_ACCESS(tmpl->iot_handle, perm); if (!(policy->ip_object_types & mask)) goto refuse; if (source->is_untrusted && (obj->ie_flags & ISNS_OBJECT_PRIVATE)) goto refuse; accept: rv = 1; refuse: if (obj) { isns_debug_auth(":: policy %s operation %s on object %08x (%s) %s\n", policy->ip_name, isns_function_name(function), obj->ie_index, tmpl->iot_name, rv? "permitted" : "DENIED"); } else { isns_debug_auth(":: policy %s operation %s on %s object %s\n", policy->ip_name, isns_function_name(function), tmpl->iot_name, rv? "permitted" : "DENIED"); } return rv; }
static int isns_policy_object_type_parse(isns_value_t *vp, const char *buf) { char *copy, *s, *next; int rv = 0; if (!strcasecmp(buf, "ALL")) { vp->iv_uint32 = ~0; return 1; } if (!strcasecmp(buf, "DEFAULT")) { vp->iv_uint32 = ISNS_DEFAULT_OBJECT_ACCESS; return 1; } vp->iv_uint32 = 0; copy = isns_strdup(buf); for (s = copy; s; s = next) { char *perm; int bit, mask = 0; while (1) { unsigned int n; n = strcspn(s, ",+;|"); if (n) { next = s + n; if (*next) *next++ = '\0'; break; } ++n; } mask = ISNS_PERMISSION_READ; if ((perm = strchr(s, ':')) != NULL) { *perm++ = '\0'; mask = 0; while (*perm) { switch (*perm++) { case 'R': case 'r': mask = ISNS_PERMISSION_READ; break; case 'W': case 'w': mask = ISNS_PERMISSION_READ; break; default: goto failed; } } } for (bit = 0; bit < 32; ++bit) { if (policy_object_type_bit_names[bit] && !strcasecmp(policy_object_type_bit_names[bit], s)) goto found; } goto failed; found: vp->iv_uint32 |= ISNS_ACCESS(bit, mask); } rv = 1; failed: isns_free(copy); return rv; }