ubus.c 24 KB

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