Commit 0437d116 authored by Seblu's avatar Seblu

Fix connection bug

Command are now executed
login/auth is ok
parent b5f09f10
......@@ -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 .*~
......
/*
This file is part of SLC.
Copyright (C) 2008 Sebastien LUTTRINGER <contact@seblu.net>
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 <name>: Change username.\n";
S << INF_DATA << "/pass <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";
}
}
/*
This file is part of SLC.
Copyright (C) 2008 Sebastien LUTTRINGER <contact@seblu.net>
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 <string.h>
#include <openssl/sha.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include <openssl/md5.h>
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");
}
/*
This file is part of SLC.
Copyright (C) 2008 Sebastien LUTTRINGER <contact@seblu.net>
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
......@@ -16,16 +16,17 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <ctype.h>
#include <signal.h>
#include <math.h>
#include "slc.hh"
#include "screen.hh"
#include "options.hh"
#include "history.hh"
#include "engine.hh"
#include "sll/connection.hh"
#include <ctype.h>
#include <signal.h>
#include <math.h>
/*
*********************************************************************************
*************************************** 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";
}
}
/*!
......
......@@ -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
......@@ -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
......
......@@ -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;
......
......@@ -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");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment