libubus-acl.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * Copyright (C) 2015 John Cripin <blogic@openwrt.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License version 2.1
  6. * as published by the Free Software Foundation
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <unistd.h>
  14. #include <libubox/blob.h>
  15. #include <libubox/blobmsg.h>
  16. #include "libubus.h"
  17. #include <libubox/avl-cmp.h>
  18. static struct ubus_event_handler acl_event;
  19. static struct ubus_request acl_req;
  20. static struct blob_attr *acl_blob;
  21. static int acl_cmp(const void *k1, const void *k2, void *ptr)
  22. {
  23. const struct ubus_acl_key *key1 = k1;
  24. const struct ubus_acl_key *key2 = k2;
  25. int ret = 0;
  26. if (key1->user && key2->user)
  27. ret = strcmp(key1->user, key2->user);
  28. if (ret)
  29. return ret;
  30. if (key1->group && key2->group)
  31. ret = strcmp(key1->group, key2->group);
  32. if (ret)
  33. return ret;
  34. return strcmp(key1->object, key2->object);
  35. }
  36. AVL_TREE(acl_objects, acl_cmp, true, NULL);
  37. enum {
  38. ACL_OBJ_OBJECT,
  39. ACL_OBJ_USER,
  40. ACL_OBJ_GROUP,
  41. ACL_OBJ_ACL,
  42. __ACL_OBJ_MAX
  43. };
  44. static const struct blobmsg_policy acl_obj_policy[__ACL_OBJ_MAX] = {
  45. [ACL_OBJ_OBJECT] = { .name = "obj", .type = BLOBMSG_TYPE_STRING },
  46. [ACL_OBJ_USER] = { .name = "user", .type = BLOBMSG_TYPE_STRING },
  47. [ACL_OBJ_GROUP] = { .name = "group", .type = BLOBMSG_TYPE_STRING },
  48. [ACL_OBJ_ACL] = { .name = "acl", .type = BLOBMSG_TYPE_TABLE },
  49. };
  50. static void
  51. acl_add(struct blob_attr *obj)
  52. {
  53. struct blob_attr *tb[__ACL_OBJ_MAX];
  54. struct acl_object *acl;
  55. blobmsg_parse(acl_obj_policy, __ACL_OBJ_MAX, tb, blobmsg_data(obj),
  56. blobmsg_data_len(obj));
  57. if (!tb[ACL_OBJ_OBJECT] || !tb[ACL_OBJ_ACL])
  58. return;
  59. if (!tb[ACL_OBJ_USER] && !tb[ACL_OBJ_GROUP])
  60. return;
  61. acl = calloc(1, sizeof(*acl));
  62. if (!acl)
  63. return;
  64. acl->avl.key = &acl->key;
  65. acl->key.object = blobmsg_get_string(tb[ACL_OBJ_OBJECT]);
  66. acl->key.user = blobmsg_get_string(tb[ACL_OBJ_USER]);
  67. acl->key.group = blobmsg_get_string(tb[ACL_OBJ_GROUP]);
  68. acl->acl = tb[ACL_OBJ_ACL];
  69. avl_insert(&acl_objects, &acl->avl);
  70. }
  71. enum {
  72. ACL_POLICY_SEQ,
  73. ACL_POLICY_ACL,
  74. __ACL_POLICY_MAX
  75. };
  76. static const struct blobmsg_policy acl_policy[__ACL_POLICY_MAX] = {
  77. [ACL_POLICY_SEQ] = { .name = "seq", .type = BLOBMSG_TYPE_INT32 },
  78. [ACL_POLICY_ACL] = { .name = "acl", .type = BLOBMSG_TYPE_ARRAY },
  79. };
  80. static void acl_recv_cb(struct ubus_request *req,
  81. int type, struct blob_attr *msg)
  82. {
  83. struct blob_attr *tb[__ACL_POLICY_MAX];
  84. struct blob_attr *cur;
  85. size_t rem;
  86. if (acl_blob) {
  87. struct acl_object *p, *q;
  88. avl_for_each_element_safe(&acl_objects, p, avl, q) {
  89. avl_delete(&acl_objects, &p->avl);
  90. free(p);
  91. }
  92. free(acl_blob);
  93. }
  94. acl_blob = blob_memdup(msg);
  95. blobmsg_parse(acl_policy, __ACL_POLICY_MAX, tb, blobmsg_data(msg),
  96. blobmsg_data_len(msg));
  97. if (!tb[ACL_POLICY_SEQ] && !tb[ACL_POLICY_ACL])
  98. return;
  99. blobmsg_for_each_attr(cur, tb[ACL_POLICY_ACL], rem)
  100. acl_add(cur);
  101. }
  102. static void acl_query(struct ubus_context *ctx)
  103. {
  104. ubus_invoke_async(ctx, UBUS_SYSTEM_OBJECT_ACL, "query", NULL, &acl_req);
  105. acl_req.data_cb = acl_recv_cb;
  106. ubus_complete_request_async(ctx, &acl_req);
  107. }
  108. static void acl_subscribe_cb(struct ubus_context *ctx, struct ubus_event_handler *ev,
  109. const char *type, struct blob_attr *msg)
  110. {
  111. if (strcmp(type, "ubus.acl.sequence"))
  112. return;
  113. acl_query(ctx);
  114. }
  115. int ubus_register_acl(struct ubus_context *ctx)
  116. {
  117. int ret;
  118. acl_event.cb = acl_subscribe_cb;
  119. ret = ubus_register_event_handler(ctx, &acl_event, "ubus.acl.sequence");
  120. if (!ret)
  121. acl_query(ctx);
  122. return ret;
  123. }