test_integration_auth.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. /*
  2. * Copyright (c) 2019 - 2024 Stefan Strobel <stefan.strobel@shimatta.net>
  3. *
  4. * This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
  7. */
  8. /**
  9. * @file test_integration_auth.cpp
  10. * @brief integration test implementation for the authentication functions
  11. * @author Stefan Strobel <stefan.strobel@shimatta.net>
  12. */
  13. #include "test/framework/catch.hpp"
  14. extern "C" {
  15. #include "shellmatta.h"
  16. }
  17. #include <string.h>
  18. static uint32_t write_callCnt = 0u;
  19. static char write_data[1024];
  20. static uint32_t write_length;
  21. static uint32_t userIdTemp;
  22. static bool successTemp;
  23. #define TEST_SHELLMATTA_SETUP shellmatta_retCode_t ret; \
  24. shellmatta_instance_t inst; \
  25. shellmatta_handle_t handle; \
  26. char buffer[1024] = {0}; \
  27. char historyBuffer[1024] = {0}; \
  28. \
  29. shellmatta_doInit( &inst, \
  30. &handle, \
  31. buffer, \
  32. sizeof(buffer), \
  33. historyBuffer, \
  34. sizeof(historyBuffer), \
  35. "shellmatta->", \
  36. NULL, \
  37. writeFct); \
  38. \
  39. write_callCnt = 0u; \
  40. memset(write_data, 0, sizeof(write_data)); \
  41. write_length = 0u; \
  42. userIdTemp = 255u; \
  43. successTemp = false; \
  44. \
  45. shellmatta_addCmd(handle, &publicCmd); \
  46. shellmatta_addCmd(handle, &privateCmd);
  47. #define TEST_SHELLMATTA_AUTH_SETUP shellmatta_auth_user_t userList[] = { \
  48. {1, "shimatta", "12345678"}, \
  49. {2, "not_shimatta", "87654321"} \
  50. }; \
  51. \
  52. uint32_t privateCmdPerms[] = {1}; \
  53. shellmatta_auth_perm_t permList[] = { \
  54. {"private", privateCmdPerms, sizeof(privateCmdPerms)/sizeof(privateCmdPerms[0])} \
  55. }; \
  56. \
  57. shellmatta_auth_init(handle, userList, 2, permList, 1, false, NULL, NULL);
  58. static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
  59. {
  60. write_callCnt ++;
  61. while((length > 0) && (write_length < sizeof(write_data)))
  62. {
  63. write_data[write_length] = *data;
  64. data ++;
  65. length --;
  66. write_length ++;
  67. }
  68. return SHELLMATTA_OK;
  69. }
  70. static shellmatta_retCode_t publicCmdFct(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  71. {
  72. (void) handle;
  73. (void) arguments;
  74. (void) length;
  75. shellmatta_retCode_t ret = SHELLMATTA_OK;
  76. return ret;
  77. }
  78. shellmatta_cmd_t publicCmd = {(char*)"public", (char*)"p", NULL, NULL, publicCmdFct, NULL, NULL};
  79. static shellmatta_retCode_t privateCmdFct(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  80. {
  81. (void) handle;
  82. (void) arguments;
  83. (void) length;
  84. return SHELLMATTA_OK;
  85. }
  86. shellmatta_cmd_t privateCmd = {(char*)"private", (char*)"r", NULL, NULL, privateCmdFct, NULL, NULL};
  87. SCENARIO("Check help auth uninitialized") {
  88. GIVEN("An initialized shellmatta instance without initialized auth") {
  89. TEST_SHELLMATTA_SETUP;
  90. WHEN("The help command is called") {
  91. ret = shellmatta_processData(handle, (char*)"help\r", 5);
  92. CHECK(ret == SHELLMATTA_OK);
  93. THEN("The help command prints all commands.") {
  94. char *dummyData = (char*) "help\r\n"
  95. "help ? help [command] - print help or usage information\r\n"
  96. "login li Login command\r\n"
  97. "logout lo Logout command\r\n"
  98. "private r\r\n"
  99. "public p\r\n"
  100. "\r\n"
  101. "shellmatta->";
  102. CHECK(ret == SHELLMATTA_OK);
  103. CHECK(write_length == strlen(dummyData));
  104. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  105. }
  106. }
  107. }
  108. }
  109. SCENARIO("Check help auth unauthorized") {
  110. GIVEN("An initialized shellmatta instance with initialized auth") {
  111. TEST_SHELLMATTA_SETUP;
  112. TEST_SHELLMATTA_AUTH_SETUP;
  113. WHEN("The help command is called") {
  114. ret = shellmatta_processData(handle, (char*)"help\r", 5);
  115. CHECK(ret == SHELLMATTA_OK);
  116. THEN("The help command prints only public commands.") {
  117. char *dummyData = (char*) "help\r\n"
  118. "help ? help [command] - print help or usage information\r\n"
  119. "login li Login command\r\n"
  120. "logout lo Logout command\r\n"
  121. "public p\r\n"
  122. "\r\n"
  123. "shellmatta->";
  124. CHECK(ret == SHELLMATTA_OK);
  125. CHECK(write_length == strlen(dummyData));
  126. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  127. }
  128. }
  129. }
  130. }
  131. SCENARIO("Check help authorized") {
  132. GIVEN("An initialized shellmatta instance with initialized auth") {
  133. TEST_SHELLMATTA_SETUP;
  134. TEST_SHELLMATTA_AUTH_SETUP;
  135. WHEN("The user shellmatta is logged in") {
  136. ret = shellmatta_auth_login(handle, 1);
  137. CHECK(ret == SHELLMATTA_OK);
  138. AND_WHEN("The help command is called") {
  139. ret = shellmatta_processData(handle, (char*)"help\r", 5);
  140. CHECK(ret == SHELLMATTA_OK);
  141. THEN("The help command prints all commands.") {
  142. char *dummyData = (char*) "help\r\n"
  143. "help ? help [command] - print help or usage information\r\n"
  144. "login li Login command\r\n"
  145. "logout lo Logout command\r\n"
  146. "private r\r\n"
  147. "public p\r\n"
  148. "\r\n"
  149. "shimatta@shellmatta->";
  150. CHECK(ret == SHELLMATTA_OK);
  151. CHECK(write_length == strlen(dummyData));
  152. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  153. AND_THEN("The shimatta user is logged in") {
  154. char usernameBuffer[16] = {0};
  155. uint32_t usernameBufferLength = sizeof(usernameBuffer);
  156. CHECK(1 == shellmatta_auth_getLoggedInUserId(handle));
  157. ret = shellmatta_auth_getLoggedInUserName(handle, usernameBuffer, &usernameBufferLength);
  158. CHECK(ret == SHELLMATTA_OK);
  159. CHECK(usernameBufferLength == strlen("shimatta"));
  160. REQUIRE_THAT(usernameBuffer, Catch::Matchers::Equals("shimatta"));
  161. }
  162. }
  163. AND_WHEN("The user is logged out using the logout command") {
  164. write_length = 0;
  165. memset(write_data, 0, sizeof(write_data));
  166. ret = shellmatta_processData(handle, (char*)"logout\r", 7);
  167. CHECK(ret == SHELLMATTA_OK);
  168. THEN("The Shellmatta prints the logout message") {
  169. char *dummyData = (char*) "logout\r\n"
  170. "good bye\r\n\r\n"
  171. "shellmatta->";
  172. CHECK(write_length == strlen(dummyData));
  173. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  174. }
  175. AND_WHEN("The help command is called") {
  176. write_length = 0;
  177. memset(write_data, 0, sizeof(write_data));
  178. ret = shellmatta_processData(handle, (char*)"help\r", 5);
  179. CHECK(ret == SHELLMATTA_OK);
  180. THEN("The help command prints only public commands.") {
  181. char *dummyData = (char*) "help\r\n"
  182. "help ? help [command] - print help or usage information\r\n"
  183. "login li Login command\r\n"
  184. "logout lo Logout command\r\n"
  185. "public p\r\n"
  186. "\r\n"
  187. "shellmatta->";
  188. CHECK(ret == SHELLMATTA_OK);
  189. CHECK(write_length == strlen(dummyData));
  190. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  191. }
  192. }
  193. }
  194. }
  195. }
  196. WHEN("The user not_shellmatta is logged in") {
  197. ret = shellmatta_auth_login(handle, 2);
  198. CHECK(ret == SHELLMATTA_OK);
  199. AND_WHEN("The help command is called") {
  200. ret = shellmatta_processData(handle, (char*)"help\r", 5);
  201. CHECK(ret == SHELLMATTA_OK);
  202. THEN("The help command prints not all commands.") {
  203. char *dummyData = (char*) "help\r\n"
  204. "help ? help [command] - print help or usage information\r\n"
  205. "login li Login command\r\n"
  206. "logout lo Logout command\r\n"
  207. "public p\r\n"
  208. "\r\n"
  209. "not_shimatta@shellmatta->";
  210. CHECK(ret == SHELLMATTA_OK);
  211. CHECK(write_length == strlen(dummyData));
  212. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  213. AND_THEN("The not_shimatta user is logged in") {
  214. char usernameBuffer[16] = {0};
  215. uint32_t usernameBufferLength = sizeof(usernameBuffer);
  216. CHECK(2 == shellmatta_auth_getLoggedInUserId(handle));
  217. ret = shellmatta_auth_getLoggedInUserName(handle, usernameBuffer, &usernameBufferLength);
  218. CHECK(ret == SHELLMATTA_OK);
  219. CHECK(usernameBufferLength == strlen("not_shimatta"));
  220. REQUIRE_THAT(usernameBuffer, Catch::Matchers::Equals("not_shimatta"));
  221. }
  222. }
  223. }
  224. }
  225. }
  226. }
  227. SCENARIO("Check login command with privileged user") {
  228. GIVEN("An initialized shellmatta instance with initialized auth") {
  229. TEST_SHELLMATTA_SETUP;
  230. TEST_SHELLMATTA_AUTH_SETUP;
  231. WHEN("The user shellmatta logges in interactively using the correct credentials") {
  232. ret = shellmatta_processData(handle, (char*)"login\r\n"
  233. "shimatta\r\n"
  234. "12345678\r", 26);
  235. CHECK(ret == SHELLMATTA_OK);
  236. THEN("The login message is printed - password is hidden") {
  237. char *dummyData = (char*) "login\r\n"
  238. "enter username:\r\n"
  239. "shimatta\r\n"
  240. "enter password:\r\n"
  241. "\r\n"
  242. "login successful\r\n"
  243. "\r\n"
  244. "shimatta@shellmatta->";
  245. CHECK(write_length == strlen(dummyData));
  246. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  247. AND_THEN("The shimatta user is logged in") {
  248. REQUIRE(1 == shellmatta_auth_getLoggedInUserId(handle));
  249. }
  250. }
  251. }
  252. WHEN("The user shellmatta logges in interactively using wrong credentials") {
  253. ret = shellmatta_processData(handle, (char*)"login\r\n"
  254. "shimatta\r\n"
  255. "11111111\r", 26);
  256. CHECK(ret == SHELLMATTA_OK);
  257. THEN("A warning message is printed") {
  258. char *dummyData = (char*) "login\r\n"
  259. "enter username:\r\n"
  260. "shimatta\r\n"
  261. "enter password:\r\n"
  262. "\r\n"
  263. "username or password is wrong\r\n"
  264. "\r\n"
  265. "shellmatta->";
  266. CHECK(write_length == strlen(dummyData));
  267. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  268. AND_THEN("The shimatta user is not logged in") {
  269. REQUIRE(0 == shellmatta_auth_getLoggedInUserId(handle));
  270. }
  271. }
  272. }
  273. WHEN("The user shellmatta logges in interactively manipulating the input") {
  274. ret = shellmatta_processData(handle, (char*)"login\r"
  275. "shimg\batta\r"
  276. "1h" "\x7f" "2346\033[D5\033[C78\b8\r", 36);
  277. CHECK(ret == SHELLMATTA_OK);
  278. THEN("The login message is printed - password is hidden") {
  279. char *dummyData = (char*) "login\r\n"
  280. "enter username:\r\n"
  281. "shimg\033[1D\033[K\033[s\033[uatta\r\n"
  282. "enter password:\r\n"
  283. "\r\n"
  284. "login successful\r\n"
  285. "\r\n"
  286. "shimatta@shellmatta->";
  287. CHECK(write_length == strlen(dummyData));
  288. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  289. AND_THEN("The shimatta user is logged in") {
  290. REQUIRE(1 == shellmatta_auth_getLoggedInUserId(handle));
  291. }
  292. }
  293. }
  294. WHEN("The user shellmatta logges in passing the credentials none interactive") {
  295. ret = shellmatta_processData(handle, (char*)"login -u shimatta -p 12345678\r", 30);
  296. CHECK(ret == SHELLMATTA_OK);
  297. THEN("The login message is printed") {
  298. char *dummyData = (char*) "login -u shimatta -p 12345678\r\n"
  299. "login successful\r\n"
  300. "\r\n"
  301. "shimatta@shellmatta->";
  302. CHECK(write_length == strlen(dummyData));
  303. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  304. AND_THEN("The shimatta user is logged in") {
  305. REQUIRE(1 == shellmatta_auth_getLoggedInUserId(handle));
  306. }
  307. }
  308. }
  309. WHEN("The user shellmatta logges in passing the credentials half interactive") {
  310. ret = shellmatta_processData(handle, (char*)"login -u shimatta\r12345678\r", 27);
  311. CHECK(ret == SHELLMATTA_OK);
  312. THEN("The login message is printed - password is hidden") {
  313. char *dummyData = (char*) "login -u shimatta\r\n\r\n"
  314. "enter password:\r\n"
  315. "\r\n"
  316. "login successful\r\n"
  317. "\r\n"
  318. "shimatta@shellmatta->";
  319. CHECK(write_length == strlen(dummyData));
  320. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  321. AND_THEN("The shimatta user is logged in") {
  322. REQUIRE(1 == shellmatta_auth_getLoggedInUserId(handle));
  323. }
  324. }
  325. }
  326. WHEN("The user shellmatta tries to login non interactive without username") {
  327. ret = shellmatta_processData(handle, (char*)"login -p 12345678\r", 18);
  328. CHECK(ret == SHELLMATTA_OK);
  329. THEN("A warning message is printed") {
  330. char *dummyData = (char*) "login -p 12345678\r\n"
  331. "Missing username\r\n"
  332. "\r\n"
  333. "shellmatta->";
  334. CHECK(write_length == strlen(dummyData));
  335. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  336. AND_THEN("The shimatta user is not logged in") {
  337. REQUIRE(0 == shellmatta_auth_getLoggedInUserId(handle));
  338. }
  339. }
  340. }
  341. WHEN("The user shellmatta tries to login using the wrong options") {
  342. ret = shellmatta_processData(handle, (char*)"login -o meow\r", 14);
  343. CHECK(ret == SHELLMATTA_OK);
  344. THEN("A warning message is printed") {
  345. char *dummyData = (char*) "login -o meow\r\n"
  346. "Unknown option\r\n"
  347. "\r\n"
  348. "shellmatta->";
  349. CHECK(write_length == strlen(dummyData));
  350. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  351. AND_THEN("The shimatta user is not logged in") {
  352. REQUIRE(0 == shellmatta_auth_getLoggedInUserId(handle));
  353. }
  354. }
  355. }
  356. }
  357. }
  358. SCENARIO("Check login command with unprivileged user") {
  359. GIVEN("An initialized shellmatta instance with initialized auth") {
  360. TEST_SHELLMATTA_SETUP;
  361. TEST_SHELLMATTA_AUTH_SETUP;
  362. WHEN("The user not_shimatta logges in interactively using the correct credentials") {
  363. ret = shellmatta_processData(handle, (char*)"login\r"
  364. "not_shimatta\r"
  365. "87654321\r", 28);
  366. CHECK(ret == SHELLMATTA_OK);
  367. THEN("The login message is printed - password is hidden") {
  368. char *dummyData = (char*) "login\r\n"
  369. "enter username:\r\n"
  370. "not_shimatta\r\n"
  371. "enter password:\r\n"
  372. "\r\n"
  373. "login successful\r\n"
  374. "\r\n"
  375. "not_shimatta@shellmatta->";
  376. CHECK(write_length == strlen(dummyData));
  377. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  378. AND_THEN("The not_shimatta user is logged in") {
  379. REQUIRE(2 == shellmatta_auth_getLoggedInUserId(handle));
  380. }
  381. }
  382. }
  383. }
  384. }
  385. shellmatta_retCode_t customLogin(const uint32_t userId, const char *password)
  386. {
  387. if ((userId == 1) && (0 == strcmp(password, "12345678")))
  388. {
  389. return SHELLMATTA_OK;
  390. }
  391. else if ((userId == 2) && (0 == strcmp(password, "87654321")))
  392. {
  393. return SHELLMATTA_OK;
  394. }
  395. return SHELLMATTA_ERROR;
  396. }
  397. void logFct(const uint32_t userId, bool success)
  398. {
  399. userIdTemp = userId;
  400. successTemp = success;
  401. }
  402. SCENARIO("Check custom login") {
  403. GIVEN("An initialized shellmatta instance with initialized auth with custom login and log") {
  404. TEST_SHELLMATTA_SETUP;
  405. shellmatta_auth_user_t userList[] = {
  406. {1, "shimatta", "12345678"},
  407. {2, "not_shimatta", "87654321"}
  408. };
  409. uint32_t privateCmdPerms[] = {1};
  410. shellmatta_auth_perm_t permList[] = {
  411. {"private", privateCmdPerms, sizeof(privateCmdPerms)/sizeof(privateCmdPerms[0])}
  412. };
  413. shellmatta_auth_init(handle, userList, 2, permList, 1, false, customLogin, logFct);
  414. WHEN("The user not_shimatta logges in interactively using the correct credentials") {
  415. ret = shellmatta_processData(handle, (char*)"login\r"
  416. "shimatta\r"
  417. "12345678\r", 24);
  418. CHECK(ret == SHELLMATTA_OK);
  419. THEN("The login message is printed - password is hidden") {
  420. char *dummyData = (char*) "login\r\n"
  421. "enter username:\r\n"
  422. "shimatta\r\n"
  423. "enter password:\r\n"
  424. "\r\n"
  425. "login successful\r\n"
  426. "\r\n"
  427. "shimatta@shellmatta->";
  428. CHECK(write_length == strlen(dummyData));
  429. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  430. AND_THEN("The shimatta user is logged in") {
  431. REQUIRE(1 == shellmatta_auth_getLoggedInUserId(handle));
  432. }
  433. AND_THEN("The login event is logged") {
  434. CHECK(1 == userIdTemp);
  435. REQUIRE(true == successTemp);
  436. }
  437. }
  438. }
  439. }
  440. }
  441. SCENARIO("Check custom login with custom login function") {
  442. GIVEN("An initialized shellmatta instance with initialized auth with custom login and log") {
  443. TEST_SHELLMATTA_SETUP;
  444. shellmatta_auth_user_t userList[] = {
  445. {1, "shimatta", "12345678"},
  446. {2, "not_shimatta", "87654321"}
  447. };
  448. uint32_t privateCmdPerms[] = {1};
  449. shellmatta_auth_perm_t permList[] = {
  450. {"private", privateCmdPerms, sizeof(privateCmdPerms)/sizeof(privateCmdPerms[0])}
  451. };
  452. shellmatta_auth_init(handle, userList, 2, permList, 1, true, customLogin, logFct);
  453. WHEN("The help command is called") {
  454. ret = shellmatta_processData(handle, (char*)"help\r", 5);
  455. CHECK(ret == SHELLMATTA_OK);
  456. THEN("There is no login command") {
  457. char *dummyData = (char*) "help\r\n"
  458. "help ? help [command] - print help or usage information\r\n"
  459. "logout lo Logout command\r\n"
  460. "public p\r\n"
  461. "\r\n"
  462. "shellmatta->";
  463. CHECK(write_length == strlen(dummyData));
  464. REQUIRE_THAT(write_data, Catch::Matchers::Equals(dummyData));
  465. }
  466. }
  467. }
  468. }