ktpd_session.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <assert.h>
  5. #include <unistd.h>
  6. #include <errno.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10. #include <sys/socket.h>
  11. #include <sys/un.h>
  12. #include <syslog.h>
  13. #include <faux/str.h>
  14. #include <faux/async.h>
  15. #include <faux/msg.h>
  16. #include <klish/ksession.h>
  17. #include <klish/ktp.h>
  18. #include <klish/ktp_session.h>
  19. #include "private.h"
  20. static bool_t check_ktp_header(faux_hdr_t *hdr)
  21. {
  22. assert(hdr);
  23. if (!hdr)
  24. return BOOL_FALSE;
  25. if (faux_hdr_magic(hdr) != KTP_MAGIC)
  26. return BOOL_FALSE;
  27. if (faux_hdr_major(hdr) != KTP_MAJOR)
  28. return BOOL_FALSE;
  29. if (faux_hdr_minor(hdr) != KTP_MINOR)
  30. return BOOL_FALSE;
  31. if (faux_hdr_len(hdr) < (int)sizeof(*hdr))
  32. return BOOL_FALSE;
  33. return BOOL_TRUE;
  34. }
  35. static bool_t ktpd_session_send_error(ktpd_session_t *session,
  36. ktp_cmd_e cmd, const char *error)
  37. {
  38. faux_msg_t *msg = NULL;
  39. assert(session);
  40. if (!session)
  41. return BOOL_FALSE;
  42. msg = ktp_msg_preform(cmd, KTP_STATUS_ERROR);
  43. if (error)
  44. faux_msg_add_param(msg, KTP_PARAM_ERROR, error, strlen(error));
  45. faux_msg_send_async(msg, session->async);
  46. faux_msg_free(msg);
  47. return BOOL_TRUE;
  48. }
  49. static bool_t ktpd_session_process_cmd(ktpd_session_t *session, faux_msg_t *msg)
  50. {
  51. char *line = NULL;
  52. faux_msg_t *ack = NULL;
  53. // kpargv_t *pargv = NULL;
  54. ktp_cmd_e cmd = KTP_CMD_ACK;
  55. faux_list_t *split = NULL;
  56. assert(session);
  57. assert(msg);
  58. // Get line from message
  59. if (!(line = faux_msg_get_str_param_by_type(msg, KTP_PARAM_LINE))) {
  60. ktpd_session_send_error(session, cmd,
  61. "The line is not specified");
  62. return BOOL_FALSE;
  63. }
  64. split = ksession_split_pipes(line);
  65. printf("split %ld\n", split ? (ssize_t)faux_list_len(split) : -1);
  66. faux_list_free(split);
  67. /* // Parsing
  68. pargv = ksession_parse_line(session->ksession, line, KPURPOSE_EXEC);
  69. faux_str_free(line);
  70. kpargv_debug(pargv);
  71. if (kpargv_status(pargv) != KPARSE_OK) {
  72. char *error = NULL;
  73. error = faux_str_sprintf("Can't parse line: %s",
  74. kpargv_status_str(pargv));
  75. kpargv_free(pargv);
  76. ktpd_session_send_error(session, cmd, error);
  77. return BOOL_FALSE;
  78. }
  79. kpargv_free(pargv);
  80. */
  81. // Send ACK message
  82. ack = ktp_msg_preform(cmd, KTP_STATUS_NONE);
  83. faux_msg_send_async(ack, session->async);
  84. faux_msg_free(ack);
  85. return BOOL_TRUE;
  86. }
  87. static bool_t ktpd_session_process_completion(ktpd_session_t *session, faux_msg_t *msg)
  88. {
  89. char *line = NULL;
  90. faux_msg_t *ack = NULL;
  91. kpargv_t *pargv = NULL;
  92. ktp_cmd_e cmd = KTP_COMPLETION_ACK;
  93. assert(session);
  94. assert(msg);
  95. // Get line from message
  96. if (!(line = faux_msg_get_str_param_by_type(msg, KTP_PARAM_LINE))) {
  97. ktpd_session_send_error(session, cmd, NULL);
  98. return BOOL_FALSE;
  99. }
  100. // Parsing
  101. pargv = ksession_parse_for_completion(session->ksession, line);
  102. faux_str_free(line);
  103. if (!pargv) {
  104. ktpd_session_send_error(session, cmd, NULL);
  105. return BOOL_FALSE;
  106. }
  107. kpargv_debug(pargv);
  108. kpargv_free(pargv);
  109. // Send ACK message
  110. ack = ktp_msg_preform(cmd, KTP_STATUS_NONE);
  111. faux_msg_send_async(ack, session->async);
  112. faux_msg_free(ack);
  113. return BOOL_TRUE;
  114. }
  115. static bool_t ktpd_session_process_help(ktpd_session_t *session, faux_msg_t *msg)
  116. {
  117. char *line = NULL;
  118. faux_msg_t *ack = NULL;
  119. // kpargv_t *pargv = NULL;
  120. ktp_cmd_e cmd = KTP_HELP_ACK;
  121. assert(session);
  122. assert(msg);
  123. // Get line from message
  124. if (!(line = faux_msg_get_str_param_by_type(msg, KTP_PARAM_LINE))) {
  125. ktpd_session_send_error(session, cmd, NULL);
  126. return BOOL_FALSE;
  127. }
  128. /* // Parsing
  129. pargv = ksession_parse_line(session->ksession, line, KPURPOSE_HELP);
  130. faux_str_free(line);
  131. kpargv_free(pargv);
  132. */
  133. // Send ACK message
  134. ack = ktp_msg_preform(cmd, KTP_STATUS_NONE);
  135. faux_msg_send_async(ack, session->async);
  136. faux_msg_free(ack);
  137. return BOOL_TRUE;
  138. }
  139. static bool_t ktpd_session_dispatch(ktpd_session_t *session, faux_msg_t *msg)
  140. {
  141. uint16_t cmd = 0;
  142. assert(session);
  143. if (!session)
  144. return BOOL_FALSE;
  145. assert(msg);
  146. if (!msg)
  147. return BOOL_FALSE;
  148. cmd = faux_msg_get_cmd(msg);
  149. switch (cmd) {
  150. case KTP_CMD:
  151. ktpd_session_process_cmd(session, msg);
  152. break;
  153. case KTP_COMPLETION:
  154. ktpd_session_process_completion(session, msg);
  155. break;
  156. case KTP_HELP:
  157. ktpd_session_process_help(session, msg);
  158. break;
  159. default:
  160. syslog(LOG_WARNING, "Unsupported command: 0x%04u\n", cmd);
  161. break;
  162. }
  163. return BOOL_TRUE;
  164. }
  165. /** @brief Low-level function to receive KTP message.
  166. *
  167. * Firstly function gets the header of message. Then it checks and parses
  168. * header and find out the length of whole message. Then it receives the rest
  169. * of message.
  170. */
  171. static bool_t ktpd_session_read_cb(faux_async_t *async,
  172. void *data, size_t len, void *user_data)
  173. {
  174. ktpd_session_t *session = (ktpd_session_t *)user_data;
  175. faux_msg_t *completed_msg = NULL;
  176. assert(async);
  177. assert(data);
  178. assert(session);
  179. // Receive header
  180. if (!session->hdr) {
  181. size_t whole_len = 0;
  182. size_t msg_wo_hdr = 0;
  183. session->hdr = (faux_hdr_t *)data;
  184. // Check for broken header
  185. if (!check_ktp_header(session->hdr)) {
  186. faux_free(session->hdr);
  187. session->hdr = NULL;
  188. return BOOL_FALSE;
  189. }
  190. whole_len = faux_hdr_len(session->hdr);
  191. // msg_wo_hdr >= 0 because check_ktp_header() validates whole_len
  192. msg_wo_hdr = whole_len - sizeof(faux_hdr_t);
  193. // Plan to receive message body
  194. if (msg_wo_hdr > 0) {
  195. faux_async_set_read_limits(async,
  196. msg_wo_hdr, msg_wo_hdr);
  197. return BOOL_TRUE;
  198. }
  199. // Here message is completed (msg body has zero length)
  200. completed_msg = faux_msg_deserialize_parts(session->hdr, NULL, 0);
  201. // Receive message body
  202. } else {
  203. completed_msg = faux_msg_deserialize_parts(session->hdr, data, len);
  204. faux_free(data);
  205. }
  206. // Plan to receive msg header
  207. faux_async_set_read_limits(session->async,
  208. sizeof(faux_hdr_t), sizeof(faux_hdr_t));
  209. faux_free(session->hdr);
  210. session->hdr = NULL; // Ready to recv new header
  211. // Here message is completed
  212. ktpd_session_dispatch(session, completed_msg);
  213. faux_msg_free(completed_msg);
  214. return BOOL_TRUE;
  215. }
  216. static bool_t ktpd_session_stall_cb(faux_async_t *async,
  217. size_t len, void *user_data)
  218. {
  219. ktpd_session_t *session = (ktpd_session_t *)user_data;
  220. assert(async);
  221. assert(session);
  222. if (!session->stall_cb)
  223. return BOOL_TRUE;
  224. session->stall_cb(session, session->stall_udata);
  225. async = async; // Happy compiler
  226. len = len; // Happy compiler
  227. return BOOL_TRUE;
  228. }
  229. ktpd_session_t *ktpd_session_new(int sock, const kscheme_t *scheme,
  230. const char *start_entry)
  231. {
  232. ktpd_session_t *session = NULL;
  233. if (sock < 0)
  234. return NULL;
  235. session = faux_zmalloc(sizeof(*session));
  236. assert(session);
  237. if (!session)
  238. return NULL;
  239. // Init
  240. session->state = KTPD_SESSION_STATE_NOT_AUTHORIZED;
  241. session->ksession = ksession_new(scheme, start_entry);
  242. assert(session->ksession);
  243. session->async = faux_async_new(sock);
  244. assert(session->async);
  245. // Receive message header first
  246. faux_async_set_read_limits(session->async,
  247. sizeof(faux_hdr_t), sizeof(faux_hdr_t));
  248. faux_async_set_read_cb(session->async, ktpd_session_read_cb, session);
  249. session->hdr = NULL;
  250. return session;
  251. }
  252. void ktpd_session_free(ktpd_session_t *session)
  253. {
  254. if (!session)
  255. return;
  256. ksession_free(session->ksession);
  257. faux_free(session->hdr);
  258. close(ktpd_session_fd(session));
  259. faux_async_free(session->async);
  260. faux_free(session);
  261. }
  262. bool_t ktpd_session_connected(ktpd_session_t *session)
  263. {
  264. assert(session);
  265. if (!session)
  266. return BOOL_FALSE;
  267. if (KTPD_SESSION_STATE_DISCONNECTED == session->state)
  268. return BOOL_FALSE;
  269. return BOOL_TRUE;
  270. }
  271. int ktpd_session_fd(const ktpd_session_t *session)
  272. {
  273. assert(session);
  274. if (!session)
  275. return BOOL_FALSE;
  276. return faux_async_fd(session->async);
  277. }
  278. bool_t ktpd_session_async_in(ktpd_session_t *session)
  279. {
  280. assert(session);
  281. if (!session)
  282. return BOOL_FALSE;
  283. if (!ktpd_session_connected(session))
  284. return BOOL_FALSE;
  285. if (faux_async_in(session->async) < 0)
  286. return BOOL_FALSE;
  287. return BOOL_TRUE;
  288. }
  289. bool_t ktpd_session_async_out(ktpd_session_t *session)
  290. {
  291. assert(session);
  292. if (!session)
  293. return BOOL_FALSE;
  294. if (!ktpd_session_connected(session))
  295. return BOOL_FALSE;
  296. if (faux_async_out(session->async) < 0)
  297. return BOOL_FALSE;
  298. return BOOL_TRUE;
  299. }
  300. void ktpd_session_set_stall_cb(ktpd_session_t *session,
  301. faux_session_stall_cb_fn stall_cb, void *user_data)
  302. {
  303. assert(session);
  304. if (!session)
  305. return;
  306. session->stall_cb = stall_cb;
  307. session->stall_udata = user_data;
  308. faux_async_set_stall_cb(session->async, ktpd_session_stall_cb, session);
  309. }
  310. #if 0
  311. static void ktpd_session_bad_socket(ktpd_session_t *session)
  312. {
  313. assert(session);
  314. if (!session)
  315. return;
  316. session->state = KTPD_SESSION_STATE_DISCONNECTED;
  317. }
  318. #endif