test_integration_auth.cpp 26 KB

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