From 62898a7d19c507dc992b032010f030686413223a Mon Sep 17 00:00:00 2001
From: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
Date: Mon, 30 Jul 2012 17:01:19 -0400
Subject: [PATCH] * #14077: sip: check if server address in SIP transactions is
 our proxy

---
 daemon/src/managerimpl.cpp     | 13 +++++++++-
 daemon/src/sip/sip_utils.cpp   | 45 ++++++++++++++++++++++++++++++++++
 daemon/src/sip/sip_utils.h     |  4 +++
 daemon/src/sip/sipaccount.cpp  | 12 ++++++++-
 daemon/src/sip/sipaccount.h    |  1 +
 daemon/src/sip/sipvoiplink.cpp | 33 +------------------------
 6 files changed, 74 insertions(+), 34 deletions(-)

diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp
index 41e42e4d5e..2a2e1db187 100644
--- a/daemon/src/managerimpl.cpp
+++ b/daemon/src/managerimpl.cpp
@@ -2669,7 +2669,8 @@ ManagerImpl::getAccount(const std::string& accountID)
     return accountMap_[SIPAccount::IP2IP_PROFILE];
 }
 
-std::string ManagerImpl::getAccountIdFromNameAndServer(const std::string& userName, const std::string& server) const
+std::string
+ManagerImpl::getAccountIdFromNameAndServer(const std::string& userName, const std::string& server) const
 {
     DEBUG("username = %s, server = %s", userName.c_str(), server.c_str());
     // Try to find the account id from username and server name by full match
@@ -2703,6 +2704,16 @@ std::string ManagerImpl::getAccountIdFromNameAndServer(const std::string& userNa
         }
     }
 
+    // We failed! Then only match the hostname against our proxy
+    for (AccountMap::const_iterator iter = accountMap_.begin(); iter != accountMap_.end(); ++iter) {
+        SIPAccount *account = dynamic_cast<SIPAccount *>(iter->second);
+
+        if (account and account->isEnabled() and account->proxyMatch(server)) {
+            DEBUG("Matching account id in request with proxy %s", server.c_str());
+            return iter->first;
+        }
+    }
+
     DEBUG("Username %s or server %s doesn't match any account, using IP2IP", userName.c_str(), server.c_str());
     return "";
 }
diff --git a/daemon/src/sip/sip_utils.cpp b/daemon/src/sip/sip_utils.cpp
index bdcd57542a..d64a2f6c2d 100644
--- a/daemon/src/sip/sip_utils.cpp
+++ b/daemon/src/sip/sip_utils.cpp
@@ -42,6 +42,13 @@
 #include <pj/list.h>
 #include "sip_utils.h"
 
+// for resolveDns
+#include <list>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
 std::string
 sip_utils::fetchHeaderValue(pjsip_msg *msg, const std::string &field)
 {
@@ -124,3 +131,41 @@ sip_utils::stripSipUriPrefix(std::string& sipUri)
     if (found != std::string::npos)
         sipUri.erase(found);
 }
+
+/**
+ * This function looks for '@' and replaces the second part with the corresponding ip address (when possible)
+ */
+std::string
+sip_utils::resolveDns(const std::string &url)
+{
+   size_t pos;
+   if ((pos = url.find("@")) == std::string::npos)
+      return url;
+
+   const std::string hostname = url.substr(pos + 1);
+
+   std::list<std::string> ipList(resolveServerDns(hostname));
+   if (not ipList.empty() and ipList.front().size() > 7 )
+       return url.substr(0, pos + 1) + ipList.front();
+   else
+       return hostname;
+}
+
+/**
+ * This function finds the list of IP addresses (when possible) for a given server
+ */
+std::list<std::string>
+sip_utils::resolveServerDns(const std::string &server)
+{
+   struct hostent *he;
+   std::list<std::string> ipList;
+
+   if ((he = gethostbyname(server.c_str())) == NULL)
+      return ipList;
+   struct in_addr **addr_list = (struct in_addr **) he->h_addr_list;
+
+   for (int i = 0; addr_list[i] != NULL; ++i)
+      ipList.push_back(inet_ntoa(*addr_list[i]));
+
+   return ipList;
+}
diff --git a/daemon/src/sip/sip_utils.h b/daemon/src/sip/sip_utils.h
index 4d430af97c..99c56002cf 100644
--- a/daemon/src/sip/sip_utils.h
+++ b/daemon/src/sip/sip_utils.h
@@ -33,6 +33,7 @@
 #define SIP_UTILS_H_
 
 #include <string>
+#include <list>
 
 #include <pjsip/sip_msg.h>
 
@@ -50,6 +51,9 @@ namespace sip_utils {
     void stripSipUriPrefix(std::string& sipUri);
 
     std::string parseDisplayName(const char * buffer);
+
+    std::string resolveDns(const std::string &url);
+    std::list<std::string> resolveServerDns(const std::string &server);
 }
 
 #endif // SIP_UTILS_H_
diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp
index 5e04cb4ec8..b578bbda4b 100644
--- a/daemon/src/sip/sipaccount.cpp
+++ b/daemon/src/sip/sipaccount.cpp
@@ -36,6 +36,7 @@
 
 #include "account_schema.h"
 #include "sipaccount.h"
+#include "sip_utils.h"
 #include "sipvoiplink.h"
 #include "config/yamlnode.h"
 #include "config/yamlemitter.h"
@@ -43,7 +44,8 @@
 #include "manager.h"
 #include <pwd.h>
 #include <sstream>
-#include <stdlib.h>
+#include <algorithm>
+#include <cstdlib>
 
 #ifdef SFL_VIDEO
 #include "video/libav_utils.h"
@@ -794,6 +796,14 @@ bool SIPAccount::hostnameMatch(const std::string& hostname) const
     return hostname == hostname_;
 }
 
+bool SIPAccount::proxyMatch(const std::string& hostname) const
+{
+    if (hostname == serviceRoute_)
+        return true;
+    const std::list<std::string> ipList(sip_utils::resolveServerDns(serviceRoute_));
+    return std::find(ipList.begin(), ipList.end(), hostname) != ipList.end();
+}
+
 std::string SIPAccount::getLoginName()
 {
     struct passwd * user_info = getpwuid(getuid());
diff --git a/daemon/src/sip/sipaccount.h b/daemon/src/sip/sipaccount.h
index cb4292f3d0..6829909ced 100644
--- a/daemon/src/sip/sipaccount.h
+++ b/daemon/src/sip/sipaccount.h
@@ -250,6 +250,7 @@ class SIPAccount : public Account {
         bool fullMatch(const std::string& username, const std::string& hostname) const;
         bool userMatch(const std::string& username) const;
         bool hostnameMatch(const std::string& hostname) const;
+        bool proxyMatch(const std::string& hostname) const;
 
         /**
          * Registration flag
diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp
index 65249ec98c..b8b00713e8 100644
--- a/daemon/src/sip/sipvoiplink.cpp
+++ b/daemon/src/sip/sipvoiplink.cpp
@@ -725,43 +725,12 @@ bool isValidIpAddress(const std::string &address)
     return result != 0;
 }
 
-/**
- * This function look for '@' and replace the second part with the corresponding ip address (when possible)
- */
-std::string resolvDns(const std::string& url)
-{
-   size_t pos;
-   if ((pos = url.find("@")) == std::string::npos) {
-      return url;
-   }
-   std::string hostname = url.substr(pos+1);
-
-   int i;
-   struct hostent *he;
-   struct in_addr **addr_list;
-
-   if ((he = gethostbyname(hostname.c_str())) == NULL) {
-      return url;
-   }
-
-   addr_list = (struct in_addr **)he->h_addr_list;
-   std::list<std::string> ipList;
-
-   for(i = 0; addr_list[i] != NULL; i++) {
-      ipList.push_back(inet_ntoa(*addr_list[i]));
-   }
-
-   if (ipList.size() > 0 && ipList.front().size() > 7 )
-      return url.substr(0,pos+1)+ipList.front();
-   else
-      return hostname;
-}
 
 Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toUrl)
 {
     DEBUG("New outgoing call to %s", toUrl.c_str());
     std::string toCpy = toUrl;
-    std::string resolvedUrl = resolvDns(toUrl);
+    std::string resolvedUrl = sip_utils::resolveDns(toUrl);
     DEBUG("URL resolved to %s", resolvedUrl.c_str());
 
     sip_utils::stripSipUriPrefix(toCpy);
-- 
GitLab