[7928] Player must standup at stun (from 1.5 client starting)
[getmangos.git] / src / mangosd / RASocket.cpp
blobdca788232d04f6b0cf8b5f27fc5f04edc0e0acb0
1 /*
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
19 /** \file
20 \ingroup mangosd
23 #include "Common.h"
24 #include "Database/DatabaseEnv.h"
25 #include "Log.h"
26 #include "RASocket.h"
27 #include "World.h"
28 #include "Config/ConfigEnv.h"
29 #include "Util.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.
33 SOCKET r;
35 #define dropclient {Sendf("I'm busy right now, come back later."); \
36 SetCloseAndDelete(); \
37 return; \
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
52 iSess =iSession++ ;
54 ///- Get the config parameters
55 bSecure = sConfig.GetBoolDefault( "RA.Secure", true );
56 iMinLevel = sConfig.GetIntDefault( "RA.MinLevel", 3 );
58 ///- Initialize buffer and data
59 iInputLength=0;
60 buff=new char[RA_BUFF_SIZE];
61 stage=NONE;
64 /// RASocket destructor
65 RASocket::~RASocket()
67 ///- Delete buffer and decrease active admins count
68 delete [] buff;
70 sLog.outRALog("Connection was closed.\n");
72 if(stage==OK)
73 iUsers--;
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
82 if(iUsers)
83 dropclient
85 ///- Else print Motd
86 Sendf("%s\r\n",sWorld.GetMotd());
89 /// Read data from the network
90 void RASocket::OnRead()
92 ///- Read data and check input length
93 TcpSocket::OnRead();
95 unsigned int sz=ibuf.GetLength();
96 if(iInputLength+sz>=RA_BUFF_SIZE)
98 sLog.outRALog("Input buffer overflow, possible DOS attack.\n");
99 SetCloseAndDelete();
100 return;
103 ///- If there is already an active admin (other than you), drop the connection
104 if(stage!=OK && iUsers)
105 dropclient
107 char *inp = new char [sz+1];
108 ibuf.Read(inp,sz);
110 /// \todo Can somebody explain this 'Linux bugfix'?
111 if(stage==NONE)
112 if(sz>4) //linux remote telnet
113 if(memcmp(inp ,"USER ",5))
115 delete [] inp;return;
116 printf("lin bugfix");
117 } //linux bugfix
119 ///- Discard data after line break or line feed
120 bool gotenter=false;
121 unsigned int y=0;
122 for(;y<sz;y++)
123 if(inp[y]=='\r'||inp[y]=='\n')
125 gotenter=true;
126 break;
129 //No buffer overflow (checked above)
130 memcpy(&buff[iInputLength],inp,y);
131 iInputLength+=y;
132 delete [] inp;
133 if(gotenter)
136 buff[iInputLength]=0;
137 iInputLength=0;
138 switch(stage)
140 /// <ul> <li> If the input is 'USER <username>'
141 case NONE:
142 if(!memcmp(buff,"USER ",5)) //got "USER" cmd
144 szLogin=&buff[5];
146 ///- Get the gmlevel and password from the account table
147 std::string login = szLogin;
149 ///- Convert Account name to Upper Format
150 AccountMgr::normilizeString(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
158 if(!result)
160 Sendf("-No such user.\r\n");
161 sLog.outRALog("User %s does not exist.\n",szLogin.c_str());
162 if(bSecure)SetCloseAndDelete();
164 else
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();
176 } else
178 stage=LG;
180 delete result;
183 break;
184 ///<li> If the input is 'PASS <password>' (and the user already gave his username)
185 case LG:
186 if(!memcmp(buff,"PASS ",5)) //got "PASS" cmd
187 { //login+pass ok
188 ///- If password is correct, increment the number of active administrators
189 std::string login = szLogin;
190 std::string pw = &buff[5];
192 AccountMgr::normilizeString(login);
193 AccountMgr::normilizeString(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());
201 if(check)
203 delete check;
204 r=GetSocket();
205 stage=OK;
206 ++iUsers;
208 Sendf("+Logged in.\r\n");
209 sLog.outRALog("User %s has logged in.\n",szLogin.c_str());
210 Sendf("mangos>");
212 else
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();
220 break;
221 ///<li> If user is logged, parse and execute the command
222 case OK:
223 if(strlen(buff))
225 sLog.outRALog("Got '%s' cmd.\n",buff);
226 sWorld.QueueCliCommand(&RASocket::zprint , buff);
228 else
229 Sendf("mangos>");
230 break;
231 ///</ul>
237 /// Output function
238 void RASocket::zprint( const char * szText )
240 if( !szText )
241 return;
243 #ifdef RA_CRYPT
245 char *megabuffer=strdup(szText);
246 unsigned int sz=strlen(megabuffer);
247 Encrypt(megabuffer,sz);
248 send(r,megabuffer,sz,0);
249 delete [] megabuffer;
251 #else
253 unsigned int sz=strlen(szText);
254 send(r,szText,sz,0);
256 #endif