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 | }
|
---|