Jump to content

Mangos Remote Admin


Guest Kroket

Recommended Posts

Im making a C# program that connects to RA and logs in.

But how do i log in?

      private void Login()
       {
           WriteToStream(this.User);
           WriteToStream(this.Pass);
       }

public void WriteToStream(String text)
       {
           try
           {
               if (getStream().CanWrite && getStream().CanRead)
               {
                   Byte[] sendBytes = Encoding.ASCII.GetBytes(text);
                   getStream().Write(sendBytes, 0, sendBytes.Length);
                   getStream().Dispose();
                   getStream().Flush();
               }
           }    catch (SocketException se)
           {
               PerfectRA.methods.WriteLine(se.Message);
           }
       }

Link to comment
Share on other sites

Thanks works but now it always returns invalid password, first i write the username to the stream followed by the password;

If i write/read to/from the stream to fast it throws an IOException, i try catched it but thats not really a good solution, whats causing this?

Link to comment
Share on other sites

Try asking on some C# specific forums how to handle network stream I/O, how to read it, identify and send replies.

I'm no C# programmer, but I'd use poll() or select() in C. That is, the remote side sends "username:" and "password:" strings, which trigger a POLLIN event that you can use to call read() / recv() / recvfrom() on the socket and compare the input with those username/password strings. If it matches, you can send a reply. A simple version of tcl's "expect".

Link to comment
Share on other sites

// C# to convert a string to a byte array.
       public static byte[] StrToByteArray(string str)
       {
           System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
           return encoding.GetBytes(str);
       }

       public static void RAWrite(this NetworkStream networkStream, string data)
       {
           try
           {
               //byte[] buffer = Encoding.ASCII.GetBytes(data);
                byte[] buffer = StrToByteArray(data);
                   networkStream.Write(buffer, 0, buffer.Length);
                   networkStream.WriteByte((byte)'\\n');
                   networkStream.Flush();
           } catch(Exception) {
           }
       }

Tried it with UTF8 & ASCII as encoding, it returns wrong password.

Link to comment
Share on other sites

Checked that already.

RASocket.cpp (MangosZero latest rev):


/*
* Copyright (C) 2005-2010 MaNGOS <http://getmangos.eu/>
* Copyright (C) 2009-2010 MaNGOSZero <http://github.com/mangoszero/mangoszero/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/** \\file
   \\ingroup mangosd
*/

#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "Log.h"
#include "RASocket.h"
#include "World.h"
#include "Config/Config.h"
#include "Util.h"
#include "AccountMgr.h"
#include "Language.h"
#include "ObjectMgr.h"

/// RASocket constructor
RASocket::RASocket()
:RAHandler(),
pendingCommands(0, USYNC_THREAD, "pendingCommands"),
outActive(false),
inputBufferLen(0),
outputBufferLen(0),
stage(NONE)
{
   ///- Get the config parameters
   bSecure = sConfig.GetBoolDefault( "RA.Secure", true );
   bStricted = sConfig.GetBoolDefault( "RA.Stricted", false );
   iMinLevel = AccountTypes(sConfig.GetIntDefault( "RA.MinLevel", SEC_ADMINISTRATOR ));
   reference_counting_policy ().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
}

/// RASocket destructor
RASocket::~RASocket()
{
   peer().close();
   sLog.outRALog("Connection was closed.");
}

/// Accept an incoming connection
int RASocket::open(void* )
{
   if (reactor ()->register_handler(this, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK) == -1)
   {
       sLog.outError ("RASocket::open: unable to register client handler errno = %s", ACE_OS::strerror (errno));
       return -1;
   }

   ACE_INET_Addr remote_addr;

   if (peer ().get_remote_addr (remote_addr) == -1)
   {
       sLog.outError ("RASocket::open: peer ().get_remote_addr errno = %s", ACE_OS::strerror (errno));
       return -1;
   }


   sLog.outRALog("Incoming connection from %s.",remote_addr.get_host_addr());

   ///- print Motd
   sendf(sWorld.GetMotd());
   sendf("\\r\\n");
   sendf(sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_USER));

   return 0;
}

int RASocket::close(int)
{
   if(closing_)
       return -1;
   DEBUG_LOG("RASocket::close");
   shutdown();

   closing_ = true;

   remove_reference();
   return 0;
}

int RASocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask)
{
   if(closing_)
       return -1;
   DEBUG_LOG("RASocket::handle_close");
   ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, outBufferLock, -1);

   closing_ = true;

   if (h == ACE_INVALID_HANDLE)
       peer ().close_writer ();
   remove_reference();
   return 0;
}

int RASocket::handle_output (ACE_HANDLE)
{
   ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, outBufferLock, -1);

   if(closing_)
       return -1;

   if (!outputBufferLen)
   {
       if(reactor()->cancel_wakeup(this, ACE_Event_Handler::WRITE_MASK) == -1)
       {
           sLog.outError ("RASocket::handle_output: error while cancel_wakeup");
           return -1;
       }
       outActive = false;
       return 0;
   }
#ifdef MSG_NOSIGNAL
   ssize_t n = peer ().send (outputBuffer, outputBufferLen, MSG_NOSIGNAL);
#else
   ssize_t n = peer ().send (outputBuffer, outputBufferLen);
#endif // MSG_NOSIGNAL

   if(n<=0)
       return -1;

   ACE_OS::memmove(outputBuffer, outputBuffer+n, outputBufferLen-n);

   outputBufferLen -= n;

   return 0;
}

/// Read data from the network
int RASocket::handle_input(ACE_HANDLE)
{
   DEBUG_LOG("RASocket::handle_input");
   if(closing_)
   {
       sLog.outError("Called RASocket::handle_input with closing_ = true");
       return -1;
   }

   size_t readBytes = peer().recv(inputBuffer+inputBufferLen, RA_BUFF_SIZE-inputBufferLen-1);

   if(readBytes <= 0)
   {
       DEBUG_LOG("read %u bytes in RASocket::handle_input", readBytes);
       return -1;
   }

   ///- Discard data after line break or line feed
   bool gotenter=false;
   for(; readBytes > 0 ; --readBytes)
   {
       char c = inputBuffer[inputBufferLen];
       if (c=='\\r'|| c=='\\n')
       {
           gotenter=true;
           break;
       }
       ++inputBufferLen;
   }

   if (gotenter)
   {
       inputBuffer[inputBufferLen]=0;
       inputBufferLen=0;
       switch(stage)
       {
           /// <ul> [*] If the input is '<username>'
           case NONE:
           {
               std::string szLogin=inputBuffer;

               accId = sAccountMgr.GetId(szLogin);

               ///- If the user is not found, deny access
               if(!accId)
               {
                   sendf("-No such user.\\r\\n");
                   sLog.outRALog("User %s does not exist.",szLogin.c_str());
                   if(bSecure)
                   {
                       handle_output();
                       return -1;
                   }
                   sendf("\\r\\n");
                   sendf(sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_USER));
                   break;
               }

               accAccessLevel = sAccountMgr.GetSecurity(accId);

               ///- if gmlevel is too low, deny access
               if (accAccessLevel < iMinLevel)
               {
                   sendf("-Not enough privileges.\\r\\n");
                   sLog.outRALog("User %s has no privilege.",szLogin.c_str());
                   if(bSecure)
                   {
                       handle_output();
                       return -1;
                   }
                   sendf("\\r\\n");
                   sendf(sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_USER));
                   break;
               }

               ///- allow by remotely connected admin use console level commands dependent from config setting
               if (accAccessLevel >= SEC_ADMINISTRATOR && !bStricted)
                   accAccessLevel = SEC_CONSOLE;

               stage=LG;
               sendf(sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_PASS));
               break;
           }
           ///[*] If the input is '<password>' (and the user already gave his username)
           case LG:
           {                                               //login+pass ok
               std::string pw = inputBuffer;

               if (sAccountMgr.CheckPassword(accId, pw))
               {
                   stage=OK;

                   sendf("+Logged in.\\r\\n");
                   sLog.outRALog("User account %u has logged in.", accId);
                   sendf("mangos>");
               }
               else
               {
                   ///- Else deny access
                   sendf("-Wrong pass.\\r\\n");
                   sLog.outRALog("User account %u has failed to log in.", accId);
                   if(bSecure)
                   {
                       handle_output();
                       return -1;
                   }
                   sendf("\\r\\n");
                   sendf(sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_PASS));
               }
               break;
           }
           ///[*] If user is logged, parse and execute the command
           case OK:
               if (strlen(inputBuffer))
               {
                   sLog.outRALog("Got '%s' cmd.",inputBuffer);
                   if (strncmp(inputBuffer,"quit",4)==0)
                       return -1;
                   else
                   {
                       CliCommandHolder* cmd = new CliCommandHolder(accId, accAccessLevel, this, inputBuffer, &RASocket::zprint, &RASocket::commandFinished);
                       sWorld.QueueCliCommand(cmd);
                       pendingCommands.acquire();
                   }
               }
               else
                   sendf("mangos>");
               break;
           ///[/list]
       };

   }
   // no enter yet? wait for next input...
   return 0;
}

/// Output function
void RASocket::zprint(void* callbackArg, const char * szText )
{
   if( !szText )
       return;

   ((RASocket*)callbackArg)->sendf(szText);
}

void RASocket::commandFinished(void* callbackArg, bool success)
{
   RASocket* raSocket = (RASocket*)callbackArg;
   raSocket->sendf("mangos>");
   raSocket->pendingCommands.release();
}

int RASocket::sendf(const char* msg)
{
   ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, outBufferLock, -1);

   if(closing_)
       return -1;

   int msgLen = strlen(msg);

   if(msgLen+outputBufferLen > RA_BUFF_SIZE)
       return -1;

   ACE_OS::memcpy(outputBuffer+outputBufferLen, msg, msgLen);
   outputBufferLen += msgLen;

   if(!outActive)
   {
       if (reactor ()->schedule_wakeup
           (this, ACE_Event_Handler::WRITE_MASK) == -1)
       {
           sLog.outError ("RASocket::sendf error while schedule_wakeup");
           return -1;
       }
       outActive = true;
   }
   return 0;
}

Link to comment
Share on other sites

this piece of code handles authentication:

           ///[*] If the input is '<password>' (and the user already gave his username)
           case LG:
           {                                               //login+pass ok
               std::string pw = inputBuffer;

               if (sAccountMgr.CheckPassword(accId, pw))
               {
                   stage=OK;

                   sendf("+Logged in.\\r\\n");
                   sLog.outRALog("User account %u has logged in.", accId);
                   sendf("mangos>");
               }
               else
               {
                   ///- Else deny access
                   sendf("-Wrong pass.\\r\\n");
                   sLog.outRALog("User account %u has failed to log in.", accId);
                   if(bSecure)
                   {
                       handle_output();
                       return -1;
                   }
                   sendf("\\r\\n");
                   sendf(sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_PASS));
               }
               break;

Link to comment
Share on other sites

  • 2 weeks later...
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use