]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/configuration/sgconfig/rsconf.cpp
Усунуто проблему race conditions у 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 <cerrno>
30 #include <csignal>
31
32 #include "configproto.h"
33 #include "blowfish.h"
34
35 #ifndef ENODATA
36 // FreeBSD 4.* - suxx
37 #define ENODATA -1
38 #endif
39
40 enum CONF_STATE
41     {
42     confHdr,
43     confLogin,
44     confLoginCipher,
45     confData
46     };
47
48 enum
49     {
50     ans_ok = 0,
51     ans_err
52     };
53
54 //-----------------------------------------------------------------------------
55 int CONFIGPROTO::Prepare()
56 {
57 list<string> ansList; //óÀÄÁ ÂÕÄÅÔ ÐÏÍÅÝÅΠÏÔ×ÅÔ ÄÌÑ ÍÅÎÅÄÖÅÒÁ ËÌÉÅÎÔÏ×
58 int res;
59 struct sockaddr_in listenAddr;
60
61 sigset_t sigmask, oldmask;
62 sigemptyset(&sigmask);
63 sigaddset(&sigmask, SIGINT);
64 sigaddset(&sigmask, SIGTERM);
65 sigaddset(&sigmask, SIGUSR1);
66 sigaddset(&sigmask, SIGHUP);
67 pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
68
69 listenSocket = socket(PF_INET, SOCK_STREAM, 0);
70
71 if (listenSocket < 0)
72     {
73     errorStr = "Create NET_CONFIGURATOR socket failed.";
74     return -1;
75     }
76
77 listenAddr.sin_family = PF_INET;
78 listenAddr.sin_port = htons(port);
79 listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
80
81 int lng = 1;
82
83 if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4))
84     {
85     errorStr = "Setsockopt failed. " + string(strerror(errno));
86     return -1;
87     }
88
89 res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr));
90
91 if (res == -1)
92     {
93     errorStr = "Bind admin socket failed";
94     return -1;
95     }
96
97 res = listen(listenSocket, 0);
98 if (res == -1)
99     {
100     errorStr = "Listen admin socket failed";
101     return -1;
102     }
103
104 errorStr = "";
105 nonstop = true;
106 return 0;
107 }
108 //-----------------------------------------------------------------------------
109 int CONFIGPROTO::Stop()
110 {
111 nonstop = false;
112 close(listenSocket);
113 //TODO: Idiotism
114 int                 sock;
115 struct sockaddr_in  addr;
116 socklen_t           addrLen;
117 addr.sin_family = PF_INET;
118 addr.sin_port = htons(port);
119 addr.sin_addr.s_addr = inet_addr("127.0.0.1");
120
121 addrLen = sizeof(addr);
122 sock = socket(PF_INET, SOCK_STREAM, 0);
123 connect(sock, (sockaddr*)&addr, addrLen);
124 close(sock);
125 //Idiotism end
126 return 0;
127 }
128 //-----------------------------------------------------------------------------
129 // æÕÎËÃÉÑ ÏÂÝÅÎÉÑ Ó ËÏÎÆÉÇÕÒÁÔÏÒÏÍ
130 void * CONFIGPROTO::Run(void * a)
131 {
132 /*
133  * Function Name:ReciveSendConf
134  * Parameters: void * a ÕËÁÚÁÔÅÌØ ÎÁ ÜËÚÅÍÐÌÑÒ ËÌÁÓÓÁ CONFIGPROTO
135  * Description: üÔÁ ÆÕÎËÃÉÑ ÏÂÅÓÐÅÞÉ×ÁÅÔ ÓÅÔÅ×ÏÅ ×ÚÁÉÍÏÄÅÊÓÔ×ÉÅ
136  *  Ó íÅÎÅÄÖÅÒÏÍ ëÌÉÅÎÔÏ×. ÷ ÅÅ ÚÁÄÁÞÉ ×ÈÏÄÉÔ: ÐÒÉÅÍ ÚÁÐÒÏÓÏ× ÐÏ TCP/IP
137  *  ÉÈ ÒÁÓÛÉÆÒÏ×ËÁ, ÐÅÒÅÄÁÞÁ ÐÒÉÎÑÔÙÈ ÄÁÎÎÙÈ ÁÎÁÌÉÚÁÔÏÒÕ É ÏÔÐÒÁ×ËÁ ÏÔ×ÅÔÁ ÎÁÚÁÄ.
138  * Returns: ×ÏÚ×ÒÁÝÁÅÔ NULL
139  */
140
141 CONFIGPROTO * cp = (CONFIGPROTO*)a;
142 cp->state = confHdr;
143
144 while (cp->nonstop)
145     {
146     cp->state = confHdr;
147     struct sockaddr_in outerAddr;
148     socklen_t outerAddrLen(sizeof(outerAddr));
149     int outerSocket = accept(cp->listenSocket,
150                              (struct sockaddr*)(&outerAddr),
151                              &outerAddrLen);
152
153     if (!cp->nonstop)
154         {
155         continue;
156         }
157
158     if (outerSocket == -1)
159         {
160         printfd(__FILE__, "accept failed\n");
161         usleep(100000);
162         continue;
163         }
164
165     cp->adminIP = *(unsigned int*)&(outerAddr.sin_addr);
166
167     printfd(__FILE__, "Connection accepted from %s\n", inet_ntostring(outerAddr.sin_addr.s_addr).c_str());
168
169     if (cp->state == confHdr)
170         {
171         if (cp->RecvHdr(outerSocket) < 0)
172             {
173             close(outerSocket);
174             continue;
175             }
176         if (cp->state == confLogin)
177             {
178             if (cp->SendHdrAnswer(outerSocket, ans_ok) < 0)
179                 {
180                 close(outerSocket);
181                 continue;
182                 }
183
184             if (cp->RecvLogin(outerSocket) < 0)
185                 {
186                 close(outerSocket);
187                 continue;
188                 }
189
190             if (cp->state == confLoginCipher)
191                 {
192                 if (cp->SendLoginAnswer(outerSocket, ans_ok) < 0)
193                     {
194                     close(outerSocket);
195                     continue;
196                     }
197                 if (cp->RecvLoginS(outerSocket) < 0)
198                     {
199                     close(outerSocket);
200                     continue;
201                     }
202
203                 if (cp->state == confData)
204                     {
205                     if (cp->SendLoginSAnswer(outerSocket, ans_ok) < 0)
206                         {
207                         close(outerSocket);
208                         continue;
209                         }
210                     if (cp->RecvData(outerSocket) < 0)
211                         {
212                         close(outerSocket);
213                         continue;
214                         }
215                     cp->state = confHdr;
216                     }
217                 else
218                     {
219                     if (cp->SendLoginSAnswer(outerSocket, ans_err) < 0)
220                         {
221                         close(outerSocket);
222                         continue;
223                         }
224                     cp->WriteLogAccessFailed(cp->adminIP);
225                     }
226                 }
227             else
228                 {
229                 cp->WriteLogAccessFailed(cp->adminIP);
230                 }
231             }
232         else
233             {
234             cp->WriteLogAccessFailed(cp->adminIP);
235             if (cp->SendHdrAnswer(outerSocket, ans_err) < 0)
236                 {
237                 close(outerSocket);
238                 continue;
239                 }
240             }
241         }
242     else
243         {
244         cp->WriteLogAccessFailed(cp->adminIP);
245         }
246     close(outerSocket);
247     }
248
249 return NULL;
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.SetAdminIP(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 sprintf(s, "<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 //-----------------------------------------------------------------------------