Coverage Report

Created: 2026-02-14 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/resiprocate/resip/stack/Helper.hxx
Line
Count
Source
1
#if !defined(RESIP_HELPER_HXX)
2
#define RESIP_HELPER_HXX 
3
4
#include <time.h>
5
#include <vector>
6
7
#include "resip/stack/NonceHelper.hxx"
8
#include "resip/stack/Symbols.hxx"
9
#include "resip/stack/Uri.hxx"
10
#include "resip/stack/MethodTypes.hxx"
11
#include "rutil/BaseException.hxx"
12
#include "rutil/Data.hxx"
13
#include "rutil/DigestStream.hxx"
14
#include "resip/stack/Contents.hxx"
15
#include "resip/stack/SecurityAttributes.hxx"
16
#include "resip/stack/SdpContents.hxx"
17
18
namespace resip
19
{
20
21
class SipMessage;
22
class NameAddr;
23
class SecurityAttributes;
24
class Security;
25
26
27
/**
28
   @ingroup resip_crit
29
   @brief An aggregation of useful static functions.
30
31
   These are mostly involved with
32
      - The manufacture of SIP messages (requests and responses). This is of 
33
      particular importance to app-writers.
34
      - Digest auth related functions.
35
*/
36
class Helper
37
{
38
   public:
39
40
      /// bytes in to-tag& from-tag, should prob. live somewhere else
41
      const static int tagSize;
42
43
      /** 
44
          Used by Registration, Publication and Subscription refreshes, to
45
          calculate the time at which a refresh should be performed (which
46
          is some time, that is a bit smaller than the Expiration interval).
47
          The recommended calculation from the RFC's is the minimnum of the 
48
          Exipiration interval less 5 seconds and nine tenths of the exipiration 
49
          interval.
50
      */
51
      template<typename T>
52
      static T aBitSmallerThan(T secs)
53
      {
54
         return resipMax(T(0), resipMin(T(secs-5), T(9*secs/10)));
55
      }
56
57
      /** 
58
          Converts an interger in a character string containing the
59
          hexidecimal representation of the integer.  Note:  The 
60
          string buffer provided should be at least 8 characters long.
61
          This function will NOT NULL terminate the string.
62
63
          @param _d     A pointer to the character buffer to write
64
                        the hex string
65
66
          @param _s     The integer value to convert.
67
68
          @param _l     Boolean flag to include leading 0 zeros or 
69
                        not.
70
      */
71
      static void integer2hex(char* _d, unsigned int _s, bool _l = true);
72
73
      /** 
74
          Converts a character string containing a hexidecimal value
75
          into an unsigned int.  Note:  Parsing stops after the first
76
          non-hex character, or after 8 characters have been processed.
77
78
          @param _s     A pointer to the character buffer to convert.
79
80
          @returns      The integer value of the coverted hex string.
81
      */
82
      static unsigned int hex2integer(const char* _s);
83
84
      /**
85
           Used to jitter the expires in a SUBSCRIBE or REGISTER expires header
86
87
           @param input            Value to jitter
88
89
           @param lowerPercentage  The lower range of the random percentage by which 
90
                                   to jitter the value by.
91
92
           @param upperPercentage  The upper range of the random percentage by which
93
                                   to jitter the value by.  Must be greater than or equal 
94
                                   to lowerPercentage
95
96
           @param minimum          Only jitter the input if greater than minimum
97
       */
98
      static int jitterValue(int input, int lowerPercentage, int upperPercentage, int minimum=0);
99
100
101
      /// ///////////////////////////////////////////////////////////////////////////////////////////
102
      ///
103
      /// SIP Message Helpers
104
      ///
105
      /// ///////////////////////////////////////////////////////////////////////////////////////////
106
107
      /**
108
          Make a new request with a overridden Contact.  To, maxforward=70, requestline
109
          created, cseq method set, cseq sequence is 1, from and from tag set, contact
110
          set, CallId created.  Caller owns the returned pointer and is responsible for
111
          deleting it.
112
113
          @note While contact is only necessary for requests that establish a dialog,
114
                those are the requests most likely created by this method, others will
115
                be generated by the dialog.
116
117
          @param target Ends up in the RequestURI and To header
118
119
          @param from   Ends up in the From header
120
121
          @param contact Ends up in the Contact header.  Stack will not change this
122
                         when sent.
123
124
          @param method Type of request to create.  Methos is used in the Request Line
125
                        and the CSeq.
126
127
          @returns SipMessage request created.  Caller must deallocate.
128
      */
129
      static SipMessage* makeRequest(const NameAddr& target, const NameAddr& from, const NameAddr& contact, MethodTypes method);
130
131
      /**
132
          Make a new request.  To, maxforward=70, requestline created, cseq method set,
133
          cseq sequence is 1, from and from tag set, CallId created.  Caller owns the
134
          returned pointer and is responsible for deleting it.
135
136
          @note An empty contact header is added.  This signals to the stack that it
137
                should be populated by the transports when sent.
138
139
          @param target Ends up in the RequestURI and To header
140
141
          @param from   Ends up in the From header
142
143
          @param method Type of request to create.  Methos is used in the Request Line
144
                        and the CSeq.
145
146
          @returns SipMessage request created.  Caller must deallocate.
147
      */
148
      static SipMessage* makeRequest(const NameAddr& target, const NameAddr& from, MethodTypes method);
149
150
      /// Create a Register request with an empty Contact.  See makeRequest.
151
      static SipMessage* makeRegister(const NameAddr& to, const NameAddr& from);
152
153
      /// Create a Register request with an overriden Contact.  See makeRequest.
154
      static SipMessage* makeRegister(const NameAddr& to, const NameAddr& from, const NameAddr& contact);
155
156
      /// Create a Register request with an empty Contact, transport is added to Request URI.  See makeRequest.
157
      static SipMessage* makeRegister(const NameAddr& to, const Data& transport);
158
159
      /// Create a Register request with an overriden Contact, transport is added to Request URI.  See makeRequest.
160
      static SipMessage* makeRegister(const NameAddr& to, const Data& transport, const NameAddr& contact);
161
162
      /**
163
          Make an invite request - Empty Contact and Via is added and will be populated 
164
          by the stack when sent.
165
            
166
          @param target Ends up in the RequestURI and To header
167
168
          @param from   Ends up in the From header
169
      */
170
      static SipMessage* makeInvite(const NameAddr& target, const NameAddr& from);
171
      
172
      /**
173
          Make an invite request using a overridden contact header - Empty Via is added 
174
          and will be populated by the stack when sent.
175
            
176
          @param target Ends up in the RequestURI and To header
177
178
          @param from   Ends up in the From header
179
180
          @param contact Ends up in the Contact header.  Stack will not change this
181
                         when sent.
182
      */
183
      static SipMessage* makeInvite(const NameAddr& target, const NameAddr& from, const NameAddr& contact);
184
185
      /**
186
          Make a new Cancel request for the specified request.  Caller owns the
187
          returned pointer and is responsible for deleting it.
188
189
          @param request Request for which the Cancel will apply. ie. Invite request.
190
191
          @returns Created Cancel request.  Caller must deallocate.
192
      */
193
      static SipMessage* makeCancel(const SipMessage& request);
194
195
      /**
196
          This interface should be used by the stack (TransactionState) to create an
197
          AckMsg to a failure response.  See RFC3261 section 17.1.1.3.  Caller owns the
198
          returned pointer and is responsible for deleting it.
199
200
          @note The branch in this ACK needs to be the one from the request.
201
                For TU generated ACK, see Dialog::makeAck(...)
202
203
          @param request Request that this ACK applies to.
204
205
          @param response Response that we are ACKing - required so that we can get the To tag
206
                          into the generated ACK.
207
208
          @returns Created Ack request.  Caller must deallocate.
209
       */
210
      static SipMessage* makeFailureAck(const SipMessage& request, const SipMessage& response);
211
212
      /// Create a Publish request with an empty Contact.  See makeRequest.
213
      static SipMessage* makePublish(const NameAddr& target, const NameAddr& from);
214
215
      /// Create a Publish request with an overriden Contact.  See makeRequest.
216
      static SipMessage* makePublish(const NameAddr& target, const NameAddr& from, const NameAddr& contact);
217
218
      /// Create a Message request with an empty Contact.  See makeRequest.
219
      static SipMessage* makeMessage(const NameAddr& target, const NameAddr& from);
220
221
      /// Create a Message request with an overriden Contact.  See makeRequest.
222
      static SipMessage* makeMessage(const NameAddr& target, const NameAddr& from, const NameAddr& contact);
223
224
      /// Create a Subscribe request with an empty Contact.  See makeRequest.
225
      static SipMessage* makeSubscribe(const NameAddr& target, const NameAddr& from);
226
227
      /// Create a Subscribe request with an overriden Contact.  See makeRequest.
228
      static SipMessage* makeSubscribe(const NameAddr& target, const NameAddr& from, const NameAddr& contact);
229
230
      /**
231
          Make a response to a provided request.  Adds a To tag, Contact and Record-Route
232
          headers appropriately.
233
            
234
          @param response SipMessage populated with the appropriate response
235
236
          @param request  SipMessage request from which to generate the response
237
238
          @param responseCode Response code to use on status line.
239
240
          @param reason   Optional reason string to use on status line.  If not provided
241
                          then a default reason string will be added for well defined
242
                          response codes.
243
244
          @param hostname Optional hostname to use in Warning header.  Only used if
245
                          warning is also provided.
246
247
          @param warning  Optional warning text.  If present a Warning header is added
248
                          and hostname is used in warning header.
249
      */
250
      static void makeResponse(SipMessage& response, 
251
                               const SipMessage& request, 
252
                               int responseCode, 
253
                               const Data& reason = Data::Empty,
254
                               const Data& hostname = Data::Empty,
255
                               const Data& warning=Data::Empty);
256
257
      /**
258
          Make a response to a provided request with an overridden Contact.  
259
          Adds a To tag, Contact and Record-Route headers appropriately.
260
            
261
          @param response SipMessage populated with the appropriate response
262
263
          @param request  SipMessage request from which to generate the response
264
265
          @param responseCode Response code to use on status line.
266
267
          @param myContact Contact header to add to response.
268
269
          @param reason   Optional reason string to use on status line.  If not provided
270
                          then a default reason string will be added for well defined
271
                          response codes.
272
273
          @param hostname Optional hostname to use in Warning header.  Only used if
274
                          warning is also provided.
275
276
          @param warning  Optional warning text.  If present a Warning header is added
277
                          and hostname is used in warning header.
278
      */
279
      static void makeResponse(SipMessage& response, 
280
                               const SipMessage& request, 
281
                               int responseCode, 
282
                               const NameAddr& myContact, 
283
                               const Data& reason = Data::Empty,
284
                               const Data& hostname = Data::Empty,
285
                               const Data& warning=Data::Empty);
286
287
      /**
288
          Make a new response to a provided request.  Adds a To tag, Contact and 
289
          Record-Route headers appropriately.  Caller owns the returned pointer and
290
          is responsible for deleting it.
291
            
292
          @param request  SipMessage request from which to generate the response
293
294
          @param responseCode Response code to use on status line.
295
296
          @param reason   Optional reason string to use on status line.  If not provided
297
                          then a default reason string will be added for well defined
298
                          response codes.
299
300
          @param hostname Optional hostname to use in Warning header.  Only used if
301
                          warning is also provided.
302
303
          @param warning  Optional warning text.  If present a Warning header is added
304
                          and hostname is used in warning header
305
306
          @returns SipMessage populated with the appropriate response.
307
                   Caller must deallocate.
308
      */
309
      static SipMessage* makeResponse(const SipMessage& request,
310
                                      int responseCode,
311
                                      const Data& reason = Data::Empty, 
312
                                      const Data& hostname = Data::Empty,
313
                                      const Data& warning=Data::Empty);
314
315
      /**
316
          Make a new response to a provided request with an overridden Contact.  
317
          Adds a To tag, Contact and Record-Route headers appropriately.
318
          Caller owns the returned pointer and is responsible for deleting it.
319
320
          @param request  SipMessage request from which to generate the response
321
322
          @param responseCode Response code to use on status line.
323
324
          @param myContact Contact header to add to response.
325
326
          @param reason   Optional reason string to use on status line.  If not provided
327
                          then a default reason string will be added for well defined
328
                          response codes.
329
330
          @param hostname Optional hostname to use in Warning header.  Only used if
331
                          warning is also provided.
332
333
          @param warning  Optional warning text.  If present a Warning header is added
334
                          and hostname is used in warning header.
335
336
          @returns SipMessage populated with the appropriate response.
337
                   Caller must deallocate.
338
      */
339
      static SipMessage* makeResponse(const SipMessage& request, 
340
                                      int responseCode, 
341
                                      const NameAddr& myContact, 
342
                                      const Data& reason = Data::Empty,
343
                                      const Data& hostname = Data::Empty,
344
                                      const Data& warning=Data::Empty);
345
346
      static void makeRawResponse(Data& rawBuffer,
347
                                    const SipMessage& request, 
348
                                    int responseCode,
349
                                    const Data& additionalHeaders=Data::Empty,
350
                                    const Data& body=Data::Empty);
351
352
      /**
353
          Make a 405 response to a provided request.  Allows header is added
354
          with specified methods, or with all methods the stack knows about.
355
          Caller owns the returned pointer and is responsible for deleting it.
356
357
          @param request  SipMessage request from which to generate the response
358
359
          @param allowedMethods Array of integers representing a list of Method 
360
                                Types to add to the generated Allows header. 
361
                                See MethodTypes.hxx.
362
363
          @param nMethods Number of methods specified in the allowedMethods 
364
                          integer array.  Specify -1 to have this method fill
365
                          in the Allows header automatically with each method
366
                          supported by the stack.
367
368
          @returns SipMessage populated with the appropriate response.    
369
                   Caller must deallocate.
370
      */
371
      static SipMessage* make405(const SipMessage& request,
372
                                 const int* allowedMethods = 0,
373
                                 int nMethods = -1);
374
375
      /**
376
          Returns the default reason string for a particular response code.
377
378
          @param responseCode  Response code to get reason for
379
380
          @param reason Data where the reason string associated with the 
381
                   responseCode will be set.
382
      */
383
      static void getResponseCodeReason(int responseCode, Data& reason);
384
385
      /** 
386
          Creates and returns a unique branch parameter.  Generated branch will contain
387
          the RFC3261 magic cookie + 4 randome hex characters + "C1" + 2 random hex characters.
388
389
          @deprecated Not used by stack.
390
      */
391
      static Data computeUniqueBranch();
392
393
      static Data computeCallId();
394
      static Data computeTag(int numBytes);
395
396
397
      /// ///////////////////////////////////////////////////////////////////////////////////////////
398
      ///
399
      /// Digest Authentication Helpers
400
      ///
401
      /// ///////////////////////////////////////////////////////////////////////////////////////////
402
      
403
      /// Note: Helper assumes control of NonceHelper object and will delete when global scope is cleaned up
404
      static void setNonceHelper(NonceHelper* nonceHelper);
405
      static NonceHelper* getNonceHelper();
406
      static Data makeNonce(const SipMessage& request, const Data& timestamp);
407
408
      // returns true if the digest scheme is supported, and sets digestType
409
      static bool isDigestAlgorithmSupported(const Auth& auth, DigestType& digestType);
410
      static bool isDigestAlgorithmSupported(const Data& algorithmName, DigestType& digestType);
411
412
      // Create a custom A1 string (applicable for password storage, that supports multiple digest algorithms)
413
      // Format: [<algorithm_name>]<hex_encoded_A1_hash>[<algorithm2_name>]<hex_encoded_A1_hash2>....
414
      // Example: [MD5]5f4dcc3b5aa765d61d8327deb882cf99[SHA-256]6bb4837eb74329105ee4568dda7dc67ed2ca2ad9e59fcbfbcde5e7f8c1b6d9d1
415
      // For backward compatibility, if no algorithm name is found, MD5 is assumed.
416
      static Data createResipA1HashString(const Data& username,
417
                                          const Data& realm,
418
                                          const Data& password);
419
      // Extract the algorithm specific A1 hash from a custom resip A1 hash string. Returns empty string if hash 
420
      // algorithm not found in string.
421
      static Data extractA1FromResipA1HashString(const Data& resipA1HashString, DigestType digestType);
422
      static bool isDigestTypeSupportedInResipA1HashString(const Data& resipA1HashString, DigestType digestType);
423
424
      enum AuthResult { Failed = 1, Authenticated, Expired, BadlyFormed };
425
      static AuthResult authenticateRequest(const SipMessage& request,
426
                                            const Data& realm,
427
                                            const Data& password,
428
                                            int expiresDelta = 0);
429
430
      static AuthResult authenticateRequestWithA1(const SipMessage& request, 
431
                                                  const Data& realm,
432
                                                  const Data& resipPasswordHashA1,
433
                                                  int expiresDelta = 0);
434
435
      static AuthResult authenticateRequest(const SipMessage& request, 
436
                                            const Data& realm,
437
                                            const Data& passwordOrResipPasswordHashA1,
438
                                            int expiresDelta,
439
                                            bool isPasswordHashResipA1);
440
441
      // Only looks a Proxy-Authorization or Authorization header based on proxyAuthorization flag
442
      // Returns username in std::pair second if authentication is successful
443
      static std::pair<AuthResult, Data> advancedAuthenticateRequest(const SipMessage& request,
444
                                                                     const Data& realm,
445
                                                                     const Data& resipPasswordHashA1,
446
                                                                     int expiresDelta = 0,
447
                                                                     bool proxyAuthorization = true);
448
449
      // create a 407 response with Proxy-Authenticate header filled in
450
      static SipMessage* makeProxyChallenge(const SipMessage& request, 
451
                                            const Data& realm,
452
                                            bool useAuth = true,
453
                                            bool stale = false,
454
                                            const std::vector<DigestType>& digestTypes = std::vector<DigestType>());
455
456
      // create a 401 response with WWW-Authenticate header filled in
457
      static SipMessage* makeWWWChallenge(const SipMessage& request, 
458
                                          const Data& realm,
459
                                          bool useAuth = true,
460
                                          bool stale = false,
461
                                          const std::vector<DigestType>& digestTypes = std::vector<DigestType>());
462
463
      // create a 401 or 407 response with Proxy-Authenticate or Authenticate header 
464
      // filled in
465
      static SipMessage* makeChallenge(const SipMessage& request, 
466
                                       const Data& realm,
467
                                       bool useAuth = true,
468
                                       bool stale = false,
469
                                       bool proxy = false,
470
                                       const std::vector<DigestType>& digestTypes = std::vector<DigestType>());
471
472
      // add an additional Proxy-Authenticate or WWW-Authenticate header to an existing response
473
      static void addChallenge(SipMessage& response,
474
                               const SipMessage& request,
475
                               const Data& realm,
476
                               bool useAuth = true,
477
                               bool stale = false,
478
                               bool proxy = false,
479
                               DigestType digestType = MD5);
480
481
      static Data qopOption(const Auth& challenge);
482
      static void updateNonceCount(unsigned int& nonceCount, Data& nonceCountString);
483
484
      //Used by clients to determine if they can respond to a given challenge
485
      static bool algorithmAndQopSupported(const Auth& challenge);
486
      static bool algorithmAndQopSupported(const Auth& challenge, DigestType& digestType);
487
488
      // adds authorization headers in reponse to the 401 or 407
489
      static SipMessage& addAuthorization(SipMessage& request,
490
                                          const SipMessage& challenge,
491
                                          const Data& username,
492
                                          const Data& password,
493
                                          const Data& cnonce,
494
                                          unsigned int& nonceCount);
495
496
      static Auth makeChallengeResponseAuth(const SipMessage& request,
497
                                            const Data& username,
498
                                            const Data& password,
499
                                            const Auth& challenge,
500
                                            const Data& cnonce,
501
                                            unsigned int& nonceCount,
502
                                            Data& nonceCountString);
503
504
      static void makeChallengeResponseAuth(const SipMessage& request,
505
                                            const Data& username,
506
                                            const Data& password,
507
                                            const Auth& challenge,
508
                                            const Data& cnonce,
509
                                            const Data& authQop,
510
                                            const Data& nonceCountString,
511
                                            Auth& auth);
512
513
      static Auth makeChallengeResponseAuthWithA1(const SipMessage& request,
514
                                                  const Data& username,
515
                                                  const Data& resipPasswordHashA1,
516
                                                  const Auth& challenge,
517
                                                  const Data& cnonce,
518
                                                  unsigned int& nonceCount,
519
                                                  Data& nonceCountString);
520
521
      static void makeChallengeResponseAuthWithA1(const SipMessage& request,
522
                                                  const Data& username,
523
                                                  const Data& resipPasswordHashA1,
524
                                                  const Auth& challenge,
525
                                                  const Data& cnonce,
526
                                                  const Data& authQop,
527
                                                  const Data& nonceCountString,
528
                                                  Auth& auth);
529
530
      // Backwards compatiblity (legacy API)
531
      static Data makeResponseMD5WithA1(const Data& a1,
532
                                        const Data& method, const Data& digestUri, const Data& nonce,
533
                                        const Data& qop = Data::Empty, const Data& cnonce = Data::Empty, 
534
                                        const Data& cnonceCount = Data::Empty, const Contents *entityBody = 0)
535
0
      {
536
0
         return makeResponseDigestWithA1(a1, method, digestUri, nonce, qop, cnonce, cnonceCount, entityBody, MD5);
537
0
      }
538
539
      static Data makeResponseDigestWithA1(const Data& a1,
540
                                           const Data& method, const Data& digestUri, const Data& nonce,
541
                                           const Data& qop = Data::Empty, const Data& cnonce = Data::Empty,
542
                                           const Data& cnonceCount = Data::Empty, const Contents* entityBody = 0,
543
                                           DigestType digestType = MD5);
544
545
      // Backwards compatiblity (legacy API)
546
      static Data makeResponseMD5(const Data& username, const Data& password, const Data& realm, 
547
                                  const Data& method, const Data& digestUri, const Data& nonce,
548
                                  const Data& qop = Data::Empty, const Data& cnonce = Data::Empty, 
549
                                  const Data& cnonceCount = Data::Empty, const Contents *entityBody = 0)
550
0
      {
551
0
         return makeResponseDigest(username, password, realm, method, digestUri, nonce, qop, cnonce, cnonceCount, entityBody, MD5);
552
0
      }
553
554
      static Data makeResponseDigest(const Data& username, const Data& password, const Data& realm, 
555
                                     const Data& method, const Data& digestUri, const Data& nonce,
556
                                     const Data& qop = Data::Empty, const Data& cnonce = Data::Empty, 
557
                                     const Data& cnonceCount = Data::Empty, const Contents *entityBody = 0,
558
                                     DigestType digestType = MD5);
559
560
561
      /// ///////////////////////////////////////////////////////////////////////////////////////////
562
      ///
563
      /// Miscellaneous Helpers
564
      ///
565
      /// ///////////////////////////////////////////////////////////////////////////////////////////
566
567
      static Uri makeUri(const Data& aor, const Data& scheme=Symbols::DefaultSipScheme);
568
569
      static void processStrictRoute(SipMessage& request);
570
571
      // return the port that the response should be sent to using rules from 
572
      // RFC 3261 - 18.2.2
573
      static int getPortForReply(SipMessage& request);
574
575
      static void massageRoute(const SipMessage& request, NameAddr& route);
576
577
      static Uri fromAor(const Data& aor, const Data& scheme=Symbols::DefaultSipScheme);
578
579
      // Do basic checks to validate a received message off the wire
580
      // If the basic check fails, and reason is non-null, reason will be set
581
      // to the reason the check failed. This function does not take ownership
582
      // of reason.
583
      static bool validateMessage(const SipMessage& message,resip::Data* reason=0);
584
585
      // GRUU support -- reversibly and opaquely combine instance id and aor
586
      static Data gruuUserPart(const Data& instanceId,
587
                               const Data& aor,
588
                               const Data& key);
589
590
      // GRUU support -- extract instance id and aor from user portion
591
      static std::pair<Data,Data> fromGruuUserPart(const Data& gruuUserPart,
592
                                                   const Data& key);
593
594
      struct ContentsSecAttrs
595
      {
596
            ContentsSecAttrs() = default;
597
            ContentsSecAttrs(std::unique_ptr<Contents> contents,
598
                             std::unique_ptr<SecurityAttributes> attributes);
599
            ContentsSecAttrs(const ContentsSecAttrs&) = delete;
600
            ContentsSecAttrs(ContentsSecAttrs&&) = default;
601
            ~ContentsSecAttrs() = default;
602
603
            ContentsSecAttrs& operator=(const ContentsSecAttrs&) = delete;
604
            ContentsSecAttrs& operator=(ContentsSecAttrs&&) = default;
605
606
            mutable std::unique_ptr<Contents> mContents;
607
            mutable std::unique_ptr<SecurityAttributes> mAttributes;
608
      };
609
610
      static ContentsSecAttrs extractFromPkcs7(const SipMessage& message, Security& security);
611
612
      
613
      enum FailureMessageEffect{ DialogTermination, TransactionTermination, UsageTermination, 
614
                                 RetryAfter, OptionalRetryAfter, ApplicationDependant };
615
      
616
      static FailureMessageEffect determineFailureMessageEffect(const SipMessage& response,
617
          const std::set<int>* additionalTransactionTerminatingResponses = NULL);
618
619
      // Just simply walk the contents tree and return the first SdpContents in
620
      // the tree.
621
      static std::unique_ptr<SdpContents> getSdp(Contents* tree);
622
623
      /** Looks at SIP headers and message source for a mismatch to make an
624
          assumption that the sender is behind a NAT device.
625
626
          @param request Request message that we use for checking.
627
628
          @privateToPublicOnly If enabled then we ensure that the via is private
629
                               address and that the source was a public address.
630
                               This allows us to ignore cases of private-private NAT'ing
631
                               or false detections, when a server behind a load balancer
632
                               is sending us requests and using the load balancer address
633
                               in the Via, instead of the real of the adapter.
634
      */
635
      static bool isClientBehindNAT(const SipMessage& request, bool privateToPublicOnly=true);
636
637
      /** Look at Via headers, and find the first public IP address closest to the sending
638
          client.
639
640
          @param request Request message that we use for checking.
641
642
          @note If no public IP's are found, then an empty Tuple is returned.  This
643
                can be tested by checking if Tuple::getType() returns UNKNOWN_TRANSPORT.
644
      */
645
      static Tuple getClientPublicAddress(const SipMessage& request);
646
647
   private:
648
      class NonceHelperPtr
649
      {
650
         public:
651
2
            NonceHelperPtr() : mNonceHelper(0) {}
652
0
            ~NonceHelperPtr() { delete mNonceHelper; }
653
            NonceHelper *mNonceHelper;
654
      };
655
      static NonceHelperPtr mNonceHelperPtr;
656
};
657
658
}
659
660
#endif
661
662
/* ====================================================================
663
 * The Vovida Software License, Version 1.0 
664
 * 
665
 * Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
666
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
667
 * 
668
 * Redistribution and use in source and binary forms, with or without
669
 * modification, are permitted provided that the following conditions
670
 * are met:
671
 * 
672
 * 1. Redistributions of source code must retain the above copyright
673
 *    notice, this list of conditions and the following disclaimer.
674
 * 
675
 * 2. Redistributions in binary form must reproduce the above copyright
676
 *    notice, this list of conditions and the following disclaimer in
677
 *    the documentation and/or other materials provided with the
678
 *    distribution.
679
 * 
680
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
681
 *    and "Vovida Open Communication Application Library (VOCAL)" must
682
 *    not be used to endorse or promote products derived from this
683
 *    software without prior written permission. For written
684
 *    permission, please contact vocal@vovida.org.
685
 *
686
 * 4. Products derived from this software may not be called "VOCAL", nor
687
 *    may "VOCAL" appear in their name, without prior written
688
 *    permission of Vovida Networks, Inc.
689
 * 
690
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
691
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
692
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
693
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
694
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
695
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
696
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
697
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
698
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
699
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
700
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
701
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
702
 * DAMAGE.
703
 * 
704
 * ====================================================================
705
 * 
706
 * This software consists of voluntary contributions made by Vovida
707
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
708
 * Inc.  For more information on Vovida Networks, Inc., please see
709
 * <http://www.vovida.org/>.
710
 *
711
 */