diff --git a/slc/trunk/Makefile.am b/slc/trunk/Makefile.am index 542984833891ceeef9216b8085e4a6f5e6ab81fb..df0390698aed33f3d0bc83a6ed2beaa45ad5da57 100644 --- a/slc/trunk/Makefile.am +++ b/slc/trunk/Makefile.am @@ -20,9 +20,11 @@ slc_SOURCES= src/slc.cc \ src/options.cc \ src/engine.cc \ src/screen.cc \ + src/cmd.cc \ src/history.cc \ src/sll/connection.cc \ - src/sll/error.cc + src/sll/error.cc \ + src/sll/cypher.cc noinst_SOURCES= src/slc.hh \ src/options.hh \ @@ -31,7 +33,8 @@ noinst_SOURCES= src/slc.hh \ src/history.hh \ src/sll/error.hh \ src/sll/connection.hxx \ - src/sll/connection.hh + src/sll/connection.hh \ + src/sll/cypher.hh CLEANFILES= *~ '\#*' .*.swp .*~ diff --git a/slc/trunk/src/cmd.cc b/slc/trunk/src/cmd.cc new file mode 100644 index 0000000000000000000000000000000000000000..a3be4d90b2278cf51768a0a9693fadb87e9e9e69 --- /dev/null +++ b/slc/trunk/src/cmd.cc @@ -0,0 +1,153 @@ +/* + This file is part of SLC. + Copyright (C) 2008 Sebastien LUTTRINGER + + SLC 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; version 2 of the License. + + SLC 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 SLC; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "slc.hh" +#include "engine.hh" +#include "screen.hh" +#include "options.hh" +#include "sll/connection.hh" + +namespace cmd { + + /*! + ** Exec command if @param s is not a command. + */ + void exec(const char *s) { + // string is a local command + if (*s == '/') { + if (!strcmp(s, "/exit")) { + S << INF_DATA << "Exiting.\n"; + exit(0); + } + else if (!strcmp(s, "/logout")) + cmd::logout(); + else if (!strcmp(s, "/login")) + cmd::login(); + else if (!strcmp(s, "/help")) + cmd::help(); + else if (!strncmp(s, "/user", 5)) + cmd::user(s); + else if (!strncmp(s, "/pass", 5)) + cmd::pass(s); + else + S << WAR_DATA << s << ": Unkown command.\n"; + } + // String is a remote command + else { + if (C.connected()) { + C.sendln(s); + S << ">> " << s << "\n"; + } + else + S << "Unable to send: " << s << ". Try to connect with /login !\n"; + } + } + + + /** + * Log into server + * + */ + void login() { + if (C.connected()) { + S << INF_DATA << "Already connected. Please disconnect before.\n"; + return; + } + S << INF_DATA << "Login.\n"; + E.login(); + } + + + /** + * Log out of server + * + */ + void logout() { + if (!C.connected()) { + S << INF_DATA << "Not connected. Please connect before.\n"; + return; + } + S << INF_DATA << "Logout.\n"; + C.disconnect(); + } + + /** + * Print cmd help + * + */ + void help() { + S << INF_DATA << "Commands:\n"; + S << INF_DATA << "/exit: Quit.\n"; + S << INF_DATA << "/login: Connect and try to login on server.\n"; + S << INF_DATA << "/logout: Disconnect from server.\n"; + S << INF_DATA << "/user : Change username.\n"; + S << INF_DATA << "/pass : Change password.\n"; + S << INF_DATA << "/help: Print this help.\n"; + } + + /** + * Change user name to @param s + */ + void user(const char *s) { + if (C.connected()) { + S << INF_DATA << "Your are connected. Please deconnect before.\n"; + return; + } + + // extract name + string login = s; + login.erase(0, 6); + + if (login.empty()) { + S << WAR_DATA << "Empty username.\n"; + return; + } + + // set new name + O.login = login; + + // display + S << INF_DATA << "Username changed to `" << O.login << "'.\n"; + } + + /** + * Change pass name @param s + */ + void pass(const char *s) { + if (C.connected()) { + S << INF_DATA << "Your are connected. Please deconnect before.\n"; + return; + } + + // extract name + string pass = s; + pass.erase(0, 6); + + if (pass.empty()) { + S << WAR_DATA << "Empty password.\n"; + return; + } + + // set new name + O.pass = pass; + + // display + S << INF_DATA << "Password changed.\n"; + } + +} diff --git a/slc/trunk/src/engine.cc b/slc/trunk/src/engine.cc new file mode 100644 index 0000000000000000000000000000000000000000..dab1453bf36861c083545f5a15b8f551e44544b5 --- /dev/null +++ b/slc/trunk/src/engine.cc @@ -0,0 +1,100 @@ +/* + This file is part of SLC. + Copyright (C) 2008 Sebastien LUTTRINGER + + SLC 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; version 2 of the License. + + SLC 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 SLC; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "slc.hh" + +#include "sll/connection.hh" +#include "sll/cypher.hh" + +#include "engine.hh" +#include "screen.hh" +#include "options.hh" + +#include +#include +#include +#include +#include +#include + +void Engine::on() { + // Create graphic env + S.init(); + + // Show login screen + S.login(); + + // Showing dialog screen + S.dialog(); + + // connect and auth + login(); + + // Treat keyboards events + S.eventsloop(); +} + +void Engine::off() { + // Close connection + try { C.disconnect(); } + catch (...) {} +} + +/** + * Connect and auth to server + * + */ +void Engine::login() { + try { + + S << INF_DATA << "Trying to connect to " << O.server << " on " << O.port << ".\n"; + C.connect(O.server.c_str(), O.port); + + S << INF_DATA << "Trying to auth as " << O.login << ".\n"; + auth(); + } + catch (const Error &e) { + try {C.disconnect(); } + catch (...) {} + + if (e.code() == ERR_NET || e.code() == ERR_AUTH) + S << WAR_DATA << e.message() << ".\n"; + else + throw; + } +} + +/** + * Try authenticate to server + * + */ +void Engine::auth() { + char buf[MAX_LINE_SIZE]; + + snprintf(buf, MAX_LINE_SIZE, "USER %s", O.login.c_str()); + C.sendln(buf); + + snprintf(buf, MAX_LINE_SIZE, "PASS %s", + Cypher::sha1_64(O.pass.c_str(), O.pass.length()).c_str()); + C.sendln(buf); + + string valid = C.recvln(); + + if (valid != "OK") + throw Error(ERR_AUTH, "Authentication refused"); +} diff --git a/slc/trunk/src/engine.hh b/slc/trunk/src/engine.hh new file mode 100644 index 0000000000000000000000000000000000000000..cf5a490229434254c686c353e93aa48c09fd75e1 --- /dev/null +++ b/slc/trunk/src/engine.hh @@ -0,0 +1,32 @@ +/* + This file is part of SLC. + Copyright (C) 2008 Sebastien LUTTRINGER + + SLC 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; version 2 of the License. + + SLC 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 SLC; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef ENGINE_HH +# define ENGINE_HH + +class Engine { +public: + void on(); + void off(); + void login(); + +protected: + void auth(); +}; + +#endif diff --git a/slc/trunk/src/screen.cc b/slc/trunk/src/screen.cc index 4f37f14a4aea12f4cbfb58567f07234f297325e5..d2fa08c802df8f32bb4fe937160b8e10a57fd673 100644 --- a/slc/trunk/src/screen.cc +++ b/slc/trunk/src/screen.cc @@ -16,16 +16,17 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include -#include - #include "slc.hh" #include "screen.hh" #include "options.hh" #include "history.hh" +#include "engine.hh" #include "sll/connection.hh" +#include +#include +#include + /* ********************************************************************************* *************************************** PUBLIC ********************************** @@ -210,9 +211,10 @@ void Screen::eventsloop() { // check non empty buffer if (*cmd_buffer_ == 0) break; // save in history - H.add(cmd_buffer_); + if (strncmp(cmd_buffer_, "/pass", 4)) + H.add(cmd_buffer_); // Send to execution - cmd_exec(cmd_buffer_); + cmd::exec(cmd_buffer_); // purge buffer *cmd_buffer_ = 0; cmd_buf_off_ = 0; @@ -513,38 +515,6 @@ void Screen::msg_save(const string &filename) const { } fs.close(); - -} - -/*! -** Exec command or send if @param s is not a command. -*/ -void Screen::cmd_exec(const char *s) { - // string is a local command - if (*s == '/') { - if (!strcmp(s, "/exit")) { - S << s << "\n"; - exit(0); - } - else if (!strcmp(s, "/logout")) { - S << s << "\n"; - //C.stop(); - } - else if (!strcmp(s, "/login")) { - S << s << "\n"; - //C.start(); - } - else - S << s << ": Unkown command.\n"; - } - // String is a remote command - else { - if (C.connected()) { - C.sendln(s); - S << ">> " << s << "\n"; - } - else S << "Unable to send: " << s << ". Try to reconnect with /login !\n"; - } } /*! diff --git a/slc/trunk/src/screen.hh b/slc/trunk/src/screen.hh index 258229a9e2b36c5cce99c31d3561a237d0afb0d8..b078e7ebe35d29001eff3458e364ae5869513f46 100644 --- a/slc/trunk/src/screen.hh +++ b/slc/trunk/src/screen.hh @@ -48,7 +48,6 @@ private: void create_windows(); void cmd_draw(); - void cmd_exec(const char *s); void msg_draw(); void msg_add(const string &s); @@ -79,4 +78,15 @@ private: Screen &operator<< (Screen &, const string &s); Screen &operator<< (Screen &, int i); +// exec commands + +namespace cmd { + void exec(const char *); + void login(); + void logout(); + void user(const char *); + void pass(const char *); + void help(); +} + #endif diff --git a/slc/trunk/src/slc.hh b/slc/trunk/src/slc.hh index 061e9c1c2b654f0bd2d0b6e7be0c8744d83fb602..f45d1327897ce6986609a2eadf0eba2a6836a2bb 100644 --- a/slc/trunk/src/slc.hh +++ b/slc/trunk/src/slc.hh @@ -29,6 +29,9 @@ static const int MAX_CONF_LINE_SIZE = 2048; static const string RCV_DATA = "<< "; static const string SND_DATA = ">> "; +static const string INF_DATA = "-- "; +static const string WAR_DATA = "!! "; + // ----------------------------------------------------------------------------- // Global var diff --git a/slc/trunk/src/sll/connection.cc b/slc/trunk/src/sll/connection.cc index d78aa7752092db4bb30eb3dad884009f6ce55071..0450e697759480d4f8f0f7f36ec62c27d6be5b04 100644 --- a/slc/trunk/src/sll/connection.cc +++ b/slc/trunk/src/sll/connection.cc @@ -106,14 +106,14 @@ void Connection::connect(const char *addr, int port) { } // take read and write mutex - pthread_mutex_lock(&r_mutex_); pthread_mutex_lock(&w_mutex_); + pthread_mutex_lock(&r_mutex_); // retrieve remote host info struct hostent *h = gethostbyname(addr); if (h == 0) { - pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&r_mutex_); + pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&c_mutex_); throw Error(ERR_NET, (string) "Unable to resolve: " + addr + ": " + hstrerror(h_errno)); } @@ -121,8 +121,8 @@ void Connection::connect(const char *addr, int port) { // create socket try { socket_(); } catch (...) { - pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&r_mutex_); + pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&c_mutex_); throw; } @@ -138,8 +138,8 @@ void Connection::connect(const char *addr, int port) { if (::connect(socket_fd_, (struct sockaddr *) &daddr, sizeof daddr) == -1) { int errno__ = errno; disconnect_(); - pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&r_mutex_); + pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&c_mutex_); throw Error(ERR_NET, (string) "Unable to connect to " + addr + ": " + strerror(errno__)); } @@ -152,14 +152,14 @@ void Connection::connect(const char *addr, int port) { setremoteport_(); } catch (...) { - pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&r_mutex_); + pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&c_mutex_); throw; } - pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&r_mutex_); + pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&c_mutex_); } @@ -243,26 +243,34 @@ void Connection::listen(int port, int max) { * @return null on error, else a new connection */ Connection *Connection::accept() { - // keep the socket fd + // accept is a read/write op pthread_mutex_lock(&c_mutex_); + pthread_mutex_lock(&r_mutex_); + pthread_mutex_lock(&w_mutex_); + + // get the socket fd int socket_fd = socket_fd_; pthread_mutex_unlock(&c_mutex_); // test socket validity - if (socket_fd < 0) + if (socket_fd < 0) { + pthread_mutex_unlock(&r_mutex_); + pthread_mutex_unlock(&w_mutex_); throw Error(ERR_NET, "No connection established but trying to accept"); + } struct sockaddr_in r_addr; socklen_t r_sin_size = sizeof r_addr; int r_fd; - // accept is a read/write operation - pthread_mutex_lock(&r_mutex_); - pthread_mutex_lock(&w_mutex_); - if ((r_fd = ::accept(socket_fd, (struct sockaddr *) &r_addr, &r_sin_size)) == -1) { + int errno__ = errno; + pthread_mutex_lock(&c_mutex_); + disconnect_(); + pthread_mutex_unlock(&r_mutex_); + pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&c_mutex_); - throw Error(ERR_NET, (string) "accept: " + strerror(errno)); + throw Error(ERR_NET, (string) "accept: " + strerror(errno__)); } pthread_mutex_unlock(&r_mutex_); @@ -299,8 +307,8 @@ void Connection::send(const char* buf, size_t len) { pthread_mutex_lock(&r_mutex_); disconnect_(); pthread_mutex_unlock(&r_mutex_); - pthread_mutex_unlock(&c_mutex_); pthread_mutex_unlock(&w_mutex_); + pthread_mutex_unlock(&c_mutex_); if (errno__ == ECONNRESET || errno__ == EPIPE) throw Error(ERR_NET, "Connection reset by peer"); else @@ -315,7 +323,7 @@ void Connection::send(const char* buf, size_t len) { * Receive raw data */ char *Connection::recv(size_t size) { - assert(0); + assert(size == size + 1); return 0; } @@ -354,9 +362,9 @@ string Connection::recvln() { pthread_mutex_lock(&c_mutex_); pthread_mutex_lock(&w_mutex_); disconnect_(); + pthread_mutex_unlock(&w_mutex_); pthread_mutex_unlock(&r_mutex_); pthread_mutex_unlock(&c_mutex_); - pthread_mutex_unlock(&r_mutex_); *local_buf = 0; diff --git a/slc/trunk/src/sll/cypher.cc b/slc/trunk/src/sll/cypher.cc index 01485946e13cf3d7666353a9ccfe1d7b71a10f29..b9aa4e2c2d77056e7322883152556aaf5e23d3ae 100644 --- a/slc/trunk/src/sll/cypher.cc +++ b/slc/trunk/src/sll/cypher.cc @@ -52,7 +52,7 @@ string Cypher::sha1_64(const char *data, size_t size) { BIO_get_mem_ptr(b64, &bptr); if (bptr->length > 0) - ret.insert(0, bptr->data, bptr->length); + ret.insert(0, bptr->data, bptr->length - 1); else throw Error(ERR_CYPHER, "Unable to compute sha1_64");