| 1 | /****************************************************************************************
|
|---|
| 2 | *
|
|---|
| 3 | * cmd_login.c
|
|---|
| 4 | *
|
|---|
| 5 | * Àóòåíòèôèêàöèÿ è óïðàâëåíèå ïîëüçîâàòåëÿìè
|
|---|
| 6 | ****************************************************************************************/
|
|---|
| 7 |
|
|---|
| 8 | #include "commands.h"
|
|---|
| 9 | #include "main.h"
|
|---|
| 10 | #include "Time.h"
|
|---|
| 11 | #include "MD5.h"
|
|---|
| 12 | #include "cookie.h"
|
|---|
| 13 | #include <string.h>
|
|---|
| 14 | #include <stdio.h>
|
|---|
| 15 | #include "rng.h"
|
|---|
| 16 | #include "log_and_debug.h"
|
|---|
| 17 | #include "fatfs.h"
|
|---|
| 18 | #include "xml.h"
|
|---|
| 19 |
|
|---|
| 20 | #define AMOUNT_MAX_USER 1 // ïîëüçîâàòåëåé ïîêà ÷òî îäèí
|
|---|
| 21 |
|
|---|
| 22 | extern RealTimeClock_typeDef RealTimeClock;
|
|---|
| 23 | extern char *cookie_out;
|
|---|
| 24 | extern xSemaphoreHandle MutexAccessFlash;
|
|---|
| 25 |
|
|---|
| 26 | struct { // ñòðóêòóðà ïîëüçîâàòåëåé
|
|---|
| 27 | char user[17]; // 16 - ñèìâîëîâ ñòðîêà + íóëü òåðìèíàòîð
|
|---|
| 28 | uint8_t len_user;
|
|---|
| 29 | char passHash[33]; // õåø ïàðîëÿ 32 áàéòà ñèìâîëîâ + íóëü òåðìèíàòîð
|
|---|
| 30 | //uint8_t len_password;
|
|---|
| 31 | uint32_t permissions; // ïðàâà ïîëüçîâàòåëÿ
|
|---|
| 32 | }userTable[AMOUNT_MAX_USER] = {0};
|
|---|
| 33 |
|
|---|
| 34 | _Bool change_pass_to_file(uint8_t indx, char *user, char* new_pass)
|
|---|
| 35 | {
|
|---|
| 36 | char str_indx[3] = {0};
|
|---|
| 37 | char *p = NULL, BufferRead[128] = {0};
|
|---|
| 38 | FIL FileLogin_old, FileLogin_new;
|
|---|
| 39 |
|
|---|
| 40 | xSemaphoreTake(MutexAccessFlash, portMAX_DELAY);
|
|---|
| 41 | if(f_open(&FileLogin_new, "Tlogin.xml", FA_OPEN_ALWAYS | FA_WRITE) == FR_OK){ // íîâûé âðåìåííûé ôàéë
|
|---|
| 42 | if(f_open(&FileLogin_old, "login.xml", FA_READ) == FR_OK){ // îòêðûâàåì ñóùåñòâóþùèé ôàéë
|
|---|
| 43 | for(;;){
|
|---|
| 44 | if(f_gets(BufferRead, 128, &FileLogin_old) != NULL) { // ïîëó÷àåì ñòðîêó äàííûõ
|
|---|
| 45 | if((p = strchr(BufferRead, '<')) != NULL){ //ïåðåøëè â íà÷àëî òåãà
|
|---|
| 46 | if((p = strstr(p, "user")) != NULL){
|
|---|
| 47 | if((p = strstr(p, "id")) != NULL){
|
|---|
| 48 | if((p = strchr(p, '"')) != NULL){
|
|---|
| 49 | _substr(p, 1, '"', str_indx);
|
|---|
| 50 | if(indx == atoi(str_indx)){
|
|---|
| 51 | f_printf(&FileLogin_new, "\t<user id=\"%d\" name=\"%s\" pass=\"%s\" permissions=\"2147483647\"/>\n", indx, user, new_pass);/*âìåñòî íåå âñòàâèòü íîâóþ*/
|
|---|
| 52 | continue;
|
|---|
| 53 | }
|
|---|
| 54 | }
|
|---|
| 55 | }
|
|---|
| 56 | }
|
|---|
| 57 | f_printf(&FileLogin_new, BufferRead);
|
|---|
| 58 | }
|
|---|
| 59 | }
|
|---|
| 60 | else if(f_eof(&FileLogin_old) != 0){
|
|---|
| 61 | f_close(&FileLogin_old);
|
|---|
| 62 | f_close(&FileLogin_new);
|
|---|
| 63 | f_unlink("login.xml");
|
|---|
| 64 | f_rename("Tlogin.xml", "login.xml");
|
|---|
| 65 | xSemaphoreGive(MutexAccessFlash);
|
|---|
| 66 | return 1;
|
|---|
| 67 | }
|
|---|
| 68 | }
|
|---|
| 69 | }
|
|---|
| 70 | }
|
|---|
| 71 | xSemaphoreGive(MutexAccessFlash);
|
|---|
| 72 | return 0;
|
|---|
| 73 | }
|
|---|
| 74 |
|
|---|
| 75 | void hashtostr(char *str, uint8_t lenstr, char *hash_out)
|
|---|
| 76 | {
|
|---|
| 77 | uint8_t hash[16] = {0};
|
|---|
| 78 | md5((uint8_t*)str, lenstr, hash);
|
|---|
| 79 |
|
|---|
| 80 | char *out = hash_out;
|
|---|
| 81 | for(int i = 0; i < 16; i++) {
|
|---|
| 82 | out += sprintf(out, "%02x", hash[i]);
|
|---|
| 83 | }
|
|---|
| 84 | hash_out[32] = 0;
|
|---|
| 85 | }
|
|---|
| 86 |
|
|---|
| 87 | void setAuth(char *user, char *pass, char *cookie)
|
|---|
| 88 | {
|
|---|
| 89 | char hash_md5[33] = {0};
|
|---|
| 90 | char nonce[11] = {0}, time[11] = {0};
|
|---|
| 91 | uint8_t cnt = 0;
|
|---|
| 92 |
|
|---|
| 93 | sprintf(&nonce[0], "%010x", RNG_get());
|
|---|
| 94 | sprintf(&time[0], "%u", time_to_unix(&RealTimeClock));
|
|---|
| 95 |
|
|---|
| 96 | char str[70] = {0};
|
|---|
| 97 | cnt += sprintf(&str[cnt], "%s", user); //16 ñèìâîëîâ
|
|---|
| 98 | cnt += sprintf(&str[cnt], "%s", pass); // hash 32 ñèìâîëà
|
|---|
| 99 | cnt += sprintf(&str[cnt], "%s", time); // unixtime 10 ñèìâîëîâ
|
|---|
| 100 | cnt += sprintf(&str[cnt], "%s", nonce); // id ñåññèè 10 ñèìâîëîâ
|
|---|
| 101 |
|
|---|
| 102 | hashtostr(str, cnt, hash_md5);
|
|---|
| 103 |
|
|---|
| 104 | cookie_write_open(cookie, 512);
|
|---|
| 105 | cookie_set("login", user);
|
|---|
| 106 | cookie_set("time", time);
|
|---|
| 107 | cookie_set("nonce", nonce);
|
|---|
| 108 | cookie_set("password", hash_md5);
|
|---|
| 109 | cookie_close();
|
|---|
| 110 | }
|
|---|
| 111 |
|
|---|
| 112 | void clearAuth(char *cookie) // 30 us
|
|---|
| 113 | {
|
|---|
| 114 | cookie_write_open(cookie, 512);
|
|---|
| 115 | cookie_set("login", "");
|
|---|
| 116 | cookie_set("time", "");
|
|---|
| 117 | cookie_set("nonce", "");
|
|---|
| 118 | cookie_set("password", "");
|
|---|
| 119 | cookie_close();
|
|---|
| 120 | }
|
|---|
| 121 |
|
|---|
| 122 | uint8_t checkLogin(cookie_token_data_typDef *cookieIn, char *cookieOut)
|
|---|
| 123 | {
|
|---|
| 124 | char hash_md5[33] = {0};
|
|---|
| 125 | char user[17] = {0}, nonce[11] = {0}, time[11] = {0}, pass[33] = {0};
|
|---|
| 126 | uint8_t cnt = 0, index = 0;
|
|---|
| 127 | uint32_t cookie_time, unix_time;
|
|---|
| 128 |
|
|---|
| 129 | if(cookieIn != NULL){
|
|---|
| 130 | cookie_get_option(cookieIn, "login", user);
|
|---|
| 131 | cookie_get_option(cookieIn, "nonce", nonce);
|
|---|
| 132 | cookie_get_option(cookieIn, "time", time);
|
|---|
| 133 | cookie_get_option(cookieIn, "password", pass);
|
|---|
| 134 |
|
|---|
| 135 | for(uint8_t i = 0; i < AMOUNT_MAX_USER; i++){
|
|---|
| 136 | if((memcmp(userTable[i].user, user, userTable[i].len_user) && (userTable[i].len_user > 0)) == 0) {
|
|---|
| 137 | index = i;
|
|---|
| 138 | break;
|
|---|
| 139 | }
|
|---|
| 140 | }
|
|---|
| 141 |
|
|---|
| 142 | cookie_time = atoi(time);
|
|---|
| 143 | unix_time = time_to_unix(&RealTimeClock);
|
|---|
| 144 | if((unix_time < cookie_time) || (unix_time - cookie_time > 86400)) return 0;
|
|---|
| 145 |
|
|---|
| 146 | char str[70] = {0};
|
|---|
| 147 | cnt += sprintf(&str[cnt], "%s", user);
|
|---|
| 148 | cnt += sprintf(&str[cnt], "%s", userTable[index].passHash);
|
|---|
| 149 | cnt += sprintf(&str[cnt], "%s", time);
|
|---|
| 150 | cnt += sprintf(&str[cnt], "%s", nonce);
|
|---|
| 151 |
|
|---|
| 152 | hashtostr(str, cnt, hash_md5);
|
|---|
| 153 |
|
|---|
| 154 | if(memcmp(pass, hash_md5, 32) == 0){
|
|---|
| 155 | setAuth(user, userTable[index].passHash, cookieOut); //óñòàíàâëèâàåì íîâóþ àóòåíòèôèêàöèþ
|
|---|
| 156 | return 1;
|
|---|
| 157 | }
|
|---|
| 158 | }
|
|---|
| 159 | return 0;
|
|---|
| 160 | }
|
|---|
| 161 |
|
|---|
| 162 | void cmd_changePass(json_tokens_data_t *tokens_data, json_response_t *json_response)
|
|---|
| 163 | {
|
|---|
| 164 | char login[17] = {0}, hash_md5_curr[33] = {0}, hash_md5_new[33] = {0};
|
|---|
| 165 | volatile _Bool flagFound = 0;
|
|---|
| 166 | uint8_t ptr_user = 0;
|
|---|
| 167 |
|
|---|
| 168 | if(json_get_value_object(tokens_data, "user", login, json_type_string , json_root) == json_success){ // ïðîâåðèòü åñòü ëè òàêîé ïîëüçîâàòåëü
|
|---|
| 169 | for(uint8_t i = 0; i < AMOUNT_MAX_USER; i++){
|
|---|
| 170 | if(userTable[i].len_user > 0){
|
|---|
| 171 | if(memcmp(userTable[i].user, login, userTable[i].len_user) == 0) { /* åñòü ïîëüçîâàòåëü â òàáëèöå */
|
|---|
| 172 | flagFound = 1;
|
|---|
| 173 | ptr_user = i;
|
|---|
| 174 | break;
|
|---|
| 175 | }
|
|---|
| 176 | }
|
|---|
| 177 | else {
|
|---|
| 178 | json_write_obj_string("status", "error");
|
|---|
| 179 | json_write_obj_string("error", "invalid parametr");
|
|---|
| 180 | }
|
|---|
| 181 | }
|
|---|
| 182 | /* íåò çàïðàøèâàåìîãî ïîëüçîâàòåëÿ */
|
|---|
| 183 | if(!flagFound){
|
|---|
| 184 | json_write_obj_string("status", "error");
|
|---|
| 185 | json_write_obj_string("error", "password change error");
|
|---|
| 186 | return;
|
|---|
| 187 | }
|
|---|
| 188 | /* íåò ïîëÿ new */
|
|---|
| 189 | if(json_get_value_object(tokens_data, "new", hash_md5_new, json_type_string , json_root) != json_success){
|
|---|
| 190 | json_write_obj_string("status", "error");
|
|---|
| 191 | json_write_obj_string("error", "invalid parametr");
|
|---|
| 192 | return;
|
|---|
| 193 | }
|
|---|
| 194 | /* íåò ïîëÿ current */
|
|---|
| 195 | if(json_get_value_object(tokens_data, "current", hash_md5_curr, json_type_string, json_root) != json_success){
|
|---|
| 196 | json_write_obj_string("status", "error");
|
|---|
| 197 | json_write_obj_string("error", "invalid parametr");
|
|---|
| 198 | return;
|
|---|
| 199 | }
|
|---|
| 200 | /* åñëè õåøè íå ñîâïàëè */
|
|---|
| 201 | if(memcmp(userTable[ptr_user].passHash, hash_md5_curr, sizeof(userTable[ptr_user].passHash)) != 0) {
|
|---|
| 202 | json_write_obj_string("status", "error");
|
|---|
| 203 | json_write_obj_string("error", "password change error");
|
|---|
| 204 | return;
|
|---|
| 205 | }
|
|---|
| 206 | /* ïàðîëè ñîâïàëè ïèøåì íîâûé â òàáëèöó */
|
|---|
| 207 | memcpy(userTable[ptr_user].passHash, hash_md5_new, sizeof(userTable[ptr_user].passHash));
|
|---|
| 208 | /*òóò íîâûé ïàðîëü çàïèñûâàåì â ôàéë login.xml*/
|
|---|
| 209 | if(change_pass_to_file(ptr_user, userTable[ptr_user].user, userTable[ptr_user].passHash)) json_write_obj_string("status", "ok");
|
|---|
| 210 | else {
|
|---|
| 211 | json_write_obj_string("status", "error");
|
|---|
| 212 | json_write_obj_string("error", "password change error");
|
|---|
| 213 | }
|
|---|
| 214 | }
|
|---|
| 215 | }
|
|---|
| 216 |
|
|---|
| 217 | extern _Bool ClearPassword;
|
|---|
| 218 |
|
|---|
| 219 | void cmd_login(json_tokens_data_t *tokens_data, json_response_t *json_response)
|
|---|
| 220 | {
|
|---|
| 221 | FIL FileLogin;
|
|---|
| 222 | xml_status_typeDef xmlStatus;
|
|---|
| 223 | char login[17] = {0}, xml_data[33] = {0}, password[33] = {0}, attr[8] = {0};
|
|---|
| 224 |
|
|---|
| 225 | if(json_get_value_object(tokens_data, "user", login, json_type_string, json_root) == json_success){ // çàáèðàåì ïîëå user
|
|---|
| 226 | if(strlen(login) > 0){
|
|---|
| 227 | xmlStatus = xml_get_attr("login.xml", "user", attr, "name", xml_data);
|
|---|
| 228 | if(xmlStatus == XML_ERR_NO_FILE){ // íåò ôàéëà
|
|---|
| 229 | xSemaphoreTake(MutexAccessFlash, portMAX_DELAY);
|
|---|
| 230 | if(f_open(&FileLogin, "login.xml", FA_OPEN_ALWAYS | FA_WRITE) == FR_OK){//ôàéëà íåò è çíà÷èò ïëàòó âîîáùå ïåðâûé ðàç âêëþ÷èëè è ïåðâûé ðàç çàïðîñèëè àâòîðèçàöèþ
|
|---|
| 231 | f_printf(&FileLogin, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
|---|
| 232 | f_printf(&FileLogin, "<users>\n");
|
|---|
| 233 | f_printf(&FileLogin, "\t<user id=\"0\" name=\"admin\" pass=\"\" permissions=\"2147483647\"/>\n"); //ñîçäàåì ïîëüçîâàòåëÿ admin ñ ïóñòûì ïàðîëåì
|
|---|
| 234 | f_printf(&FileLogin, "</users>\n");
|
|---|
| 235 | f_close(&FileLogin);
|
|---|
| 236 | }
|
|---|
| 237 | else{}// îøèáêà ñîçäàíèÿ ôàéëà, ÷òî äåëàòü â ýòîì ñëó÷àå!
|
|---|
| 238 | xSemaphoreGive(MutexAccessFlash);
|
|---|
| 239 | }
|
|---|
| 240 | for(uint8_t i = 0; i < AMOUNT_MAX_USER; i++){
|
|---|
| 241 | sprintf(attr, "id=\"%d\"", i);
|
|---|
| 242 | if((xmlStatus != XML_OK) && (xml_get_attr("login.xml", "user", attr, "name", xml_data) == XML_OK)){
|
|---|
| 243 | userTable[i].len_user = strlen(xml_data);
|
|---|
| 244 | if(userTable[i].len_user > 0){
|
|---|
| 245 | memcpy(userTable[i].user, xml_data, strlen(xml_data));
|
|---|
| 246 | if(memcmp(userTable[i].user, login, userTable[i].len_user) == 0){
|
|---|
| 247 | if(json_get_value_object(tokens_data, "password", password, json_type_string , json_root) == json_success){
|
|---|
| 248 | if(xml_get_attr("login.xml", "user", attr, "pass", xml_data) == XML_OK){
|
|---|
| 249 | uint8_t lenHash = strlen(xml_data);
|
|---|
| 250 | if((ClearPassword) || (lenHash == 0)) memset(userTable[i].passHash, 0x00, sizeof(userTable[i].passHash)); // ClearPassword ïðèìåíÿòü òîëüêî ó admin
|
|---|
| 251 | else if(lenHash > 0) memcpy(userTable[i].passHash, xml_data, sizeof(userTable[i].passHash));
|
|---|
| 252 | if(memcmp(userTable[i].passHash, password, sizeof(userTable[i].passHash)) == 0){
|
|---|
| 253 | setAuth(login, password, cookie_out);
|
|---|
| 254 | json_write_obj_string("status", "ok");
|
|---|
| 255 | __logWrite("Autentification successfully for \"%s\". Remoute ip:%s;\n", login, ip4addr_ntoa(tokens_data->remote_addr));
|
|---|
| 256 | return;
|
|---|
| 257 | }
|
|---|
| 258 | else __logWrite("Autentification error: incorrect password for \"%s\". Remoute ip:%s;\n", login, ip4addr_ntoa(tokens_data->remote_addr));
|
|---|
| 259 | }
|
|---|
| 260 | }
|
|---|
| 261 | }
|
|---|
| 262 | }
|
|---|
| 263 | }
|
|---|
| 264 | }
|
|---|
| 265 | }
|
|---|
| 266 | }
|
|---|
| 267 | json_write_obj_string("status", "error");// îøèáêà ëîãèíà è ïàðîëÿ
|
|---|
| 268 | json_write_obj_string("error", "incorrect login attempt");
|
|---|
| 269 | }
|
|---|