Changes to bring the SSH Menu system online!

* Commandline Options added (./retroshare-nogui -h for help).
 * Added Password Hash system.
 * Shifted Menu output to std::string buffers.
 * Built interface to SSH server.
 * changed menus to lowercase.
 * Fixed SSH server restart issue.
 * Updates Output regularly now.
	


git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-gxs-b1@5398 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2012-08-09 13:45:05 +00:00
parent fa65173171
commit 8f2ff3eaf5
10 changed files with 814 additions and 186 deletions

View File

@ -6,48 +6,59 @@
#include <iostream> #include <iostream>
#include "util/rsstring.h"
/********************************************************** /**********************************************************
* Menu Base Interface. * Menu Base Interface.
*/ */
int tailrec_printparents(Menu *m, std::ostream &out) // RsTermServer Interface.
void MenuInterface::reset()
{
mBase->reset();
mCurrentMenu = mBase;
mInputRequired = false;
}
int MenuInterface::tick(bool haveInput, char keypress, std::string &output)
{
if (!haveInput)
{
/* make a harmless key */
keypress = ' ';
}
if ((mInputRequired) && (!haveInput))
{
return 1;
}
uint32_t rt = process(keypress, mDrawFlags, output);
mInputRequired = (rt == MENU_PROCESS_NEEDDATA);
if (rt == MENU_PROCESS_QUIT)
{
return -1;
}
return 1;
}
int tailrec_printparents(Menu *m, std::string &buffer)
{ {
Menu *p = m->parent(); Menu *p = m->parent();
if (p) if (p)
{ {
tailrec_printparents(p, out); tailrec_printparents(p, buffer);
} }
out << m->ShortFnDesc() << " => "; buffer += m->ShortFnDesc();
buffer += " => ";
#if 0
MenuList *ml = dynamic_cast<MenuList *>(m);
MenuOpBasicKey *mbk = dynamic_cast<MenuOpBasicKey *>(m);
MenuOpTwoKeys *mtk = dynamic_cast<MenuOpTwoKeys *>(m);
if (ml)
{
out << "MenuList@" << (void *) m << " ";
}
else if (mbk)
{
out << "MenuBasicKey@" << (void *) m << " ";
}
else if (mtk)
{
out << "MenuOpTwoKeys@" << (void *) m << " ";
}
else
{
out << "Menu@" << (void *) m << " ";
}
#endif
return 1; return 1;
} }
uint32_t MenuInterface::process(char key) uint32_t MenuInterface::process(char key, uint32_t drawFlags, std::string &buffer)
{ {
#ifdef MENU_DEBUG #ifdef MENU_DEBUG
@ -66,18 +77,23 @@ uint32_t MenuInterface::process(char key)
std::cout << std::endl; std::cout << std::endl;
#endif // MENU_DEBUG #endif // MENU_DEBUG
switch(rt)
uint32_t base_rt = (rt & MENU_PROCESS_MASK);
bool needData = (rt & MENU_PROCESS_NEEDDATA);
switch(base_rt)
{ {
case MENU_PROCESS_NONE: case MENU_PROCESS_NONE:
if (needData)
{
/* no redraw, this could be called many times */
doRedraw = false;
}
break;
case MENU_PROCESS_DONE: case MENU_PROCESS_DONE:
/* no changes - operation performed, or noop */ /* no changes - operation performed, or noop */
break; break;
case MENU_PROCESS_NEEDDATA:
/* no redraw, this could be called many times */
doRedraw = false;
break;
case MENU_PROCESS_ERROR: case MENU_PROCESS_ERROR:
/* Show Error at top of Page */ /* Show Error at top of Page */
showError = true; showError = true;
@ -114,6 +130,11 @@ uint32_t MenuInterface::process(char key)
break; break;
} }
if (drawFlags & MENU_DRAW_FLAGS_ECHO)
{
buffer += key;
}
/* now we redraw, and wait for next data */ /* now we redraw, and wait for next data */
if (!doRedraw) if (!doRedraw)
{ {
@ -123,7 +144,7 @@ uint32_t MenuInterface::process(char key)
/* HEADER */ /* HEADER */
for(int i = 0; i < 20; i++) for(int i = 0; i < 20; i++)
{ {
std::cout << std::endl; buffer += "\r\n";
} }
/* ERROR */ /* ERROR */
@ -138,17 +159,19 @@ uint32_t MenuInterface::process(char key)
} }
/* MENU PAGE */ /* MENU PAGE */
drawHeader(); drawHeader(drawFlags, buffer);
mCurrentMenu->drawPage(); mCurrentMenu->drawPage(drawFlags, buffer);
return MENU_PROCESS_NEEDDATA;
if (needData)
return MENU_PROCESS_NEEDDATA;
return MENU_PROCESS_NONE;
} }
uint32_t MenuInterface::drawHeader() uint32_t MenuInterface::drawHeader(uint32_t drawFlags, std::string &buffer)
{ {
std::cout << "======================================================="; buffer += "=======================================================\r\n";
std::cout << std::endl; buffer += "Retroshare Terminal Menu V2.xxxx ======================\r\n";
std::cout << "Retroshare Terminal Menu V2.xxxx ======================";
std::cout << std::endl;
unsigned int nTotal = 0; unsigned int nTotal = 0;
unsigned int nConnected = 0; unsigned int nConnected = 0;
@ -200,18 +223,19 @@ uint32_t MenuInterface::drawHeader()
float upKb = 0; float upKb = 0;
rsicontrol -> ConfigGetDataRates(downKb, upKb); rsicontrol -> ConfigGetDataRates(downKb, upKb);
std::cout << "Friends " << nConnected << "/" << nTotal; rs_sprintf_append(buffer, "Friends %d / %d Network: %s\r\n",
std::cout << " Network: " << natState; nConnected, nTotal, natState.c_str());
std::cout << std::endl;
std::cout << "Down: " << downKb << " (kB/s) ";
std::cout << " Up: " << upKb << " (kB/s) ";
std::cout << std::endl;
std::cout << "Menu State: ";
tailrec_printparents(mCurrentMenu, std::cout);
std::cout << std::endl;
std::cout << "======================================================="; rs_sprintf_append(buffer, "Down: %2.2f Up %2.2f\r\n", downKb, upKb);
std::cout << std::endl;
std::string menuState;
tailrec_printparents(mCurrentMenu, menuState);
buffer += "Menu State: ";
buffer += menuState;
buffer += "\r\n";
buffer += "=======================================================\r\n";
return 1; return 1;
} }
@ -251,6 +275,16 @@ int Menu::addMenuItem(char key, Menu *child)
return 1; return 1;
} }
void Menu::reset()
{
mSelectedMenu = NULL;
std::map<uint8_t, Menu *>::iterator it;
for(it = mChildren.begin(); it != mChildren.end(); it++)
{
it->second->reset();
}
}
uint32_t Menu::process(char key) uint32_t Menu::process(char key)
{ {
@ -309,11 +343,11 @@ uint32_t Menu::process_children(char key)
/* now return, depending on type */ /* now return, depending on type */
switch(it->second->op()) switch(it->second->op())
{ {
/* Think I can handle these the same! Both will call DrawPage,
* then Process on New Menu
*/
case MENU_OP_NEEDDATA: case MENU_OP_NEEDDATA:
setSelectedMenu(it->second);
return MENU_PROCESS_MENU | MENU_PROCESS_NEEDDATA;
break;
case MENU_OP_SUBMENU: case MENU_OP_SUBMENU:
setSelectedMenu(it->second); setSelectedMenu(it->second);
return MENU_PROCESS_MENU; return MENU_PROCESS_MENU;
@ -335,31 +369,40 @@ uint32_t Menu::process_children(char key)
} }
uint32_t Menu::drawPage() uint32_t Menu::drawPage(uint32_t drawFlags, std::string &buffer)
{ {
std::cout << "Universal Commands ( "; buffer += "Universal Commands ( ";
std::cout << (char) MENU_KEY_QUIT << ":Quit "; if (!(drawFlags & MENU_DRAW_FLAGS_NOQUIT))
std::cout << (char) MENU_KEY_HELP << ":Help "; {
std::cout << (char) MENU_KEY_TOP << ":Top "; buffer += (char) MENU_KEY_QUIT;
std::cout << (char) MENU_KEY_UP << ":Up "; buffer += ":Quit ";
std::cout << ")"; }
std::cout << std::endl; buffer += (char) MENU_KEY_HELP;
buffer += ":Help ";
buffer += (char) MENU_KEY_TOP;
buffer += ":Top ";
buffer += (char) MENU_KEY_UP;
buffer += ":Up ";
buffer += ")";
buffer += "\r\n";
std::cout << "Specific Commands ("; buffer += "Specific Commands ( ";
std::map<uint8_t, Menu *>::iterator it; std::map<uint8_t, Menu *>::iterator it;
for(it = mChildren.begin(); it != mChildren.end(); it++) for(it = mChildren.begin(); it != mChildren.end(); it++)
{ {
std::cout << (char) it->first << ":"; buffer += (char) it->first;
std::cout << it->second->ShortFnDesc() << " "; buffer += ":";
buffer += it->second->ShortFnDesc();
buffer += " ";
} }
std::cout << ")"; buffer += ")";
std::cout << std::endl; buffer += "\r\n";
return 1; return 1;
} }
uint32_t Menu::drawHelpPage() uint32_t Menu::drawHelpPage(uint32_t drawFlags, std::string &buffer)
{ {
std::cout << "Menu Help: Universal Commands are:"; std::cout << "Menu Help: Universal Commands are:";
std::cout << std::endl; std::cout << std::endl;
@ -391,22 +434,20 @@ uint32_t Menu::drawHelpPage()
*/ */
uint32_t MenuList::drawPage() uint32_t MenuList::drawPage(uint32_t drawFlags, std::string &buffer)
{ {
Menu::drawPage(); Menu::drawPage(drawFlags, buffer);
std::cout << "Navigation Commands ("; buffer += "Navigation Commands (";
//std::cout << (char) MENULIST_KEY_LIST << ":List "; buffer += (char) MENULIST_KEY_NEXT;
std::cout << (char) MENULIST_KEY_NEXT << ":Next "; buffer += ":Next ";
std::cout << (char) MENULIST_KEY_PREV << ":Prev "; buffer += (char) MENULIST_KEY_PREV;
std::cout << ")"; buffer += ":Prev ";
std::cout << std::endl; buffer += ")";
buffer += "\r\n";
std::cout << "MenuList::Internals "; rs_sprintf_append(buffer, "MenuList::Internals ListSize: %d, SelectIdx: %d Cursor: %d\r\n",
std::cout << "ListSize: " << getListCount(); getListCount(), mSelectIdx, mCursor);
std::cout << " SelectIdx: " << mSelectIdx;
std::cout << " Cursor: " << mCursor;
std::cout << std::endl;
int i = 0; int i = 0;
@ -420,28 +461,28 @@ uint32_t MenuList::drawPage()
if (mSelectIdx >= 0) if (mSelectIdx >= 0)
{ {
std::cout << "Current Selection Idx: " << mSelectIdx << " : ";
rs_sprintf_append(buffer, "Current Selection Idx: %d : ", mSelectIdx);
std::string desc; std::string desc;
if (getEntryDesc(mSelectIdx, desc) & (desc != "")) if (getEntryDesc(mSelectIdx, desc) & (desc != ""))
{ {
std::cout << desc; buffer += desc;
} }
else else
{ {
std::cout << "Missing Description"; buffer += "Missing Description";
} }
std::cout << std::endl; buffer += "\r\n";
} }
else else
{ {
std::cout << "No Current Selection: Use 0 - 9 to choose an Entry"; buffer += "No Current Selection: Use 0 - 9 to choose an Entry";
std::cout << std::endl; buffer += "\r\n";
} }
std::cout << "Showing " << startCount; rs_sprintf_append(buffer, "Showing %d to %d of %d Entries\r\n",
std::cout << " to " << endCount << " of " << listCount << " Entries"; startCount, endCount, listCount);
std::cout << std::endl;
std::list<std::string>::iterator it; std::list<std::string>::iterator it;
for (it = mList.begin(); it != mList.end(); it++, i++) for (it = mList.begin(); it != mList.end(); it++, i++)
@ -451,32 +492,35 @@ uint32_t MenuList::drawPage()
{ {
if (i == mSelectIdx) if (i == mSelectIdx)
{ {
std::cout << "SELECTED => (" << curIdx << ") "; rs_sprintf_append(buffer, "SELECTED (%d) ", curIdx);
} }
else else
{ {
std::cout << "\t(" << curIdx << ") "; rs_sprintf_append(buffer, "\t(%d) ", curIdx);
} }
std::string desc; std::string desc;
if (getEntryDesc(i, desc) & (desc != "")) if (getEntryDesc(i, desc) & (desc != ""))
{ {
std::cout << desc; buffer += desc;
} }
else else
{ {
std::cout << *it << " => "; buffer += *it;
std::cout << "Missing Description"; buffer += " => ";
buffer += "Missing Description";
} }
std::cout << std::endl; buffer += "\r\n";
} }
} }
buffer += "\r\n";
buffer += "Make Your Choice > ";
return 1; return 1;
} }
uint32_t MenuList::drawHelpPage() uint32_t MenuList::drawHelpPage(uint32_t drawFlags, std::string &buffer)
{ {
Menu::drawPage(); Menu::drawHelpPage(drawFlags, buffer);
std::cout << "MenuList Help: Navigation Commands are:"; std::cout << "MenuList Help: Navigation Commands are:";
std::cout << std::endl; std::cout << std::endl;
@ -499,11 +543,18 @@ uint32_t MenuList::drawHelpPage()
} }
void MenuList::reset()
{
Menu::reset(); // clears children too.
mList.clear();
mSelectIdx = -1;
mCursor = 0;
}
uint32_t MenuList::op() uint32_t MenuList::op()
{ {
/* load friend list*/
mList.clear(); mList.clear();
//rsPeers->getGpgAcceptedList(mList);
mSelectIdx = -1; mSelectIdx = -1;
mCursor = 0; mCursor = 0;
@ -734,7 +785,7 @@ uint32_t MenuOpLineInput::process(char key)
{ {
/* read data in and add to buffer */ /* read data in and add to buffer */
mInput += key; mInput += key;
if (key != '\n') if ((key != '\n') && (key != '\r'))
{ {
return MENU_PROCESS_NEEDDATA; return MENU_PROCESS_NEEDDATA;
} }

View File

@ -7,25 +7,30 @@
#include <map> #include <map>
#include <list> #include <list>
#define MENU_PROCESS_NONE 0 #include "rstermserver.h" // generic processing command.
#define MENU_PROCESS_TOP 1
#define MENU_PROCESS_MENU 2 #define MENU_PROCESS_MASK 0x0fff
#define MENU_PROCESS_NEEDDATA 3
#define MENU_PROCESS_DONE 4 #define MENU_PROCESS_NONE 0x0000
#define MENU_PROCESS_QUIT 5 #define MENU_PROCESS_TOP 0x0001
#define MENU_PROCESS_SHUTDOWN 6 #define MENU_PROCESS_MENU 0x0002
#define MENU_PROCESS_HELP 7 #define MENU_PROCESS_DONE 0x0004
#define MENU_PROCESS_ERROR 8 #define MENU_PROCESS_QUIT 0x0008
#define MENU_PROCESS_SHUTDOWN 0x0010
#define MENU_PROCESS_HELP 0x0020
#define MENU_PROCESS_ERROR 0x0040
#define MENU_PROCESS_NEEDDATA 0x1000 // Able to be OR'd with ANOTHER CASE.
#define MENU_KEY_QUIT 'Q' #define MENU_KEY_QUIT 'Q'
#define MENU_KEY_HELP 'H' #define MENU_KEY_HELP 'h'
#define MENU_KEY_TOP 'T' #define MENU_KEY_TOP 't'
#define MENU_KEY_REPEAT 'R' #define MENU_KEY_REPEAT 'r'
#define MENU_KEY_UP 'U' #define MENU_KEY_UP 'u'
#define MENULIST_KEY_LIST 'L' // Don't need this. #define MENULIST_KEY_LIST 'l' // Don't need this.
#define MENULIST_KEY_NEXT 'N' #define MENULIST_KEY_NEXT 'n'
#define MENULIST_KEY_PREV 'P' #define MENULIST_KEY_PREV 'p'
#define MENU_OP_ERROR 0 #define MENU_OP_ERROR 0
#define MENU_OP_INSTANT 1 #define MENU_OP_INSTANT 1
@ -35,6 +40,11 @@
#define MENU_ENTRY_NONE 0 #define MENU_ENTRY_NONE 0
#define MENU_ENTRY_OKAY 1 #define MENU_ENTRY_OKAY 1
#define MENU_DRAW_FLAGS_STD 0
#define MENU_DRAW_FLAGS_HTML 1
#define MENU_DRAW_FLAGS_ECHO 2
#define MENU_DRAW_FLAGS_NOQUIT 4
class Menu; class Menu;
class Screen; class Screen;
@ -49,19 +59,20 @@ virtual ~Menu();
Menu *selectedMenu() { return mSelectedMenu; } Menu *selectedMenu() { return mSelectedMenu; }
int addMenuItem(char key, Menu *child); int addMenuItem(char key, Menu *child);
virtual void reset();
virtual uint32_t op() { return MENU_OP_SUBMENU; } /* what type is it? returns SUBMENU, INSTANT, NEEDINPUT */ virtual uint32_t op() { return MENU_OP_SUBMENU; } /* what type is it? returns SUBMENU, INSTANT, NEEDINPUT */
virtual uint32_t process(char key); virtual uint32_t process(char key);
// THE BIT STILL TO BE DEFINED! // THE BIT STILL TO BE DEFINED!
std::string ShortFnDesc() { return mShortDesc; }// Menu Text (for Help). std::string ShortFnDesc() { return mShortDesc; }// Menu Text (for Help).
virtual uint32_t drawPage(uint32_t drawFlags, std::string &buffer);
virtual uint32_t drawHelpPage(uint32_t drawFlags, std::string &buffer);
//virtual std::string menuText() = 0; //virtual std::string menuText() = 0;
//virtual std::string menuHelp() = 0; //virtual std::string menuHelp() = 0;
virtual void setOpMessage(std::string msg) { return; } virtual void setOpMessage(std::string msg) { return; }
virtual void setErrorMessage(std::string msg) { return; } virtual void setErrorMessage(std::string msg) { return; }
virtual uint32_t drawPage(); // { return 1; } //= 0;
virtual uint32_t drawHelpPage(); // { return 1; } //= 0;
virtual uint32_t showError() { return 1; } //= 0; virtual uint32_t showError() { return 1; } //= 0;
virtual uint32_t showHelp() { return 1; } //= 0; virtual uint32_t showHelp() { return 1; } //= 0;
@ -92,6 +103,7 @@ class MenuList: public Menu
public: public:
MenuList(std::string shortDesc): Menu(shortDesc) { return; } MenuList(std::string shortDesc): Menu(shortDesc) { return; }
virtual void reset();
virtual uint32_t op(); virtual uint32_t op();
virtual uint32_t process(char key); virtual uint32_t process(char key);
@ -103,8 +115,8 @@ virtual uint32_t process(char key);
virtual int getEntryDesc(int idx, std::string &desc); virtual int getEntryDesc(int idx, std::string &desc);
// Output. // Output.
virtual uint32_t drawPage(); virtual uint32_t drawPage(uint32_t drawFlags, std::string &buffer);
virtual uint32_t drawHelpPage(); virtual uint32_t drawHelpPage(uint32_t drawFlags, std::string &buffer);
protected: protected:
virtual uint32_t list_process(char key); virtual uint32_t list_process(char key);
@ -161,17 +173,24 @@ protected:
class MenuInterface class MenuInterface: public RsTermServer
{ {
public: public:
MenuInterface(Menu *b) :mCurrentMenu(b), mBase(b) { return; } MenuInterface(Menu *b, uint32_t drawFlags) :mCurrentMenu(b), mBase(b), mDrawFlags(drawFlags), mInputRequired(false) { return; }
uint32_t process(char key); uint32_t process(char key, uint32_t drawFlags, std::string &buffer);
uint32_t drawHeader(); uint32_t drawHeader(uint32_t drawFlags, std::string &buffer);
// RsTermServer Interface.
virtual void reset();
virtual int tick(bool haveInput, char keypress, std::string &output);
private: private:
Menu *mCurrentMenu; Menu *mCurrentMenu;
Menu *mBase; Menu *mBase;
uint32_t mDrawFlags;
bool mInputRequired;
}; };

View File

@ -10,30 +10,30 @@
// or L, N, P (list ops). // or L, N, P (list ops).
// or 0-9,a-f (list selection). // or 0-9,a-f (list selection).
#define MENU_FRIENDS_KEY_ADD 'A' #define MENU_FRIENDS_KEY_ADD 'a'
#define MENU_FRIENDS_KEY_VIEW 'V' #define MENU_FRIENDS_KEY_VIEW 'v'
#define MENU_FRIENDS_KEY_REMOVE 'D' #define MENU_FRIENDS_KEY_REMOVE 'd'
#define MENU_FRIENDS_KEY_CHAT 'C' #define MENU_FRIENDS_KEY_CHAT 'c'
#define MENU_TRANSFER_KEY_STOP 'S' #define MENU_TRANSFER_KEY_STOP 's'
#define MENU_TRANSFER_KEY_CANCEL 'C' #define MENU_TRANSFER_KEY_CANCEL 'c'
#define MENU_SEARCH_KEY_ADD 'A' #define MENU_SEARCH_KEY_ADD 'a'
#define MENU_SEARCH_KEY_REMOVE 'D' #define MENU_SEARCH_KEY_REMOVE 'd'
#define MENU_SEARCH_KEY_VIEW 'V' #define MENU_SEARCH_KEY_VIEW 'v'
#define MENU_SEARCH_KEY_DOWNLOAD 'G' #define MENU_SEARCH_KEY_DOWNLOAD 'g'
#define MENU_FRIENDS_KEY_ADD 'A' #define MENU_FRIENDS_KEY_ADD 'a'
#define MENU_FRIENDS_KEY_VIEW 'V' #define MENU_FRIENDS_KEY_VIEW 'v'
#define MENU_FRIENDS_KEY_REMOVE 'D' #define MENU_FRIENDS_KEY_REMOVE 'd'
#define MENU_FRIENDS_KEY_CHAT 'C' #define MENU_FRIENDS_KEY_CHAT 'c'
#define MENU_TOPLEVEL_KEY_FRIENDS 'F' #define MENU_TOPLEVEL_KEY_FRIENDS 'f'
#define MENU_TOPLEVEL_KEY_NETWORK 'W' #define MENU_TOPLEVEL_KEY_NETWORK 'w'
#define MENU_TOPLEVEL_KEY_TRANSFER 'D' #define MENU_TOPLEVEL_KEY_TRANSFER 'd'
#define MENU_TOPLEVEL_KEY_SEARCH 'S' #define MENU_TOPLEVEL_KEY_SEARCH 's'
#define MENU_TOPLEVEL_KEY_FORUMS 'O' #define MENU_TOPLEVEL_KEY_FORUMS 'o'
Menu *CreateMenuStructure(NotifyTxt *notify) Menu *CreateMenuStructure(NotifyTxt *notify)
@ -199,7 +199,7 @@ int MenuListTransfer::getEntryDesc(int idx, std::string &desc)
return 0; return 0;
} }
float frac = (float) info.transfered / info.size; float frac = 100.0 * (float) info.transfered / info.size;
if (frac != 1.0) if (frac != 1.0)
{ {
@ -335,6 +335,13 @@ int MenuListSearch::removeSearch(std::string strSearchId)
return 1; return 1;
} }
uint32_t MenuOpSearchNew::drawPage(uint32_t drawFlags, std::string &buffer)
{
buffer += "Enter New Search Term > ";
return 1;
}
uint32_t MenuOpSearchNew::process_lines(std::string input) uint32_t MenuOpSearchNew::process_lines(std::string input)
{ {

View File

@ -139,6 +139,9 @@ class MenuOpSearchNew: public MenuOpLineInput
MenuOpSearchNew() :MenuOpLineInput("New") { return; } MenuOpSearchNew() :MenuOpLineInput("New") { return; }
virtual uint32_t process_lines(std::string input); virtual uint32_t process_lines(std::string input);
virtual uint32_t drawPage(uint32_t drawFlags, std::string &buffer);
}; };

View File

@ -15,7 +15,9 @@ int tick()
{ {
int c = mIn.get(); int c = mIn.get();
uint8_t key = (uint8_t) c; uint8_t key = (uint8_t) c;
mMenus->process(key); uint32_t drawFlags = 0;
std::string buffer;
mMenus->process(key, drawFlags, buffer);
return 1; return 1;
} }
@ -28,5 +30,65 @@ private:
std::ostream &mOut; std::ostream &mOut;
}; };
#include <unistd.h>
#include <fcntl.h>
#include "rstermserver.h"
class RsConsole
{
public:
RsConsole(RsTermServer *s, int infd, int outfd)
:mServer(s), mIn(infd), mOut(outfd)
{
const int fcflags = fcntl(mIn,F_GETFL);
if (fcflags < 0)
{
std::cerr << "RsConsole() ERROR getting fcntl FLAGS";
std::cerr << std::endl;
exit(1);
}
if (fcntl(mIn,F_SETFL,fcflags | O_NONBLOCK) <0)
{
std::cerr << "RsConsole() ERROR setting fcntl FLAGS";
std::cerr << std::endl;
exit(1);
}
}
int tick()
{
char buf;
std::string output;
int size = read(mIn, &buf, 1);
bool haveInput = (size > 0);
int rt = mServer->tick(haveInput, buf, output);
if (output.size() > 0)
{
write(mOut, output.c_str(), output.size());
}
if (rt < 0)
{
std::cerr << "Exit Request";
exit(1);
}
if (!haveInput)
{
return 0;
}
return 1;
}
private:
RsTermServer *mServer;
int mIn, mOut;
};

View File

@ -2,7 +2,7 @@ TEMPLATE = app
TARGET = retroshare-nogui TARGET = retroshare-nogui
CONFIG += bitdht CONFIG += bitdht
#CONFIG += introserver #CONFIG += introserver
#CONFIG += sshserver CONFIG += sshserver
CONFIG += debug CONFIG += debug
debug { debug {
@ -23,6 +23,7 @@ linux-* {
LIBS += ../../libretroshare/src/lib/libretroshare.a LIBS += ../../libretroshare/src/lib/libretroshare.a
LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2 LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2
LIBS += -lssl -lupnp -lixml -lgnome-keyring LIBS += -lssl -lupnp -lixml -lgnome-keyring
LIBS += -lsqlite3
} }
linux-g++ { linux-g++ {
@ -134,10 +135,12 @@ sshserver {
# #
# You can connect from a standard ssh, eg: ssh -p 7022 127.0.0.1 # You can connect from a standard ssh, eg: ssh -p 7022 127.0.0.1
# #
# The Menu system is available from the command-line now, # The Menu system is available from the command-line (-T) and SSH (-S)
# but not over SSH yet...
# if it get covered by debug gunk, just press <return> to refresh. # if it get covered by debug gunk, just press <return> to refresh.
# #
# ./retroshare-nogui -h provides some more instructions.
#
INCLUDEPATH += ../../../lib/libssh-0.5.2/include/ INCLUDEPATH += ../../../lib/libssh-0.5.2/include/
LIBS += ../../../lib/libssh-0.5.2/build/src/libssh.a LIBS += ../../../lib/libssh-0.5.2/build/src/libssh.a
LIBS += ../../../lib/libssh-0.5.2/build/src/threads/libssh_threads.a LIBS += ../../../lib/libssh-0.5.2/build/src/threads/libssh_threads.a
@ -146,6 +149,7 @@ sshserver {
HEADERS += menu/menu.h \ HEADERS += menu/menu.h \
menu/menus.h \ menu/menus.h \
rstermserver.h \
SOURCES += menu/menu.cc \ SOURCES += menu/menu.cc \
menu/menus.cc \ menu/menus.cc \

View File

@ -82,8 +82,198 @@ int main(int argc, char **argv)
* LoadPassword(...) set password for existing certificate. * LoadPassword(...) set password for existing certificate.
**/ **/
bool strictCheck = true;
#ifdef RS_SSH_SERVER
/* parse commandline for additional nogui options */
int c;
// libretroshare's getopt str - so don't use any of these: "hesamui:p:c:w:l:d:U:r:R:"
// need options for
// enable SSH. (-S)
// set user/password for SSH. -L "user:pwdhash"
// accept RSA Key Auth. -K "RsaPubKeyFile"
// Terminal mode. -T
bool enableSsh = false;
bool enableSshHtml = false;
bool enableSshPwd = false;
bool enableTerminal = false;
bool enableSshRsa = false;
bool genPwdHash = false;
std::string sshUser = "user";
std::string sshPwdHash = "";
std::string sshRsaFile = "";
std::string sshPortStr = "7022";
while((c = getopt(argc, argv,"hTL:P:K:GS::")) != -1)
{
switch(c)
{
case 'S':
enableSsh = true;
if (optarg)
{
sshPortStr = optarg; // optional.
}
strictCheck = false;
break;
case 'H':
enableSshHtml = true;
strictCheck = false;
break;
case 'T':
enableTerminal = true;
strictCheck = false;
break;
case 'L':
sshUser = optarg;
strictCheck = false;
break;
case 'P':
enableSshPwd = true;
sshPwdHash = optarg;
strictCheck = false;
break;
#if 0 // NOT FINISHED YET.
case 'K':
enableSshRsa = true;
sshRsaFile = optarg;
strictCheck = false;
break;
#endif
case 'G':
genPwdHash = true;
break;
case 'h':
/* nogui help */
std::cerr << argv[0] << std::endl;
std::cerr << "Specific Help Options: " << std::endl;
std::cerr << "\t-G Generate a Password Hash for SSH Server" << std::endl;
std::cerr << "\t-T Enable Terminal Interface" << std::endl;
std::cerr << "\t-S [port] Enable SSH Server, optionally specify port" << std::endl;
std::cerr << "\t-L <user> Specify SSH login user (default:user)" << std::endl;
std::cerr << "\t-P <pwdhash> Enable SSH login via Password" << std::endl;
//std::cerr << "\t-K [rsapubkeyfile] Enable SSH login via RSA key" << std::endl;
//std::cerr << "\t NB: Two Factor Auth, specify both -P & -K" << std::endl;
std::cerr << std::endl;
std::cerr << "\t To setup rs-nogui as a SSH Server is a three step process: " << std::endl;
std::cerr << "\t 1) \"ssh-keygen -t rsa -f rs_ssh_host_rsa_key\" " << std::endl;
std::cerr << "\t 2) \"./retroshare-nogui -G\" " << std::endl;
std::cerr << "\t 3) \"./retroshare-nogui -S [port] -L <user> -P <passwordhash>\" " << std::endl;
std::cerr << std::endl;
std::cerr << "Further Options ";
/* libretroshare will call exit(1) after printing its options */
break;
default:
/* let others through - for libretroshare */
break;
}
}
// reset optind for Retroshare commandline arguments.
optind = 1;
if (genPwdHash)
{
std::string saltBin;
std::string pwdHashRadix64;
std::string sshPwdForHash = "";
std::cout << "Type in your Password:" << std::flush;
char pwd[1024];
if (!fgets(pwd, 1024, stdin))
{
std::cerr << "Error Reading Password";
std::cerr << std::endl;
exit(1);
}
// strip newline.
for(int i = 0; (i < 1024) && (pwd[i] != '\n') && (pwd[i] != '\0'); i++)
{
sshPwdForHash += pwd[i];
}
std::cerr << "Chosen Password : " << sshPwdForHash;
std::cerr << std::endl;
GenerateSalt(saltBin);
if (!GeneratePasswordHash(saltBin, sshPwdForHash, pwdHashRadix64))
{
std::cerr << "Error Generating Password Hash, password probably too short";
std::cerr << pwdHashRadix64;
std::cerr << std::endl;
exit(1);
}
std::cout << "Generated Password Hash for rs-nogui: ";
std::cout << pwdHashRadix64;
std::cout << std::endl;
std::cout << std::endl;
/* checking match */
if (CheckPasswordHash(pwdHashRadix64, sshPwdForHash))
{
std::cerr << "Passed Check Okay!";
std::cerr << std::endl;
}
else
{
std::cerr << "ERROR: Failed CheckPassword!";
std::cerr << std::endl;
exit(1);
}
std::cerr << "Usage: ./retroshare-nogui -S [port] -L <username> -P " << pwdHashRadix64;
std::cerr << std::endl;
exit(1);
}
/* enforce conditions */
if (((enableSshRsa) || (enableSshPwd)) && (!enableSsh))
{
std::cerr << "ERROR: SSH Server (-S) must be enabled to specify SSH Pwd (-P) or SSH RSA (-K)";
std::cerr << std::endl;
exit(1);
}
if (enableSsh && (!enableSshRsa) && (!enableSshPwd))
{
std::cerr << "ERROR: One of (or both) SSH Pwd (-P) and SSH RSA (-K) must be specified with SSH Server (-S)";
std::cerr << std::endl;
exit(1);
}
/* parse -S, -L & -K parameters */
if (enableSshRsa)
{
/* check the file exists */
/* TODO */
}
if (enableSsh)
{
/* try parse it */
/* TODO */
}
if (enableSshPwd)
{
/* try parse it */
/* TODO */
}
#endif
RsInit::InitRsConfig(); RsInit::InitRsConfig();
int initResult = RsInit::InitRetroShare(argc, argv); int initResult = RsInit::InitRetroShare(argc, argv, strictCheck);
if (initResult < 0) { if (initResult < 0) {
/* Error occured */ /* Error occured */
@ -143,8 +333,25 @@ int main(int argc, char **argv)
#ifdef RS_SSH_SERVER #ifdef RS_SSH_SERVER
// Says it must be called before all the threads are launched! */ // Says it must be called before all the threads are launched! */
// NB: this port number is not currently used. // NB: this port number is not currently used.
RsSshd *ssh = RsSshd::InitRsSshd(22, "rs_ssh_host_rsa_key"); RsSshd *ssh = NULL;
ssh->adduser("anrsuser", "test");
if (enableSsh)
{
ssh = RsSshd::InitRsSshd(sshPortStr, "rs_ssh_host_rsa_key");
// TODO Parse Option
if (enableSshRsa)
{
//ssh->adduser("anrsuser", "test");
}
if (enableSshPwd)
{
ssh->adduserpwdhash(sshUser, sshPwdHash);
}
}
#endif #endif
/* Start-up libretroshare server threads */ /* Start-up libretroshare server threads */
@ -155,11 +362,30 @@ int main(int argc, char **argv)
#endif #endif
#ifdef RS_SSH_SERVER #ifdef RS_SSH_SERVER
ssh->start(); uint32_t baseDrawFlags = 0;
if (enableSshHtml)
baseDrawFlags = MENU_DRAW_FLAGS_HTML;
if (enableSsh)
{
/* create menu system for SSH */
Menu *baseMenu = CreateMenuStructure(notify);
MenuInterface *menuInterface = new MenuInterface(baseMenu, baseDrawFlags | MENU_DRAW_FLAGS_ECHO);
ssh->setTermServer(menuInterface);
ssh->start();
}
//MenuTest *menuTerminal = NULL;
RsConsole *menuTerminal = NULL;
if (enableTerminal)
{
/* Terminal Version */
Menu *baseMenu = CreateMenuStructure(notify);
MenuInterface *menuInterface = new MenuInterface(baseMenu, baseDrawFlags | MENU_DRAW_FLAGS_NOQUIT);
menuTerminal = new RsConsole(menuInterface, fileno(stdin), fileno(stdout));
}
Menu *baseMenu = CreateMenuStructure(notify);
MenuInterface *menuInterface = new MenuInterface(baseMenu);
MenuTest menuTest(menuInterface, std::cin, std::cout);
#endif #endif
@ -167,20 +393,30 @@ int main(int argc, char **argv)
while(1) while(1)
{ {
//std::cerr << "GUI Tick()" << std::endl; //std::cerr << "GUI Tick()" << std::endl;
#ifndef WINDOWS_SYS
sleep(1);
#else
Sleep(1000);
#endif
#ifdef RS_INTRO_SERVER #ifdef RS_INTRO_SERVER
rsIS.tick(); rsIS.tick();
#endif #endif
int rt = 0;
#ifdef RS_SSH_SERVER #ifdef RS_SSH_SERVER
menuTest.tick(); if (menuTerminal)
{
rt = menuTerminal->tick();
}
#endif #endif
// If we have a MenuTerminal ...
// only want to sleep if there is no input. (rt == 0).
if (rt == 0)
{
#ifndef WINDOWS_SYS
sleep(1);
#else
Sleep(1000);
#endif
}
} }
return 1; return 1;
} }

View File

@ -0,0 +1,13 @@
#ifndef RS_TERM_SERVER_H
#define RS_TERM_SERVER_H
class RsTermServer
{
public:
/* this must be regularly ticked to update the display */
virtual void reset() = 0;
virtual int tick(bool haveInput, char keypress, std::string &output) = 0;
};
#endif // RS_TERM_SERVER_H

View File

@ -30,12 +30,12 @@ clients must be made or how a client should react.
RsSshd *rsSshd = NULL; // External Reference Variable. RsSshd *rsSshd = NULL; // External Reference Variable.
// NB: This must be called EARLY before all the threads are launched. // NB: This must be called EARLY before all the threads are launched.
RsSshd *RsSshd::InitRsSshd(uint16_t port, std::string rsakeyfile) RsSshd *RsSshd::InitRsSshd(std::string portStr, std::string rsakeyfile)
{ {
ssh_threads_set_callbacks(ssh_threads_get_pthread()); ssh_threads_set_callbacks(ssh_threads_get_pthread());
ssh_init(); ssh_init();
rsSshd = new RsSshd(port); rsSshd = new RsSshd(portStr);
if (rsSshd->init(rsakeyfile)) if (rsSshd->init(rsakeyfile))
{ {
return rsSshd; return rsSshd;
@ -46,12 +46,13 @@ RsSshd *RsSshd::InitRsSshd(uint16_t port, std::string rsakeyfile)
} }
RsSshd::RsSshd(uint16_t port) RsSshd::RsSshd(std::string portStr)
:mSshMtx("sshMtx"), mPort(port), mChannel(0) :mSshMtx("sshMtx"), mPortStr(portStr), mChannel(0)
{ {
mState = RSSSHD_STATE_NULL; mState = RSSSHD_STATE_NULL;
mBindState = 0; mBindState = 0;
mTermServer = NULL;
return; return;
} }
@ -62,13 +63,12 @@ int RsSshd::init(std::string pathrsakey)
{ {
mBind=ssh_bind_new(); mBind=ssh_bind_new();
mSession=ssh_new();
//ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); //ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
//ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); //ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
//ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_BINDPORT_STR, arg); //ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_BINDPORT_STR, "7022"); ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_BINDPORT_STR, mPortStr.c_str());
//ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_DSAKEY, arg); //ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_DSAKEY, arg);
//ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_HOSTKEY, arg); //ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_HOSTKEY, arg);
ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_RSAKEY, pathrsakey.c_str()); ssh_bind_options_set(mBind, SSH_BIND_OPTIONS_RSAKEY, pathrsakey.c_str());
@ -136,6 +136,7 @@ int RsSshd::listenConnect()
std::cerr << std::endl; std::cerr << std::endl;
} }
mSession=ssh_new();
int r=ssh_bind_accept(mBind,mSession); int r=ssh_bind_accept(mBind,mSession);
if(r==SSH_ERROR) if(r==SSH_ERROR)
{ {
@ -188,7 +189,8 @@ int RsSshd::interactive()
std::cerr << "RsSshd::interactive()"; std::cerr << "RsSshd::interactive()";
std::cerr << std::endl; std::cerr << std::endl;
doEcho(); doTermServer();
//doEcho();
return 1; return 1;
} }
@ -337,12 +339,74 @@ int RsSshd::doEcho()
} }
int RsSshd::setTermServer(RsTermServer *s)
{
mTermServer = s;
return 1;
}
int RsSshd::doTermServer()
{
std::cerr << "RsSshd::doTermServer()";
std::cerr << std::endl;
if (!mTermServer)
{
std::cerr << "RsSshd::doTermServer() ERROR Not Set";
std::cerr << std::endl;
return 0;
}
mTermServer->reset(); // clear everything for new user.
bool okay = true;
while(okay)
{
char buf;
int size = ssh_channel_read_nonblocking(mChannel, &buf, 1, 0);
bool haveInput = (size > 0);
std::string output;
int rt = mTermServer->tick(haveInput, buf, output);
if (output.size() > 0)
{
ssh_channel_write(mChannel, output.c_str(), output.size());
}
if (!haveInput)
{
/* have a little sleep */
sleep(1); //0000000); // 1/10th sec.
//usleep(10000000); // 1/10th sec.
}
else
{
usleep(10000); // 1/100th sec.
}
if (rt < 0)
{
okay = false; // exit.
}
}
std::cerr << "RsSshd::doTermServer() Finished";
std::cerr << std::endl;
return 1;
}
int RsSshd::cleanupSession() int RsSshd::cleanupSession()
{ {
std::cerr << "RsSshd::cleanupSession()"; std::cerr << "RsSshd::cleanupSession()";
std::cerr << std::endl; std::cerr << std::endl;
ssh_disconnect(mSession); ssh_disconnect(mSession);
ssh_free(mSession);
return 1; return 1;
} }
@ -433,15 +497,17 @@ int RsSshd::auth_password_basic(char *name, char *pwd)
} }
#endif // ALLOW_CLEARPWDS #endif // ALLOW_CLEARPWDS
#define RSSSHD_HASH_PWD_LENGTH 40 //#define RSSSHD_HASH_PWD_LENGTH 40
int RsSshd::adduserpwdhash(std::string username, std::string hash) int RsSshd::adduserpwdhash(std::string username, std::string hash)
{ {
#if 0
if (hash.length() != RSSSHD_HASH_PWD_LENGTH) if (hash.length() != RSSSHD_HASH_PWD_LENGTH)
{ {
std::cerr << "RsSshd::adduserpwdhash() Hash Wrong Length"; std::cerr << "RsSshd::adduserpwdhash() Hash Wrong Length";
return 0; return 0;
} }
#endif
if (username.length() < RSSSHD_MIN_USERNAME) if (username.length() < RSSSHD_MIN_USERNAME)
{ {
@ -464,21 +530,18 @@ int RsSshd::adduserpwdhash(std::string username, std::string hash)
int RsSshd::auth_password_hashed(char *name, char *pwd) int RsSshd::auth_password_hashed(char *name, char *pwd)
{ {
std::cerr << "RsSshd::auth_password_hashed() Not Finished Yet!";
return 0;
std::string username(name); std::string username(name);
std::string password(pwd); std::string password(pwd);
std::map<std::string, std::string>::iterator it; std::map<std::string, std::string>::iterator it;
it = mPasswords.find(username); it = mPwdHashs.find(username);
if (it == mPasswords.end()) if (it == mPwdHashs.end())
{ {
std::cerr << "RsSshd::auth_password_hashed() Unknown username"; std::cerr << "RsSshd::auth_password_hashed() Unknown username";
return 0; return 0;
} }
if (it->second == password) if (CheckPasswordHash(it->second, password))
{ {
std::cerr << "RsSshd::auth_password_hashed() logged in " << username; std::cerr << "RsSshd::auth_password_hashed() logged in " << username;
return 1; return 1;
@ -488,4 +551,161 @@ int RsSshd::auth_password_hashed(char *name, char *pwd)
return 0; return 0;
} }
#include "util/radix64.h"
#include "util/rsrandom.h"
#include <openssl/evp.h>
#define RSSSHD_PWD_SALT_LEN 16
#define RSSSHD_PWD_MIN_LEN 8
#if 0
int printHex(const char *data, int len)
{
for(int i = 0; i < len; i++)
{
fprintf(stderr, "%02x", (uint8_t) data[i]);
}
return 1;
}
#endif
int GenerateSalt(std::string &saltBin)
{
/* get from random */
for(int i = 0; i < RSSSHD_PWD_SALT_LEN / 4; i++)
{
uint32_t rnd = RSRandom::random_u32();
saltBin += ((char *) &rnd)[0];
saltBin += ((char *) &rnd)[1];
saltBin += ((char *) &rnd)[2];
saltBin += ((char *) &rnd)[3];
}
#if 0
std::cerr << "HexSalt: ";
printHex(saltBin.c_str(), saltBin.size());
std::cerr << std::endl;
#endif
return 1;
}
int GeneratePasswordHash(std::string saltBin, std::string password, std::string &pwdHashRadix64)
{
#if 0
std::cerr << "GeneratePasswordHash()";
std::cerr << std::endl;
std::cerr << "HexSalt: ";
printHex(saltBin.c_str(), saltBin.size());
std::cerr << std::endl;
#endif
if (saltBin.size() != RSSSHD_PWD_SALT_LEN)
{
return 0;
}
if (password.size() < RSSSHD_PWD_MIN_LEN)
{
return 0;
}
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
EVP_DigestInit(ctx, EVP_sha256());
EVP_DigestUpdate(ctx, saltBin.c_str(), saltBin.size());
EVP_DigestUpdate(ctx, password.c_str(), password.size());
unsigned char hash[1024];
unsigned int s = 1024 - RSSSHD_PWD_SALT_LEN;
for(int i = 0; i < RSSSHD_PWD_SALT_LEN; i++)
{
hash[i] = saltBin[i];
}
EVP_DigestFinal(ctx, &(hash[RSSSHD_PWD_SALT_LEN]), &s);
Radix64::encode((char *)hash, s + RSSSHD_PWD_SALT_LEN, pwdHashRadix64);
#if 0
std::cerr << "Salt Length: " << RSSSHD_PWD_SALT_LEN;
std::cerr << std::endl;
std::cerr << "Hash Length: " << s;
std::cerr << std::endl;
std::cerr << "Total Length: " << s + RSSSHD_PWD_SALT_LEN;
std::cerr << std::endl;
std::cerr << "Encoded Length: " << pwdHashRadix64.size();
std::cerr << std::endl;
std::cerr << "GeneratePasswordHash() Output: " << pwdHashRadix64;
std::cerr << std::endl;
#endif
return 1;
}
int CheckPasswordHash(std::string pwdHashRadix64, std::string password)
{
char output[1024];
char *buf = NULL;
size_t len = 1024;
Radix64::decode(pwdHashRadix64, buf, len);
for(int i = 0; (i < len) && (i < 1024); i++)
{
output[i] = buf[i];
}
delete []buf;
#if 0
std::cerr << "CheckPasswordHash() Input: " << pwdHashRadix64;
std::cerr << std::endl;
std::cerr << "Decode Length: " << len;
std::cerr << std::endl;
std::cerr << "HexDecoded: ";
printHex(output, len);
std::cerr << std::endl;
#endif
/* first N bytes are SALT */
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
EVP_DigestInit(ctx, EVP_sha256());
EVP_DigestUpdate(ctx, output, RSSSHD_PWD_SALT_LEN);
EVP_DigestUpdate(ctx, password.c_str(), password.size());
#if 0
std::cerr << "HexSalt: ";
printHex(output, RSSSHD_PWD_SALT_LEN);
std::cerr << std::endl;
#endif
unsigned char hash[128];
unsigned int s = 128;
EVP_DigestFinal(ctx, hash, &s);
/* Final Comparison */
if (s != len - RSSSHD_PWD_SALT_LEN)
{
std::cerr << "Length Mismatch";
return 0;
}
if (0 == strncmp(&(output[RSSSHD_PWD_SALT_LEN]), (char *) hash, s))
{
return 1;
}
return 0;
}

View File

@ -34,6 +34,7 @@ clients must be made or how a client should react.
#include <string> #include <string>
#include <map> #include <map>
#include "rstermserver.h"
#ifndef KEYS_FOLDER #ifndef KEYS_FOLDER
#ifdef _WIN32 #ifdef _WIN32
@ -53,17 +54,22 @@ clients must be made or how a client should react.
#define ALLOW_CLEARPWDS 1 //#define ALLOW_CLEARPWDS 1
class RsSshd; class RsSshd;
extern RsSshd *rsSshd; extern RsSshd *rsSshd;
// TODO: NB: THIS FN DOES NOT USE A "SLOW" HASH FUNCTION.
// THE FIRST HALF OF THE HASH STRING IS THE SALT
int CheckPasswordHash(std::string pwdHashRadix64, std::string password);
int GeneratePasswordHash(std::string saltBin, std::string password, std::string &pwdHashRadix64);
int GenerateSalt(std::string &saltBin);
class RsSshd: public RsThread class RsSshd: public RsThread
{ {
public: public:
// TODO: NB: THIS FN DOES NOT USE A "SLOW" HASH FUNCTION.
// THE FIRST HALF OF THE HASH STRING IS THE SALT
int adduserpwdhash(std::string username, std::string hash); int adduserpwdhash(std::string username, std::string hash);
#ifdef ALLOW_CLEARPWDS #ifdef ALLOW_CLEARPWDS
int adduser(std::string username, std::string password); int adduser(std::string username, std::string password);
@ -74,10 +80,13 @@ int adduser(std::string username, std::string password);
virtual void run(); /* overloaded from RsThread => called once the thread is started */ virtual void run(); /* overloaded from RsThread => called once the thread is started */
// NB: This must be called EARLY before all the threads are launched. // NB: This must be called EARLY before all the threads are launched.
static RsSshd *InitRsSshd(uint16_t port, std::string rsakeyfile); static RsSshd *InitRsSshd(std::string portstr, std::string rsakeyfile);
// Terminal Handling!
int setTermServer(RsTermServer *s);
private: private:
RsSshd(uint16_t port); /* private constructor => so can only create with */ RsSshd(std::string portStr); /* private constructor => so can only create with */
int init(std::string pathrsakey); int init(std::string pathrsakey);
@ -92,6 +101,9 @@ int setupChannel();
int setupShell(); int setupShell();
int doEcho(); int doEcho();
// Terminal Handling!
int doTermServer();
int cleanupSession(); int cleanupSession();
int cleanupAll(); int cleanupAll();
@ -109,11 +121,12 @@ int auth_password_basic(char *name, char *pwd);
uint32_t mState; uint32_t mState;
uint32_t mBindState; uint32_t mBindState;
uint16_t mPort; std::string mPortStr;
ssh_session mSession; ssh_session mSession;
ssh_bind mBind; ssh_bind mBind;
ssh_channel mChannel; ssh_channel mChannel;
RsTermServer *mTermServer;
#ifdef ALLOW_CLEARPWDS #ifdef ALLOW_CLEARPWDS
std::map<std::string, std::string> mPasswords; std::map<std::string, std::string> mPasswords;
#endif // ALLOW_CLEARPWDS #endif // ALLOW_CLEARPWDS