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