1 /*
2 * h235caps.cxx
3 *
4 * H.235 Capability wrapper class.
5 *
6 * h323plus library
7 *
8 * Copyright (c) 2011 Spranto Australia Pty Ltd.
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.1 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Alternatively, the contents of this file may be used under the terms
16 * of the General Public License (the "GNU License"), in which case the
17 * provisions of GNU License are applicable instead of those
18 * above. If you wish to allow use of your version of this file only
19 * under the terms of the GNU License and not to allow others to use
20 * your version of this file under the MPL, indicate your decision by
21 * deleting the provisions above and replace them with the notice and
22 * other provisions required by the GNU License. If you do not delete
23 * the provisions above, a recipient may use your version of this file
24 * under either the MPL or the GNU License."
25 *
26 * Software distributed under the License is distributed on an "AS IS"
27 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
28 * the License for the specific language governing rights and limitations
29 * under the License.
30 *
31 *
32 * The Initial Developer of the Original Code is ISVO (Asia) Pte. Ltd.
33 *
34 *
35 * Contributor(s): ______________________________________.
36 *
37 * $Id$
38 *
39 *
40 */
41
42
43 #include <ptlib.h>
44 #include "openh323buildopts.h"
45
46 #ifdef H323_H235
47
48 #include "h235/h235caps.h"
49 #include "h235/h235chan.h"
50 #include "h235/h235support.h"
51 #include "h323.h"
52
53 /////////////////////////////////////////////////////////////////////////////
54
H235SecurityCapability(H323Capabilities * capabilities,unsigned capabilityNo)55 H235SecurityCapability::H235SecurityCapability(H323Capabilities * capabilities, unsigned capabilityNo)
56 : m_capabilities(capabilities), m_capNumber(capabilityNo)
57 {
58 GetMediaFormat();
59 }
60
~H235SecurityCapability()61 H235SecurityCapability::~H235SecurityCapability()
62 {
63 m_capList.RemoveAll();
64 }
65
Clone() const66 PObject * H235SecurityCapability::Clone() const
67 {
68 return new H235SecurityCapability(*this);
69 }
70
GetMainType() const71 H323Capability::MainTypes H235SecurityCapability::GetMainType() const
72 {
73 return e_Security;
74 }
75
GetSubType() const76 unsigned H235SecurityCapability::GetSubType() const
77 {
78 return m_capNumber;
79 }
80
GetFormatName() const81 PString H235SecurityCapability::GetFormatName() const
82 {
83 PStringStream name;
84 name << "SecCapability [" << m_capNumber << "]";
85 return name;
86 }
87
CreateChannel(H323Connection &,H323Channel::Directions,unsigned,const H245_H2250LogicalChannelParameters *) const88 H323Channel * H235SecurityCapability::CreateChannel(H323Connection &,
89 H323Channel::Directions,
90 unsigned,
91 const H245_H2250LogicalChannelParameters *) const
92 {
93 PTRACE(1, "Codec\tCannot create Security channel");
94 return NULL;
95 }
96
CreateCodec(H323Codec::Direction) const97 H323Codec * H235SecurityCapability::CreateCodec(H323Codec::Direction) const
98 {
99 PTRACE(1, "Codec\tCannot create security codec");
100 return NULL;
101 }
102
GetAlgorithmCount()103 PINDEX H235SecurityCapability::GetAlgorithmCount()
104 {
105 return m_capList.GetSize();
106 }
107
GetAlgorithm()108 PString H235SecurityCapability::GetAlgorithm()
109 {
110 if (m_capList.GetSize() > 0)
111 return m_capList[0];
112 else
113 return PString();
114 }
115
OnSendingPDU(H245_EncryptionAuthenticationAndIntegrity & encAuth,H323Capability::CommandType type) const116 PBoolean H235SecurityCapability::OnSendingPDU(H245_EncryptionAuthenticationAndIntegrity & encAuth, H323Capability::CommandType type) const
117 {
118 if (m_capList.GetSize() == 0)
119 return false;
120
121 encAuth.IncludeOptionalField(H245_EncryptionAuthenticationAndIntegrity::e_encryptionCapability);
122
123 H245_EncryptionCapability & enc = encAuth.m_encryptionCapability;
124
125 if (type == e_OLC) { // only the 1st (preferred) Algorithm.
126 enc.SetSize(1);
127 H245_MediaEncryptionAlgorithm & alg = enc[0];
128 alg.SetTag(H245_MediaEncryptionAlgorithm::e_algorithm);
129 PASN_ObjectId & id = alg;
130 id.SetValue(m_capList[0]);
131 return true;
132 } else if (type == e_TCS) { // all the supported Algorithms
133 enc.SetSize(m_capList.GetSize());
134 for (PINDEX i=0; i < m_capList.GetSize(); ++i) {
135 H245_MediaEncryptionAlgorithm & alg = enc[i];
136 alg.SetTag(H245_MediaEncryptionAlgorithm::e_algorithm);
137 PASN_ObjectId & id = alg;
138 id.SetValue(m_capList[i]);
139 }
140 return true;
141 } else
142 return false;
143 }
144
OnSendingPDU(H245_Capability & pdu) const145 PBoolean H235SecurityCapability::OnSendingPDU(H245_Capability & pdu) const
146 {
147 if (m_capList.GetSize() == 0)
148 return false;
149
150 pdu.SetTag(H245_Capability::e_h235SecurityCapability);
151 H245_H235SecurityCapability & sec = pdu;
152
153 if (!OnSendingPDU(sec.m_encryptionAuthenticationAndIntegrity))
154 return false;
155
156 H245_CapabilityTableEntryNumber & capNo = sec.m_mediaCapability;
157 capNo = m_capNumber;
158
159 return TRUE;
160 }
161
OnSendingPDU(H245_DataType &) const162 PBoolean H235SecurityCapability::OnSendingPDU(H245_DataType &) const
163 {
164 PTRACE(1, "Codec\tCannot have Security Capability in DataType. Capability " << m_capNumber);
165 return FALSE;
166 }
167
OnSendingPDU(H245_ModeElement &) const168 PBoolean H235SecurityCapability::OnSendingPDU(H245_ModeElement &) const
169 {
170 PTRACE(1, "Codec\tCannot have Security Capability in ModeElement");
171 return FALSE;
172 }
173
OnReceivedPDU(const H245_Capability & pdu)174 PBoolean H235SecurityCapability::OnReceivedPDU(const H245_Capability & pdu)
175 {
176
177 if (pdu.GetTag() != H245_Capability::e_h235SecurityCapability)
178 return false;
179
180 const H245_H235SecurityCapability & sec = pdu;
181 if (!OnReceivedPDU(sec.m_encryptionAuthenticationAndIntegrity,e_TCS))
182 return false;
183
184 const H245_CapabilityTableEntryNumber & capNo = sec.m_mediaCapability;
185 PRemoveConst(H235SecurityCapability, this)->SetAssociatedCapability(capNo);
186 return true;
187 }
188
OnReceivedPDU(const H245_DataType &,PBoolean)189 PBoolean H235SecurityCapability::OnReceivedPDU(const H245_DataType &, PBoolean)
190 {
191 PTRACE(1, "Codec\tCannot have Security Capability in DataType. Capability " << m_capNumber);
192 return FALSE;
193 }
194
SetAssociatedCapability(unsigned capNumber)195 void H235SecurityCapability::SetAssociatedCapability(unsigned capNumber)
196 {
197 m_capNumber = capNumber;
198 }
199
MergeAlgorithms(const PStringArray & remote)200 PBoolean H235SecurityCapability::MergeAlgorithms(const PStringArray & remote)
201 {
202 PStringArray toKeep;
203 for (PINDEX i=0; i< m_capList.GetSize(); ++i) {
204 for (PINDEX j=0; j< remote.GetSize(); ++j) {
205 if (m_capList[i] == remote[j]) {
206 toKeep.AppendString(m_capList[i]);
207 break;
208 }
209 }
210 }
211 m_capList.SetSize(0);
212 m_capList = toKeep;
213
214 if (m_capList.GetSize() > 0) {
215 if (m_capabilities) {
216 H323Capability * cap = m_capabilities->FindCapability(m_capNumber);
217 if (cap)
218 cap->SetEncryptionAlgorithm(m_capList[0]);
219 }
220 return true;
221 }
222 return false;
223 }
224
OnReceivedPDU(const H245_EncryptionAuthenticationAndIntegrity & encAuth,H323Capability::CommandType type) const225 PBoolean H235SecurityCapability::OnReceivedPDU(const H245_EncryptionAuthenticationAndIntegrity & encAuth,
226 H323Capability::CommandType type) const
227 {
228 if (!encAuth.HasOptionalField(H245_EncryptionAuthenticationAndIntegrity::e_encryptionCapability))
229 return false;
230
231 const H245_EncryptionCapability & enc = encAuth.m_encryptionCapability;
232 if (type == e_OLC) {
233 if (m_capList.GetSize()==0 && enc.GetSize() > 0) {
234 PTRACE(4,"H235\tLOGIC ERROR No Agreed algorithms loaded!");
235 }
236 return true;
237 }
238
239 PStringArray other;
240 for (PINDEX i=0; i < enc.GetSize(); ++i) {
241 const H245_MediaEncryptionAlgorithm & alg = enc[i];
242 if (alg.GetTag() == H245_MediaEncryptionAlgorithm::e_algorithm) {
243 const PASN_ObjectId & id = alg;
244 other.AppendString(id.AsString());
245 }
246 }
247
248 return PRemoveConst(H235SecurityCapability, this)->MergeAlgorithms(other);
249 }
250
GetDefaultSessionID() const251 unsigned H235SecurityCapability::GetDefaultSessionID() const
252 {
253 return OpalMediaFormat::NonRTPSessionID;
254 }
255
IsUsable(const H323Connection & connection) const256 PBoolean H235SecurityCapability::IsUsable(const H323Connection & connection) const
257 {
258 const H235Capabilities & caps = (const H235Capabilities &)connection.GetLocalCapabilities();
259 return caps.GetAlgorithms(m_capList);
260 }
261
262 /////////////////////////////////////////////////////////////////////////////
263
H323SecureRealTimeCapability(H323Capability * childCapability,H323Capabilities * capabilities,unsigned secNo,PBoolean active)264 H323SecureRealTimeCapability::H323SecureRealTimeCapability(H323Capability * childCapability, H323Capabilities * capabilities, unsigned secNo, PBoolean active)
265 : ChildCapability(childCapability), chtype(H235ChNew), m_active(active),
266 m_capabilities(capabilities), m_secNo(secNo), nrtpqos(NULL)
267 {
268 assignedCapabilityNumber = ChildCapability->GetCapabilityNumber();
269 }
270
271
H323SecureRealTimeCapability(RTP_QOS * _rtpqos,H323Capability * childCapability)272 H323SecureRealTimeCapability::H323SecureRealTimeCapability(RTP_QOS * _rtpqos,H323Capability * childCapability)
273 : ChildCapability(childCapability), chtype(H235ChNew), m_active(false),
274 m_capabilities(NULL), m_secNo(0), nrtpqos(_rtpqos)
275 {
276 }
277
~H323SecureRealTimeCapability()278 H323SecureRealTimeCapability::~H323SecureRealTimeCapability()
279 {
280 delete ChildCapability;
281 }
282
283
AttachQoS(RTP_QOS * _rtpqos)284 void H323SecureRealTimeCapability::AttachQoS(RTP_QOS * _rtpqos)
285 {
286 #ifdef P_QOS
287 delete nrtpqos;
288 nrtpqos = _rtpqos;
289 #endif
290 }
291
SetAssociatedCapability(unsigned _secNo)292 void H323SecureRealTimeCapability::SetAssociatedCapability(unsigned _secNo)
293 {
294 m_secNo = _secNo;
295 }
296
CreateChannel(H323Connection & connection,H323Channel::Directions dir,unsigned sessionID,const H245_H2250LogicalChannelParameters * param) const297 H323Channel * H323SecureRealTimeCapability::CreateChannel(H323Connection & connection,
298 H323Channel::Directions dir,
299 unsigned sessionID,
300 const H245_H2250LogicalChannelParameters * param) const
301 {
302
303 // create a standard RTP channel if we don't have a DH token
304 H235Capabilities * caps = dynamic_cast<H235Capabilities*>(connection.GetLocalCapabilitiesRef());
305 if (!caps || !caps->GetDiffieHellMan())
306 return connection.CreateRealTimeLogicalChannel(*ChildCapability, dir, sessionID, param, nrtpqos);
307
308 // Support for encrypted external RTP Channel
309 H323Channel * extRTPChannel = connection.CreateRealTimeLogicalChannel(*this, dir, sessionID, param, nrtpqos);
310 if (extRTPChannel)
311 return extRTPChannel;
312
313 RTP_Session * session = NULL; // Session
314 if (
315 #ifdef H323_H46026
316 connection.H46026IsMediaTunneled() ||
317 #endif
318 !param || !param->HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaControlChannel)) {
319 // Make a fake transport address from the connection so gets initialised with
320 // the transport type (IP, IPX, multicast etc).
321 H245_TransportAddress addr;
322 connection.GetControlChannel().SetUpTransportPDU(addr, H323Transport::UseLocalTSAP);
323 session = connection.UseSession(sessionID, addr, dir, nrtpqos);
324 } else {
325 session = connection.UseSession(param->m_sessionID, param->m_mediaControlChannel, dir, nrtpqos);
326 }
327
328 if (!session)
329 return NULL;
330
331 return new H323SecureRTPChannel(connection, *this, dir, *session);
332 }
333
GetCapabilityNumber() const334 unsigned H323SecureRealTimeCapability::GetCapabilityNumber() const
335 {
336 return ChildCapability->GetCapabilityNumber();
337 };
338
SetCapabilityNumber(unsigned num)339 void H323SecureRealTimeCapability::SetCapabilityNumber(unsigned num)
340 {
341 assignedCapabilityNumber = num;
342 ChildCapability->SetCapabilityNumber(num);
343 }
344
SetCapabilityList(H323Capabilities * capabilities)345 void H323SecureRealTimeCapability::SetCapabilityList(H323Capabilities * capabilities)
346 {
347 m_capabilities = capabilities;
348 }
349
SetEncryptionActive(PBoolean active)350 void H323SecureRealTimeCapability::SetEncryptionActive(PBoolean active)
351 {
352 m_active = active;
353 }
354
IsEncryptionActive() const355 PBoolean H323SecureRealTimeCapability::IsEncryptionActive() const
356 {
357 return m_active;
358 }
359
SetEncryptionAlgorithm(const PString & alg)360 void H323SecureRealTimeCapability::SetEncryptionAlgorithm(const PString & alg)
361 {
362 m_algorithm = alg;
363 }
364
GetEncryptionAlgorithm() const365 const PString & H323SecureRealTimeCapability::GetEncryptionAlgorithm() const
366 {
367 return m_algorithm;
368 }
369
GetMediaFormat() const370 const OpalMediaFormat & H323SecureRealTimeCapability::GetMediaFormat() const
371 {
372 return ChildCapability->GetMediaFormat();
373 }
374
GetWritableMediaFormat()375 OpalMediaFormat & H323SecureRealTimeCapability::GetWritableMediaFormat()
376 {
377 return ChildCapability->GetWritableMediaFormat();
378 }
379
380 /////////////////////////////////////////////////////////////////////////////
381
H323SecureCapability(H323Capability & childCapability,H235ChType Ch,H323Capabilities * capabilities,unsigned secNo,PBoolean active)382 H323SecureCapability::H323SecureCapability(H323Capability & childCapability,
383 H235ChType Ch,
384 H323Capabilities * capabilities,
385 unsigned secNo,
386 PBoolean active
387 )
388 : H323SecureRealTimeCapability((H323Capability *)childCapability.Clone(), capabilities, secNo, active)
389 {
390 chtype = Ch;
391 }
392
GetMainType() const393 H323Capability::MainTypes H323SecureCapability::GetMainType() const
394 {
395 return ChildCapability->GetMainType();
396 }
397
398
Clone() const399 PObject * H323SecureCapability::Clone() const
400 {
401 PTRACE(4, "H235RTP\tCloning Capability: " << GetFormatName());
402
403 H235ChType ch = H235ChNew;
404
405 switch (chtype) {
406 case H235ChNew:
407 ch = H235ChClone;
408 break;
409 case H235ChClone:
410 ch = H235Channel;
411 break;
412 case H235Channel:
413 ch = H235Channel;
414 break;
415 }
416
417 return new H323SecureCapability(*ChildCapability, ch, m_capabilities, m_secNo, m_active);
418 }
419
IsMatch(const PASN_Choice & subTypePDU) const420 PBoolean H323SecureCapability::IsMatch(const PASN_Choice & subTypePDU) const
421 {
422
423 if (PIsDescendant(&subTypePDU, H245_AudioCapability) &&
424 ChildCapability->GetMainType() == H323Capability::e_Audio) {
425 const H245_AudioCapability & audio = (const H245_AudioCapability &)subTypePDU;
426 return ChildCapability->IsMatch(audio);
427 }
428
429 if (PIsDescendant(&subTypePDU, H245_VideoCapability) &&
430 ChildCapability->GetMainType() == H323Capability::e_Video) {
431 const H245_VideoCapability & video = (const H245_VideoCapability &)subTypePDU;
432 return ChildCapability->IsMatch(video);
433 }
434
435 if (PIsDescendant(&subTypePDU, H245_DataApplicationCapability_application) &&
436 ChildCapability->GetMainType() == H323Capability::e_Data) {
437 const H245_DataApplicationCapability_application & data =
438 (const H245_DataApplicationCapability_application &)subTypePDU;
439 return ChildCapability->IsMatch(data);
440 }
441
442 if (PIsDescendant(&subTypePDU, H245_H235Media_mediaType)) {
443 const H245_H235Media_mediaType & data =
444 (const H245_H235Media_mediaType &)subTypePDU;
445 return IsSubMatch(data);
446 }
447 return false;
448 }
449
450
IsSubMatch(const PASN_Choice & subTypePDU) const451 PBoolean H323SecureCapability::IsSubMatch(const PASN_Choice & subTypePDU) const
452 {
453 const H245_H235Media_mediaType & dataType = (const H245_H235Media_mediaType &)subTypePDU;
454 if (dataType.GetTag() == H245_H235Media_mediaType::e_audioData &&
455 ChildCapability->GetMainType() == H323Capability::e_Audio) {
456 const H245_AudioCapability & audio = dataType;
457 return ChildCapability->IsMatch(audio);
458 }
459
460 if (dataType.GetTag() == H245_H235Media_mediaType::e_videoData &&
461 ChildCapability->GetMainType() == H323Capability::e_Video) {
462 const H245_VideoCapability & video = dataType;
463 return ChildCapability->IsMatch(video);
464 }
465
466 return false;
467 }
468
Compare(const PObject & obj) const469 PObject::Comparison H323SecureCapability::Compare(const PObject & obj) const
470 {
471 if (!PIsDescendant(&obj, H323SecureCapability))
472 return LessThan;
473
474 Comparison result = H323Capability::Compare(obj);
475 if (result != EqualTo)
476 return result;
477
478 const H323SecureCapability & other = (const H323SecureCapability &)obj;
479
480 return ChildCapability->Compare(*(other.GetChildCapability()));
481 }
482
GetDefaultSessionID() const483 unsigned H323SecureCapability::GetDefaultSessionID() const
484 {
485 return ChildCapability->GetDefaultSessionID();
486 }
487
488 ////////////////////////////////////////////////////////////////////////
489 // PDU Sending
490
OnSendingPDU(H245_ModeElement & mode) const491 PBoolean H323SecureCapability::OnSendingPDU(H245_ModeElement & mode) const
492 {
493 switch (ChildCapability->GetMainType()) {
494 case H323Capability::e_Audio:
495 return ((H323AudioCapability *)ChildCapability)->OnSendingPDU(mode);
496 case H323Capability::e_Video:
497 #ifdef H323_VIDEO
498 return ((H323VideoCapability *)ChildCapability)->OnSendingPDU(mode);
499 #endif // H323_VIDEO
500 case H323Capability::e_Data:
501 default:
502 return false;
503 }
504 }
505
OnSendingPDU(H245_DataType & dataType) const506 PBoolean H323SecureCapability::OnSendingPDU(H245_DataType & dataType) const
507 {
508 // find the matching H235SecurityCapability to get the agreed algorithms
509 // if not found or no matching algorithm then assume no encryption.
510 H235SecurityCapability * secCap = NULL;
511 if (m_capabilities) {
512 secCap = (H235SecurityCapability *)m_capabilities->FindCapability(m_secNo);
513 if (secCap && secCap->GetAlgorithmCount() > 0) {
514 (PRemoveConst(H323SecureCapability,this))->SetEncryptionActive(true);
515 (PRemoveConst(H323SecureCapability,this))->SetEncryptionAlgorithm(secCap->GetAlgorithm());
516 }
517 }
518
519 if (!IsEncryptionActive()) {
520 unsigned txFramesInPacket =0;
521 switch (ChildCapability->GetMainType()) {
522 case H323Capability::e_Audio:
523 dataType.SetTag(H245_DataType::e_audioData);
524 txFramesInPacket = ((H323AudioCapability *)ChildCapability)->GetTxFramesInPacket();
525 return ((H323AudioCapability *)ChildCapability)->OnSendingPDU((H245_AudioCapability &)dataType, txFramesInPacket, e_OLC);
526 case H323Capability::e_Video:
527 #ifdef H323_VIDEO
528 dataType.SetTag(H245_DataType::e_videoData);
529 return ((H323VideoCapability *)ChildCapability)->OnSendingPDU((H245_VideoCapability &)dataType, e_OLC);
530 #endif // H323_VIDEO
531 case H323Capability::e_Data:
532 default:
533 break;
534 }
535 return false;
536 }
537
538 dataType.SetTag(H245_DataType::e_h235Media);
539 H245_H235Media & h235Media = dataType;
540 // Load the algorithm
541 if (secCap)
542 secCap->OnSendingPDU(h235Media.m_encryptionAuthenticationAndIntegrity, e_OLC);
543
544 H245_H235Media_mediaType & cType = h235Media.m_mediaType;
545 unsigned txFramesInPacket =0;
546 switch (ChildCapability->GetMainType()) {
547 case H323Capability::e_Audio:
548 cType.SetTag(H245_H235Media_mediaType::e_audioData);
549 txFramesInPacket = ((H323AudioCapability *)ChildCapability)->GetTxFramesInPacket();
550 return ((H323AudioCapability *)ChildCapability)->OnSendingPDU((H245_AudioCapability &)cType, txFramesInPacket, e_OLC);
551 case H323Capability::e_Video:
552 #ifdef H323_VIDEO
553 cType.SetTag(H245_H235Media_mediaType::e_videoData);
554 return ((H323VideoCapability *)ChildCapability)->OnSendingPDU((H245_VideoCapability &)cType, e_OLC);
555 #endif // H323_VIDEO
556 case H323Capability::e_Data:
557 default:
558 break;
559 }
560 return false;
561 }
562
OnReceivedPDU(const H245_DataType & dataType,PBoolean receiver)563 PBoolean H323SecureCapability::OnReceivedPDU(const H245_DataType & dataType,PBoolean receiver)
564 {
565 if (dataType.GetTag() != H245_DataType::e_h235Media)
566 return ChildCapability->OnReceivedPDU(dataType, receiver);
567
568 const H245_H235Media & h235Media = dataType;
569
570 if (m_capabilities) {
571 H235SecurityCapability * secCap = (H235SecurityCapability *)m_capabilities->FindCapability(m_secNo);
572 if (!secCap || !secCap->OnReceivedPDU(h235Media.m_encryptionAuthenticationAndIntegrity, e_OLC)) {
573 PTRACE(4,"H235\tFailed to locate security capability " << m_secNo);
574 return false;
575 }
576 if (secCap && secCap->GetAlgorithmCount() > 0) {
577 SetEncryptionAlgorithm(secCap->GetAlgorithm());
578 SetEncryptionActive(true);
579 }
580 }
581
582 const H245_H235Media_mediaType & mediaType = h235Media.m_mediaType;
583
584 switch (ChildCapability->GetMainType()) {
585 case H323Capability::e_Audio:
586 if (mediaType.GetTag() == H245_H235Media_mediaType::e_audioData) {
587 unsigned packetSize = (receiver) ?
588 ChildCapability->GetRxFramesInPacket() : ChildCapability->GetTxFramesInPacket();
589 return ((H323AudioCapability *)ChildCapability)->OnReceivedPDU((const H245_AudioCapability &)mediaType, packetSize, e_OLC);
590 }
591 break;
592
593 case H323Capability::e_Video:
594 #ifdef H323_VIDEO
595 if (mediaType.GetTag() == H245_H235Media_mediaType::e_videoData)
596 return ((H323VideoCapability *)ChildCapability)->OnReceivedPDU((const H245_VideoCapability &)mediaType, e_OLC);
597 break;
598 #endif // H323_VIDEO
599
600 case H323Capability::e_Data:
601 default:
602 break;
603 }
604
605 return false;
606 }
607
608 //////////////////////////////////////////////////////////////////////////////
609 // Child Capability Intercept
610
OnSendingPDU(H245_Capability & pdu) const611 PBoolean H323SecureCapability::OnSendingPDU(H245_Capability & pdu) const
612 {
613 switch (ChildCapability->GetMainType()) {
614 case H323Capability::e_Audio:
615 return ((H323AudioCapability *)ChildCapability)->OnSendingPDU(pdu);
616 case H323Capability::e_Video:
617 #ifdef H323_VIDEO
618 return ((H323VideoCapability *)ChildCapability)->OnSendingPDU(pdu);
619 #endif // H323_VIDEO
620 case H323Capability::e_Data:
621 case H323Capability::e_UserInput:
622 case H323Capability::e_ExtendVideo:
623 default:
624 return false;
625 }
626 }
627
OnReceivedPDU(const H245_Capability & pdu)628 PBoolean H323SecureCapability::OnReceivedPDU(const H245_Capability & pdu)
629 {
630 switch (ChildCapability->GetMainType()) {
631 case H323Capability::e_Audio:
632 return ((H323AudioCapability *)ChildCapability)->OnReceivedPDU(pdu);
633 case H323Capability::e_Video:
634 #ifdef H323_VIDEO
635 return ((H323VideoCapability *)ChildCapability)->OnReceivedPDU(pdu);
636 #endif // H323_VIDEO
637 case H323Capability::e_Data:
638 case H323Capability::e_UserInput:
639 case H323Capability::e_ExtendVideo:
640 default:
641 return false;
642 }
643 }
644
645
GetFormatName() const646 PString H323SecureCapability::GetFormatName() const
647 {
648 return ChildCapability->GetFormatName() + (m_active ? " #" : "");
649 }
650
GetSubType() const651 unsigned H323SecureCapability::GetSubType() const
652 {
653 return ChildCapability->GetSubType();
654 }
655
GetIdentifier() const656 PString H323SecureCapability::GetIdentifier() const
657 {
658 return ChildCapability->GetIdentifier();
659 }
660
CreateCodec(H323Codec::Direction direction) const661 H323Codec * H323SecureCapability::CreateCodec(H323Codec::Direction direction) const
662 {
663 return ChildCapability->CreateCodec(direction);
664 }
665
666
667 /////////////////////////////////////////////////////////////////////////////
668 // For extended
669
H323SecureExtendedCapability(H323Capability * childCapability,enum H235ChType Ch,H323Capabilities * capabilities,unsigned secNo,PBoolean active)670 H323SecureExtendedCapability::H323SecureExtendedCapability(H323Capability * childCapability, enum H235ChType Ch, H323Capabilities * capabilities, unsigned secNo, PBoolean active)
671 : H323ExtendedVideoCapability(""),
672 ChildCapability(childCapability), chtype(Ch), m_active(active),
673 m_capabilities(capabilities), m_secNo(secNo), nrtpqos(NULL)
674 {
675 assignedCapabilityNumber = ChildCapability->GetCapabilityNumber();
676 }
677
678
H323SecureExtendedCapability(RTP_QOS * _rtpqos,H323Capability * childCapability)679 H323SecureExtendedCapability::H323SecureExtendedCapability(RTP_QOS * _rtpqos,H323Capability * childCapability)
680 : H323ExtendedVideoCapability(""),
681 ChildCapability(childCapability), chtype(H235ChNew), m_active(false),
682 m_capabilities(NULL), m_secNo(0), nrtpqos(_rtpqos)
683 {
684 }
685
~H323SecureExtendedCapability()686 H323SecureExtendedCapability::~H323SecureExtendedCapability()
687 {
688 delete ChildCapability;
689 }
690
691
AttachQoS(RTP_QOS * _rtpqos)692 void H323SecureExtendedCapability::AttachQoS(RTP_QOS * _rtpqos)
693 {
694 #ifdef P_QOS
695 delete nrtpqos;
696 nrtpqos = _rtpqos;
697 #endif
698 }
699
SetAssociatedCapability(unsigned _secNo)700 void H323SecureExtendedCapability::SetAssociatedCapability(unsigned _secNo)
701 {
702 m_secNo = _secNo;
703 }
704
CreateChannel(H323Connection & connection,H323Channel::Directions dir,unsigned sessionID,const H245_H2250LogicalChannelParameters * param) const705 H323Channel * H323SecureExtendedCapability::CreateChannel(H323Connection & connection,
706 H323Channel::Directions dir,
707 unsigned sessionID,
708 const H245_H2250LogicalChannelParameters * param) const
709 {
710
711 // create a standard RTP channel if we don't have a DH token
712 H235Capabilities * caps = dynamic_cast<H235Capabilities*>(connection.GetLocalCapabilitiesRef());
713 if (!caps || !caps->GetDiffieHellMan())
714 return connection.CreateRealTimeLogicalChannel(*ChildCapability, dir, sessionID, param, nrtpqos);
715
716 // Support for encrypted external RTP Channel
717 H323Channel * extRTPChannel = connection.CreateRealTimeLogicalChannel(*this, dir, sessionID, param, nrtpqos);
718 if (extRTPChannel)
719 return extRTPChannel;
720
721 RTP_Session * session = NULL; // Session
722 if (
723 #ifdef H323_H46026
724 connection.H46026IsMediaTunneled() ||
725 #endif
726 !param || !param->HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaControlChannel)) {
727 // Make a fake transport address from the connection so gets initialised with
728 // the transport type (IP, IPX, multicast etc).
729 H245_TransportAddress addr;
730 connection.GetControlChannel().SetUpTransportPDU(addr, H323Transport::UseLocalTSAP);
731 session = connection.UseSession(sessionID, addr, dir, nrtpqos);
732 } else {
733 session = connection.UseSession(param->m_sessionID, param->m_mediaControlChannel, dir, nrtpqos);
734 }
735
736 if (!session)
737 return NULL;
738
739 return new H323SecureRTPChannel(connection, *this, dir, *session);
740 }
741
GetCapabilityNumber() const742 unsigned H323SecureExtendedCapability::GetCapabilityNumber() const
743 {
744 return ChildCapability->GetCapabilityNumber();
745 };
746
SetCapabilityNumber(unsigned num)747 void H323SecureExtendedCapability::SetCapabilityNumber(unsigned num)
748 {
749 assignedCapabilityNumber = num;
750 ChildCapability->SetCapabilityNumber(num);
751 }
752
SetCapabilityList(H323Capabilities * capabilities)753 void H323SecureExtendedCapability::SetCapabilityList(H323Capabilities * capabilities)
754 {
755 m_capabilities = capabilities;
756 }
757
SetEncryptionActive(PBoolean active)758 void H323SecureExtendedCapability::SetEncryptionActive(PBoolean active)
759 {
760 m_active = active;
761 }
762
IsEncryptionActive() const763 PBoolean H323SecureExtendedCapability::IsEncryptionActive() const
764 {
765 return m_active;
766 }
767
SetEncryptionAlgorithm(const PString & alg)768 void H323SecureExtendedCapability::SetEncryptionAlgorithm(const PString & alg)
769 {
770 m_algorithm = alg;
771 }
772
GetEncryptionAlgorithm() const773 const PString & H323SecureExtendedCapability::GetEncryptionAlgorithm() const
774 {
775 return m_algorithm;
776 }
777
GetMediaFormat() const778 const OpalMediaFormat & H323SecureExtendedCapability::GetMediaFormat() const
779 {
780 return ChildCapability->GetMediaFormat();
781 }
782
GetWritableMediaFormat()783 OpalMediaFormat & H323SecureExtendedCapability::GetWritableMediaFormat()
784 {
785 return ChildCapability->GetWritableMediaFormat();
786 }
787
GetMainType() const788 H323Capability::MainTypes H323SecureExtendedCapability::GetMainType() const
789 {
790 return ChildCapability->GetMainType();
791 }
792
Clone() const793 PObject * H323SecureExtendedCapability::Clone() const
794 {
795 PTRACE(3, "H235ExtRTP\tCloning Capability: " << GetFormatName());
796
797 H235ChType ch = H235ChNew;
798
799 switch (chtype) {
800 case H235ChNew:
801 ch = H235ChClone;
802 break;
803 case H235ChClone:
804 ch = H235Channel;
805 break;
806 case H235Channel:
807 ch = H235Channel;
808 break;
809 }
810
811 return new H323SecureExtendedCapability((H323Capability *)ChildCapability->Clone(), ch, m_capabilities, m_secNo, m_active);
812 }
813
IsMatch(const PASN_Choice & subTypePDU) const814 PBoolean H323SecureExtendedCapability::IsMatch(const PASN_Choice & subTypePDU) const
815 {
816 if (PIsDescendant(&subTypePDU, H245_VideoCapability) &&
817 ChildCapability->GetMainType() == H323Capability::e_Video) {
818 const H245_VideoCapability & video = (const H245_VideoCapability &)subTypePDU;
819 return ChildCapability->IsMatch(video);
820 }
821
822 if (PIsDescendant(&subTypePDU, H245_H235Media_mediaType)) {
823 const H245_H235Media_mediaType & data =
824 (const H245_H235Media_mediaType &)subTypePDU;
825 return IsSubMatch(data);
826 }
827 return false;
828 }
829
830
IsSubMatch(const PASN_Choice & subTypePDU) const831 PBoolean H323SecureExtendedCapability::IsSubMatch(const PASN_Choice & subTypePDU) const
832 {
833 const H245_H235Media_mediaType & dataType = (const H245_H235Media_mediaType &)subTypePDU;
834
835 if (dataType.GetTag() == H245_H235Media_mediaType::e_videoData &&
836 ChildCapability->GetMainType() == H323Capability::e_Video) {
837 const H245_VideoCapability & video = dataType;
838 return ChildCapability->IsMatch(video);
839 }
840
841 return false;
842 }
843
Compare(const PObject & obj) const844 PObject::Comparison H323SecureExtendedCapability::Compare(const PObject & obj) const
845 {
846 if (!PIsDescendant(&obj, H323SecureExtendedCapability))
847 return LessThan;
848
849 Comparison result = H323Capability::Compare(obj);
850 if (result != EqualTo)
851 return result;
852
853 const H323SecureExtendedCapability & other = (const H323SecureExtendedCapability &)obj;
854
855 return ChildCapability->Compare(*(other.GetChildCapability()));
856 }
857
GetDefaultSessionID() const858 unsigned H323SecureExtendedCapability::GetDefaultSessionID() const
859 {
860 return ChildCapability->GetDefaultSessionID();
861 }
862
863 ////////////////////////////////////////////////////////////////////////
864 // PDU Sending
865
OnSendingPDU(H245_ModeElement & mode) const866 PBoolean H323SecureExtendedCapability::OnSendingPDU(H245_ModeElement & mode) const
867 {
868 switch (ChildCapability->GetMainType()) {
869 case H323Capability::e_Video:
870 #ifdef H323_VIDEO
871 return ((H323ExtendedVideoCapability *)ChildCapability)->OnSendingPDU(mode);
872 #endif // H323_VIDEO
873 case H323Capability::e_Audio:
874 case H323Capability::e_Data:
875 default:
876 return false;
877 }
878 }
879
OnSendingPDU(H245_DataType & dataType) const880 PBoolean H323SecureExtendedCapability::OnSendingPDU(H245_DataType & dataType) const
881 {
882 // find the matching H235SecurityCapability to get the agreed algorithms
883 // if not found or no matching algorithm then assume no encryption.
884 H235SecurityCapability * secCap = NULL;
885 if (m_capabilities) {
886 secCap = (H235SecurityCapability *)m_capabilities->FindCapability(m_secNo);
887 if (secCap && secCap->GetAlgorithmCount() > 0) {
888 (PRemoveConst(H323SecureExtendedCapability,this))->SetEncryptionActive(true);
889 (PRemoveConst(H323SecureExtendedCapability,this))->SetEncryptionAlgorithm(secCap->GetAlgorithm());
890 }
891 }
892
893 if (!IsEncryptionActive()) {
894 switch (ChildCapability->GetMainType()) {
895 case H323Capability::e_Video:
896 #ifdef H323_VIDEO
897 dataType.SetTag(H245_DataType::e_videoData);
898 return ((H323CodecExtendedVideoCapability *)ChildCapability)->OnSendingPDU((H245_VideoCapability &)dataType, e_OLC);
899 #endif // H323_VIDEO
900 case H323Capability::e_Audio:
901 case H323Capability::e_Data:
902 default:
903 break;
904 }
905 return false;
906 }
907
908 dataType.SetTag(H245_DataType::e_h235Media);
909 H245_H235Media & h235Media = dataType;
910 // Load the algorithm
911 if (secCap)
912 secCap->OnSendingPDU(h235Media.m_encryptionAuthenticationAndIntegrity, e_OLC);
913
914 H245_H235Media_mediaType & cType = h235Media.m_mediaType;
915 switch (ChildCapability->GetMainType()) {
916 case H323Capability::e_Video:
917 #ifdef H323_VIDEO
918 cType.SetTag(H245_H235Media_mediaType::e_videoData);
919 return ((H323CodecExtendedVideoCapability *)ChildCapability)->OnSendingPDU((H245_VideoCapability &)cType, e_OLC);
920 #endif // H323_VIDEO
921 case H323Capability::e_Audio:
922 case H323Capability::e_Data:
923 default:
924 break;
925 }
926 return false;
927 }
928
OnReceivedPDU(const H245_DataType & dataType,PBoolean receiver)929 PBoolean H323SecureExtendedCapability::OnReceivedPDU(const H245_DataType & dataType,PBoolean receiver)
930 {
931 if (dataType.GetTag() != H245_DataType::e_h235Media)
932 return ChildCapability->OnReceivedPDU(dataType, receiver);
933
934 const H245_H235Media & h235Media = dataType;
935
936 if (m_capabilities) {
937 H235SecurityCapability * secCap = (H235SecurityCapability *)m_capabilities->FindCapability(m_secNo);
938 if (!secCap || !secCap->OnReceivedPDU(h235Media.m_encryptionAuthenticationAndIntegrity, e_OLC)) {
939 PTRACE(4,"H235\tFailed to locate security capability " << m_secNo);
940 return false;
941 }
942 if (secCap && secCap->GetAlgorithmCount() > 0) {
943 SetEncryptionAlgorithm(secCap->GetAlgorithm());
944 SetEncryptionActive(true);
945 }
946 }
947
948 const H245_H235Media_mediaType & mediaType = h235Media.m_mediaType;
949
950 switch (ChildCapability->GetMainType()) {
951 case H323Capability::e_Video:
952 #ifdef H323_VIDEO
953 if (mediaType.GetTag() == H245_H235Media_mediaType::e_videoData)
954 return ((H323CodecExtendedVideoCapability *)ChildCapability)->OnReceivedPDU((const H245_VideoCapability &)mediaType);
955 break;
956 #endif // H323_VIDEO
957
958 case H323Capability::e_Audio:
959 case H323Capability::e_Data:
960 default:
961 break;
962 }
963 return false;
964 }
965
966 //////////////////////////////////////////////////////////////////////////////
967 // Child Capability Intercept
968
OnSendingPDU(H245_Capability & pdu) const969 PBoolean H323SecureExtendedCapability::OnSendingPDU(H245_Capability & pdu) const
970 {
971 switch (ChildCapability->GetMainType()) {
972 case H323Capability::e_Video:
973 #ifdef H323_VIDEO
974 return ((H323CodecExtendedVideoCapability *)ChildCapability)->OnSendingPDU(pdu);
975 #endif // H323_VIDEO
976 case H323Capability::e_Audio:
977 case H323Capability::e_Data:
978 case H323Capability::e_UserInput:
979 case H323Capability::e_ExtendVideo:
980 default:
981 return false;
982 }
983 }
984
OnReceivedPDU(const H245_Capability & pdu)985 PBoolean H323SecureExtendedCapability::OnReceivedPDU(const H245_Capability & pdu)
986 {
987 switch (ChildCapability->GetMainType()) {
988 case H323Capability::e_Video:
989 #ifdef H323_VIDEO
990 return ((H323CodecExtendedVideoCapability *)ChildCapability)->OnReceivedPDU(pdu);
991 #endif // H323_VIDEO
992 case H323Capability::e_Audio:
993 case H323Capability::e_Data:
994 case H323Capability::e_UserInput:
995 case H323Capability::e_ExtendVideo:
996 default:
997 return false;
998 }
999 }
1000
1001
GetFormatName() const1002 PString H323SecureExtendedCapability::GetFormatName() const
1003 {
1004 return ChildCapability->GetFormatName() + (m_active ? " #" : "");
1005 }
1006
GetSubType() const1007 unsigned H323SecureExtendedCapability::GetSubType() const
1008 {
1009 return ChildCapability->GetSubType();
1010 }
1011
GetIdentifier() const1012 PString H323SecureExtendedCapability::GetIdentifier() const
1013 {
1014 return ChildCapability->GetIdentifier();
1015 }
1016
CreateCodec(H323Codec::Direction direction) const1017 H323Codec * H323SecureExtendedCapability::CreateCodec(H323Codec::Direction direction) const
1018 {
1019 return ChildCapability->CreateCodec(direction);
1020 }
1021
GetCapabilities() const1022 const H323Capabilities & H323SecureExtendedCapability::GetCapabilities() const
1023 {
1024 H323ExtendedVideoCapability* extCap = dynamic_cast<H323ExtendedVideoCapability*>(ChildCapability);
1025 if (extCap)
1026 return extCap->GetCapabilities();
1027 else
1028 return extCapabilities;
1029 }
1030
1031 /////////////////////////////////////////////////////////////////////////////
1032
1033
H323SecureDataCapability(H323Capability & childCapability,enum H235ChType Ch,H323Capabilities * capabilities,unsigned secNo,PBoolean active)1034 H323SecureDataCapability::H323SecureDataCapability(H323Capability & childCapability, enum H235ChType Ch, H323Capabilities * capabilities,
1035 unsigned secNo, PBoolean active )
1036 : ChildCapability((H323Capability *)childCapability.Clone()), chtype(Ch), m_active(active), m_capabilities(capabilities),
1037 m_secNo(secNo), m_algorithm(PString())
1038 {
1039 assignedCapabilityNumber = childCapability.GetCapabilityNumber();
1040 }
1041
~H323SecureDataCapability()1042 H323SecureDataCapability::~H323SecureDataCapability()
1043 {
1044 delete ChildCapability;
1045 }
1046
SetAssociatedCapability(unsigned _secNo)1047 void H323SecureDataCapability::SetAssociatedCapability(unsigned _secNo)
1048 {
1049 m_secNo = _secNo;
1050 }
1051
1052
Compare(const PObject & obj) const1053 PObject::Comparison H323SecureDataCapability::Compare(const PObject & obj) const
1054 {
1055 if (!PIsDescendant(&obj, H323SecureDataCapability))
1056 return LessThan;
1057
1058 Comparison result = H323Capability::Compare(obj);
1059 if (result != EqualTo)
1060 return result;
1061
1062 const H323SecureDataCapability & other = (const H323SecureDataCapability &)obj;
1063
1064 return ChildCapability->Compare(*(other.GetChildCapability()));
1065 }
1066
Clone() const1067 PObject * H323SecureDataCapability::Clone() const
1068 {
1069 PTRACE(4, "H235Data\tCloning Capability: " << GetFormatName());
1070
1071 H235ChType ch = H235ChNew;
1072 switch (chtype) {
1073 case H235ChNew:
1074 ch = H235ChClone;
1075 break;
1076 case H235ChClone:
1077 ch = H235Channel;
1078 break;
1079 case H235Channel:
1080 ch = H235Channel;
1081 break;
1082 }
1083 return new H323SecureDataCapability(*ChildCapability, ch, m_capabilities, m_secNo, m_active);
1084 }
1085
1086
GetSubType() const1087 unsigned H323SecureDataCapability::GetSubType() const
1088 {
1089 return ChildCapability->GetSubType();
1090 }
1091
1092
GetFormatName() const1093 PString H323SecureDataCapability::GetFormatName() const
1094 {
1095 return ChildCapability->GetFormatName() + (m_active ? " #" : "");
1096 }
1097
1098
IsMatch(const PASN_Choice & subTypePDU) const1099 PBoolean H323SecureDataCapability::IsMatch(const PASN_Choice & subTypePDU) const
1100 {
1101 if (PIsDescendant(&subTypePDU, H245_DataApplicationCapability_application) &&
1102 ChildCapability->GetMainType() == H323Capability::e_Data) {
1103 const H245_DataApplicationCapability_application & data =
1104 (const H245_DataApplicationCapability_application &)subTypePDU;
1105 return ChildCapability->IsMatch(data);
1106 }
1107
1108 if (PIsDescendant(&subTypePDU, H245_H235Media_mediaType)) {
1109 const H245_H235Media_mediaType & data =
1110 (const H245_H235Media_mediaType &)subTypePDU;
1111 return IsSubMatch(data);
1112 }
1113 return false;
1114 }
1115
IsSubMatch(const PASN_Choice & subTypePDU) const1116 PBoolean H323SecureDataCapability::IsSubMatch(const PASN_Choice & subTypePDU) const
1117 {
1118 const H245_H235Media_mediaType & dataType = (const H245_H235Media_mediaType &)subTypePDU;
1119
1120 if (dataType.GetTag() == H245_H235Media_mediaType::e_data &&
1121 ChildCapability->GetMainType() == H323Capability::e_Data) {
1122 const H245_DataApplicationCapability & data = dataType;
1123 return ChildCapability->IsMatch(data.m_application);
1124 }
1125 return false;
1126 }
1127
SetEncryptionActive(PBoolean active)1128 void H323SecureDataCapability::SetEncryptionActive(PBoolean active)
1129 {
1130 m_active = active;
1131 }
1132
IsEncryptionActive() const1133 PBoolean H323SecureDataCapability::IsEncryptionActive() const
1134 {
1135 return m_active;
1136 }
1137
SetEncryptionAlgorithm(const PString & alg)1138 void H323SecureDataCapability::SetEncryptionAlgorithm(const PString & alg)
1139 {
1140 m_algorithm = alg;
1141 }
1142
GetEncryptionAlgorithm() const1143 const PString & H323SecureDataCapability::GetEncryptionAlgorithm() const
1144 {
1145 return m_algorithm;
1146 }
1147
CreateChannel(H323Connection & connection,H323Channel::Directions dir,unsigned sessionID,const H245_H2250LogicalChannelParameters * param) const1148 H323Channel * H323SecureDataCapability::CreateChannel(H323Connection & connection,
1149 H323Channel::Directions dir,
1150 unsigned sessionID,
1151 const H245_H2250LogicalChannelParameters * param) const
1152 {
1153
1154 H235Capabilities * caps = dynamic_cast<H235Capabilities*>(connection.GetLocalCapabilitiesRef());
1155 if (!caps || !caps->GetDiffieHellMan())
1156 return ChildCapability->CreateChannel(connection, dir, sessionID, param);
1157
1158 // We create the primary channel with a clone of the child
1159 // then delete the clone and replace the clone with this one
1160 // via ReplaceCapability() in the constructor of H323SecureChannel
1161 return new H323SecureChannel(connection, *this, ((H323Capability *)ChildCapability->Clone())->CreateChannel(connection, dir, sessionID, param));
1162 }
1163
OnSendingPDU(H245_Capability & pdu) const1164 PBoolean H323SecureDataCapability::OnSendingPDU(H245_Capability & pdu) const
1165 {
1166 return ((H323DataCapability *)ChildCapability)->OnSendingPDU(pdu);
1167 }
1168
OnReceivedPDU(const H245_Capability & pdu)1169 PBoolean H323SecureDataCapability::OnReceivedPDU(const H245_Capability & pdu)
1170 {
1171 return ((H323DataCapability *)ChildCapability)->OnReceivedPDU(pdu);
1172 }
1173
OnSendingPDU(H245_ModeElement & mode) const1174 PBoolean H323SecureDataCapability::OnSendingPDU(H245_ModeElement & mode) const
1175 {
1176 return ((H323DataCapability *)ChildCapability)->OnSendingPDU(mode);
1177 }
1178
OnSendingPDU(H245_DataType & dataType) const1179 PBoolean H323SecureDataCapability::OnSendingPDU(H245_DataType & dataType) const
1180 {
1181 // find the matching H235SecurityCapability to get the agreed algorithms
1182 // if not found or no matching algorithm then assume no encryption.
1183 H235SecurityCapability * secCap = NULL;
1184 if (m_capabilities) {
1185 secCap = (H235SecurityCapability *)m_capabilities->FindCapability(m_secNo);
1186 if (secCap && secCap->GetAlgorithmCount() > 0) {
1187 (PRemoveConst(H323SecureDataCapability,this))->SetEncryptionActive(true);
1188 (PRemoveConst(H323SecureDataCapability,this))->SetEncryptionAlgorithm(secCap->GetAlgorithm());
1189 }
1190 }
1191
1192 if (!IsEncryptionActive())
1193 return ((H323DataCapability *)ChildCapability)->OnSendingPDU(dataType);
1194
1195 dataType.SetTag(H245_DataType::e_h235Media);
1196 H245_H235Media & h235Media = dataType;
1197 // Load the algorithm
1198 if (secCap)
1199 secCap->OnSendingPDU(h235Media.m_encryptionAuthenticationAndIntegrity, e_OLC);
1200
1201 H245_H235Media_mediaType & cType = h235Media.m_mediaType;
1202 cType.SetTag(H245_H235Media_mediaType::e_data);
1203 return ((H323DataCapability *)ChildCapability)->OnSendingPDU((H245_DataApplicationCapability &)cType, e_OLC);
1204 }
1205
1206
OnReceivedPDU(const H245_DataType & dataType,PBoolean receiver)1207 PBoolean H323SecureDataCapability::OnReceivedPDU(const H245_DataType & dataType, PBoolean receiver)
1208 {
1209 if (dataType.GetTag() != H245_DataType::e_h235Media)
1210 return ChildCapability->OnReceivedPDU(dataType, receiver);
1211
1212 const H245_H235Media & h235Media = dataType;
1213 if (m_capabilities) {
1214 H235SecurityCapability * secCap = (H235SecurityCapability *)m_capabilities->FindCapability(m_secNo);
1215 if (!secCap || !secCap->OnReceivedPDU(h235Media.m_encryptionAuthenticationAndIntegrity, e_OLC)) {
1216 PTRACE(4,"H235\tFailed to locate security capability " << m_secNo);
1217 return false;
1218 }
1219 if (secCap && secCap->GetAlgorithmCount() > 0) {
1220 SetEncryptionAlgorithm(secCap->GetAlgorithm());
1221 SetEncryptionActive(true);
1222 }
1223 }
1224 const H245_H235Media_mediaType & mediaType = h235Media.m_mediaType;
1225 if (mediaType.GetTag() == H245_H235Media_mediaType::e_data)
1226 return ((H323DataCapability *)ChildCapability)->OnReceivedPDU((const H245_DataApplicationCapability &)mediaType, e_OLC);
1227 else
1228 return false;
1229 }
1230
1231
OnSendingPDU(H245_DataMode & pdu) const1232 PBoolean H323SecureDataCapability::OnSendingPDU(H245_DataMode & pdu) const
1233 {
1234 return ((H323DataCapability *)ChildCapability)->OnSendingPDU(pdu);
1235 }
1236
1237
1238 /////////////////////////////////////////////////////////////////////////////
1239
GetH235Codecs()1240 static PStringArray & GetH235Codecs()
1241 {
1242 static const char * defaultCodecs[] = { "all" };
1243 static PStringArray codecs(
1244 sizeof(defaultCodecs)/sizeof(defaultCodecs[0]),
1245 defaultCodecs
1246 );
1247 return codecs;
1248 }
1249
GetH235CodecsMutex()1250 static PMutex & GetH235CodecsMutex()
1251 {
1252 static PMutex mutex;
1253 return mutex;
1254 }
1255
1256 /////////////////////////////////////////////////////////////////////////////
1257
H235Capabilities()1258 H235Capabilities::H235Capabilities()
1259 : m_DHkey(NULL), m_h245Master(false)
1260 {
1261 m_algorithms.SetSize(0);
1262 }
1263
H235Capabilities(const H323Capabilities & original)1264 H235Capabilities::H235Capabilities(const H323Capabilities & original)
1265 : m_DHkey(NULL), m_h245Master(false)
1266 {
1267 m_algorithms.SetSize(0);
1268 const H323CapabilitiesSet rset = original.GetSet();
1269
1270 for (PINDEX i = 0; i < original.GetSize(); i++) {
1271 unsigned capabilityNumber = original[i].GetCapabilityNumber();
1272 PINDEX outer=0,middle=0,inner=0;
1273 for (outer = 0; outer < rset.GetSize(); outer++) {
1274 for (middle = 0; middle < rset[outer].GetSize(); middle++) {
1275 for (inner = 0; inner < rset[outer][middle].GetSize(); inner++) {
1276 if (rset[outer][middle][inner].GetCapabilityNumber() == capabilityNumber) {
1277 WrapCapability(outer, middle, original[i]);
1278 break;
1279 }
1280 }
1281 if (rset[outer][middle].GetSize() == 0) {
1282 WrapCapability(outer, middle, original[i]);
1283 break;
1284 }
1285 }
1286 if (rset[outer].GetSize() == 0) {
1287 WrapCapability(outer, middle, original[i]);
1288 break;
1289 }
1290 }
1291 }
1292 }
1293
H235Capabilities(const H323Connection & connection,const H245_TerminalCapabilitySet & pdu)1294 H235Capabilities::H235Capabilities(const H323Connection & connection, const H245_TerminalCapabilitySet & pdu)
1295 : H323Capabilities(connection, pdu), m_DHkey(NULL), m_h245Master(false)
1296 {
1297 const H235Capabilities & localCapabilities = (const H235Capabilities &)connection.GetLocalCapabilities();
1298 PRemoveConst(H235Capabilities,&localCapabilities)->GetDHKeyPair(m_algorithms, m_DHkey, m_h245Master);
1299 }
1300
SetCapabilityNumber(const H323CapabilitiesList & table,unsigned newCapabilityNumber)1301 static unsigned SetCapabilityNumber(const H323CapabilitiesList & table,
1302 unsigned newCapabilityNumber)
1303 {
1304 // Assign a unique number to the codec, check if the user wants a specific
1305 // value and start with that.
1306 if (newCapabilityNumber == 0)
1307 newCapabilityNumber = 1;
1308
1309 PINDEX i = 0;
1310 while (i < table.GetSize()) {
1311 if (table[i].GetCapabilityNumber() != newCapabilityNumber)
1312 i++;
1313 else {
1314 // If it already in use, increment it
1315 newCapabilityNumber++;
1316 i = 0;
1317 }
1318 }
1319
1320 return newCapabilityNumber;
1321 }
1322
AddSecure(PINDEX descriptorNum,PINDEX simultaneous,H323Capability * capability)1323 void H235Capabilities::AddSecure(PINDEX descriptorNum, PINDEX simultaneous, H323Capability * capability)
1324 {
1325 if (capability == NULL)
1326 return;
1327
1328 if (!PIsDescendant(capability,H323SecureCapability) &&
1329 !PIsDescendant(capability,H323SecureExtendedCapability) &&
1330 !PIsDescendant(capability,H323SecureDataCapability) &&
1331 !PIsDescendant(capability,H235SecurityCapability))
1332 return;
1333
1334 // See if already added, confuses things if you add the same instance twice
1335 if (table.GetObjectsIndex(capability) != P_MAX_INDEX)
1336 return;
1337
1338 // Create the secure capability wrapper
1339 unsigned capNumber = SetCapabilityNumber(table, capability->GetCapabilityNumber());
1340 unsigned secNumber = 100+capNumber;
1341
1342 capability->SetCapabilityNumber(capNumber);
1343 SetCapability(descriptorNum, simultaneous, capability);
1344
1345 // Create the security capability
1346 H235SecurityCapability * secCap = new H235SecurityCapability(this, capNumber);
1347 secCap->SetCapabilityNumber(secNumber);
1348 SetCapability(descriptorNum, simultaneous, secCap);
1349
1350 capability->SetCapabilityList(this);
1351 capability->SetAssociatedCapability(secNumber);
1352
1353 PTRACE(3, "H323\tAdded Secure Capability: " << *capability);
1354 }
1355
CopySecure(PINDEX descriptorNum,PINDEX simultaneous,const H323Capability & capability)1356 H323Capability * H235Capabilities::CopySecure(PINDEX descriptorNum, PINDEX simultaneous, const H323Capability & capability)
1357 {
1358 if (!PIsDescendant(&capability,H323SecureCapability) &&
1359 !PIsDescendant(&capability,H323SecureExtendedCapability) &&
1360 !PIsDescendant(&capability,H323SecureDataCapability) &&
1361 !PIsDescendant(&capability,H235SecurityCapability))
1362 return NULL;
1363
1364 if (PIsDescendant(&capability,H235SecurityCapability)) {
1365 H235SecurityCapability * newCapability = (H235SecurityCapability *)capability.Clone();
1366 newCapability->SetCapabilityNumber(capability.GetCapabilityNumber());
1367 table.Append(newCapability);
1368 SetCapability(descriptorNum, simultaneous, newCapability);
1369 return newCapability;
1370 } else {
1371 H323Capability * newCapability = (H323Capability *)capability.Clone();
1372 newCapability->SetCapabilityNumber(capability.GetCapabilityNumber());
1373 newCapability->SetCapabilityList(this);
1374 SetCapability(descriptorNum, simultaneous, newCapability);
1375 PTRACE(3, "H323\tCopied Secure Capability: " << *newCapability);
1376 return newCapability;
1377 }
1378 }
1379
WrapCapability(PINDEX descriptorNum,PINDEX simultaneous,H323Capability & capability)1380 void H235Capabilities::WrapCapability(PINDEX descriptorNum, PINDEX simultaneous, H323Capability & capability)
1381 {
1382 if (PIsDescendant(&capability,H323SecureCapability) ||
1383 PIsDescendant(&capability,H323SecureExtendedCapability) ||
1384 PIsDescendant(&capability,H323SecureDataCapability) ||
1385 PIsDescendant(&capability,H235SecurityCapability)) {
1386 CopySecure(descriptorNum, simultaneous, capability);
1387 return;
1388 }
1389
1390 if (!IsH235Codec(capability.GetFormatName())) {
1391 SetCapability(descriptorNum, simultaneous, (H323Capability *)capability.Clone());
1392 return;
1393 }
1394
1395 switch (capability.GetDefaultSessionID()) {
1396 case OpalMediaFormat::DefaultAudioSessionID:
1397 case OpalMediaFormat::DefaultVideoSessionID:
1398 AddSecure(descriptorNum, simultaneous, new H323SecureCapability(capability, H235ChNew,this));
1399 break;
1400 case OpalMediaFormat::DefaultExtVideoSessionID:
1401 AddSecure(descriptorNum, simultaneous, new H323SecureExtendedCapability((H323Capability *)capability.Clone(), H235ChNew,this));
1402 break;
1403 case OpalMediaFormat::DefaultDataSessionID:
1404 AddSecure(descriptorNum, simultaneous, new H323SecureDataCapability(capability, H235ChNew,this));
1405 break;
1406 case OpalMediaFormat::NonRTPSessionID:
1407 //case OpalMediaFormat::DefaultDataSessionID:
1408 //case OpalMediaFormat::DefaultExtVideoSessionID:
1409 case OpalMediaFormat::DefaultFileSessionID:
1410 default:
1411 SetCapability(descriptorNum, simultaneous, (H323Capability *)capability.Clone());
1412 break;
1413 }
1414 }
1415
MatchWildcard(const PCaselessString & str,const PStringArray & wildcard)1416 static PBoolean MatchWildcard(const PCaselessString & str, const PStringArray & wildcard)
1417 {
1418 PINDEX last = 0;
1419 for (PINDEX i = 0; i < wildcard.GetSize(); i++) {
1420 if (wildcard[i].IsEmpty())
1421 last = str.GetLength();
1422 else {
1423 PINDEX next = str.Find(wildcard[i], last);
1424 if (next == P_MAX_INDEX)
1425 return FALSE;
1426 last = next + wildcard[i].GetLength();
1427 }
1428 }
1429
1430 return TRUE;
1431 }
1432
AddAllCapabilities(PINDEX descriptorNum,PINDEX simultaneous,const PString & name)1433 PINDEX H235Capabilities::AddAllCapabilities(PINDEX descriptorNum,
1434 PINDEX simultaneous,
1435 const PString & name)
1436 {
1437 PINDEX reply = descriptorNum == P_MAX_INDEX ? P_MAX_INDEX : simultaneous;
1438
1439 PStringArray wildcard = name.Tokenise('*', FALSE);
1440
1441 H323CapabilityFactory::KeyList_T stdCaps = H323CapabilityFactory::GetKeyList();
1442
1443 for (unsigned session = OpalMediaFormat::FirstSessionID; session <= OpalMediaFormat::LastSessionID; session++) {
1444 for (H323CapabilityFactory::KeyList_T::const_iterator r = stdCaps.begin(); r != stdCaps.end(); ++r) {
1445 PString capName(*r);
1446 if (MatchWildcard(capName, wildcard) && (FindCapability(capName) == NULL)) {
1447 OpalMediaFormat mediaFormat(capName);
1448 if (!mediaFormat.IsValid() && (capName.Right(4) == "{sw}") && capName.GetLength() > 4)
1449 mediaFormat = OpalMediaFormat(capName.Left(capName.GetLength()-4));
1450 if (mediaFormat.IsValid() && mediaFormat.GetDefaultSessionID() == session) {
1451 // add the capability
1452 H323Capability * capability = H323Capability::Create(capName);
1453 H323Capability * newCapability = NULL;
1454 PINDEX num=0;
1455 switch (session) {
1456 case OpalMediaFormat::DefaultAudioSessionID:
1457 case OpalMediaFormat::DefaultVideoSessionID:
1458 newCapability = new H323SecureCapability(*capability, H235ChNew, this);
1459 // TODO: assigning to num twice doesn't make sense
1460 num = SetCapability(descriptorNum, simultaneous, newCapability);
1461 num = SetCapability(descriptorNum, simultaneous,
1462 new H235SecurityCapability(this, newCapability->GetCapabilityNumber()));
1463 break;
1464 case OpalMediaFormat::DefaultDataSessionID:
1465 newCapability = new H323SecureDataCapability(*capability, H235ChNew, this);
1466 // TODO: assigning to num twice doesn't make sense
1467 num = SetCapability(descriptorNum, simultaneous, newCapability);
1468 num = SetCapability(descriptorNum, simultaneous,
1469 new H235SecurityCapability(this, newCapability->GetCapabilityNumber()));
1470 break;
1471 case OpalMediaFormat::DefaultExtVideoSessionID:
1472 newCapability = new H323SecureExtendedCapability((H323Capability *)capability->Clone(), H235ChNew, this);
1473 // TODO: assigning to num twice doesn't make sense
1474 num = SetCapability(descriptorNum, simultaneous, newCapability);
1475 num = SetCapability(descriptorNum, simultaneous,
1476 new H235SecurityCapability(this, newCapability->GetCapabilityNumber()));
1477 break;
1478 case OpalMediaFormat::DefaultFileSessionID:
1479 default:
1480 num = SetCapability(descriptorNum, simultaneous, capability);
1481 break;
1482 }
1483
1484 if (descriptorNum == P_MAX_INDEX) {
1485 reply = num;
1486 descriptorNum = num;
1487 simultaneous = P_MAX_INDEX;
1488 }
1489 else if (simultaneous == P_MAX_INDEX) {
1490 if (reply == P_MAX_INDEX)
1491 reply = num;
1492 simultaneous = num;
1493 }
1494 }
1495 }
1496 }
1497 simultaneous = P_MAX_INDEX;
1498 }
1499
1500 return reply;
1501 }
1502
SetDHKeyPair(const PStringList & keyOIDs,H235_DiffieHellman * key,PBoolean isMaster)1503 void H235Capabilities::SetDHKeyPair(const PStringList & keyOIDs, H235_DiffieHellman * key, PBoolean isMaster)
1504 {
1505 m_algorithms.SetSize(0);
1506 for (PINDEX i=0; i < keyOIDs.GetSize(); ++i)
1507 m_algorithms.AppendString(keyOIDs[i]);
1508
1509 m_DHkey = key;
1510 m_h245Master = isMaster;
1511
1512 PTRACE(2,"H235\tDiffieHellman selected. Key " << (isMaster ? "Master" : "Slave"));
1513
1514 }
1515
GetDHKeyPair(PStringList & keyOIDs,H235_DiffieHellman * & key,PBoolean & isMaster)1516 void H235Capabilities::GetDHKeyPair(PStringList & keyOIDs, H235_DiffieHellman * & key, PBoolean & isMaster)
1517 {
1518 for (PINDEX i=0; i < m_algorithms.GetSize(); ++i)
1519 keyOIDs.AppendString(m_algorithms[i]);
1520
1521 if (m_DHkey)
1522 key = m_DHkey;
1523
1524 isMaster = m_h245Master;
1525 }
1526
GetAlgorithms(const PStringList & algorithms) const1527 PBoolean H235Capabilities::GetAlgorithms(const PStringList & algorithms) const
1528 {
1529 PStringList * m_localAlgorithms = PRemoveConst(PStringList,&algorithms);
1530 m_localAlgorithms->SetSize(0);
1531 for (PINDEX i=0; i < m_algorithms.GetSize(); ++i)
1532 m_localAlgorithms->AppendString(m_algorithms[i]);
1533
1534 return (algorithms.GetSize() > 0);
1535 }
1536
SetH235Codecs(const PStringArray & servers)1537 void H235Capabilities::SetH235Codecs(const PStringArray & servers)
1538 {
1539 PWaitAndSignal m(GetH235CodecsMutex());
1540 GetH235Codecs() = servers;
1541 }
1542
IsH235Codec(const PString & name)1543 PBoolean H235Capabilities::IsH235Codec(const PString & name)
1544 {
1545 PStringArray codecs = GetH235Codecs();
1546
1547 if ((codecs.GetSize() == 0) || (codecs[0] *= "all"))
1548 return true;
1549
1550 for (PINDEX i=0; i<codecs.GetSize(); ++i) {
1551 if (name.Find(codecs[i]) != P_MAX_INDEX)
1552 return true;
1553 }
1554 return false;
1555 }
1556
1557 #endif
1558
1559