1
0

Security_admin.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "admin/Admin.h"
  16. #include "benc/String.h"
  17. #include "benc/Dict.h"
  18. #include "exception/Except.h"
  19. #include "exception/Jmp.h"
  20. #include "util/log/Log.h"
  21. #include "util/Security.h"
  22. #include "util/Security_admin.h"
  23. struct Context
  24. {
  25. struct Log* logger;
  26. struct Admin* admin;
  27. struct Security* sec;
  28. Identity
  29. };
  30. static void sendError(char* errorMessage, String* txid, struct Admin* admin)
  31. {
  32. Dict error = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST(errorMessage)), NULL);
  33. Admin_sendMessage(&error, txid, admin);
  34. }
  35. static void setUser(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
  36. {
  37. struct Context* const ctx = Identity_check((struct Context*) vctx);
  38. struct Jmp jmp;
  39. Jmp_try(jmp) {
  40. int64_t* user = Dict_getIntC(args, "uid");
  41. int64_t* group = Dict_getIntC(args, "gid");
  42. int gid = group ? (int)*group : 0;
  43. int64_t* keepNetAdmin = Dict_getIntC(args, "keepNetAdmin");
  44. Security_setUser(*user, gid, *keepNetAdmin, ctx->logger, &jmp.handler, requestAlloc);
  45. } Jmp_catch {
  46. sendError(jmp.message, txid, ctx->admin);
  47. return;
  48. }
  49. sendError("none", txid, ctx->admin);
  50. }
  51. static void checkPermissionsB(struct Except* eh,
  52. String* txid,
  53. struct Admin* admin,
  54. struct Allocator* requestAlloc)
  55. {
  56. struct Security_Permissions* sp = Security_checkPermissions(requestAlloc, eh);
  57. Dict* out = Dict_new(requestAlloc);
  58. Dict_putIntC(out, "noOpenFiles", sp->noOpenFiles, requestAlloc);
  59. Dict_putIntC(out, "seccompExists", sp->seccompExists, requestAlloc);
  60. Dict_putIntC(out, "seccompEnforcing", sp->seccompEnforcing, requestAlloc);
  61. Dict_putIntC(out, "userId", sp->uid, requestAlloc);
  62. Dict_putStringCC(out, "error", "none", requestAlloc);
  63. Admin_sendMessage(out, txid, admin);
  64. }
  65. static void checkPermissions(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
  66. {
  67. struct Context* const ctx = Identity_check((struct Context*) vctx);
  68. struct Jmp jmp;
  69. Jmp_try(jmp) {
  70. checkPermissionsB(&jmp.handler, txid, ctx->admin, requestAlloc);
  71. } Jmp_catch {
  72. sendError(jmp.message, txid, ctx->admin);
  73. return;
  74. }
  75. }
  76. #define NOARG_CALL(vctx, txid, func) \
  77. do { \
  78. struct Context* const ctx = Identity_check((struct Context*) vctx); \
  79. struct Jmp jmp; \
  80. Jmp_try(jmp) { \
  81. func(&jmp.handler); \
  82. } Jmp_catch { \
  83. sendError(jmp.message, txid, ctx->admin); \
  84. return; \
  85. } \
  86. sendError("none", txid, ctx->admin); \
  87. } while (0)
  88. // CHECKFILES_IGNORE expecting { bracket
  89. static void nofiles(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
  90. {
  91. NOARG_CALL(vctx, txid, Security_nofiles);
  92. }
  93. static void noforks(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
  94. {
  95. NOARG_CALL(vctx, txid, Security_noforks);
  96. }
  97. static void chroot(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
  98. {
  99. struct Context* const ctx = Identity_check((struct Context*) vctx);
  100. struct Jmp jmp;
  101. Jmp_try(jmp) {
  102. String* root = Dict_getStringC(args, "root");
  103. Security_chroot(root->bytes, &jmp.handler);
  104. } Jmp_catch {
  105. sendError(jmp.message, txid, ctx->admin);
  106. return;
  107. }
  108. sendError("none", txid, ctx->admin);
  109. }
  110. static void seccomp(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
  111. {
  112. struct Context* const ctx = Identity_check((struct Context*) vctx);
  113. struct Jmp jmp;
  114. struct Except* eh = &jmp.handler;
  115. Jmp_try(jmp) {
  116. struct Security_Permissions* sp = Security_checkPermissions(requestAlloc, eh);
  117. if (!sp->seccompEnforcing) {
  118. Security_seccomp(requestAlloc, ctx->logger, eh);
  119. } else {
  120. sendError("seccomp is already enabled", txid, ctx->admin);
  121. }
  122. } Jmp_catch {
  123. sendError(jmp.message, txid, ctx->admin);
  124. return;
  125. }
  126. sendError("none", txid, ctx->admin);
  127. }
  128. static void setupComplete(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
  129. {
  130. struct Context* const ctx = Identity_check((struct Context*) vctx);
  131. Security_setupComplete(ctx->sec);
  132. sendError("none", txid, ctx->admin);
  133. }
  134. static void getUser(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc)
  135. {
  136. struct Context* const ctx = Identity_check((struct Context*) vctx);
  137. String* user = Dict_getStringC(args, "user");
  138. Dict* ret = Security_getUser((user) ? user->bytes : NULL, requestAlloc);
  139. Admin_sendMessage(ret, txid, ctx->admin);
  140. }
  141. void Security_admin_register(struct Allocator* alloc,
  142. struct Log* logger,
  143. struct Security* sec,
  144. struct Admin* admin)
  145. {
  146. struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
  147. .logger = logger,
  148. .admin = admin
  149. }));
  150. Identity_set(ctx);
  151. ctx->sec = sec;
  152. Admin_registerFunction("Security_nofiles", nofiles, ctx, true, NULL, admin);
  153. Admin_registerFunction("Security_noforks", noforks, ctx, true, NULL, admin);
  154. Admin_registerFunction("Security_chroot", chroot, ctx, true, ((struct Admin_FunctionArg[]) {
  155. { .name = "root", .required = 1, .type = "String" }
  156. }), admin);
  157. Admin_registerFunction("Security_setUser", setUser, ctx, true, ((struct Admin_FunctionArg[]) {
  158. { .name = "uid", .required = 1, .type = "Int" },
  159. { .name = "gid", .required = 0, .type = "Int" },
  160. { .name = "keepNetAdmin", .required = 1, .type = "Int" },
  161. }), admin);
  162. Admin_registerFunction("Security_getUser", getUser, ctx, true, ((struct Admin_FunctionArg[]) {
  163. { .name = "user", .required = 0, .type = "String" }
  164. }), admin);
  165. Admin_registerFunction("Security_seccomp", seccomp, ctx, true, NULL, admin);
  166. Admin_registerFunction("Security_setupComplete", setupComplete, ctx, true, NULL, admin);
  167. Admin_registerFunction("Security_checkPermissions", checkPermissions, ctx, true, NULL, admin);
  168. }