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