diff --git a/sources/thelib/include/protocols/liveflv/baseliveflvappprotocolhandler.h b/sources/thelib/include/protocols/liveflv/baseliveflvappprotocolhandler.h index fdbc91fd..6ea0a948 100644 --- a/sources/thelib/include/protocols/liveflv/baseliveflvappprotocolhandler.h +++ b/sources/thelib/include/protocols/liveflv/baseliveflvappprotocolhandler.h @@ -29,14 +29,23 @@ class InboundLiveFLVProtocol; class DLLEXP BaseLiveFLVAppProtocolHandler : public BaseAppProtocolHandler { +protected: + Variant _users; + string _usersFile; + double _lastUsersFileUpdate; private: map _protocols; public: BaseLiveFLVAppProtocolHandler(Variant &configuration); virtual ~BaseLiveFLVAppProtocolHandler(); + virtual bool ParseAuthenticationNode(Variant &node, Variant &result); + virtual bool AuthenticateUser(string user, string password); + virtual void RegisterProtocol(BaseProtocol *pProtocol); virtual void UnRegisterProtocol(BaseProtocol *pProtocol); +private: + bool ParseUsersFile(); }; #endif /* _BASELIVEFLVAPPPROTOCOLHANDLER_H */ diff --git a/sources/thelib/src/application/baseclientapplication.cpp b/sources/thelib/src/application/baseclientapplication.cpp index 6e31a200..1cdc610e 100644 --- a/sources/thelib/src/application/baseclientapplication.cpp +++ b/sources/thelib/src/application/baseclientapplication.cpp @@ -211,6 +211,13 @@ BaseAppProtocolHandler *BaseClientApplication::GetProtocolHandler(string &scheme pResult = GetProtocolHandler(PT_INBOUND_RTP); } #endif /* HAS_PROTOCOL_RTP */ +#ifdef HAS_PROTOCOL_LIVEFLV + else if (scheme == "liveflv") { + pResult = GetProtocolHandler(PT_INBOUND_LIVE_FLV); + if (pResult == NULL) + pResult = GetProtocolHandler(PT_OUTBOUND_LIVE_FLV); + } +#endif /* HAS_PROTOCOL_LIVEFLV */ else { WARN("scheme %s not recognized", STR(scheme)); } diff --git a/sources/thelib/src/protocols/liveflv/baseliveflvappprotocolhandler.cpp b/sources/thelib/src/protocols/liveflv/baseliveflvappprotocolhandler.cpp index abd85b9d..2e81e559 100644 --- a/sources/thelib/src/protocols/liveflv/baseliveflvappprotocolhandler.cpp +++ b/sources/thelib/src/protocols/liveflv/baseliveflvappprotocolhandler.cpp @@ -32,6 +32,27 @@ BaseLiveFLVAppProtocolHandler::BaseLiveFLVAppProtocolHandler(Variant &configurat BaseLiveFLVAppProtocolHandler::~BaseLiveFLVAppProtocolHandler() { } +bool BaseLiveFLVAppProtocolHandler::ParseAuthenticationNode(Variant &node, + Variant &result) { + //1. Users file validation + string usersFile = node[CONF_APPLICATION_AUTH_USERS_FILE]; + if ((usersFile[0] != '/') && (usersFile[0] != '.')) { + usersFile = (string) _configuration[CONF_APPLICATION_DIRECTORY] + usersFile; + } + if (!fileExists(usersFile)) { + FATAL("Invalid authentication configuration. Missing users file: %s", STR(usersFile)); + return false; + } + _usersFile = usersFile; + + if (!ParseUsersFile()) { + FATAL("Unable to parse users file %s", STR(usersFile)); + return false; + } + + return true; +} + void BaseLiveFLVAppProtocolHandler::RegisterProtocol(BaseProtocol *pProtocol) { if (MAP_HAS1(_protocols, pProtocol->GetId())) { ASSERT("Protocol ID %u already registered", pProtocol->GetId()); @@ -57,4 +78,57 @@ void BaseLiveFLVAppProtocolHandler::UnRegisterProtocol(BaseProtocol *pProtocol) _protocols.erase(pProtocol->GetId()); FINEST("protocol %s unregistered from app %s", STR(*pProtocol), STR(GetApplication()->GetName())); } + +bool BaseLiveFLVAppProtocolHandler::ParseUsersFile() { + if (_usersFile == "") { + _users.Reset(); + return false; + } + //1. get the modification date + double modificationDate = getFileModificationDate(_usersFile); + if (modificationDate == 0) { + FATAL("Unable to get last modification date for file %s", STR(_usersFile)); + _users.Reset(); + return false; + } + + //2. Do we need to re-parse everything? + if (modificationDate == _lastUsersFileUpdate) + return true; + + _users.Reset(); + + //4. Read users + if (!ReadLuaFile(_usersFile, "users", _users)) { + FATAL("Unable to read users file: `%s`", STR(_usersFile)); + _users.Reset(); + return false; + } + + FOR_MAP(_users, string, Variant, i) { + if ((VariantType) MAP_VAL(i) != V_STRING) { + FATAL("Invalid user detected"); + _users.Reset(); + return false; + } + } + INFO("Parsed Users File %s", STR(_usersFile)); + _lastUsersFileUpdate = modificationDate; + return true; +} +bool BaseLiveFLVAppProtocolHandler::AuthenticateUser(string username, string password) +{ + ParseUsersFile(); + if (username == "") { + if (_usersFile!="") { + FATAL("Client failed to send userName/password in metadata"); + return false; + } + } else { + INFO("Authenticating '%s'", STR(username)); + return _users[username] == password; + } + return true; +} + #endif /* HAS_PROTOCOL_LIVEFLV */ diff --git a/sources/thelib/src/protocols/liveflv/inboundliveflvprotocol.cpp b/sources/thelib/src/protocols/liveflv/inboundliveflvprotocol.cpp index 983847a3..49253771 100644 --- a/sources/thelib/src/protocols/liveflv/inboundliveflvprotocol.cpp +++ b/sources/thelib/src/protocols/liveflv/inboundliveflvprotocol.cpp @@ -20,6 +20,7 @@ #ifdef HAS_PROTOCOL_LIVEFLV #include "protocols/liveflv/inboundliveflvprotocol.h" +#include "protocols/liveflv/baseliveflvappprotocolhandler.h" #include "application/baseclientapplication.h" #include "protocols/protocoltypes.h" #include "netio/netio.h" @@ -177,6 +178,8 @@ bool InboundLiveFLVProtocol::SignalInputData(IOBuffer &buffer) { //3. Read the rest of the parameters Variant parameters; string streamName = ""; + string userName = ""; + string password = ""; while (GETAVAILABLEBYTESCOUNT(metaBuffer) > 0) { Variant v; if (!amf0.Read(metaBuffer, v)) { @@ -188,9 +191,28 @@ bool InboundLiveFLVProtocol::SignalInputData(IOBuffer &buffer) { streamName = (string) v["streamName"]; } } + if (v.HasKey("userName")) { + if (v["userName"] == V_STRING) { + userName = (string) v["userName"]; + } + } + if (v.HasKey("password")) { + if (v["password"] == V_STRING) { + password = (string) v["password"]; + } + } parameters.PushToArray(v); } + if (userName != "") { + INFO("Trying to auth user '%s'", STR(userName)); + } + BaseAppProtocolHandler *pHandler=GetApplication()->GetProtocolHandler(PT_INBOUND_LIVE_FLV); + if (!((BaseLiveFLVAppProtocolHandler *) pHandler)->AuthenticateUser(userName, password)) { + FATAL("Auth failed"); + return false; + } + if (_pStream == NULL) { if (!InitializeStream(streamName)) { FATAL("Unable to initialize the stream");