88#include " settings.hpp"
99
1010#include < cstdio>
11+ #include < set>
1112
1213static SOCKET listener;
1314static std::mutex sockLock; // guards socket list
1415static std::list<SOCKET > sockets;
16+ static std::set<SOCKET > pendingAuth; // sockets that haven't authenticated yet
1517static sockaddr_in address;
1618
1719std::vector<std::string> Monitor::chats;
@@ -21,28 +23,33 @@ std::vector<std::string> Monitor::namereqs;
2123
2224using namespace Monitor ;
2325
26+ static void closeSock (SOCKET sock) {
27+ #ifdef _WIN32
28+ shutdown (sock, SD_BOTH );
29+ closesocket (sock);
30+ #else
31+ shutdown (sock, SHUT_RDWR );
32+ close (sock);
33+ #endif
34+ }
35+
2436static bool transmit (std::list<SOCKET >::iterator& it, char *buff, int len) {
2537 int n = 0 ;
2638 int sock = *it;
2739
2840 while (n < len) {
29- n + = send (sock, buff+n, len-n, 0 );
30- if (SOCKETERROR (n )) {
41+ int ret = send (sock, buff+n, len-n, 0 );
42+ if (SOCKETERROR (ret )) {
3143 printSocketError (" send" );
3244
33- #ifdef _WIN32
34- shutdown (sock, SD_BOTH );
35- closesocket (sock);
36- #else
37- shutdown (sock, SHUT_RDWR );
38- close (sock);
39- #endif
45+ closeSock (sock);
4046
4147 std::cout << " [INFO] Disconnected a monitor" << std::endl;
4248
4349 it = sockets.erase (it);
4450 return false ;
4551 }
52+ n += ret;
4653 }
4754
4855 return true ;
@@ -67,7 +74,7 @@ static int process_email(char *buff, std::string email) {
6774 int i = 6 ;
6875
6976 for (char c : email) {
70- if (i == BUFSIZE -2 )
77+ if (i >= BUFSIZE -3 )
7178 break ;
7279
7380 buff[i++] = c;
@@ -86,6 +93,38 @@ static void tick(CNServer *serv, time_t delta) {
8693 char buff[BUFSIZE ];
8794 int n;
8895
96+ // check pending auth sockets for incoming password
97+ for (auto it = pendingAuth.begin (); it != pendingAuth.end (); ) {
98+ SOCKET s = *it;
99+ char authbuf[256 ] = {};
100+ int recved = recv (s, authbuf, sizeof (authbuf) - 1 , 0 );
101+ if (recved > 0 ) {
102+ // strip trailing newline/whitespace
103+ std::string pass (authbuf, recved);
104+ while (!pass.empty () && (pass.back () == ' \n ' || pass.back () == ' \r ' || pass.back () == ' ' ))
105+ pass.pop_back ();
106+ if (timingSafeStrcmp (pass.c_str (), settings::MONITORPASS .c_str ()) == 0 ) {
107+ sockets.push_back (s);
108+ std::cout << " [INFO] Monitor client authenticated" << std::endl;
109+ } else {
110+ std::cout << " [WARN] Monitor client failed authentication" << std::endl;
111+ closeSock (s);
112+ }
113+ it = pendingAuth.erase (it);
114+ } else if (recved == 0 ) {
115+ closeSock (s);
116+ it = pendingAuth.erase (it);
117+ } else {
118+ // EWOULDBLOCK is fine, just wait
119+ if (OF_ERRNO != OF_EWOULD ) {
120+ closeSock (s);
121+ it = pendingAuth.erase (it);
122+ } else {
123+ ++it;
124+ }
125+ }
126+ }
127+
89128 auto it = sockets.begin ();
90129outer:
91130 while (it != sockets.end ()) {
@@ -179,7 +218,11 @@ bool Monitor::acceptConnection(SOCKET fd, uint16_t revents) {
179218 {
180219 std::lock_guard<std::mutex> lock (sockLock);
181220
182- sockets.push_back (sock);
221+ if (settings::MONITORPASS .empty ()) {
222+ sockets.push_back (sock);
223+ } else {
224+ pendingAuth.insert (sock);
225+ }
183226 }
184227
185228 return true ;
0 commit comments