Support for RFC 4568 (SRTP security descriptors in SIP/SDP).
git-svn-id: http://voip.null.ro/svn/yate@2557 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
1f5e3b2a8a
commit
589d7a9bef
|
@ -72,6 +72,9 @@
|
|||
; privacy: bool: Process and generate privacy related SIP headers
|
||||
;privacy=disable
|
||||
|
||||
; secure: bool: Generate and accept RFC 4568 security descriptors for SRTP
|
||||
;secure=disable
|
||||
|
||||
; forward_sdp: bool: Include the raw SDP body to be used as-is for forwarding RTP
|
||||
;forward_sdp=disable
|
||||
|
||||
|
|
|
@ -161,6 +161,12 @@ public:
|
|||
m_rfc2833 = payload;
|
||||
else
|
||||
m_rfc2833 = String::boolText(false); }
|
||||
inline const String& remoteCrypto() const
|
||||
{ return m_rCrypto; }
|
||||
inline const String& localCrypto() const
|
||||
{ return m_lCrypto; }
|
||||
inline bool securable() const
|
||||
{ return m_securable; }
|
||||
inline bool sameAs(const NetMedia* other) const
|
||||
{ return other && (other->formats() == m_formats) &&
|
||||
(other->transport() == m_transport) &&
|
||||
|
@ -170,9 +176,11 @@ public:
|
|||
void update(const Message& msg, bool pickFormat);
|
||||
void parameter(const char* name, const char* value, bool append);
|
||||
void parameter(NamedString* param, bool append);
|
||||
void crypto(const char* desc, bool remote);
|
||||
private:
|
||||
bool m_audio;
|
||||
bool m_modified;
|
||||
bool m_securable;
|
||||
// suffix used for this type
|
||||
String m_suffix;
|
||||
// transport protocol
|
||||
|
@ -191,6 +199,10 @@ private:
|
|||
String m_mappings;
|
||||
// payload for telephone/event
|
||||
String m_rfc2833;
|
||||
// remote security descriptor
|
||||
String m_rCrypto;
|
||||
// local security descriptor
|
||||
String m_lCrypto;
|
||||
};
|
||||
|
||||
class YateUDPParty : public SIPParty
|
||||
|
@ -532,6 +544,7 @@ private:
|
|||
int m_mediaStatus;
|
||||
bool m_inband;
|
||||
bool m_info;
|
||||
bool m_secure;
|
||||
// REFER already running
|
||||
bool m_referring;
|
||||
// reINVITE requested or in progress
|
||||
|
@ -635,6 +648,7 @@ static bool s_progress = false;
|
|||
static bool s_inband = false;
|
||||
static bool s_info = false;
|
||||
static bool s_rfc2833 = true;
|
||||
static bool s_secure = false;
|
||||
static bool s_forward_sdp = false;
|
||||
static bool s_start_rtp = false;
|
||||
static bool s_ack_required = true;
|
||||
|
@ -696,6 +710,7 @@ static ObjList* parseSDP(const MimeSdpBody* sdp, String& addr, ObjList* oldMedia
|
|||
String fmt;
|
||||
String aux;
|
||||
String mappings;
|
||||
String crypto;
|
||||
ObjList params;
|
||||
bool defcodecs = s_cfg.getBoolValue("codecs","default",true);
|
||||
bool first = true;
|
||||
|
@ -760,11 +775,19 @@ static ObjList* parseSDP(const MimeSdpBody* sdp, String& addr, ObjList* oldMedia
|
|||
}
|
||||
}
|
||||
else if (first) {
|
||||
int pos = line.find(':');
|
||||
if (pos >= 0)
|
||||
params.append(new NamedString(line.substr(0,pos),line.substr(pos+1)));
|
||||
else
|
||||
params.append(new NamedString(line));
|
||||
if (line.startSkip("crypto:",false)) {
|
||||
if (crypto.null())
|
||||
crypto = line;
|
||||
else
|
||||
Debug(DebugMild,"Ignoring SDES: '%s'",line.c_str());
|
||||
}
|
||||
else {
|
||||
int pos = line.find(':');
|
||||
if (pos >= 0)
|
||||
params.append(new NamedString(line.substr(0,pos),line.substr(pos+1)));
|
||||
else
|
||||
params.append(new NamedString(line));
|
||||
}
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
|
@ -819,6 +842,7 @@ static ObjList* parseSDP(const MimeSdpBody* sdp, String& addr, ObjList* oldMedia
|
|||
net->setModified(false);
|
||||
net->mappings(mappings);
|
||||
net->rfc2833(rfc2833);
|
||||
net->crypto(crypto,true);
|
||||
if (!lst)
|
||||
lst = new ObjList;
|
||||
lst->append(net);
|
||||
|
@ -846,6 +870,13 @@ static void putMedia(Message& msg, ObjList* lst, bool putPort = true)
|
|||
msg.addParam("rtp_rfc2833",m->rfc2833());
|
||||
if (putPort)
|
||||
msg.addParam("rtp_port"+m->suffix(),m->remotePort());
|
||||
if (m->remoteCrypto())
|
||||
msg.addParam("crypto"+m->suffix(),m->remoteCrypto());
|
||||
// must handle encryption differently
|
||||
const char* enc = m->getValue("encryption");
|
||||
if (enc)
|
||||
msg.addParam("encryption"+m->suffix(),enc);
|
||||
m->clearParam("encryption");
|
||||
unsigned int n = m->length();
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
const NamedString* param = m->getParam(i);
|
||||
|
@ -1125,7 +1156,7 @@ static inline int findURIParamSep(const String& str, int start)
|
|||
|
||||
NetMedia::NetMedia(const char* media, const char* transport, const char* formats, int rport, int lport)
|
||||
: NamedList(media),
|
||||
m_audio(true), m_modified(false),
|
||||
m_audio(true), m_modified(false), m_securable(true),
|
||||
m_transport(transport), m_formats(formats),
|
||||
m_rfc2833(String::boolText(false))
|
||||
{
|
||||
|
@ -1239,6 +1270,17 @@ void NetMedia::parameter(NamedString* param, bool append)
|
|||
setParam(param);
|
||||
}
|
||||
|
||||
void NetMedia::crypto(const char* desc, bool remote)
|
||||
{
|
||||
String& sdes = remote ? m_rCrypto : m_lCrypto;
|
||||
if (sdes != desc) {
|
||||
sdes = desc;
|
||||
m_modified = true;
|
||||
}
|
||||
if (remote && !desc)
|
||||
m_securable = false;
|
||||
}
|
||||
|
||||
|
||||
YateUDPParty::YateUDPParty(Socket* sock, const SocketAddr& addr, int localPort, const char* localAddr)
|
||||
: m_sock(sock), m_addr(addr)
|
||||
|
@ -2198,7 +2240,7 @@ YateSIPConnection::YateSIPConnection(SIPEvent* ev, SIPTransaction* tr)
|
|||
m_tr(tr), m_tr2(0), m_hungup(false), m_byebye(true), m_cancel(false),
|
||||
m_state(Incoming), m_rtpForward(false), m_sdpForward(false), m_rtpMedia(0),
|
||||
m_sdpSession(0), m_sdpVersion(0), m_port(0), m_route(0), m_routes(0),
|
||||
m_authBye(true), m_mediaStatus(MediaMissing), m_inband(s_inband), m_info(s_info),
|
||||
m_authBye(true), m_mediaStatus(MediaMissing), m_inband(s_inband), m_info(s_info), m_secure(s_secure),
|
||||
m_referring(false), m_reInviting(ReinviteNone), m_lastRseq(0), m_rfc2833(s_rfc2833)
|
||||
{
|
||||
Debug(this,DebugAll,"YateSIPConnection::YateSIPConnection(%p,%p) [%p]",ev,tr,this);
|
||||
|
@ -2355,7 +2397,7 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
|
|||
m_tr(0), m_tr2(0), m_hungup(false), m_byebye(true), m_cancel(true),
|
||||
m_state(Outgoing), m_rtpForward(false), m_sdpForward(false), m_rtpMedia(0),
|
||||
m_sdpSession(0), m_sdpVersion(0), m_port(0), m_route(0), m_routes(0),
|
||||
m_authBye(false), m_mediaStatus(MediaMissing), m_inband(s_inband), m_info(s_info),
|
||||
m_authBye(false), m_mediaStatus(MediaMissing), m_inband(s_inband), m_info(s_info), m_secure(s_secure),
|
||||
m_referring(false), m_reInviting(ReinviteNone), m_lastRseq(0), m_rfc2833(s_rfc2833)
|
||||
{
|
||||
Debug(this,DebugAll,"YateSIPConnection::YateSIPConnection(%p,'%s') [%p]",
|
||||
|
@ -2364,6 +2406,7 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
|
|||
setReason();
|
||||
m_inband = msg.getBoolValue("dtmfinband",s_inband);
|
||||
m_info = msg.getBoolValue("dtmfinfo",s_info);
|
||||
m_secure = msg.getBoolValue("secure",s_secure);
|
||||
m_rfc2833 = msg.getBoolValue("rfc2833",s_rfc2833);
|
||||
m_rtpForward = msg.getBoolValue("rtp_forward");
|
||||
m_user = msg.getValue("user");
|
||||
|
@ -2817,6 +2860,7 @@ MimeSdpBody* YateSIPConnection::createPasstroughSDP(Message& msg, bool update)
|
|||
rtp->mappings(msg.getValue("rtp_mapping"+rtp->suffix()));
|
||||
if (audio)
|
||||
rtp->rfc2833(msg.getIntValue("rtp_rfc2833",-1));
|
||||
rtp->crypto(msg.getValue("crypto"+rtp->suffix()),false);
|
||||
if (!lst)
|
||||
lst = new ObjList;
|
||||
lst->append(rtp);
|
||||
|
@ -2871,11 +2915,32 @@ bool YateSIPConnection::dispatchRtp(NetMedia* media, const char* addr, bool star
|
|||
m.addParam("evpayload",media->rfc2833());
|
||||
TelEngine::destruct(mappings);
|
||||
}
|
||||
if (m_secure) {
|
||||
if (media->remoteCrypto()) {
|
||||
String sdes = media->remoteCrypto();
|
||||
Regexp r("^\\([0-9]\\+\\) \\+\\([^ ]\\+\\) \\+\\([^ ]\\+\\) *\\(.*\\)$");
|
||||
if (sdes.matches(r)) {
|
||||
m.addParam("secure",String::boolText(true));
|
||||
m.addParam("crypto_tag",sdes.matchString(1));
|
||||
m.addParam("crypto_suite",sdes.matchString(2));
|
||||
m.addParam("crypto_key",sdes.matchString(3));
|
||||
if (sdes.matchLength(4))
|
||||
m.addParam("crypto_params",sdes.matchString(4));
|
||||
}
|
||||
else
|
||||
Debug(this,DebugWarn,"Invalid SDES: '%s' [%p]",sdes.c_str(),this);
|
||||
}
|
||||
else if (media->securable())
|
||||
m.addParam("secure",String::boolText(true));
|
||||
}
|
||||
else
|
||||
media->crypto(0,true);
|
||||
unsigned int n = media->length();
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
const NamedString* param = media->getParam(i);
|
||||
if (param)
|
||||
m.addParam("sdp_" + param->name(),*param);
|
||||
if (!param)
|
||||
continue;
|
||||
m.addParam("sdp_" + param->name(),*param);
|
||||
}
|
||||
if (!Engine::dispatch(m))
|
||||
return false;
|
||||
|
@ -2897,6 +2962,20 @@ bool YateSIPConnection::dispatchRtp(NetMedia* media, const char* addr, bool star
|
|||
media->parameter(tmp,*param,false);
|
||||
}
|
||||
}
|
||||
if (m_secure) {
|
||||
int tag = m.getIntValue("crypto_tag",1);
|
||||
tag = m.getIntValue("ocrypto_tag",tag);
|
||||
const String* suite = m.getParam("ocrypto_suite");
|
||||
const String* key = m.getParam("ocrypto_key");
|
||||
const String* params = m.getParam("ocrypto_params");
|
||||
if (suite && key && (tag > 0)) {
|
||||
String sdes(tag);
|
||||
sdes << " " << *suite << " " << *key;
|
||||
if (params)
|
||||
sdes << " " << *params;
|
||||
media->crypto(sdes,false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2931,6 +3010,9 @@ MimeSdpBody* YateSIPConnection::createRtpSDP(const char* addr, const Message& ms
|
|||
if (fmts.null())
|
||||
continue;
|
||||
String trans = msg.getValue("transport"+tmp,"RTP/AVP");
|
||||
String crypto;
|
||||
if (m_secure)
|
||||
crypto = msg.getValue("crypto"+tmp);
|
||||
if (audio)
|
||||
tmp = "audio";
|
||||
else
|
||||
|
@ -2949,6 +3031,7 @@ MimeSdpBody* YateSIPConnection::createRtpSDP(const char* addr, const Message& ms
|
|||
rtp = new NetMedia(tmp,trans,fmts);
|
||||
append = true;
|
||||
}
|
||||
rtp->crypto(crypto,false);
|
||||
if (sdpPrefix) {
|
||||
for (unsigned int j = 0; j < n; j++) {
|
||||
const NamedString* param = msg.getParam(j);
|
||||
|
@ -3150,6 +3233,7 @@ MimeSdpBody* YateSIPConnection::createSDP(const char* addr, ObjList* mediaList)
|
|||
}
|
||||
|
||||
sdp->addLine("m",mline + frm);
|
||||
bool enc = false;
|
||||
if (m->isModified()) {
|
||||
unsigned int n = m->length();
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
|
@ -3159,6 +3243,7 @@ MimeSdpBody* YateSIPConnection::createSDP(const char* addr, ObjList* mediaList)
|
|||
if (*param)
|
||||
tmp << ":" << *param;
|
||||
sdp->addLine("a",tmp);
|
||||
enc = enc || (param->name() == "encryption");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3167,6 +3252,11 @@ MimeSdpBody* YateSIPConnection::createSDP(const char* addr, ObjList* mediaList)
|
|||
if (s)
|
||||
sdp->addLine("a",*s);
|
||||
}
|
||||
if (addr && m->localCrypto()) {
|
||||
sdp->addLine("a","crypto:" + m->localCrypto());
|
||||
if (!enc)
|
||||
sdp->addLine("a","encryption:optional");
|
||||
}
|
||||
}
|
||||
|
||||
return sdp;
|
||||
|
@ -4131,6 +4221,7 @@ void YateSIPConnection::callAccept(Message& msg)
|
|||
if (tmp != "accepted")
|
||||
m_rtpForward = false;
|
||||
}
|
||||
m_secure = m_secure && msg.getBoolValue("secure",true);
|
||||
Channel::callAccept(msg);
|
||||
|
||||
if ((m_reInviting == ReinviteNone) && !m_rtpForward && !isAnswered() &&
|
||||
|
@ -5037,6 +5128,7 @@ void SIPDriver::initialize()
|
|||
s_inband = s_cfg.getBoolValue("general","dtmfinband",false);
|
||||
s_info = s_cfg.getBoolValue("general","dtmfinfo",false);
|
||||
s_rfc2833 = s_cfg.getBoolValue("general","rfc2833",true);
|
||||
s_secure = s_cfg.getBoolValue("general","secure",false);
|
||||
s_forward_sdp = s_cfg.getBoolValue("general","forward_sdp",false);
|
||||
s_rtpip = s_cfg.getValue("general","rtp_localip");
|
||||
s_start_rtp = s_cfg.getBoolValue("general","rtp_start",false);
|
||||
|
|
Loading…
Reference in New Issue