diff options
-rw-r--r-- | src/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/client.cpp | 37 | ||||
-rw-r--r-- | src/client.h | 2 | ||||
-rw-r--r-- | src/clientserver.h | 10 | ||||
-rw-r--r-- | src/game.cpp | 8 | ||||
-rw-r--r-- | src/guiPasswordChange.cpp | 252 | ||||
-rw-r--r-- | src/guiPasswordChange.h | 57 | ||||
-rw-r--r-- | src/guiPauseMenu.cpp | 36 | ||||
-rw-r--r-- | src/guiPauseMenu.h | 1 | ||||
-rw-r--r-- | src/main.cpp | 21 | ||||
-rw-r--r-- | src/main.h | 7 | ||||
-rw-r--r-- | src/server.cpp | 25 | ||||
-rw-r--r-- | src/utility.cpp | 23 | ||||
-rw-r--r-- | src/utility.h | 1 |
14 files changed, 457 insertions, 28 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 58596a101..49982d310 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -77,6 +77,8 @@ set(common_SRCS player.cpp utility.cpp test.cpp + sha1.cpp + base64.cpp ) # Client sources @@ -91,12 +93,11 @@ set(minetest_SRCS guiTextInputMenu.cpp guiInventoryMenu.cpp guiPauseMenu.cpp + guiPasswordChange.cpp client.cpp tile.cpp game.cpp main.cpp - sha1.cpp - base64.cpp ) # Server sources diff --git a/src/client.cpp b/src/client.cpp index c85d6e9e2..5869dc77b 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1602,6 +1602,43 @@ void Client::sendChatMessage(const std::wstring &message) Send(0, data, true); } +void Client::sendChangePassword(const std::wstring oldpassword, + const std::wstring newpassword) +{ + Player *player = m_env.getLocalPlayer(); + if(player == NULL) + return; + + std::string playername = player->getName(); + std::string oldpwd = translatePassword(playername, oldpassword); + std::string newpwd = translatePassword(playername, newpassword); + + std::ostringstream os(std::ios_base::binary); + u8 buf[2+PASSWORD_SIZE*2]; + /* + [0] u16 TOSERVER_PASSWORD + [2] u8[28] old password + [30] u8[28] new password + */ + + writeU16(buf, TOSERVER_PASSWORD); + for(u32 i=0;i<PASSWORD_SIZE-1;i++) + { + buf[2+i] = i<oldpwd.length()?oldpwd[i]:0; + buf[30+i] = i<newpwd.length()?newpwd[i]:0; + } + buf[2+PASSWORD_SIZE-1] = 0; + buf[30+PASSWORD_SIZE-1] = 0; + os.write((char*)buf, 2+PASSWORD_SIZE*2); + + // Make data buffer + std::string s = os.str(); + SharedBuffer<u8> data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); +} + + void Client::sendDamage(u8 damage) { DSTACK(__FUNCTION_NAME); diff --git a/src/client.h b/src/client.h index 222f83ab7..f661838ce 100644 --- a/src/client.h +++ b/src/client.h @@ -255,6 +255,8 @@ public: void sendSignNodeText(v3s16 p, std::string text); void sendInventoryAction(InventoryAction *a); void sendChatMessage(const std::wstring &message); + void sendChangePassword(const std::wstring oldpassword, + const std::wstring newpassword); void sendDamage(u8 damage); // locks envlock diff --git a/src/clientserver.h b/src/clientserver.h index a64a11f08..256aed362 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -285,6 +285,16 @@ enum ToServerCommand u16 command u8 amount */ + + TOSERVER_PASSWORD=0x36, + /* + Sent to change password. + + [0] u16 TOSERVER_PASSWORD + [2] u8[28] old password + [30] u8[28] new password + */ + }; inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time) diff --git a/src/game.cpp b/src/game.cpp index 99e08b7bf..e82e4cd8e 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client.h" #include "server.h" #include "guiPauseMenu.h" +#include "guiPasswordChange.h" #include "guiInventoryMenu.h" #include "guiTextInputMenu.h" #include "guiFurnaceMenu.h" @@ -912,6 +913,13 @@ void the_game( break; } + if(g_gamecallback->changepassword_requested) + { + (new GUIPasswordChange(guienv, guiroot, -1, + &g_menumgr, &client))->drop(); + g_gamecallback->changepassword_requested = false; + } + /* Process TextureSource's queue */ diff --git a/src/guiPasswordChange.cpp b/src/guiPasswordChange.cpp new file mode 100644 index 000000000..98b11b432 --- /dev/null +++ b/src/guiPasswordChange.cpp @@ -0,0 +1,252 @@ +/* +Minetest-c55 +Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com> +Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com> + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "guiPasswordChange.h" +#include "debug.h" +#include "serialization.h" +#include <string> + +const int ID_oldPassword = 256; +const int ID_newPassword1 = 257; +const int ID_newPassword2 = 258; +const int ID_change = 259; +const int ID_message = 260; + +GUIPasswordChange::GUIPasswordChange(gui::IGUIEnvironment* env, + gui::IGUIElement* parent, s32 id, + IMenuManager *menumgr, + Client* client +): + GUIModalMenu(env, parent, id, menumgr), + m_client(client) +{ +} + +GUIPasswordChange::~GUIPasswordChange() +{ + removeChildren(); +} + +void GUIPasswordChange::removeChildren() +{ + { + gui::IGUIElement *e = getElementFromId(ID_oldPassword); + if(e != NULL) + e->remove(); + } + { + gui::IGUIElement *e = getElementFromId(ID_newPassword1); + if(e != NULL) + e->remove(); + } + { + gui::IGUIElement *e = getElementFromId(ID_newPassword2); + if(e != NULL) + e->remove(); + } + { + gui::IGUIElement *e = getElementFromId(ID_change); + if(e != NULL) + e->remove(); + } +} + +void GUIPasswordChange::regenerateGui(v2u32 screensize) +{ + /* + Remove stuff + */ + removeChildren(); + + /* + Calculate new sizes and positions + */ + core::rect<s32> rect( + screensize.X/2 - 580/2, + screensize.Y/2 - 300/2, + screensize.X/2 + 580/2, + screensize.Y/2 + 300/2 + ); + + DesiredRect = rect; + recalculateAbsolutePosition(false); + + v2s32 size = rect.getSize(); + v2s32 topleft_client(40, 0); + v2s32 size_client = size - v2s32(40, 0); + + /* + Add stuff + */ + s32 ypos = 50; + { + core::rect<s32> rect(0, 0, 110, 20); + rect += topleft_client + v2s32(35, ypos+6); + const wchar_t *text = L"Old Password"; + Environment->addStaticText(text, rect, false, true, this, -1); + } + { + core::rect<s32> rect(0, 0, 230, 30); + rect += topleft_client + v2s32(160, ypos); + gui::IGUIEditBox *e = + Environment->addEditBox(L"", rect, true, this, ID_oldPassword); + Environment->setFocus(e); + e->setPasswordBox(true); + } + ypos += 50; + { + core::rect<s32> rect(0, 0, 110, 20); + rect += topleft_client + v2s32(35, ypos+6); + const wchar_t *text = L"New Password"; + Environment->addStaticText(text, rect, false, true, this, -1); + } + { + core::rect<s32> rect(0, 0, 230, 30); + rect += topleft_client + v2s32(160, ypos); + gui::IGUIEditBox *e = + Environment->addEditBox(L"", rect, true, this, ID_newPassword1); + e->setPasswordBox(true); + } + ypos += 50; + { + core::rect<s32> rect(0, 0, 110, 20); + rect += topleft_client + v2s32(35, ypos+6); + const wchar_t *text = L"Confirm Password"; + Environment->addStaticText(text, rect, false, true, this, -1); + } + { + core::rect<s32> rect(0, 0, 230, 30); + rect += topleft_client + v2s32(160, ypos); + gui::IGUIEditBox *e = + Environment->addEditBox(L"", rect, true, this, ID_newPassword2); + e->setPasswordBox(true); + } + + ypos += 50; + { + core::rect<s32> rect(0, 0, 140, 30); + rect = rect + v2s32(size.X/2-140/2, ypos); + Environment->addButton(rect, this, ID_change, L"Change"); + } + + ypos += 50; + { + core::rect<s32> rect(0, 0, 300, 20); + rect += topleft_client + v2s32(35, ypos); + const wchar_t *text = L"Passwords do not match!"; + IGUIElement *e = + Environment->addStaticText(text, rect, false, true, this, ID_message); + e->setVisible(false); + } + +} + +void GUIPasswordChange::drawMenu() +{ + gui::IGUISkin* skin = Environment->getSkin(); + if (!skin) + return; + video::IVideoDriver* driver = Environment->getVideoDriver(); + + video::SColor bgcolor(140,0,0,0); + driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect); + + gui::IGUIElement::draw(); +} + +bool GUIPasswordChange::acceptInput() +{ + std::wstring oldpass; + std::wstring newpass; + gui::IGUIElement *e; + e = getElementFromId(ID_oldPassword); + if(e != NULL) + oldpass = e->getText(); + e = getElementFromId(ID_newPassword1); + if(e != NULL) + newpass = e->getText(); + e = getElementFromId(ID_newPassword2); + if(e != NULL && newpass != e->getText()) + { + e = getElementFromId(ID_message); + if(e != NULL) + e->setVisible(true); + return false; + } + m_client->sendChangePassword(oldpass, newpass); + return true; +} + +bool GUIPasswordChange::OnEvent(const SEvent& event) +{ + if(event.EventType==EET_KEY_INPUT_EVENT) + { + if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown) + { + quitMenu(); + return true; + } + if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown) + { + if(acceptInput()) + quitMenu(); + return true; + } + } + if(event.EventType==EET_GUI_EVENT) + { + if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST + && isVisible()) + { + if(!canTakeFocus(event.GUIEvent.Element)) + { + dstream<<"GUIPasswordChange: Not allowing focus change." + <<std::endl; + // Returning true disables focus change + return true; + } + } + if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED) + { + switch(event.GUIEvent.Caller->getID()) + { + case ID_change: + if(acceptInput()) + quitMenu(); + return true; + } + } + if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER) + { + switch(event.GUIEvent.Caller->getID()) + { + case ID_oldPassword: + case ID_newPassword1: + case ID_newPassword2: + if(acceptInput()) + quitMenu(); + return true; + } + } + } + + return Parent ? Parent->OnEvent(event) : false; +} + diff --git a/src/guiPasswordChange.h b/src/guiPasswordChange.h new file mode 100644 index 000000000..defac3113 --- /dev/null +++ b/src/guiPasswordChange.h @@ -0,0 +1,57 @@ +/* +Minetest-c55 +Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com> +Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com> + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef GUIPASSWORDCHANGE_HEADER +#define GUIPASSWORDCHANGE_HEADER + +#include "common_irrlicht.h" +#include "modalMenu.h" +#include "utility.h" +#include "client.h" +#include <string> + +class GUIPasswordChange : public GUIModalMenu +{ +public: + GUIPasswordChange(gui::IGUIEnvironment* env, + gui::IGUIElement* parent, s32 id, + IMenuManager *menumgr, + Client* client); + ~GUIPasswordChange(); + + void removeChildren(); + /* + Remove and re-add (or reposition) stuff + */ + void regenerateGui(v2u32 screensize); + + void drawMenu(); + + bool acceptInput(); + + bool OnEvent(const SEvent& event); + +private: + Client* m_client; + +}; + +#endif + diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp index 2d42fdb77..d32d1a10b 100644 --- a/src/guiPauseMenu.cpp +++ b/src/guiPauseMenu.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serialization.h"
#include "porting.h"
#include "config.h"
+#include "main.h"
GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
@@ -64,6 +65,11 @@ void GUIPauseMenu::removeChildren() if(e != NULL)
e->remove();
}
+ {
+ gui::IGUIElement *e = getElementFromId(261);
+ if(e != NULL)
+ e->remove();
+ }
}
void GUIPauseMenu::regenerateGui(v2u32 screensize)
@@ -91,21 +97,34 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) /*
Add stuff
*/
+ const s32 btn_height = 30;
+ const s32 btn_gap = 20;
+ const s32 btn_num = 4;
+ s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2;
{
- core::rect<s32> rect(0, 0, 140, 30);
- rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2-50);
+ core::rect<s32> rect(0, 0, 140, btn_height);
+ rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 256, L"Continue");
}
+ btn_y += btn_height + btn_gap;
+ {
+ core::rect<s32> rect(0, 0, 140, btn_height);
+ rect = rect + v2s32(size.X/2-140/2, btn_y);
+ Environment->addButton(rect, this, 261, L"Change Password");
+ }
+ btn_y += btn_height + btn_gap;
{
- core::rect<s32> rect(0, 0, 140, 30);
- rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+0);
+ core::rect<s32> rect(0, 0, 140, btn_height);
+ rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 260, L"Disconnect");
}
+ btn_y += btn_height + btn_gap;
{
- core::rect<s32> rect(0, 0, 140, 30);
- rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+50);
+ core::rect<s32> rect(0, 0, 140, btn_height);
+ rect = rect + v2s32(size.X/2-140/2, btn_y);
Environment->addButton(rect, this, 257, L"Exit to OS");
}
+
{
core::rect<s32> rect(0, 0, 180, 240);
rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2);
@@ -172,6 +191,7 @@ void GUIPauseMenu::drawMenu() bool GUIPauseMenu::OnEvent(const SEvent& event)
{
+
if(event.EventType==EET_KEY_INPUT_EVENT)
{
if(event.KeyInput.PressedDown)
@@ -209,6 +229,10 @@ bool GUIPauseMenu::OnEvent(const SEvent& event) quitMenu();
// ALWAYS return immediately after quitMenu()
return true;
+ case 261:
+ quitMenu();
+ m_gamecallback->changePassword();
+ return true;
case 260: // disconnect
m_gamecallback->disconnect();
quitMenu();
diff --git a/src/guiPauseMenu.h b/src/guiPauseMenu.h index 22cb65b2c..64e3c71f1 100644 --- a/src/guiPauseMenu.h +++ b/src/guiPauseMenu.h @@ -28,6 +28,7 @@ class IGameCallback public:
virtual void exitToOS() = 0;
virtual void disconnect() = 0;
+ virtual void changePassword() = 0;
};
class GUIPauseMenu : public GUIModalMenu
diff --git a/src/main.cpp b/src/main.cpp index 457fa0693..06deb9310 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -362,8 +362,6 @@ Stuff to do before release: #include "materials.h"
#include "game.h"
#include "keycode.h"
-#include "sha1.h"
-#include "base64.h"
// This makes textures
ITextureSource *g_texturesource = NULL;
@@ -1477,24 +1475,7 @@ int main(int argc, char *argv[]) playername = wide_to_narrow(menudata.name);
- // Get an sha-1 hash of the player's name combined with
- // the password entered. That's what the server uses as
- // their password. (Exception : if the password field is
- // blank, we send a blank password - this is for backwards
- // compatibility with password-less players).
- if(menudata.password.length() > 0)
- {
- std::string slt=playername + wide_to_narrow(menudata.password);
- SHA1 *sha1 = new SHA1();
- sha1->addBytes(slt.c_str(), slt.length());
- unsigned char *digest = sha1->getDigest();
- password = base64_encode(digest, 20);
- free(digest);
- }
- else
- {
- password = "";
- }
+ password = translatePassword(playername, menudata.password);
address = wide_to_narrow(menudata.address);
int newport = stoi(wide_to_narrow(menudata.port));
diff --git a/src/main.h b/src/main.h index c8ac7ccf1..fcf150f87 100644 --- a/src/main.h +++ b/src/main.h @@ -119,6 +119,7 @@ class MainGameCallback : public IGameCallback public: MainGameCallback(IrrlichtDevice *a_device): disconnect_requested(false), + changepassword_requested(false), device(a_device) { } @@ -133,7 +134,13 @@ public: disconnect_requested = true; } + virtual void changePassword() + { + changepassword_requested = true; + } + bool disconnect_requested; + bool changepassword_requested; IrrlichtDevice *device; }; diff --git a/src/server.cpp b/src/server.cpp index 84f9a28e0..5c03ea8f6 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3004,6 +3004,31 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) SendPlayerHP(player); } + else if(command == TOSERVER_PASSWORD) + { + /* + [0] u16 TOSERVER_PASSWORD + [2] u8[28] old password + [30] u8[28] new password + */ + + if(datasize != 2+PASSWORD_SIZE*2) + return; + char password[PASSWORD_SIZE]; + for(u32 i=0; i<PASSWORD_SIZE-1; i++) + password[i] = data[2+i]; + password[PASSWORD_SIZE-1] = 0; + if(strcmp(player->getPassword(),password)) + { + // Wrong old password supplied!! + SendChatMessage(peer_id, L"Invalid old password supplied. Password NOT changed."); + return; + } + for(u32 i=0; i<PASSWORD_SIZE-1; i++) + password[i] = data[30+i]; + player->updatePassword(password); + SendChatMessage(peer_id, L"Password change successful"); + } else { derr_server<<"WARNING: Server::ProcessData(): Ignoring " diff --git a/src/utility.cpp b/src/utility.cpp index fc657b27b..186881c5a 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "utility.h" #include "gettime.h" +#include "sha1.h" +#include "base64.h" TimeTaker::TimeTaker(const char *name, u32 *result) { @@ -217,3 +219,24 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range, return true; } +// Get an sha-1 hash of the player's name combined with +// the password entered. That's what the server uses as +// their password. (Exception : if the password field is +// blank, we send a blank password - this is for backwards +// compatibility with password-less players). +std::string translatePassword(std::string playername, std::wstring password) +{ + if(password.length() == 0) + return ""; + + std::string slt=playername + wide_to_narrow(password); + SHA1 *sha1 = new SHA1(); + sha1->addBytes(slt.c_str(), slt.length()); + unsigned char *digest = sha1->getDigest(); + std::string pwd = base64_encode(digest, 20); + free(digest); + return pwd; +} + + + diff --git a/src/utility.h b/src/utility.h index f32dc3acf..c7513e94d 100644 --- a/src/utility.h +++ b/src/utility.h @@ -2112,6 +2112,7 @@ protected: float m_accumulator; }; +std::string translatePassword(std::string playername, std::wstring password); #endif |