ubus.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. /*
  2. * uhttpd - Tiny single-threaded httpd
  3. *
  4. * Copyright (C) 2010-2013 Jo-Philipp Wich <xm@subsignal.org>
  5. * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
  6. *
  7. * Permission to use, copy, modify, and/or distribute this software for any
  8. * purpose with or without fee is hereby granted, provided that the above
  9. * copyright notice and this permission notice appear in all copies.
  10. *
  11. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  12. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  14. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  16. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  17. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. #include <libubox/blobmsg.h>
  20. #include <libubox/blobmsg_json.h>
  21. #include <libubox/avl.h>
  22. #include <libubox/avl-cmp.h>
  23. #include <stdio.h>
  24. #include <poll.h>
  25. #include "uhttpd.h"
  26. #include "plugin.h"
  27. static const struct uhttpd_ops *ops;
  28. static struct config *_conf;
  29. #define conf (*_conf)
  30. static struct ubus_context *ctx;
  31. static struct blob_buf buf;
  32. #define UH_UBUS_MAX_POST_SIZE 65536
  33. #define UH_UBUS_DEFAULT_SID "00000000000000000000000000000000"
  34. enum {
  35. RPC_JSONRPC,
  36. RPC_METHOD,
  37. RPC_PARAMS,
  38. RPC_ID,
  39. __RPC_MAX,
  40. };
  41. static const struct blobmsg_policy rpc_policy[__RPC_MAX] = {
  42. [RPC_JSONRPC] = { .name = "jsonrpc", .type = BLOBMSG_TYPE_STRING },
  43. [RPC_METHOD] = { .name = "method", .type = BLOBMSG_TYPE_STRING },
  44. [RPC_PARAMS] = { .name = "params", .type = BLOBMSG_TYPE_UNSPEC },
  45. [RPC_ID] = { .name = "id", .type = BLOBMSG_TYPE_UNSPEC },
  46. };
  47. enum {
  48. SES_ACCESS,
  49. __SES_MAX,
  50. };
  51. static const struct blobmsg_policy ses_policy[__SES_MAX] = {
  52. [SES_ACCESS] = { .name = "access", .type = BLOBMSG_TYPE_BOOL },
  53. };
  54. struct rpc_data {
  55. struct blob_attr *id;
  56. const char *sid;
  57. const char *method;
  58. const char *object;
  59. const char *function;
  60. struct blob_attr *data;
  61. struct blob_attr *params;
  62. };
  63. struct list_data {
  64. bool verbose;
  65. bool add_object;
  66. struct blob_buf *buf;
  67. };
  68. enum rpc_error {
  69. ERROR_PARSE,
  70. ERROR_REQUEST,
  71. ERROR_METHOD,
  72. ERROR_PARAMS,
  73. ERROR_INTERNAL,
  74. ERROR_OBJECT,
  75. ERROR_SESSION,
  76. ERROR_ACCESS,
  77. ERROR_TIMEOUT,
  78. __ERROR_MAX
  79. };
  80. static const struct {
  81. int code;
  82. const char *msg;
  83. } json_errors[__ERROR_MAX] = {
  84. [ERROR_PARSE] = { -32700, "Parse error" },
  85. [ERROR_REQUEST] = { -32600, "Invalid request" },
  86. [ERROR_METHOD] = { -32601, "Method not found" },
  87. [ERROR_PARAMS] = { -32602, "Invalid parameters" },
  88. [ERROR_INTERNAL] = { -32603, "Internal error" },
  89. [ERROR_OBJECT] = { -32000, "Object not found" },
  90. [ERROR_SESSION] = { -32001, "Session not found" },
  91. [ERROR_ACCESS] = { -32002, "Access denied" },
  92. [ERROR_TIMEOUT] = { -32003, "ubus request timed out" },
  93. };
  94. enum cors_hdr {
  95. HDR_ORIGIN,
  96. HDR_ACCESS_CONTROL_REQUEST_METHOD,
  97. HDR_ACCESS_CONTROL_REQUEST_HEADERS,
  98. __HDR_MAX
  99. };
  100. static void __uh_ubus_next_batched_request(struct uloop_timeout *timeout);
  101. static void uh_ubus_next_batched_request(struct client *cl)
  102. {
  103. struct dispatch_ubus *du = &cl->dispatch.ubus;
  104. du->timeout.cb = __uh_ubus_next_batched_request;
  105. uloop_timeout_set(&du->timeout, 1);
  106. }
  107. static void uh_ubus_add_cors_headers(struct client *cl)
  108. {
  109. struct blob_attr *tb[__HDR_MAX];
  110. static const struct blobmsg_policy hdr_policy[__HDR_MAX] = {
  111. [HDR_ORIGIN] = { "origin", BLOBMSG_TYPE_STRING },
  112. [HDR_ACCESS_CONTROL_REQUEST_METHOD] = { "access-control-request-method", BLOBMSG_TYPE_STRING },
  113. [HDR_ACCESS_CONTROL_REQUEST_HEADERS] = { "access-control-request-headers", BLOBMSG_TYPE_STRING },
  114. };
  115. blobmsg_parse(hdr_policy, __HDR_MAX, tb, blob_data(cl->hdr.head), blob_len(cl->hdr.head));
  116. if (!tb[HDR_ORIGIN])
  117. return;
  118. if (tb[HDR_ACCESS_CONTROL_REQUEST_METHOD])
  119. {
  120. char *hdr = (char *) blobmsg_data(tb[HDR_ACCESS_CONTROL_REQUEST_METHOD]);
  121. if (strcmp(hdr, "POST") && strcmp(hdr, "OPTIONS"))
  122. return;
  123. }
  124. ustream_printf(cl->us, "Access-Control-Allow-Origin: %s\r\n",
  125. blobmsg_get_string(tb[HDR_ORIGIN]));
  126. if (tb[HDR_ACCESS_CONTROL_REQUEST_HEADERS])
  127. ustream_printf(cl->us, "Access-Control-Allow-Headers: %s\r\n",
  128. blobmsg_get_string(tb[HDR_ACCESS_CONTROL_REQUEST_HEADERS]));
  129. ustream_printf(cl->us, "Access-Control-Allow-Methods: POST, OPTIONS\r\n");
  130. ustream_printf(cl->us, "Access-Control-Allow-Credentials: true\r\n");
  131. }
  132. static void uh_ubus_send_header(struct client *cl, int code, const char *summary, const char *content_type)
  133. {
  134. ops->http_header(cl, code, summary);
  135. if (conf.ubus_cors)
  136. uh_ubus_add_cors_headers(cl);
  137. ustream_printf(cl->us, "Content-Type: %s\r\n", content_type);
  138. if (cl->request.method == UH_HTTP_MSG_OPTIONS)
  139. ustream_printf(cl->us, "Content-Length: 0\r\n");
  140. ustream_printf(cl->us, "\r\n");
  141. }
  142. static void uh_ubus_send_response(struct client *cl, struct blob_buf *buf)
  143. {
  144. struct dispatch_ubus *du = &cl->dispatch.ubus;
  145. const char *sep = "";
  146. char *str;
  147. if (du->array && du->array_idx > 1)
  148. sep = ",";
  149. str = blobmsg_format_json(buf->head, true);
  150. ops->chunk_printf(cl, "%s%s", sep, str);
  151. free(str);
  152. du->jsobj_cur = NULL;
  153. if (du->array)
  154. uh_ubus_next_batched_request(cl);
  155. else
  156. return ops->request_done(cl);
  157. }
  158. static void uh_ubus_init_json_rpc_response(struct client *cl, struct blob_buf *buf)
  159. {
  160. struct dispatch_ubus *du = &cl->dispatch.ubus;
  161. struct json_object *obj = du->jsobj_cur, *obj2 = NULL;
  162. blobmsg_add_string(buf, "jsonrpc", "2.0");
  163. if (obj)
  164. json_object_object_get_ex(obj, "id", &obj2);
  165. if (obj2)
  166. blobmsg_add_json_element(buf, "id", obj2);
  167. else
  168. blobmsg_add_field(buf, BLOBMSG_TYPE_UNSPEC, "id", NULL, 0);
  169. }
  170. static void uh_ubus_json_rpc_error(struct client *cl, enum rpc_error type)
  171. {
  172. void *c;
  173. blob_buf_init(&buf, 0);
  174. uh_ubus_init_json_rpc_response(cl, &buf);
  175. c = blobmsg_open_table(&buf, "error");
  176. blobmsg_add_u32(&buf, "code", json_errors[type].code);
  177. blobmsg_add_string(&buf, "message", json_errors[type].msg);
  178. blobmsg_close_table(&buf, c);
  179. uh_ubus_send_response(cl, &buf);
  180. }
  181. static void uh_ubus_error(struct client *cl, int code, const char *message)
  182. {
  183. blob_buf_init(&buf, 0);
  184. blobmsg_add_u32(&buf, "code", code);
  185. blobmsg_add_string(&buf, "message", message);
  186. uh_ubus_send_response(cl, &buf);
  187. }
  188. static void uh_ubus_posix_error(struct client *cl, int err)
  189. {
  190. uh_ubus_error(cl, -err, strerror(err));
  191. }
  192. static void uh_ubus_ubus_error(struct client *cl, int err)
  193. {
  194. uh_ubus_error(cl, err, ubus_strerror(err));
  195. }
  196. /* GET requests handling */
  197. static void uh_ubus_list_cb(struct ubus_context *ctx, struct ubus_object_data *obj, void *priv);
  198. static void uh_ubus_handle_get_list(struct client *cl, const char *path)
  199. {
  200. static struct blob_buf tmp;
  201. struct list_data data = { .verbose = true, .add_object = !path, .buf = &tmp};
  202. struct blob_attr *cur;
  203. int rem;
  204. int err;
  205. blob_buf_init(&tmp, 0);
  206. err = ubus_lookup(ctx, path, uh_ubus_list_cb, &data);
  207. if (err) {
  208. uh_ubus_send_header(cl, 500, "Ubus Protocol Error", "application/json");
  209. uh_ubus_ubus_error(cl, err);
  210. return;
  211. }
  212. blob_buf_init(&buf, 0);
  213. blob_for_each_attr(cur, tmp.head, rem)
  214. blobmsg_add_blob(&buf, cur);
  215. uh_ubus_send_header(cl, 200, "OK", "application/json");
  216. uh_ubus_send_response(cl, &buf);
  217. }
  218. static int uh_ubus_subscription_notification_cb(struct ubus_context *ctx,
  219. struct ubus_object *obj,
  220. struct ubus_request_data *req,
  221. const char *method,
  222. struct blob_attr *msg)
  223. {
  224. struct ubus_subscriber *s;
  225. struct dispatch_ubus *du;
  226. struct client *cl;
  227. char *json;
  228. s = container_of(obj, struct ubus_subscriber, obj);
  229. du = container_of(s, struct dispatch_ubus, sub);
  230. cl = container_of(du, struct client, dispatch.ubus);
  231. json = blobmsg_format_json(msg, true);
  232. if (json) {
  233. ops->chunk_printf(cl, "event: %s\ndata: %s\n\n", method, json);
  234. free(json);
  235. }
  236. return 0;
  237. }
  238. static void uh_ubus_subscription_notification_remove_cb(struct ubus_context *ctx, struct ubus_subscriber *s, uint32_t id)
  239. {
  240. struct dispatch_ubus *du;
  241. struct client *cl;
  242. du = container_of(s, struct dispatch_ubus, sub);
  243. cl = container_of(du, struct client, dispatch.ubus);
  244. ops->request_done(cl);
  245. }
  246. static void uh_ubus_handle_get_subscribe(struct client *cl, const char *sid, const char *path)
  247. {
  248. struct dispatch_ubus *du = &cl->dispatch.ubus;
  249. uint32_t id;
  250. int err;
  251. /* TODO: add ACL support */
  252. if (!conf.ubus_noauth) {
  253. uh_ubus_send_header(cl, 200, "OK", "application/json");
  254. uh_ubus_posix_error(cl, EACCES);
  255. return;
  256. }
  257. du->sub.cb = uh_ubus_subscription_notification_cb;
  258. du->sub.remove_cb = uh_ubus_subscription_notification_remove_cb;
  259. uh_client_ref(cl);
  260. err = ubus_register_subscriber(ctx, &du->sub);
  261. if (err)
  262. goto err_unref;
  263. err = ubus_lookup_id(ctx, path, &id);
  264. if (err)
  265. goto err_unregister;
  266. err = ubus_subscribe(ctx, &du->sub, id);
  267. if (err)
  268. goto err_unregister;
  269. uh_ubus_send_header(cl, 200, "OK", "text/event-stream");
  270. if (conf.events_retry)
  271. ops->chunk_printf(cl, "retry: %d\n", conf.events_retry);
  272. return;
  273. err_unregister:
  274. ubus_unregister_subscriber(ctx, &du->sub);
  275. err_unref:
  276. uh_client_unref(cl);
  277. if (err) {
  278. uh_ubus_send_header(cl, 200, "OK", "application/json");
  279. uh_ubus_ubus_error(cl, err);
  280. }
  281. }
  282. static void uh_ubus_handle_get(struct client *cl)
  283. {
  284. struct dispatch_ubus *du = &cl->dispatch.ubus;
  285. const char *url = du->url_path;
  286. url += strlen(conf.ubus_prefix);
  287. if (!strcmp(url, "/list") || !strncmp(url, "/list/", strlen("/list/"))) {
  288. url += strlen("/list");
  289. uh_ubus_handle_get_list(cl, *url ? url + 1 : NULL);
  290. } else if (!strncmp(url, "/subscribe/", strlen("/subscribe/"))) {
  291. url += strlen("/subscribe");
  292. uh_ubus_handle_get_subscribe(cl, NULL, url + 1);
  293. } else {
  294. ops->http_header(cl, 404, "Not Found");
  295. ustream_printf(cl->us, "\r\n");
  296. ops->request_done(cl);
  297. }
  298. }
  299. /* POST requests handling */
  300. static void
  301. uh_ubus_request_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
  302. {
  303. struct dispatch_ubus *du = container_of(req, struct dispatch_ubus, req);
  304. struct blob_attr *cur;
  305. int len;
  306. blob_for_each_attr(cur, msg, len)
  307. blobmsg_add_blob(&du->buf, cur);
  308. }
  309. static void
  310. uh_ubus_request_cb(struct ubus_request *req, int ret)
  311. {
  312. struct dispatch_ubus *du = container_of(req, struct dispatch_ubus, req);
  313. struct client *cl = container_of(du, struct client, dispatch.ubus);
  314. struct blob_attr *cur;
  315. void *r;
  316. int rem;
  317. blob_buf_init(&buf, 0);
  318. uloop_timeout_cancel(&du->timeout);
  319. /* Legacy format always uses "result" array - even for errors and empty
  320. * results. */
  321. if (du->legacy) {
  322. void *c;
  323. uh_ubus_init_json_rpc_response(cl, &buf);
  324. r = blobmsg_open_array(&buf, "result");
  325. blobmsg_add_u32(&buf, "", ret);
  326. c = blobmsg_open_table(&buf, NULL);
  327. blob_for_each_attr(cur, du->buf.head, rem)
  328. blobmsg_add_blob(&buf, cur);
  329. blobmsg_close_table(&buf, c);
  330. blobmsg_close_array(&buf, r);
  331. uh_ubus_send_response(cl, &buf);
  332. return;
  333. }
  334. if (ret) {
  335. void *c;
  336. uh_ubus_init_json_rpc_response(cl, &buf);
  337. c = blobmsg_open_table(&buf, "error");
  338. blobmsg_add_u32(&buf, "code", ret);
  339. blobmsg_add_string(&buf, "message", ubus_strerror(ret));
  340. blobmsg_close_table(&buf, c);
  341. uh_ubus_send_response(cl, &buf);
  342. } else {
  343. uh_ubus_init_json_rpc_response(cl, &buf);
  344. if (blob_len(du->buf.head)) {
  345. r = blobmsg_open_table(&buf, "result");
  346. blob_for_each_attr(cur, du->buf.head, rem)
  347. blobmsg_add_blob(&buf, cur);
  348. blobmsg_close_table(&buf, r);
  349. } else {
  350. blobmsg_add_field(&buf, BLOBMSG_TYPE_UNSPEC, "result", NULL, 0);
  351. }
  352. uh_ubus_send_response(cl, &buf);
  353. }
  354. }
  355. static void
  356. uh_ubus_timeout_cb(struct uloop_timeout *timeout)
  357. {
  358. struct dispatch_ubus *du = container_of(timeout, struct dispatch_ubus, timeout);
  359. struct client *cl = container_of(du, struct client, dispatch.ubus);
  360. ubus_abort_request(ctx, &du->req);
  361. uh_ubus_json_rpc_error(cl, ERROR_TIMEOUT);
  362. }
  363. static void uh_ubus_close_fds(struct client *cl)
  364. {
  365. if (ctx->sock.fd < 0)
  366. return;
  367. close(ctx->sock.fd);
  368. ctx->sock.fd = -1;
  369. }
  370. static void uh_ubus_request_free(struct client *cl)
  371. {
  372. struct dispatch_ubus *du = &cl->dispatch.ubus;
  373. blob_buf_free(&du->buf);
  374. uloop_timeout_cancel(&du->timeout);
  375. if (du->jsobj)
  376. json_object_put(du->jsobj);
  377. if (du->jstok)
  378. json_tokener_free(du->jstok);
  379. if (du->req_pending)
  380. ubus_abort_request(ctx, &du->req);
  381. free(du->url_path);
  382. du->url_path = NULL;
  383. }
  384. static void uh_ubus_single_error(struct client *cl, enum rpc_error type)
  385. {
  386. uh_ubus_send_header(cl, 200, "OK", "application/json");
  387. uh_ubus_json_rpc_error(cl, type);
  388. ops->request_done(cl);
  389. }
  390. static void uh_ubus_send_request(struct client *cl, const char *sid, struct blob_attr *args)
  391. {
  392. struct dispatch *d = &cl->dispatch;
  393. struct dispatch_ubus *du = &d->ubus;
  394. struct blob_attr *cur;
  395. static struct blob_buf req;
  396. int ret, rem;
  397. blob_buf_init(&req, 0);
  398. blobmsg_for_each_attr(cur, args, rem) {
  399. if (!strcmp(blobmsg_name(cur), "ubus_rpc_session"))
  400. return uh_ubus_json_rpc_error(cl, ERROR_PARAMS);
  401. blobmsg_add_blob(&req, cur);
  402. }
  403. blobmsg_add_string(&req, "ubus_rpc_session", sid);
  404. blob_buf_init(&du->buf, 0);
  405. memset(&du->req, 0, sizeof(du->req));
  406. ret = ubus_invoke_async(ctx, du->obj, du->func, req.head, &du->req);
  407. if (ret)
  408. return uh_ubus_json_rpc_error(cl, ERROR_INTERNAL);
  409. du->req.data_cb = uh_ubus_request_data_cb;
  410. du->req.complete_cb = uh_ubus_request_cb;
  411. ubus_complete_request_async(ctx, &du->req);
  412. du->timeout.cb = uh_ubus_timeout_cb;
  413. uloop_timeout_set(&du->timeout, conf.script_timeout * 1000);
  414. du->req_pending = true;
  415. }
  416. static void uh_ubus_list_cb(struct ubus_context *ctx, struct ubus_object_data *obj, void *priv)
  417. {
  418. struct blob_attr *sig, *attr;
  419. struct list_data *data = priv;
  420. int rem, rem2;
  421. void *t, *o;
  422. if (!data->verbose) {
  423. blobmsg_add_string(data->buf, NULL, obj->path);
  424. return;
  425. }
  426. if (!obj->signature)
  427. return;
  428. if (data->add_object)
  429. o = blobmsg_open_table(data->buf, obj->path);
  430. blob_for_each_attr(sig, obj->signature, rem) {
  431. t = blobmsg_open_table(data->buf, blobmsg_name(sig));
  432. rem2 = blobmsg_data_len(sig);
  433. __blob_for_each_attr(attr, blobmsg_data(sig), rem2) {
  434. if (blob_id(attr) != BLOBMSG_TYPE_INT32)
  435. continue;
  436. switch (blobmsg_get_u32(attr)) {
  437. case BLOBMSG_TYPE_INT8:
  438. blobmsg_add_string(data->buf, blobmsg_name(attr), "boolean");
  439. break;
  440. case BLOBMSG_TYPE_INT32:
  441. blobmsg_add_string(data->buf, blobmsg_name(attr), "number");
  442. break;
  443. case BLOBMSG_TYPE_STRING:
  444. blobmsg_add_string(data->buf, blobmsg_name(attr), "string");
  445. break;
  446. case BLOBMSG_TYPE_ARRAY:
  447. blobmsg_add_string(data->buf, blobmsg_name(attr), "array");
  448. break;
  449. case BLOBMSG_TYPE_TABLE:
  450. blobmsg_add_string(data->buf, blobmsg_name(attr), "object");
  451. break;
  452. default:
  453. blobmsg_add_string(data->buf, blobmsg_name(attr), "unknown");
  454. break;
  455. }
  456. }
  457. blobmsg_close_table(data->buf, t);
  458. }
  459. if (data->add_object)
  460. blobmsg_close_table(data->buf, o);
  461. }
  462. static void uh_ubus_send_list(struct client *cl, struct blob_attr *params)
  463. {
  464. struct blob_attr *cur, *dup;
  465. struct list_data data = { .buf = &cl->dispatch.ubus.buf, .verbose = false, .add_object = true };
  466. void *r;
  467. int rem;
  468. blob_buf_init(data.buf, 0);
  469. uh_client_ref(cl);
  470. if (!params || blob_id(params) != BLOBMSG_TYPE_ARRAY) {
  471. r = blobmsg_open_array(data.buf, "result");
  472. ubus_lookup(ctx, NULL, uh_ubus_list_cb, &data);
  473. blobmsg_close_array(data.buf, r);
  474. }
  475. else {
  476. r = blobmsg_open_table(data.buf, "result");
  477. dup = blob_memdup(params);
  478. if (dup)
  479. {
  480. rem = blobmsg_data_len(dup);
  481. data.verbose = true;
  482. __blob_for_each_attr(cur, blobmsg_data(dup), rem)
  483. ubus_lookup(ctx, blobmsg_data(cur), uh_ubus_list_cb, &data);
  484. free(dup);
  485. }
  486. blobmsg_close_table(data.buf, r);
  487. }
  488. uh_client_unref(cl);
  489. blob_buf_init(&buf, 0);
  490. uh_ubus_init_json_rpc_response(cl, &buf);
  491. blobmsg_add_blob(&buf, blob_data(data.buf->head));
  492. uh_ubus_send_response(cl, &buf);
  493. }
  494. static bool parse_json_rpc(struct rpc_data *d, struct blob_attr *data)
  495. {
  496. struct blob_attr *tb[__RPC_MAX];
  497. struct blob_attr *cur;
  498. blobmsg_parse(rpc_policy, __RPC_MAX, tb, blob_data(data), blob_len(data));
  499. cur = tb[RPC_JSONRPC];
  500. if (!cur || strcmp(blobmsg_data(cur), "2.0") != 0)
  501. return false;
  502. cur = tb[RPC_METHOD];
  503. if (!cur)
  504. return false;
  505. d->id = tb[RPC_ID];
  506. d->method = blobmsg_data(cur);
  507. cur = tb[RPC_PARAMS];
  508. if (!cur)
  509. return true;
  510. d->params = blob_memdup(cur);
  511. if (!d->params)
  512. return false;
  513. return true;
  514. }
  515. static void parse_call_params(struct rpc_data *d)
  516. {
  517. const struct blobmsg_policy data_policy[] = {
  518. { .type = BLOBMSG_TYPE_STRING },
  519. { .type = BLOBMSG_TYPE_STRING },
  520. { .type = BLOBMSG_TYPE_STRING },
  521. { .type = BLOBMSG_TYPE_TABLE },
  522. };
  523. struct blob_attr *tb[4];
  524. if (!d->params || blobmsg_type(d->params) != BLOBMSG_TYPE_ARRAY)
  525. return;
  526. blobmsg_parse_array(data_policy, ARRAY_SIZE(data_policy), tb,
  527. blobmsg_data(d->params), blobmsg_data_len(d->params));
  528. if (tb[0])
  529. d->sid = blobmsg_data(tb[0]);
  530. if (conf.ubus_noauth && (!d->sid || !*d->sid))
  531. d->sid = UH_UBUS_DEFAULT_SID;
  532. if (tb[1])
  533. d->object = blobmsg_data(tb[1]);
  534. if (tb[2])
  535. d->function = blobmsg_data(tb[2]);
  536. d->data = tb[3];
  537. }
  538. static void uh_ubus_init_batch(struct client *cl)
  539. {
  540. struct dispatch_ubus *du = &cl->dispatch.ubus;
  541. du->array = true;
  542. uh_ubus_send_header(cl, 200, "OK", "application/json");
  543. ops->chunk_printf(cl, "[");
  544. }
  545. static void uh_ubus_complete_batch(struct client *cl)
  546. {
  547. ops->chunk_printf(cl, "]");
  548. ops->request_done(cl);
  549. }
  550. static void uh_ubus_allowed_cb(struct ubus_request *req, int type, struct blob_attr *msg)
  551. {
  552. struct blob_attr *tb[__SES_MAX];
  553. bool *allow = (bool *)req->priv;
  554. if (!msg)
  555. return;
  556. blobmsg_parse(ses_policy, __SES_MAX, tb, blob_data(msg), blob_len(msg));
  557. if (tb[SES_ACCESS])
  558. *allow = blobmsg_get_bool(tb[SES_ACCESS]);
  559. }
  560. static bool uh_ubus_allowed(const char *sid, const char *obj, const char *fun)
  561. {
  562. uint32_t id;
  563. bool allow = false;
  564. static struct blob_buf req;
  565. if (ubus_lookup_id(ctx, "session", &id))
  566. return false;
  567. blob_buf_init(&req, 0);
  568. blobmsg_add_string(&req, "ubus_rpc_session", sid);
  569. blobmsg_add_string(&req, "object", obj);
  570. blobmsg_add_string(&req, "function", fun);
  571. ubus_invoke(ctx, id, "access", req.head, uh_ubus_allowed_cb, &allow, conf.script_timeout * 500);
  572. return allow;
  573. }
  574. static void uh_ubus_handle_request_object(struct client *cl, struct json_object *obj)
  575. {
  576. struct dispatch_ubus *du = &cl->dispatch.ubus;
  577. struct rpc_data data = {};
  578. enum rpc_error err = ERROR_PARSE;
  579. static struct blob_buf req;
  580. uh_client_ref(cl);
  581. if (json_object_get_type(obj) != json_type_object)
  582. goto error;
  583. du->jsobj_cur = obj;
  584. blob_buf_init(&req, 0);
  585. if (!blobmsg_add_object(&req, obj))
  586. goto error;
  587. if (!parse_json_rpc(&data, req.head))
  588. goto error;
  589. if (!strcmp(data.method, "call")) {
  590. parse_call_params(&data);
  591. if (!data.sid || !data.object || !data.function || !data.data)
  592. goto error;
  593. du->func = data.function;
  594. if (ubus_lookup_id(ctx, data.object, &du->obj)) {
  595. err = ERROR_OBJECT;
  596. goto error;
  597. }
  598. if (!conf.ubus_noauth && !uh_ubus_allowed(data.sid, data.object, data.function)) {
  599. err = ERROR_ACCESS;
  600. goto error;
  601. }
  602. uh_ubus_send_request(cl, data.sid, data.data);
  603. goto out;
  604. }
  605. else if (!strcmp(data.method, "list")) {
  606. uh_ubus_send_list(cl, data.params);
  607. goto out;
  608. }
  609. else {
  610. err = ERROR_METHOD;
  611. goto error;
  612. }
  613. error:
  614. uh_ubus_json_rpc_error(cl, err);
  615. out:
  616. if (data.params)
  617. free(data.params);
  618. uh_client_unref(cl);
  619. }
  620. static void __uh_ubus_next_batched_request(struct uloop_timeout *timeout)
  621. {
  622. struct dispatch_ubus *du = container_of(timeout, struct dispatch_ubus, timeout);
  623. struct client *cl = container_of(du, struct client, dispatch.ubus);
  624. struct json_object *obj = du->jsobj;
  625. int len;
  626. len = json_object_array_length(obj);
  627. if (du->array_idx >= len)
  628. return uh_ubus_complete_batch(cl);
  629. obj = json_object_array_get_idx(obj, du->array_idx++);
  630. uh_ubus_handle_request_object(cl, obj);
  631. }
  632. static void uh_ubus_data_done(struct client *cl)
  633. {
  634. struct dispatch_ubus *du = &cl->dispatch.ubus;
  635. struct json_object *obj = du->jsobj;
  636. switch (obj ? json_object_get_type(obj) : json_type_null) {
  637. case json_type_object:
  638. uh_ubus_send_header(cl, 200, "OK", "application/json");
  639. return uh_ubus_handle_request_object(cl, obj);
  640. case json_type_array:
  641. uh_ubus_init_batch(cl);
  642. return uh_ubus_next_batched_request(cl);
  643. default:
  644. return uh_ubus_single_error(cl, ERROR_PARSE);
  645. }
  646. }
  647. static void uh_ubus_call(struct client *cl, const char *path, const char *sid)
  648. {
  649. struct dispatch_ubus *du = &cl->dispatch.ubus;
  650. struct json_object *obj = du->jsobj;
  651. struct rpc_data data = {};
  652. enum rpc_error err = ERROR_PARSE;
  653. static struct blob_buf req;
  654. uh_client_ref(cl);
  655. if (!obj || json_object_get_type(obj) != json_type_object)
  656. goto error;
  657. uh_ubus_send_header(cl, 200, "OK", "application/json");
  658. du->jsobj_cur = obj;
  659. blob_buf_init(&req, 0);
  660. if (!blobmsg_add_object(&req, obj))
  661. goto error;
  662. if (!parse_json_rpc(&data, req.head))
  663. goto error;
  664. du->func = data.method;
  665. if (ubus_lookup_id(ctx, path, &du->obj)) {
  666. err = ERROR_OBJECT;
  667. goto error;
  668. }
  669. if (!conf.ubus_noauth && !uh_ubus_allowed(sid, path, data.method)) {
  670. err = ERROR_ACCESS;
  671. goto error;
  672. }
  673. uh_ubus_send_request(cl, sid, data.params);
  674. goto out;
  675. error:
  676. uh_ubus_json_rpc_error(cl, err);
  677. out:
  678. if (data.params)
  679. free(data.params);
  680. uh_client_unref(cl);
  681. }
  682. enum ubus_hdr {
  683. HDR_AUTHORIZATION,
  684. __HDR_UBUS_MAX
  685. };
  686. static void uh_ubus_handle_post(struct client *cl)
  687. {
  688. static const struct blobmsg_policy hdr_policy[__HDR_UBUS_MAX] = {
  689. [HDR_AUTHORIZATION] = { "authorization", BLOBMSG_TYPE_STRING },
  690. };
  691. struct dispatch_ubus *du = &cl->dispatch.ubus;
  692. struct blob_attr *tb[__HDR_UBUS_MAX];
  693. const char *url = du->url_path;
  694. const char *auth;
  695. /* Treat both: /foo AND /foo/ as legacy requests. */
  696. if (ops->path_match(conf.ubus_prefix, url) && strlen(url) - strlen(conf.ubus_prefix) <= 1) {
  697. du->legacy = true;
  698. uh_ubus_data_done(cl);
  699. return;
  700. }
  701. blobmsg_parse(hdr_policy, __HDR_UBUS_MAX, tb, blob_data(cl->hdr.head), blob_len(cl->hdr.head));
  702. auth = UH_UBUS_DEFAULT_SID;
  703. if (tb[HDR_AUTHORIZATION]) {
  704. const char *tmp = blobmsg_get_string(tb[HDR_AUTHORIZATION]);
  705. if (!strncasecmp(tmp, "Bearer ", 7))
  706. auth = tmp + 7;
  707. }
  708. url += strlen(conf.ubus_prefix);
  709. if (!strncmp(url, "/call/", strlen("/call/"))) {
  710. url += strlen("/call/");
  711. uh_ubus_call(cl, url, auth);
  712. } else {
  713. ops->http_header(cl, 404, "Not Found");
  714. ustream_printf(cl->us, "\r\n");
  715. ops->request_done(cl);
  716. }
  717. }
  718. static int uh_ubus_data_send(struct client *cl, const char *data, int len)
  719. {
  720. struct dispatch_ubus *du = &cl->dispatch.ubus;
  721. if (du->jsobj || !du->jstok)
  722. goto error;
  723. du->post_len += len;
  724. if (du->post_len > UH_UBUS_MAX_POST_SIZE)
  725. goto error;
  726. du->jsobj = json_tokener_parse_ex(du->jstok, data, len);
  727. return len;
  728. error:
  729. uh_ubus_single_error(cl, ERROR_PARSE);
  730. return 0;
  731. }
  732. static void uh_ubus_handle_request(struct client *cl, char *url, struct path_info *pi)
  733. {
  734. struct dispatch *d = &cl->dispatch;
  735. struct dispatch_ubus *du = &d->ubus;
  736. char *chr;
  737. du->url_path = strdup(url);
  738. if (!du->url_path) {
  739. ops->client_error(cl, 500, "Internal Server Error", "Failed to allocate resources");
  740. return;
  741. }
  742. chr = strchr(du->url_path, '?');
  743. if (chr)
  744. chr[0] = '\0';
  745. du->legacy = false;
  746. switch (cl->request.method)
  747. {
  748. case UH_HTTP_MSG_GET:
  749. uh_ubus_handle_get(cl);
  750. break;
  751. case UH_HTTP_MSG_POST:
  752. d->data_send = uh_ubus_data_send;
  753. d->data_done = uh_ubus_handle_post;
  754. d->close_fds = uh_ubus_close_fds;
  755. d->free = uh_ubus_request_free;
  756. du->jstok = json_tokener_new();
  757. return;
  758. case UH_HTTP_MSG_OPTIONS:
  759. uh_ubus_send_header(cl, 200, "OK", "application/json");
  760. ops->request_done(cl);
  761. break;
  762. default:
  763. ops->client_error(cl, 400, "Bad Request", "Invalid Request");
  764. }
  765. free(du->url_path);
  766. du->url_path = NULL;
  767. }
  768. static bool
  769. uh_ubus_check_url(const char *url)
  770. {
  771. return ops->path_match(conf.ubus_prefix, url);
  772. }
  773. static int
  774. uh_ubus_init(void)
  775. {
  776. static struct dispatch_handler ubus_dispatch = {
  777. .check_url = uh_ubus_check_url,
  778. .handle_request = uh_ubus_handle_request,
  779. };
  780. ctx = ubus_connect(conf.ubus_socket);
  781. if (!ctx) {
  782. fprintf(stderr, "Unable to connect to ubus socket\n");
  783. exit(1);
  784. }
  785. ops->dispatch_add(&ubus_dispatch);
  786. uloop_done();
  787. return 0;
  788. }
  789. static int uh_ubus_plugin_init(const struct uhttpd_ops *o, struct config *c)
  790. {
  791. ops = o;
  792. _conf = c;
  793. return uh_ubus_init();
  794. }
  795. static void uh_ubus_post_init(void)
  796. {
  797. ubus_add_uloop(ctx);
  798. }
  799. struct uhttpd_plugin uhttpd_plugin = {
  800. .init = uh_ubus_plugin_init,
  801. .post_init = uh_ubus_post_init,
  802. };