00001
00002
00003
00004
00005
00006
00007 #include "Error.h"
00008 #include "Value.h"
00009 #include "Telnet.h"
00010
00011 #include "Inetd.h"
00012
00013
00014
00015 unsigned int Inetd::instancesNumberLimit()
00016 {
00017 return 1;
00018 }
00019
00020
00021
00022 Inetd::Inetd(const ValueList ¶ms) : Service<Inetd>(params)
00023 {
00024 BIND(services);
00025
00026 int res;
00027
00028 if (FAILED(res = REGISTRY_GET(Inetd, services, _services))) {
00029 failure(ERROR_BACKTRACE(res));
00030 return;
00031 }
00032
00033 unsigned int i, size = _services.size();
00034
00035 if (size == 0) {
00036 failure(ERROR(SERVICE_MSG_INVALID_PARAMS, CSTRING(NAME())));
00037 return;
00038 }
00039
00040 _core = CORE();
00041
00042 TcpServer *server;
00043 for (i = 0; i < size; ++i) {
00044 if (_services[i].service.empty() || _services[i].port == 0) {
00045 failure(ERROR(SERVICE_MSG_INVALID_PARAMS, CSTRING(NAME())));
00046 return;
00047 }
00048 DEBUG("Starting to listen port %u for service '%s'.", _services[i].port, CSTRING(_services[i].service));
00049
00050 if (!(server = new TcpServer("", String::number(_services[i].port)))) {
00051 failure(ERROR(MSG_OBJECT_CANNOT_CREATE, "TcpServer"));
00052 return;
00053 }
00054 if (FAILED(res = server->failureCode())) {
00055 failure(ERROR_BACKTRACE(res));
00056 return;
00057 }
00058
00059 if (FAILED(res = CONNECT(server, accepted, this, Inetd, startService))) {
00060 failure(ERROR_BACKTRACE(res));
00061 return;
00062 }
00063 _servers[server] = _services[i];
00064 _serversByPort[_services[i].port] = server;
00065 }
00066 }
00067
00068 Inetd::~Inetd()
00069 {
00070 if (!_servers.empty()) {
00071 InetdServerList::iterator i = _servers.begin();
00072 InetdServerList::iterator e = _servers.end();
00073
00074 while (i != e) {
00075 delete i->first;
00076 ++i;
00077 }
00078 }
00079 }
00080
00081
00082
00083 int Inetd::startService(TcpConnection *connection)
00084 {
00085 InetdServersByPort::const_iterator fServer = _serversByPort.find(connection->localPort());
00086 if (fServer == _serversByPort.end())
00087 return ERROR(MSG_INETD_UNKNOWN_SERVER);
00088
00089 InetdServerList::const_iterator f = _servers.find(fServer->second);
00090 if (f == _servers.end())
00091 return ERROR(MSG_INETD_UNKNOWN_SERVER);
00092
00093 bool valid;
00094 int res;
00095
00096 if (FAILED(res = authorize(f->second, connection, valid)))
00097 return ERROR_BACKTRACE(res);
00098
00099 if (!valid) {
00100 delete connection;
00101 return ERROR(MSG_INETD_AUTHORIZATION_FAILED);
00102 }
00103
00104 ValueList params;
00105
00106 params.push_back(new Value<Object *>(connection));
00107 if (FAILED(res = _core->spawn(f->second.service, params)))
00108 return ERROR_BACKTRACE(res);
00109
00110 INFO(MSG_INETD_SERVICE_INSTANCE_STARTED, CSTRING(f->second.service), CSTRING(f->second.login), CSTRING(connection->peerIp()));
00111 return OK;
00112 }
00113
00114 int Inetd::authorize(const InetdItem &item, TcpConnection *connection, bool &valid)
00115 {
00116 if (item.login.empty() && item.password.empty()) {
00117 valid = true;
00118 return OK;
00119 }
00120
00121 String str;
00122 int res;
00123
00124 valid = true;
00125
00126 if (FAILED(res = connection->clear()))
00127 return ERROR_BACKTRACE(res);
00128
00129 if (!item.login.empty()) {
00130 if (FAILED(res = connection->writeStr(MSG_INETD_LOGIN)))
00131 return ERROR_BACKTRACE(res);
00132 if (FAILED(res = connection->readLn(str)))
00133 return ERROR_BACKTRACE(res);
00134 if (str != item.login)
00135 valid = false;
00136 }
00137 if (!item.password.empty()) {
00138 int res1;
00139
00140 if (FAILED(res = connection->writeStr(MSG_INETD_PASSWORD)))
00141 return ERROR_BACKTRACE(res);
00142 if (FAILED(res = Telnet::setEcho(connection, false)))
00143 return ERROR_BACKTRACE(res);
00144 res1 = connection->readLn(str);
00145 str.trim(true);
00146 DEBUG("Entered password: '%s'.", CSTRING(str));
00147 if (FAILED(res = connection->writeStr(String::eol())))
00148 return ERROR_BACKTRACE(res);
00149 if (FAILED(res = Telnet::setEcho(connection, true)))
00150 return ERROR_BACKTRACE(res);
00151 if (FAILED(res1))
00152 return ERROR_BACKTRACE(res1);
00153 if (!item.password.equals(str.md5(), true))
00154 valid = false;
00155 }
00156 if (!valid)
00157 if (FAILED(res = connection->writeStr(String(MSG_INETD_AUTHORIZATION_FAILED) + String::eol())))
00158 return ERROR_BACKTRACE(res);
00159 if (FAILED(res = connection->clear()))
00160 return ERROR_BACKTRACE(res);
00161 return OK;
00162 }