telnet_server.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /*
  2. * telnet_server.c
  3. *
  4. * Created on: 24.11.2017
  5. * Author: balbekova
  6. */
  7. /* Standard includes. */
  8. #include <string.h>
  9. /* lwIP core includes */
  10. #include "lwip/opt.h"
  11. #include "lwip/sockets.h"
  12. /* FreeRTOS includes. */
  13. #include "FreeRTOS.h"
  14. #include "task.h"
  15. #include "fr_timers.h"
  16. /* Utils includes. */
  17. #include "FreeRTOS_CLI.h"
  18. #include "CLI_Commands.h"
  19. #include "telnet_server.h"
  20. #include "settings_api.h"
  21. #include "parameters.h"
  22. #include "control_symbol.h"
  23. #include "log.h"
  24. #include "web_params_api.h"
  25. /* Dimensions the buffer into which input characters are placed. */
  26. #define cmdMAX_INPUT_SIZE 144
  27. /* Repeat Login timeout, 1 seconds */
  28. #define REPEAT_SENSOR_INFO_TIME configTICK_RATE_HZ*1*1
  29. static portBASE_TYPE FreeRTOS_CLIAuthProcess( const int8_t * const pcCommandInput, int8_t * pcWriteBuffer );
  30. static portBASE_TYPE FreeRTOS_ChangePWDProcess( const int8_t * const pcCommandInput, int8_t * pcWriteBuffer );
  31. void SensorInfoTimerCallback(TimerHandle_t pxTimer);
  32. TimerHandle_t RepeatSensorInfoTimer;
  33. state_telnet_server_t telnetState = TELNET_AUTH;
  34. uint8_t id_change_pwd = 0;
  35. user_level_t telnet_code_auth = USER;
  36. static int32_t lClientFd;
  37. static int8_t *pcOutputString;
  38. /**
  39. * @brief Общая структура настроек
  40. */
  41. extern SETTINGS_t sSettings;
  42. /*-----------------------------------------------------------*/
  43. void vBasicSocketsCommandInterpreterTask( void *pvParameters )
  44. {
  45. int32_t lSocket, lBytes, lAddrLen = sizeof( struct sockaddr_in );
  46. struct sockaddr_in sLocalAddr;
  47. struct sockaddr_in client_addr;
  48. const int8_t * const pcWelcomeMessage = ( const int8_t * ) "BT6706 command server - connection accepted.\r\nlogin:";
  49. static const int8_t * const pcEndOfCommandOutputString = ( int8_t * ) "\r\n[Press ENTER to execute the previous command again]\r\n>";
  50. int8_t cInChar, cInputIndex;
  51. static int8_t cInputString[ cmdMAX_INPUT_SIZE ] = { 0 }, cLastInputString[ cmdMAX_INPUT_SIZE ] = { 0 };
  52. portBASE_TYPE xReturned;
  53. ( void ) pvParameters;
  54. lSocket = lwip_socket( AF_INET, SOCK_STREAM, 0 );
  55. if( lSocket >= 0 )
  56. {
  57. /* Obtain the address of the output buffer. Note there is no mutual
  58. exclusion on this buffer as it is assumed only one command console
  59. interface will be used at any one time. */
  60. pcOutputString = FreeRTOS_CLIGetOutputBuffer();
  61. memset((char *)&sLocalAddr, 0, sizeof(sLocalAddr));
  62. sLocalAddr.sin_family = AF_INET;
  63. sLocalAddr.sin_len = sizeof(sLocalAddr);
  64. sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  65. sLocalAddr.sin_port = ntohs( ( ( uint16_t ) 23 ) );
  66. if( lwip_bind( lSocket, ( struct sockaddr *) &sLocalAddr, sizeof( sLocalAddr ) ) < 0 )
  67. {
  68. lwip_close( lSocket );
  69. vTaskDelete( NULL );
  70. }
  71. if( lwip_listen( lSocket, 20 ) != 0 )
  72. {
  73. lwip_close( lSocket );
  74. vTaskDelete( NULL );
  75. }
  76. /* Ensure the input string starts clear. */
  77. cInputString[ 0 ] = 0;
  78. cLastInputString[ 0 ] = 0;
  79. for( ;; )
  80. {
  81. lClientFd = lwip_accept( lSocket, ( struct sockaddr * ) &client_addr, ( u32_t * ) &lAddrLen );
  82. if( lClientFd > 0L )
  83. {
  84. lBytes = lwip_recv( lClientFd, cInputString, 27, 0 );
  85. telnetState = TELNET_AUTH;
  86. lwip_send( lClientFd, pcWelcomeMessage, strlen( ( const char * ) pcWelcomeMessage ), 0 );
  87. cInputIndex = 0;
  88. memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
  89. do
  90. {
  91. lBytes = lwip_recv( lClientFd, &cInChar, sizeof( cInChar ), 0 );
  92. if( lBytes > 0L )
  93. {
  94. if( cInChar == '\n' )
  95. {
  96. switch(telnetState){
  97. case TELNET_AUTH:
  98. if(FreeRTOS_CLIAuthProcess(cInputString, pcOutputString)){
  99. lwip_send( lClientFd, pcOutputString, strlen( ( const char * ) pcOutputString ), 0 );
  100. cInputIndex = 0;
  101. memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
  102. }
  103. else{
  104. /* Set lBytes to 0 to close the connection. */
  105. lBytes = 0L;
  106. }
  107. break;
  108. case TELNET_CMD:
  109. /* The input string has been terminated. Was the
  110. input a quit command? */
  111. if( strcmp( "quit", ( const char * ) cInputString ) == 0 )
  112. {
  113. /* Set lBytes to 0 to close the connection. */
  114. lBytes = 0L;
  115. }
  116. else
  117. {
  118. /* The input string was not a quit command.
  119. Pass the string to the command interpreter. */
  120. /* See if the command is empty, indicating that the last command is
  121. to be executed again. */
  122. if( cInputIndex == 0 )
  123. {
  124. strcpy( ( char * ) cInputString, ( char * ) cLastInputString );
  125. }
  126. /* Transmit a line separator, just to make the
  127. output easier to read. */
  128. lwip_send( lClientFd, "\r\n", strlen( "\r\n" ), 0 );
  129. do
  130. {
  131. /* Ensure there is not a string lingering in
  132. the output buffer. */
  133. pcOutputString[ 0 ] = 0x00;
  134. xReturned = FreeRTOS_CLIProcessCommand( cInputString, pcOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE );
  135. lwip_send( lClientFd, pcOutputString, strlen( ( const char * ) pcOutputString ), 0 );
  136. } while( xReturned != pdFALSE );
  137. if( strcmp( "sensor info", ( const char * ) cInputString ) == 0 ){
  138. strcpy( ( char * ) cLastInputString, ( char * ) cInputString );
  139. cInputIndex = 0;
  140. memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
  141. xTimerStart(RepeatSensorInfoTimer, 0);
  142. }
  143. else{
  144. /* All the strings generated by the input
  145. command have been sent. Clear the input
  146. string ready to receive the next command.
  147. Remember the command that was just processed
  148. first in case it is to be processed again. */
  149. strcpy( ( char * ) cLastInputString, ( char * ) cInputString );
  150. cInputIndex = 0;
  151. memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
  152. if(telnetState != TELNET_CHANGE_PWD)
  153. lwip_send( lClientFd, pcEndOfCommandOutputString, strlen( ( const char * ) pcEndOfCommandOutputString ), 0 );
  154. }
  155. }
  156. break;
  157. case TELNET_CHANGE_PWD:
  158. FreeRTOS_ChangePWDProcess(cInputString, pcOutputString);
  159. lwip_send( lClientFd, pcOutputString, strlen( ( const char * ) pcOutputString ), 0 );
  160. cInputIndex = 0;
  161. memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
  162. break;
  163. }
  164. }
  165. else
  166. {
  167. if( cInChar == '\r' )
  168. {
  169. /* Ignore the character. */
  170. }
  171. else if( cInChar == '\b' )
  172. {
  173. /* Backspace was pressed. Erase the last
  174. character in the string - if any. */
  175. if( cInputIndex > 0 )
  176. {
  177. cInputIndex--;
  178. cInputString[ cInputIndex ] = '\0';
  179. }
  180. }
  181. else
  182. {
  183. /* A character was entered. Add it to the string
  184. entered so far. When a \n is entered the complete
  185. string will be passed to the command interpreter. */
  186. if( cInputIndex < cmdMAX_INPUT_SIZE )
  187. {
  188. cInputString[ cInputIndex ] = cInChar;
  189. cInputIndex++;
  190. }
  191. if( strcmp( "\377\364\377\375\006", ( const char * ) cInputString ) == 0 ){
  192. xTimerStop(RepeatSensorInfoTimer, 0);
  193. cInputIndex = 0;
  194. memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
  195. cInputString[0] = 255;
  196. cInputString[1] = 251;
  197. cInputString[2] = 6;
  198. cInputString[3] = 255;
  199. cInputString[4] = 242;
  200. //if(telnetState != TELNET_CHANGE_PWD)
  201. //lwip_send( lClientFd, pcEndOfCommandOutputString, strlen( ( const char * ) pcEndOfCommandOutputString ), 0 );
  202. lwip_send( lClientFd, cInputString, strlen( ( const char * ) cInputString ), 0 );
  203. memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
  204. if(telnetState != TELNET_CHANGE_PWD)
  205. lwip_send( lClientFd, pcEndOfCommandOutputString, strlen( ( const char * ) pcEndOfCommandOutputString ), 0 );
  206. }
  207. }
  208. }
  209. }
  210. } while( lBytes > 0L );
  211. lwip_close( lClientFd );
  212. }
  213. }
  214. }
  215. /* Will only get here if a listening socket could not be created. */
  216. vTaskDelete( NULL );
  217. }
  218. void telnet_server_init(void) {
  219. vRegisterCLICommands();
  220. xTaskCreate(vBasicSocketsCommandInterpreterTask, ( char * ) "vBasicSocketsCommandInterpreterTask", 8*configMINIMAL_STACK_SIZE , NULL, tskIDLE_PRIORITY, NULL);
  221. RepeatSensorInfoTimer = xTimerCreate("SensorInfoTmr", REPEAT_SENSOR_INFO_TIME, pdFALSE, ( void * ) 0, SensorInfoTimerCallback);
  222. }
  223. void SensorInfoTimerCallback(TimerHandle_t pxTimer) {
  224. portBASE_TYPE xReturned = pdTRUE;
  225. do
  226. {
  227. /* Ensure there is not a string lingering in
  228. the output buffer. */
  229. pcOutputString[ 0 ] = 0x00;
  230. xReturned = FreeRTOS_CLIProcessCommand( "sensor info", pcOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE );
  231. lwip_send( lClientFd, pcOutputString, strlen( ( const char * ) pcOutputString ), 0 );
  232. } while( xReturned != pdFALSE );
  233. xTimerStart(RepeatSensorInfoTimer, 0);
  234. }
  235. static portBASE_TYPE FreeRTOS_CLIAuthProcess( const int8_t * const pcCommandInput, int8_t * pcWriteBuffer )
  236. {
  237. portBASE_TYPE xReturn = pdTRUE;
  238. uint32_t len;
  239. uint8_t valueLen, user_id;
  240. char WebPassword[MAX_WEB_PASSWD_LEN];
  241. char WebLogin[MAX_WEB_LOGIN_LEN];
  242. static uint8_t login_err = 0;
  243. static uint8_t telnet_state_auth = 0;
  244. static char login[ cmdMAX_INPUT_SIZE ] = { 0 };
  245. char password[ cmdMAX_INPUT_SIZE ] = { 0 };
  246. const int8_t * const pcPSWHeader = ( int8_t * ) "\r\npassword:";
  247. const int8_t * const pcLoginHeader = ( int8_t * ) "\r\nlogin:";
  248. memset(pcWriteBuffer, 0, configCOMMAND_INT_MAX_OUTPUT_SIZE);
  249. if(telnet_state_auth == 0){
  250. telnet_state_auth = 1;
  251. memset(login, 0, cmdMAX_INPUT_SIZE);
  252. len = strlen((char *)pcCommandInput);
  253. strncpy(login, (char *)pcCommandInput, len);
  254. strncpy( ( char * ) pcWriteBuffer, ( const char * ) pcPSWHeader, strlen( ( char * ) pcPSWHeader ) );
  255. xReturn = pdTRUE;
  256. }
  257. else{
  258. memset(name_login_telnet, 0, 50);
  259. telnet_state_auth = 0;
  260. memset(password, 0, cmdMAX_INPUT_SIZE);
  261. len = strlen((char *)pcCommandInput);
  262. strncpy(password, (char *)pcCommandInput, len);
  263. for (user_id = 0; user_id < MAX_WEB_USERS; user_id++) {
  264. GetUserLogin(user_id, WebLogin, &valueLen);
  265. GetUserPassword(user_id, WebPassword, &valueLen);
  266. /* Check login and password */
  267. if ((strncmp(WebLogin, login, MAX_WEB_LOGIN_LEN) == 0) &&
  268. (strncmp(WebPassword, password, MAX_WEB_PASSWD_LEN) == 0)) {
  269. /* Login and pass are valid */
  270. telnet_code_auth = user_id;
  271. login_err = 0;
  272. strcpy( ( char * ) pcWriteBuffer, "\r\nАвторизация успешно пройдена\r\n>" );
  273. telnetState = TELNET_CMD;
  274. xReturn = pdTRUE;
  275. break;
  276. }
  277. else{
  278. xReturn = pdFALSE;
  279. }
  280. }
  281. if(xReturn == pdFALSE){
  282. if(login_err < 4){
  283. login_err ++;
  284. strcpy( ( char * ) pcWriteBuffer, "\r\nОшибка авторизации\r\n" );
  285. strncat( ( char * ) pcWriteBuffer, ( const char * ) pcLoginHeader, strlen( ( char * ) pcLoginHeader ) );
  286. xReturn = pdTRUE;
  287. }
  288. else{
  289. login_err = 0;
  290. xReturn = pdFALSE;
  291. }
  292. }
  293. switch (user_id) {
  294. case 0:
  295. snprintf(name_login_telnet, sizeof(name_login_telnet), "Администратор");
  296. break;
  297. case 1:
  298. snprintf(name_login_telnet, sizeof(name_login_telnet), "Пользователь");
  299. break;
  300. default:
  301. break;
  302. }
  303. log_event_data(LOG_LOGIN_TELNET, name_login_telnet);
  304. }
  305. return xReturn;
  306. }
  307. static portBASE_TYPE FreeRTOS_ChangePWDProcess( const int8_t * const pcCommandInput, int8_t * pcWriteBuffer )
  308. {
  309. portBASE_TYPE xReturn = pdTRUE;
  310. uint32_t len;
  311. static uint8_t telnet_state_change_pwd = 0;
  312. static char password[ MAX_WEB_LOGIN_LEN ] = { 0 };
  313. char password2[ MAX_WEB_LOGIN_LEN ] = { 0 };
  314. const int8_t * const pcNewPSWHeader = ( int8_t * ) "\r\nВведите повторно новый пароль:";
  315. memset(pcWriteBuffer, 0, configCOMMAND_INT_MAX_OUTPUT_SIZE);
  316. if(telnet_state_change_pwd == 0){
  317. telnet_state_change_pwd = 1;
  318. memset(password, 0, MAX_WEB_LOGIN_LEN);
  319. len = strlen((char *)pcCommandInput);
  320. if(len >= MAX_WEB_LOGIN_LEN){
  321. strcpy( ( char * ) pcWriteBuffer, "\r\nОшибка при вводе нового пароля\r\n>" );
  322. telnetState = TELNET_CMD;
  323. }
  324. else{
  325. if(!control_string_en_digit((char *)pcCommandInput, len)){
  326. strcpy( ( char * ) pcWriteBuffer, "\r\nОшибка при вводе нового пароля\r\n>" );
  327. telnetState = TELNET_CMD;
  328. }
  329. else{
  330. strncpy(password, (char *)pcCommandInput, len);
  331. strncpy( ( char * ) pcWriteBuffer, ( const char * ) pcNewPSWHeader, strlen( ( char * ) pcNewPSWHeader ) );
  332. }
  333. }
  334. }
  335. else{
  336. telnet_state_change_pwd = 0;
  337. memset(password2, 0, cmdMAX_INPUT_SIZE);
  338. len = strlen((char *)pcCommandInput);
  339. if(len >= MAX_WEB_LOGIN_LEN){
  340. strcpy( ( char * ) pcWriteBuffer, "\r\nОшибка при вводе нового пароля\r\n>" );
  341. telnetState = TELNET_CMD;
  342. }
  343. else{
  344. strncpy(password2, (char *)pcCommandInput, len);
  345. if (strncmp(password, password2, MAX_WEB_PASSWD_LEN) == 0) {
  346. memcpy(sSettings.sAuth[id_change_pwd].password, password, 11);
  347. telnet_act = true;
  348. HTTP_SaveSettings();
  349. log_event_data(LOG_PSW_CHANGE, name_login_telnet);
  350. strcpy( ( char * ) pcWriteBuffer, "\r\nПароль успешно изменен\r\n>" );
  351. telnetState = TELNET_CMD;
  352. xReturn = pdTRUE;
  353. }
  354. else{
  355. strcpy( ( char * ) pcWriteBuffer, "\r\nОшибка при вводе нового пароля\r\n>" );
  356. telnetState = TELNET_CMD;
  357. }
  358. }
  359. }
  360. return xReturn;
  361. }