List *permission_list_load(json_t *json) { if (!json_is_array(json) || json_array_size(json) == 0) { return NULL; } List *rslt = dslink_calloc(1, sizeof(List)); list_init(rslt); size_t idx; json_t *value; json_array_foreach(json, idx, value) { if (json_array_size(value) == 2) { json_t *v0 = json_array_get(value, 0); json_t *v1 = json_array_get(value, 1); if (json_is_string(v0) && json_is_string(v1)) { const char* vc0 = json_string_value(v0); const char* vc1 = json_string_value(v1); PermissionLevel p = permission_str_level(vc1); if (p <= PERMISSION_CONFIG) { PermissionPair * pair = dslink_malloc(sizeof(PermissionPair)); pair->group = dslink_strdup(vc0); pair->permission = p; dslink_list_insert(rslt, pair); } } } } return rslt; }
int broker_msg_handle_subscribe(RemoteDSLink *link, json_t *req) { broker_utils_send_closed_resp(link, req, NULL); json_t *paths = json_object_get(req, "paths"); if (!json_is_array(paths)) { return 1; } json_t *maxPermitJson = json_object_get(req, "permit"); PermissionLevel maxPermit = PERMISSION_CONFIG; if (json_is_string(maxPermitJson)) { maxPermit = permission_str_level(json_string_value(maxPermitJson)); } if (maxPermit < PERMISSION_READ) { return 0; } size_t index; json_t *obj; json_array_foreach(paths, index, obj) { handle_subscribe(link, obj); }
int broker_msg_handle_invoke(RemoteDSLink *link, json_t *req) { json_t *reqRid = json_object_get(req, "rid"); json_t *reqPath = json_object_get(req, "path"); if (!(reqRid && reqPath)) { return 1; } json_t *maxPermitJson = json_object_get(req, "permit"); PermissionLevel maxPermit = PERMISSION_CONFIG; if (json_is_string(maxPermitJson)) { maxPermit = permission_str_level(json_string_value(maxPermitJson)); } const char *path = json_string_value(reqPath); char *out = NULL; BrokerNode *node = broker_node_get(link->broker->root, path, &out); if (!node) { broker_utils_send_closed_resp(link, req, "disconnected"); return 0; } Broker *broker = mainLoop->data; PermissionLevel permissionOnPath = get_permission(path, broker->root, link); if (permissionOnPath > maxPermit) { permissionOnPath = maxPermit; } if (permissionOnPath == PERMISSION_NONE) { broker_utils_send_closed_resp(link, req, "permissionDenied"); return 0; } if (node->type == REGULAR_NODE) { json_t *invokableJson = json_object_get(node->meta, "$invokable"); PermissionLevel level = permission_str_level(json_string_value(invokableJson)); if (level > permissionOnPath) { broker_utils_send_closed_resp(link, req, "permissionDenied"); } else if (node->on_invoke) { node->on_invoke(link, node, req, maxPermit); } return 0; } else if (node->type != DOWNSTREAM_NODE) { // Unknown node type broker_utils_send_closed_resp(link, req, "disconnected"); return 0; } DownstreamNode *ds = (DownstreamNode *) node; uint32_t rid = broker_node_incr_rid(ds); if (!ds->link) { broker_utils_send_closed_resp(link, req, "disconnected"); return 0; } BrokerInvokeStream *s = broker_stream_invoke_init(); s->responder_rid = rid; s->responder = ds->link; s->resp_close_cb = remote_invoke_resp_disconnected; s->requester_rid = (uint32_t) json_integer_value(reqRid); s->requester = link; s->req_close_cb = remote_invoke_req_closed; ref_t *refStream = dslink_ref(s, NULL); dslink_map_set(&ds->link->responder_streams, dslink_int_ref(rid), refStream); ref_t *findref = dslink_map_remove_get(&link->requester_streams, &s->requester_rid); if (findref) { BrokerStream *oldstream = findref->data; if (oldstream->req_close_cb) { oldstream->req_close_cb(oldstream, link); } broker_stream_free(oldstream); dslink_decref(findref); } dslink_map_set(&link->requester_streams, dslink_int_ref(s->requester_rid), dslink_incref(refStream)); send_invoke_request(ds, req, rid, out, permissionOnPath); return 0; }