Inetd.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 $Header$
00004 
00005 */
00006 
00007 #include "Error.h"
00008 #include "Value.h"
00009 #include "Telnet.h"
00010 
00011 #include "Inetd.h"
00012 
00013 // Public methods.
00014 
00015 unsigned int Inetd::instancesNumberLimit()
00016 {
00017   return 1;
00018 }
00019 
00020 // Protected methods.
00021 
00022 Inetd::Inetd(const ValueList &params) : 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 // Private methods.
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 }

Generated on Thu Sep 6 20:11:25 2007 for Pylon Application Platform by  doxygen 1.5.1