diff options
-rw-r--r-- | proto_lib/api_protocol.h | 1 | ||||
-rw-r--r-- | proto_lib/packet.cpp | 17 | ||||
-rw-r--r-- | restarter.workspace | 1 | ||||
-rw-r--r-- | server/api_service.h | 4 | ||||
-rw-r--r-- | server/service.h | 27 | ||||
-rw-r--r-- | server/session.cpp | 296 | ||||
-rw-r--r-- | server/session.h | 53 | ||||
-rw-r--r-- | services/unix_exec_service/main.cpp | 23 |
8 files changed, 411 insertions, 11 deletions
diff --git a/proto_lib/api_protocol.h b/proto_lib/api_protocol.h index 2e42d42..b18d2e7 100644 --- a/proto_lib/api_protocol.h +++ b/proto_lib/api_protocol.h @@ -64,6 +64,7 @@ public: static bool serv_validate_client_proto(packet&); //false on fail static packet *serv_make_services_packet(std::list<service_s>&); static packet *serv_make_command_reply_packet(std::string&, status s); + static packet *serv_make_command_reply_packet(std::vector<unsigned char>&, status s); static svc_cmd serv_extract_command(packet&); //generic diff --git a/proto_lib/packet.cpp b/proto_lib/packet.cpp index 0ed3150..92272a8 100644 --- a/proto_lib/packet.cpp +++ b/proto_lib/packet.cpp @@ -271,11 +271,18 @@ packet *packet::serv_make_command_reply_packet(std::string &str, status s) pack_serv_header(v); pack_buffer(type_command, sizeof(type_command), v); v.push_back(s); - if(!str.empty()) - { - for(size_t i = 0; i < str.length(); i++) - v.push_back(str[i]); - } + pack_buffer(str, v); + pack_buffer(proto_footer, sizeof(proto_footer), v); + return new packet(v); +} + +packet *packet::serv_make_command_reply_packet(std::vector<unsigned char>& data, status s) +{ + std::vector<unsigned char> v; + pack_serv_header(v); + pack_buffer(type_command, sizeof(type_command), v); + v.push_back(s); + pack_buffer(data, v); pack_buffer(proto_footer, sizeof(proto_footer), v); return new packet(v); } diff --git a/restarter.workspace b/restarter.workspace index 79a199e..5c304ff 100644 --- a/restarter.workspace +++ b/restarter.workspace @@ -17,6 +17,7 @@ </BuildMatrix> <Environment> <![CDATA[ + ]]> </Environment> </CodeLite_Workspace> diff --git a/server/api_service.h b/server/api_service.h index 4f5a183..ddfdc8f 100644 --- a/server/api_service.h +++ b/server/api_service.h @@ -21,8 +21,8 @@ namespace service { -enum service_return {RET_NONE = 2, RET_VOID_PTR = 4, RET_CHAR_PTR = 8, RET_STD_STRING = 16, RET_INT, RET_FLOAT = 32}; -enum service_accept {ACC_NONE = 2, ACC_VOID_PTR = 4, ACC_CHAR_PTR = 8, ACC_STD_STRING = 16, ACC_INT, ACC_FLOAT = 32}; +enum service_return {RET_NONE = 2, RET_VOID_PTR = 4, RET_CHAR_PTR = 8, RET_STD_STRING_PTR = 16, RET_INT_PTR, RET_FLOAT_PTR = 32}; +enum service_accept {ACC_NONE = 2, ACC_VOID_PTR = 4, ACC_CHAR_PTR = 8, ACC_STD_STRING_PTR = 16, ACC_INT_PTR, ACC_FLOAT_PTR = 32}; //service may have predefined command set diff --git a/server/service.h b/server/service.h new file mode 100644 index 0000000..d27f8f3 --- /dev/null +++ b/server/service.h @@ -0,0 +1,27 @@ +// Copyright © 2013 sss +// +// 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. + +#ifndef SERVICE_H +#define SERVICE_H + +#include "headers.h" + +namespace service { + +extern std::list<service_info> installed_services; + +}; +#endif diff --git a/server/session.cpp b/server/session.cpp new file mode 100644 index 0000000..6bbf107 --- /dev/null +++ b/server/session.cpp @@ -0,0 +1,296 @@ +// Copyright © 2013 sss +//. +// 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. + + +#include "headers.h" + +using namespace proto; +using namespace service; + +void session::handle_handshake(const boost::system::error_code& error) +{ + if (!error) + { + recv_data = new char [32]; + socket_.async_read_some(boost::asio::buffer(recv_data, 32), boost::bind(&session::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + } + else + { + delete this; + } +} + +void session::handle_read(const boost::system::error_code& error, size_t bytes_transferred) +{ + if (!error) + { +// std::cout<<"recieved: "<<recv_data<<"\n"; + std::vector<unsigned char> v; + v.assign(recv_data, recv_data + bytes_transferred); + delete [] recv_data; + packet p(v); + v.clear(); + if(!p.is_good()) + { + delete this; + } + switch(p.get_type()) + { + case TYPE_AUTH_REQUEST: + { + if(!packet::serv_validate_client_proto(p)) + { + packet *r = packet::make_status_packet(TYPE_AUTH_REPLY, STATUS_FAILURE); + write_w_close(r->raw()); + delete r; + return; + } + else + { + packet *r = packet::make_status_packet(TYPE_AUTH_REPLY, STATUS_SUCCESS); + write_w_response(r->raw()); + delete r; + return; + } + } + break; + case TYPE_COMMAND_REQUEST: + { + svc_cmd c = packet::serv_extract_command(p); + if(c.service.empty()) + break; + std::list<service_info>::iterator i = std::find(installed_services.begin(), installed_services.end(), c.service); + if(!c.command.empty()) + { + if(i != installed_services.end()) + { + std::list<service_info::command>::iterator ii = std::find(i->predefined.begin(), i->predefined.end(), c.command); + if(ii != i->predefined.end()) + { + switch(i->acc) + { + case ACC_CHAR_PTR: + { + switch(i->ret) + { + case RET_CHAR_PTR: + { + char *arg = strdup(c.command.c_str()); + char *data = (char*)i->exec((void*)arg); + std::string s(data); + delete [] data; + packet *p = packet::serv_make_command_reply_packet(s, STATUS_SUCCESS); + delete [] data; + write_w_response(p->raw()); + delete p; + } + break; + case RET_FLOAT_PTR: + { + char *arg = strdup(c.command.c_str()); + float *ret = (float*)i->exec((void*)arg); + //todo pack float to unsigned char vector + std::vector<unsigned char> v; + packet *p = packet::serv_make_command_reply_packet(v, STATUS_SUCCESS); + write_w_response(p->raw()); + delete p; + delete ret; + } + break; + case RET_INT_PTR: + { + char *arg = strdup(c.command.c_str()); + int *ret = (int*)i->exec((void*)arg); + //todo pack float to unsigned char vector + std::vector<unsigned char> v; + packet *p = packet::serv_make_command_reply_packet(v, STATUS_SUCCESS); + write_w_response(p->raw()); + delete p; + delete ret; + } + break; + case RET_NONE: + { + char *arg = strdup(c.command.c_str()); + i->exec((void*)arg); + packet *p = packet::make_status_packet(TYPE_AUTH_REPLY, STATUS_SUCCESS); + write_w_response(p->raw()); + delete p; + } + break; + case RET_STD_STRING_PTR: + { + char *arg = strdup(c.command.c_str()); + std::string *str = (std::string*)i->exec((void*)arg); + packet *p = packet::serv_make_command_reply_packet(*str, STATUS_SUCCESS); + write_w_response(p->raw()); + delete p; + delete str; + } + break; + case RET_VOID_PTR: + { + //TODO + } + break; + }; + } + break; + case ACC_FLOAT_PTR: + { + } + break; + case ACC_INT_PTR: + { + } + break; + case ACC_STD_STRING_PTR: + { + } + break; + case ACC_VOID_PTR: + { + } + break; + default: + break; + } + } + } + } + else + { + if(i->acc == ACC_NONE) + { + switch(i->ret) + { + case RET_CHAR_PTR: + { + char *data = (char*)i->exec((void*)NULL); + std::string s(data); + delete [] data; + packet *p = packet::serv_make_command_reply_packet(s, STATUS_SUCCESS); + delete [] data; + write_w_response(p->raw()); + delete p; + } + break; + case RET_FLOAT_PTR: + { + float *ret = (float*)i->exec((void*)NULL); + //todo pack float to unsigned char vector + std::vector<unsigned char> v; + packet *p = packet::serv_make_command_reply_packet(v, STATUS_SUCCESS); + write_w_response(p->raw()); + delete p; + delete ret; + } + break; + case RET_INT_PTR: + { + int *ret = (int*)i->exec((void*)NULL); + //todo pack float to unsigned char vector + std::vector<unsigned char> v; + packet *p = packet::serv_make_command_reply_packet(v, STATUS_SUCCESS); + write_w_response(p->raw()); + delete p; + delete ret; + } + break; + case RET_NONE: + { + i->exec((void*)NULL); + packet *p = packet::make_status_packet(TYPE_AUTH_REPLY, STATUS_SUCCESS); + write_w_response(p->raw()); + delete p; + } + break; + case RET_STD_STRING_PTR: + { + std::string *str = (std::string*)i->exec((void*)NULL); + packet *p = packet::serv_make_command_reply_packet(*str, STATUS_SUCCESS); + write_w_response(p->raw()); + delete p; + delete str; + } + break; + case RET_VOID_PTR: + { + //TODO + } + break; + }; + } + } + } + break; + } + } +} + +void session::handle_write(const boost::system::error_code& error, size_t bytes_transferred) +{ + delete [] snd_data; + if(error) + { + + delete this; + return; //? + } + recv_data = (char*)new unsigned char[128]; + socket_.async_read_some(boost::asio::buffer(recv_data, 128), boost::bind(&session::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); +} + +void session::write_w_close(const std::vector<unsigned char>& data) +{ + snd_data = (char*)new unsigned char[data.size() + 1]; + memset(snd_data, 0, data.size() + 1); + for(int i = 0; i < data.size(); i++) + snd_data[i] = data[i]; + socket_.async_write_some(boost::asio::buffer(snd_data, data.size() + 1), boost::bind(&session::handle_write_close, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); +} + +void session::write_w_response(const std::vector<unsigned char>& data) +{ + pack_buffer(data); + socket_.async_write_some(boost::asio::buffer(snd_data, data.size()+1), boost::bind(&session::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); +} + +void session::write_wo_response(const std::vector<unsigned char>& data) +{ + pack_buffer(data); + socket_.async_write_some(boost::asio::buffer(snd_data, data.size() +1), boost::bind(&session::handle_operation, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); +} + + +void session::handle_write_close(const boost::system::error_code& error, size_t bytes_transferred) +{ + delete [] snd_data; + delete this; +} + +void session::handle_operation(const boost::system::error_code& error, size_t bytes_transferred) +{ + delete [] snd_data; +} + +void session::pack_buffer(const std::vector<unsigned char>& data) +{ + snd_data = (char*)new unsigned char[data.size()+1]; + memset(snd_data, 0, data.size()+1); + for(int i = 0; i < data.size(); i++) + snd_data[i] = data[i]; +} diff --git a/server/session.h b/server/session.h new file mode 100644 index 0000000..6e3bb1b --- /dev/null +++ b/server/session.h @@ -0,0 +1,53 @@ +// Copyright © 2013 sss +//. +// 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. + +#ifndef SESSION_H +#define SESSION_H + + +using boost::asio::ip::tcp; +typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket; + +class session +{ +public: + session(boost::asio::io_service& io_service, boost::asio::ssl::context& context) : socket_(io_service, context) + {} + ssl_socket::lowest_layer_type& socket() + { + return socket_.lowest_layer(); + } + void handle_handshake(const boost::system::error_code& error); + void start() + { + socket_.async_handshake(boost::asio::ssl::stream_base::server, boost::bind(&session::handle_handshake, this, boost::asio::placeholders::error)); + } + +private: + void write_w_close(const std::vector<unsigned char>& data); + void write_w_response(const std::vector<unsigned char>& data); + void write_wo_response(const std::vector<unsigned char>& data); + void handle_read(const boost::system::error_code& error, size_t bytes_transferred); + void handle_write(const boost::system::error_code& error, size_t bytes_transferred); + void handle_write_close(const boost::system::error_code& error, size_t bytes_transferred); + void handle_operation(const boost::system::error_code& error, size_t bytes_transferred); + void pack_buffer(const std::vector<unsigned char>& data); + ssl_socket socket_; + char *snd_data, *recv_data; +}; + + +#endif diff --git a/services/unix_exec_service/main.cpp b/services/unix_exec_service/main.cpp index ad7da1f..331c98f 100644 --- a/services/unix_exec_service/main.cpp +++ b/services/unix_exec_service/main.cpp @@ -58,8 +58,21 @@ void * shell_exec(void * t) cmd = c; if(!cmd.empty()) { + FILE *f = popen(cmd.c_str(), "r"); + if(f) + { + std::string *ret = new std::string; + char buf[128]; + while(fgets(buf, 128, f)) + ret->append(buf); + return (void*)ret; + } + else + { + //TODO: handle fail (need to extend service api ?) + } } - return NULL; + return (void*)new std::string; } void load_cmds() @@ -99,15 +112,17 @@ void load_cmds() p1++; descr = str.substr(p1); } + service_info::command c; if(!_alias.empty()) { alias a; a._alias = _alias; a.cmd = cmd; + c.command = _alias; aliases.push_back(a); } - service_info::command c; - c.command = cmd; + else + c.command = cmd; c.description = descr; cmds.push_back(c); // printf("%s | %s | %s\n", _alias.c_str(), cmd.c_str(), descr.c_str()); @@ -123,7 +138,7 @@ services(get_services) { service_info shell_exec_service; shell_exec_service.acc = ACC_CHAR_PTR; - shell_exec_service.ret = RET_STD_STRING; + shell_exec_service.ret = RET_STD_STRING_PTR; shell_exec_service.name = "Shell exec"; shell_exec_service.description = "Run shell command and return output"; shell_exec_service.exec = &shell_exec; |