]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/configuration/sgconfig/rsconf.cpp
Додано розширений формат помісячної статистики
[stg.git] / projects / stargazer / plugins / configuration / sgconfig / rsconf.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*******************************************************************
18 *
19 *    DESCRIPTION: æÁÊÌ Ó ÏÓÎÏ×ÎÙÍÉ ÆÕÎËÃÉÑÍÉ ÄÌÑ ÓÅÔÅ×ÏÇÏ ÏÂÍÅÎÁ ÄÁÎÎÙÍÉ
20 *    Ó ÍÅÎÅÄÖÅÒÏÍ ËÌÉÅÎÔÏ×. ðÒÉÅÍ, ÐÅÒÅÄÁÞÁ É ÛÉÆÒÏ×ÁÎÉÅ ÓÏÏÂÝÅÎÉÊ.
21 *
22 *    AUTHOR: Boris Mikhailenko <stg34@stargazer.dp.ua>
23 *
24 *    $Revision: 1.24 $
25 *    $Date: 2010/10/04 20:24:54 $
26 *
27 *******************************************************************/
28
29 #include <cerrno>
30 #include <csignal>
31 #include <cstdio> // snprintf
32
33 #include "configproto.h"
34 #include "blowfish.h"
35
36 #ifndef ENODATA
37 // FreeBSD 4.* - suxx
38 #define ENODATA -1
39 #endif
40
41 enum CONF_STATE
42     {
43     confHdr,
44     confLogin,
45     confLoginCipher,
46     confData
47     };
48
49 enum
50     {
51     ans_ok = 0,
52     ans_err
53     };
54
55 //-----------------------------------------------------------------------------
56 int CONFIGPROTO::Prepare()
57 {
58 list<string> ansList; //óÀÄÁ ÂÕÄÅÔ ÐÏÍÅÝÅΠÏÔ×ÅÔ ÄÌÑ ÍÅÎÅÄÖÅÒÁ ËÌÉÅÎÔÏ×
59 int res;
60 struct sockaddr_in listenAddr;
61
62 sigset_t sigmask, oldmask;
63 sigemptyset(&sigmask);
64 sigaddset(&sigmask, SIGINT);
65 sigaddset(&sigmask, SIGTERM);
66 sigaddset(&sigmask, SIGUSR1);
67 sigaddset(&sigmask, SIGHUP);
68 pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
69
70 listenSocket = socket(PF_INET, SOCK_STREAM, 0);
71
72 if (listenSocket < 0)
73     {
74     errorStr = "Create NET_CONFIGURATOR socket failed.";
75     return -1;
76     }
77
78 listenAddr.sin_family = PF_INET;
79 listenAddr.sin_port = htons(port);
80 listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
81
82 int lng = 1;
83
84 if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
85     {
86     errorStr = "Setsockopt failed. " + string(strerror(errno));
87     return -1;
88     }
89
90 res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
91
92 if (res == -1)
93     {
94     errorStr = "Bind admin socket failed";
95     return -1;
96     }
97
98 res = listen(listenSocket, 0);
99 if (res == -1)
100     {
101     errorStr = "Listen admin socket failed";
102     return -1;
103     }
104
105 errorStr = "";
106 nonstop = true;
107 return 0;
108 }
109 //-----------------------------------------------------------------------------
110 int CONFIGPROTO::Stop()
111 {
112 nonstop = false;
113 close(listenSocket);
114 //TODO: Idiotism
115 int                 sock;
116 struct sockaddr_in  addr;
117 socklen_t           addrLen;
118 addr.sin_family = PF_INET;
119 addr.sin_port = htons(port);
120 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
121
122 addrLen = sizeof(addr);
123 sock = socket(PF_INET, SOCK_STREAM, 0);
124 connect(sock, (sockaddr*)&addr, addrLen);
125 close(sock);
126 //Idiotism end
127 return 0;
128 }
129 //-----------------------------------------------------------------------------
130 // æÕÎËÃÉÑ ÏÂÝÅÎÉÑ Ó ËÏÎÆÉÇÕÒÁÔÏÒÏÍ
131 void * CONFIGPROTO::Run(void * a)
132 {
133 /*
134  * Function Name:ReciveSendConf
135  * Parameters: void * a ÕËÁÚÁÔÅÌØ ÎÁ ÜËÚÅÍÐÌÑÒ ËÌÁÓÓÁ CONFIGPROTO
136  * Description: üÔÁ ÆÕÎËÃÉÑ ÏÂÅÓÐÅÞÉ×ÁÅÔ ÓÅÔÅ×ÏÅ ×ÚÁÉÍÏÄÅÊÓÔ×ÉÅ
137  *  Ó íÅÎÅÄÖÅÒÏÍ ëÌÉÅÎÔÏ×. ÷ ÅÅ ÚÁÄÁÞÉ ×ÈÏÄÉÔ: ÐÒÉÅÍ ÚÁÐÒÏÓÏ× ÐÏ TCP/IP
138  *  ÉÈ ÒÁÓÛÉÆÒÏ×ËÁ, ÐÅÒÅÄÁÞÁ ÐÒÉÎÑÔÙÈ ÄÁÎÎÙÈ ÁÎÁÌÉÚÁÔÏÒÕ É ÏÔÐÒÁ×ËÁ ÏÔ×ÅÔÁ ÎÁÚÁÄ.
139  * Returns: ×ÏÚ×ÒÁÝÁÅÔ NULL
140  */
141
142 CONFIGPROTO * cp = (CONFIGPROTO*)a;
143 cp->state = confHdr;
144
145 while (cp->nonstop)
146     {
147     cp->state = confHdr;
148     struct sockaddr_in outerAddr;
149     socklen_t outerAddrLen(sizeof(outerAddr));
150     int outerSocket = accept(cp->listenSocket,
151                              (struct sockaddr*)(&outerAddr),
152                              &outerAddrLen);
153
154     if (!cp->nonstop)
155         {
156         continue;
157         }
158
159     if (outerSocket == -1)
160         {
161         printfd(__FILE__, "accept failed\n");
162         usleep(100000);
163         continue;
164         }
165
166     cp->adminIP = *(unsigned int*)&(outerAddr.sin_addr);
167
168     printfd(__FILE__, "Connection accepted from %s\n", inet_ntostring(outerAddr.sin_addr.s_addr).c_str());
169
170     if (cp->state == confHdr)
171         {
172         if (cp->RecvHdr(outerSocket) < 0)
173             {
174             close(outerSocket);
175             continue;
176             }
177         if (cp->state == confLogin)
178             {
179             if (cp->SendHdrAnswer(outerSocket, ans_ok) < 0)
180                 {
181                 close(outerSocket);
182                 continue;
183                 }
184
185             if (cp->RecvLogin(outerSocket) < 0)
186                 {
187                 close(outerSocket);
188                 continue;
189                 }
190
191             if (cp->state == confLoginCipher)
192                 {
193                 if (cp->SendLoginAnswer(outerSocket, ans_ok) < 0)
194                     {
195                     close(outerSocket);
196                     continue;
197                     }
198                 if (cp->RecvLoginS(outerSocket) < 0)
199                     {
200                     close(outerSocket);
201                     continue;
202                     }
203
204                 if (cp->state == confData)
205                     {
206                     if (cp->SendLoginSAnswer(outerSocket, ans_ok) < 0)
207                         {
208                         close(outerSocket);
209                         continue;
210                         }
211                     if (cp->RecvData(outerSocket) < 0)
212                         {
213                         close(outerSocket);
214                         continue;
215                         }
216                     cp->state = confHdr;
217                     }
218                 else
219                     {
220                     if (cp->SendLoginSAnswer(outerSocket, ans_err) < 0)
221                         {
222                         close(outerSocket);
223                         continue;
224                         }
225                     cp->WriteLogAccessFailed(cp->adminIP);
226                     }
227                 }
228             else
229                 {
230                 cp->WriteLogAccessFailed(cp->adminIP);
231                 }
232             }
233         else
234             {
235             cp->WriteLogAccessFailed(cp->adminIP);
236             if (cp->SendHdrAnswer(outerSocket, ans_err) < 0)
237                 {
238                 close(outerSocket);
239                 continue;
240                 }
241             }
242         }
243     else
244         {
245         cp->WriteLogAccessFailed(cp->adminIP);
246         }
247     close(outerSocket);
248     }
249
250 return NULL;
251 }
252 //-----------------------------------------------------------------------------
253 int CONFIGPROTO::RecvHdr(int sock)
254 {
255 char buf[sizeof(STG_HEADER)];
256 memset(buf, 0, sizeof(STG_HEADER));
257 int ret;
258 int stgHdrLen = strlen(STG_HEADER);
259 for (int i = 0; i < stgHdrLen; i++)
260     {
261     ret = recv(sock, &buf[i], 1, 0);
262     if (ret <= 0)
263         {
264         state = confHdr;
265         return -1;
266         }
267     }
268
269 if (0 == strncmp(buf, STG_HEADER, strlen(STG_HEADER)))
270     {
271     state = confLogin;
272     return 0;
273     }
274 else
275     {
276     SendError("Bad request");
277     }
278
279 state = confHdr;
280 return -1;
281 }
282 //-----------------------------------------------------------------------------
283 int CONFIGPROTO::SendHdrAnswer(int sock, int err)
284 {
285 int ret;
286
287 if (err)
288     {
289     ret = send(sock, ERR_HEADER, sizeof(ERR_HEADER)-1, 0);
290     if (ret < 0)
291         {
292         WriteServLog("send ERR_HEADER error in SendHdrAnswer.");
293         return -1;
294         }
295     }
296 else
297     {
298     ret = send(sock, OK_HEADER, sizeof(OK_HEADER)-1, 0);
299     if (ret < 0)
300         {
301         WriteServLog("send OK_HEADER error in SendHdrAnswer.");
302         return -1;
303         }
304     }
305
306 return 0;
307 }
308 //-----------------------------------------------------------------------------
309 int CONFIGPROTO::RecvLogin(int sock)
310 {
311 char login[ADM_LOGIN_LEN+1];
312 int ret;
313
314 memset(login, 0, ADM_LOGIN_LEN + 1);
315
316 ret = recv(sock, login, ADM_LOGIN_LEN, 0);
317
318 if (ret < 0)
319     {
320     // Error in network
321     close(sock);
322     state = confHdr;
323     return ENODATA;
324     }
325
326 if (ret < ADM_LOGIN_LEN)
327     {
328     // Error in protocol
329     close(sock);
330     state = confHdr;
331     return ENODATA;
332     }
333
334 if (admins->FindAdmin(login, &currAdmin))
335     {
336     // Admin not found
337     close(sock);
338     state = confHdr;
339     return ENODATA;
340     }
341 currAdmin.SetAdminIP(adminIP);
342 adminLogin = login;
343 state = confLoginCipher;
344 return 0;
345 }
346 //-----------------------------------------------------------------------------
347 int CONFIGPROTO::SendLoginAnswer(int sock, int)
348 {
349 int ret;
350
351 ret = send(sock, OK_LOGIN, sizeof(OK_LOGIN)-1, 0);
352 if (ret < 0)
353     {
354     WriteServLog("Send OK_LOGIN error in SendLoginAnswer.");
355     return -1;
356     }
357 return 0;
358 }
359 //-----------------------------------------------------------------------------
360 int CONFIGPROTO::RecvLoginS(int sock)
361 {
362 char loginS[ADM_LOGIN_LEN + 1];
363 char login[ADM_LOGIN_LEN + 1];
364 int ret;
365 BLOWFISH_CTX ctx;
366 memset(loginS, 0, ADM_LOGIN_LEN + 1);
367
368 int total = 0;
369
370 while (total < ADM_LOGIN_LEN)
371     {
372     ret = recv(sock, &loginS[total], ADM_LOGIN_LEN - total, 0);
373
374     if (ret < 0)
375         {
376         // Network error
377         printfd(__FILE__, "recv error: '%s'\n", strerror(errno));
378         close(sock);
379         state = confHdr;
380         return ENODATA;
381         }
382
383     total += ret;
384     }
385
386 if (currAdmin.GetLogin() == "")
387     {
388     state = confHdr;
389     return ENODATA;
390     }
391
392 EnDecodeInit(currAdmin.GetPassword().c_str(), ADM_PASSWD_LEN, &ctx);
393
394 for (int i = 0; i < ADM_LOGIN_LEN/8; i++)
395     {
396     DecodeString(login + i*8, loginS + i*8, &ctx);
397     }
398
399 if (currAdmin == admins->GetNoAdmin())
400     {
401     // If there are no admins registered in the system - give access with any password
402     state = confData;
403     return 0;
404     }
405
406 if (strncmp(currAdmin.GetLogin().c_str(), login, ADM_LOGIN_LEN) != 0)
407     {
408     state = confHdr;
409     return ENODATA;
410     }
411
412 state = confData;
413 return 0;
414 }
415 //-----------------------------------------------------------------------------
416 int CONFIGPROTO::SendLoginSAnswer(int sock, int err)
417 {
418 int ret;
419
420 if (err)
421     {
422     ret = send(sock, ERR_LOGINS, sizeof(ERR_LOGINS)-1, 0);
423     if (ret < 0)
424         {
425         WriteServLog("send ERR_LOGIN error in SendLoginAnswer.");
426         return -1;
427         }
428     }
429 else
430     {
431     ret = send(sock, OK_LOGINS, sizeof(OK_LOGINS)-1, 0);
432     if (ret < 0)
433         {
434         WriteServLog("send OK_LOGINS error in SendLoginSAnswer.");
435         return -1;
436         }
437     }
438 return 0;
439 }
440 //-----------------------------------------------------------------------------
441 int CONFIGPROTO::RecvData(int sock)
442 {
443 int ret;
444 char bufferS[8];
445 char buffer[9];
446
447 buffer[8] = 0;
448
449 requestList.clear();
450 BLOWFISH_CTX ctx;
451
452 EnDecodeInit(currAdmin.GetPassword().c_str(), ADM_PASSWD_LEN, &ctx);
453
454 while (1)
455     {
456     int total = 0;
457     bool done = false;
458     while (total < 8)
459         {
460         ret = recv(sock, &bufferS[total], 8 - total, 0);
461         if (ret < 0)
462             {
463             // Network error
464             close(sock);
465             return 0;
466             }
467
468         if (ret < 8)
469             {
470             if (memchr(buffer, 0, ret) != NULL)
471                 {
472                 done = true;
473                 break;
474                 }
475             }
476
477         total += ret;
478         }
479
480     DecodeString(buffer, bufferS, &ctx);
481     requestList.push_back(std::string(buffer, total));
482
483     if (done || memchr(buffer, 0, total) != NULL)
484         {
485         // ëÏÎÅàÐÏÓÙÌËÉ
486         if (ParseCommand())
487             {
488             SendError("Bad command");
489             }
490         return SendDataAnswer(sock);
491         }
492     }
493 return 0;
494 }
495 //-----------------------------------------------------------------------------
496 int CONFIGPROTO::SendDataAnswer(int sock)
497 {
498 list<string>::iterator li;
499 li = answerList.begin();
500
501 BLOWFISH_CTX ctx;
502
503 char buff[8];
504 char buffS[8];
505 int n = 0;
506 int k = 0;
507 int ret = 0;
508
509 EnDecodeInit(currAdmin.GetPassword().c_str(), ADM_PASSWD_LEN, &ctx);
510
511 while (li != answerList.end())
512     {
513     while ((*li).c_str()[k])
514         {
515         buff[n%8] = (*li).c_str()[k];
516         n++;
517         k++;
518
519         if (n%8 == 0)
520             {
521             EncodeString(buffS, buff, &ctx);
522             ret = send(sock, buffS, 8, 0);
523             if (ret < 0)
524                 {
525                 return -1;
526                 }
527             }
528         }
529     k = 0;// new node
530     li++;
531     }
532
533 if (answerList.empty()) {
534     return 0;
535 }
536
537 buff[n%8] = 0;
538 EncodeString(buffS, buff, &ctx);
539
540 answerList.clear();
541
542 return send(sock, buffS, 8, 0);
543 }
544 //-----------------------------------------------------------------------------
545 void CONFIGPROTO::SendError(const char * text)
546 {
547 char s[255];
548 answerList.clear();
549 snprintf(s, 255, "<Error value=\"%s\"/>", text);
550 answerList.push_back(s);
551 }
552 //-----------------------------------------------------------------------------
553 void CONFIGPROTO::WriteLogAccessFailed(uint32_t ip)
554 {
555 WriteServLog("Admin's connect failed. IP %s", inet_ntostring(ip).c_str());
556 }
557 //-----------------------------------------------------------------------------