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