2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "Database/DatabaseEnv.h"
28 #include "Config/ConfigEnv.h"
30 #include "AccountMgr.h"
32 /// \todo Make this thread safe if in the future 2 admins should be able to log at the same time.
35 #define dropclient {Sendf("I'm busy right now, come back later."); \
36 SetCloseAndDelete(); \
40 uint32 iSession
=0; ///< Session number (incremented each time a new connection is made)
41 unsigned int iUsers
=0; ///< Number of active administrators
43 typedef int(* pPrintf
)(const char*,...);
45 void ParseCommand(CliCommandHolder::Print
*, char*command
);
47 /// RASocket constructor
48 RASocket::RASocket(ISocketHandler
&h
): TcpSocket(h
)
51 ///- Increment the session number
54 ///- Get the config parameters
55 bSecure
= sConfig
.GetBoolDefault( "RA.Secure", true );
56 iMinLevel
= sConfig
.GetIntDefault( "RA.MinLevel", 3 );
58 ///- Initialize buffer and data
60 buff
=new char[RA_BUFF_SIZE
];
64 /// RASocket destructor
67 ///- Delete buffer and decrease active admins count
70 sLog
.outRALog("Connection was closed.\n");
76 /// Accept an incoming connection
77 void RASocket::OnAccept()
79 std::string ss
=GetRemoteAddress();
80 sLog
.outRALog("Incoming connection from %s.\n",ss
.c_str());
81 ///- If there is already an active admin, drop the connection
86 Sendf("%s\r\n",sWorld
.GetMotd());
89 /// Read data from the network
90 void RASocket::OnRead()
92 ///- Read data and check input length
95 unsigned int sz
=ibuf
.GetLength();
96 if(iInputLength
+sz
>=RA_BUFF_SIZE
)
98 sLog
.outRALog("Input buffer overflow, possible DOS attack.\n");
103 ///- If there is already an active admin (other than you), drop the connection
104 if(stage
!=OK
&& iUsers
)
107 char *inp
= new char [sz
+1];
110 /// \todo Can somebody explain this 'Linux bugfix'?
112 if(sz
>4) //linux remote telnet
113 if(memcmp(inp
,"USER ",5))
115 delete [] inp
;return;
116 printf("lin bugfix");
119 ///- Discard data after line break or line feed
123 if(inp
[y
]=='\r'||inp
[y
]=='\n')
129 //No buffer overflow (checked above)
130 memcpy(&buff
[iInputLength
],inp
,y
);
136 buff
[iInputLength
]=0;
140 /// <ul> <li> If the input is 'USER <username>'
142 if(!memcmp(buff
,"USER ",5)) //got "USER" cmd
146 ///- Get the gmlevel and password from the account table
147 std::string login
= szLogin
;
149 ///- Convert Account name to Upper Format
150 AccountMgr::normalizeString(login
);
152 ///- Escape the Login to allow quotes in names
153 loginDatabase
.escape_string(login
);
155 QueryResult
* result
= loginDatabase
.PQuery("SELECT gmlevel FROM account WHERE username = '%s'",login
.c_str());
157 ///- If the user is not found, deny access
160 Sendf("-No such user.\r\n");
161 sLog
.outRALog("User %s does not exist.\n",szLogin
.c_str());
162 if(bSecure
)SetCloseAndDelete();
166 Field
*fields
= result
->Fetch();
168 //szPass=fields[0].GetString();
170 ///- if gmlevel is too low, deny access
171 if(fields
[0].GetUInt32()<iMinLevel
)
173 Sendf("-Not enough privileges.\r\n");
174 sLog
.outRALog("User %s has no privilege.\n",szLogin
.c_str());
175 if(bSecure
)SetCloseAndDelete();
184 ///<li> If the input is 'PASS <password>' (and the user already gave his username)
186 if(!memcmp(buff
,"PASS ",5)) //got "PASS" cmd
188 ///- If password is correct, increment the number of active administrators
189 std::string login
= szLogin
;
190 std::string pw
= &buff
[5];
192 AccountMgr::normalizeString(login
);
193 AccountMgr::normalizeString(pw
);
194 loginDatabase
.escape_string(login
);
195 loginDatabase
.escape_string(pw
);
197 QueryResult
*check
= loginDatabase
.PQuery(
198 "SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))",
199 login
.c_str(), pw
.c_str());
208 Sendf("+Logged in.\r\n");
209 sLog
.outRALog("User %s has logged in.\n",szLogin
.c_str());
214 ///- Else deny access
215 Sendf("-Wrong pass.\r\n");
216 sLog
.outRALog("User %s has failed to log in.\n",szLogin
.c_str());
217 if(bSecure
)SetCloseAndDelete();
221 ///<li> If user is logged, parse and execute the command
225 sLog
.outRALog("Got '%s' cmd.\n",buff
);
226 sWorld
.QueueCliCommand(&RASocket::zprint
, buff
);
238 void RASocket::zprint( const char * szText
)
245 char *megabuffer
= mangos_strdup(szText
);
246 unsigned int sz
=strlen(megabuffer
);
247 Encrypt(megabuffer
,sz
);
248 send(r
,megabuffer
,sz
,0);
249 delete [] megabuffer
;
253 unsigned int sz
=strlen(szText
);