root/trunk/src/trinitycore/RASocket.cpp @ 149

Revision 149, 7.9 kB (checked in by yumileroy, 17 years ago)

[svn] *Implement new player conditions CONDITION_NO_AURA, CONDITION_ACTIVE_EVENT
* Default behaviour of pets for creatures changed to REACT_DEFENSIVE
* Disallowed sending wrapped items as COD
* Prevent loading and saving single target auras for pet in same way as already implemented for player
* Correctly limit use some flask types to zones.
* Fixed extracting common.MPQ under *nix
* Many small xleanups and fixes.
** mangos merge rev.

TEST REV so be careful of creepy crawly bugs!

Original author: KingPin?
Date: 2008-11-02 16:53:46-06:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/** \file
22    \ingroup Trinityd
23*/
24
25#include "Common.h"
26#include "Database/DatabaseEnv.h"
27#include "Log.h"
28#include "RASocket.h"
29#include "World.h"
30#include "Config/ConfigEnv.h"
31#include "Util.h"
32#include "AccountMgr.h"
33
34/// \todo Make this thread safe if in the future 2 admins should be able to log at the same time.
35SOCKET r;
36
37#define dropclient {Sendf("I'm busy right now, come back later."); \
38        SetCloseAndDelete(); \
39        return; \
40    }
41
42uint32 iSession=0;                                          ///< Session number (incremented each time a new connection is made)
43unsigned int iUsers=0;                                      ///< Number of active administrators
44
45typedef int(* pPrintf)(const char*,...);
46
47void ParseCommand(CliCommandHolder::Print*, char*command);
48
49/// RASocket constructor
50RASocket::RASocket(ISocketHandler &h): TcpSocket(h)
51{
52
53    ///- Increment the session number
54    iSess =iSession++ ;
55
56    ///- Get the config parameters
57    bSecure = sConfig.GetBoolDefault( "RA.Secure", true );
58    iMinLevel = sConfig.GetIntDefault( "RA.MinLevel", 3 );
59
60    ///- Initialize buffer and data
61    iInputLength=0;
62    buff=new char[RA_BUFF_SIZE];
63    stage=NONE;
64}
65
66/// RASocket destructor
67RASocket::~RASocket()
68{
69    ///- Delete buffer and decrease active admins count
70    delete [] buff;
71
72    sLog.outRALog("Connection was closed.\n");
73
74    if(stage==OK)
75        iUsers--;
76}
77
78/// Accept an incoming connection
79void RASocket::OnAccept()
80{
81    std::string ss=GetRemoteAddress();
82    sLog.outRALog("Incoming connection from %s.\n",ss.c_str());
83    ///- If there is already an active admin, drop the connection
84    if(iUsers)
85        dropclient
86
87        ///- Else print Motd
88            Sendf("%s\r\n",sWorld.GetMotd());
89}
90
91/// Read data from the network
92void RASocket::OnRead()
93{
94    ///- Read data and check input length
95    TcpSocket::OnRead();
96
97    unsigned int sz=ibuf.GetLength();
98    if(iInputLength+sz>=RA_BUFF_SIZE)
99    {
100        sLog.outRALog("Input buffer overflow, possible DOS attack.\n");
101        SetCloseAndDelete();
102        return;
103    }
104
105    ///- If there is already an active admin (other than you), drop the connection
106    if(stage!=OK && iUsers)
107        dropclient
108
109            char *inp = new char [sz+1];
110    ibuf.Read(inp,sz);
111
112    /// \todo Can somebody explain this 'Linux bugfix'?
113    if(stage==NONE)
114        if(sz>4)                                            //linux remote telnet
115            if(memcmp(inp ,"USER ",5))
116            {
117                delete [] inp;return;
118                printf("lin bugfix");
119            }                                               //linux bugfix
120
121    ///- Discard data after line break or line feed
122    bool gotenter=false;
123    unsigned int y=0;
124    for(;y<sz;y++)
125        if(inp[y]=='\r'||inp[y]=='\n')
126    {
127        gotenter=true;
128        break;
129    }
130
131    //No buffer overflow (checked above)
132    memcpy(&buff[iInputLength],inp,y);
133    iInputLength+=y;
134    delete [] inp;
135    if(gotenter)
136    {
137
138        buff[iInputLength]=0;
139        iInputLength=0;
140        switch(stage)
141        {
142            /// <ul> <li> If the input is 'USER <username>'
143            case NONE:
144                if(!memcmp(buff,"USER ",5))                 //got "USER" cmd
145                {
146                    szLogin=&buff[5];
147
148                    ///- Get the gmlevel and password from the account table
149                    std::string login = szLogin;
150
151                    ///- Convert Account name to Upper Format
152                    AccountMgr::normilizeString(login);
153
154                    ///- Escape the Login to allow quotes in names
155                    loginDatabase.escape_string(login);
156
157                    QueryResult* result = loginDatabase.PQuery("SELECT gmlevel FROM account WHERE username = '%s'",login.c_str());
158
159                    ///- If the user is not found, deny access
160                    if(!result)
161                    {
162                        Sendf("-No such user.\r\n");
163                        sLog.outRALog("User %s does not exist.\n",szLogin.c_str());
164                        if(bSecure)SetCloseAndDelete();
165                    }
166                    else
167                    {
168                        Field *fields = result->Fetch();
169
170                        //szPass=fields[0].GetString();
171
172                        ///- if gmlevel is too low, deny access
173                        if(fields[0].GetUInt32()<iMinLevel)
174                        {
175                            Sendf("-Not enough privileges.\r\n");
176                            sLog.outRALog("User %s has no privilege.\n",szLogin.c_str());
177                            if(bSecure)SetCloseAndDelete();
178                        }   else
179                        {
180                            stage=LG;
181                        }
182                        delete result;
183                    }
184                }
185                break;
186                ///<li> If the input is 'PASS <password>' (and the user already gave his username)
187            case LG:
188                if(!memcmp(buff,"PASS ",5))                 //got "PASS" cmd
189                {                                           //login+pass ok
190                    ///- If password is correct, increment the number of active administrators
191                    std::string login = szLogin;
192                    std::string pw = &buff[5];
193
194                    AccountMgr::normilizeString(login);
195                    AccountMgr::normilizeString(pw);
196                    loginDatabase.escape_string(login);
197                    loginDatabase.escape_string(pw);
198
199                    QueryResult *check = loginDatabase.PQuery(
200                                                "SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))",
201                                                login.c_str(), pw.c_str());
202
203                    if(check)
204                    {
205                        delete check;
206                        r=GetSocket();
207                        stage=OK;
208                        ++iUsers;
209
210                        Sendf("+Logged in.\r\n");
211                        sLog.outRALog("User %s has logged in.\n",szLogin.c_str());
212                        Sendf("TC>");
213                    }
214                    else
215                    {
216                        ///- Else deny access
217                        Sendf("-Wrong pass.\r\n");
218                        sLog.outRALog("User %s has failed to log in.\n",szLogin.c_str());
219                        if(bSecure)SetCloseAndDelete();
220                    }
221                }
222                break;
223                ///<li> If user is logged, parse and execute the command
224            case OK:
225                if(strlen(buff))
226                {
227                    sLog.outRALog("Got '%s' cmd.\n",buff);
228                    sWorld.QueueCliCommand(&RASocket::zprint , buff);
229                }
230                else
231                    Sendf("TC>");
232                break;
233                ///</ul>
234        };
235
236    }
237}
238
239/// Output function
240void RASocket::zprint( const char * szText )
241{
242    if( !szText )
243        return;
244
245    #ifdef RA_CRYPT
246
247        char *megabuffer=strdup(szText);
248    unsigned int sz=strlen(megabuffer);
249    Encrypt(megabuffer,sz);
250        send(r,megabuffer,sz,0);
251    delete [] megabuffer;
252   
253        #else
254
255    unsigned int sz=strlen(szText);
256    send(r,szText,sz,0);
257
258    #endif
259}
Note: See TracBrowser for help on using the browser.