1 #include <cassert>
2 #include <cstring>
3 #include <iostream>
4 #include <cstdlib>
5 #include <errno.h>
6 
7 #ifdef WIN32
8 #include <winsock2.h>
9 #include <stdlib.h>
10 #include <io.h>
11 #include <time.h>
12 #else
13 
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <sys/ioctl.h>
18 #include <sys/socket.h>
19 #include <sys/time.h>
20 #include <sys/types.h>
21 #include <arpa/inet.h>
22 #include <fcntl.h>
23 #include <netdb.h>
24 #include <netinet/in.h>
25 #include <arpa/nameser.h>
26 #include <resolv.h>
27 #include <net/if.h>
28 
29 #endif
30 
31 
32 #if defined(__sparc__) || defined(WIN32)
33 #define NOSSL
34 #endif
35 #define NOSSL
36 
37 #include "udp.h"
38 #include "stun.h"
39 
40 
41 using namespace std;
42 
43 
44 static void
45 computeHmac(char* hmac, const char* input, int length, const char* key, int keySize);
46 
47 static bool
stunParseAtrAddress(char * body,unsigned int hdrLen,StunAtrAddress4 & result)48 stunParseAtrAddress( char* body, unsigned int hdrLen,  StunAtrAddress4& result )
49 {
50    if ( hdrLen != 8 )
51    {
52       clog << "hdrLen wrong for Address" <<endl;
53       return false;
54    }
55    result.pad = *body++;
56    result.family = *body++;
57    if (result.family == IPv4Family)
58    {
59       UInt16 nport;
60       memcpy(&nport, body, 2); body+=2;
61       result.ipv4.port = ntohs(nport);
62 
63       UInt32 naddr;
64       memcpy(&naddr, body, 4); body+=4;
65       result.ipv4.addr = ntohl(naddr);
66       return true;
67    }
68    else if (result.family == IPv6Family)
69    {
70       clog << "ipv6 not supported" << endl;
71    }
72    else
73    {
74       clog << "bad address family: " << result.family << endl;
75    }
76 
77    return false;
78 }
79 
80 static bool
stunParseAtrChangeRequest(char * body,unsigned int hdrLen,StunAtrChangeRequest & result)81 stunParseAtrChangeRequest( char* body, unsigned int hdrLen,  StunAtrChangeRequest& result )
82 {
83    if ( hdrLen != 4 )
84    {
85       clog << "hdr length = " << hdrLen << " expecting " << sizeof(result) << endl;
86 
87       clog << "Incorrect size for ChangeRequest" << endl;
88       return false;
89    }
90    else
91    {
92       memcpy(&result.value, body, 4);
93       result.value = ntohl(result.value);
94       return true;
95    }
96 }
97 
98 static bool
stunParseAtrError(char * body,unsigned int hdrLen,StunAtrError & result)99 stunParseAtrError( char* body, unsigned int hdrLen,  StunAtrError& result )
100 {
101    if ( hdrLen >= sizeof(result) )
102    {
103       clog << "head on Error too large" << endl;
104       return false;
105    }
106    else
107    {
108       memcpy(&result.pad, body, 2); body+=2;
109       result.pad = ntohs(result.pad);
110       result.errorClass = *body++;
111       result.number = *body++;
112 
113       result.sizeReason = hdrLen - 4;
114       memcpy(&result.reason, body, result.sizeReason);
115       result.reason[result.sizeReason] = 0;
116       return true;
117    }
118 }
119 
120 static bool
stunParseAtrUnknown(char * body,unsigned int hdrLen,StunAtrUnknown & result)121 stunParseAtrUnknown( char* body, unsigned int hdrLen,  StunAtrUnknown& result )
122 {
123    if ( hdrLen >= sizeof(result) )
124    {
125       return false;
126    }
127    else
128    {
129       if (hdrLen % 4 != 0) return false;
130       result.numAttributes = hdrLen / 4;
131       for (int i=0; i<result.numAttributes; i++)
132       {
133          memcpy(&result.attrType[i], body, 2); body+=2;
134          result.attrType[i] = ntohs(result.attrType[i]);
135       }
136       return true;
137    }
138 }
139 
140 
141 static bool
stunParseAtrString(char * body,unsigned int hdrLen,StunAtrString & result)142 stunParseAtrString( char* body, unsigned int hdrLen,  StunAtrString& result )
143 {
144    if ( hdrLen >= STUN_MAX_STRING )
145    {
146       clog << "String is too large" << endl;
147       return false;
148    }
149    else
150    {
151       if (hdrLen % 4 != 0)
152       {
153          clog << "Bad length string " << hdrLen << endl;
154          return false;
155       }
156 
157       result.sizeValue = hdrLen;
158       memcpy(&result.value, body, hdrLen);
159       result.value[hdrLen] = 0;
160       return true;
161    }
162 }
163 
164 
165 static bool
stunParseAtrIntegrity(char * body,unsigned int hdrLen,StunAtrIntegrity & result)166 stunParseAtrIntegrity( char* body, unsigned int hdrLen,  StunAtrIntegrity& result )
167 {
168    if ( hdrLen != 20)
169    {
170       clog << "MessageIntegrity must be 20 bytes" << endl;
171       return false;
172    }
173    else
174    {
175       memcpy(&result.hash, body, hdrLen);
176       return true;
177    }
178 }
179 
180 
181 bool
stunParseMessage(char * buf,unsigned int bufLen,StunMessage & msg,bool verbose)182 stunParseMessage( char* buf, unsigned int bufLen, StunMessage& msg, bool verbose)
183 {
184    if (verbose) clog << "Received stun message: " << bufLen << " bytes" << endl;
185    memset(&msg, 0, sizeof(msg));
186 
187    if (sizeof(StunMsgHdr) > bufLen)
188    {
189       clog << "Bad message" << endl;
190       return false;
191    }
192 
193    memcpy(&msg.msgHdr, buf, sizeof(StunMsgHdr));
194    msg.msgHdr.msgType = ntohs(msg.msgHdr.msgType);
195    msg.msgHdr.msgLength = ntohs(msg.msgHdr.msgLength);
196 
197    if (msg.msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen)
198    {
199       clog << "Message header length doesn't match message size: "
200            << msg.msgHdr.msgLength << " - " << bufLen << endl;
201       return false;
202    }
203 
204    char* body = buf + sizeof(StunMsgHdr);
205    unsigned int size = msg.msgHdr.msgLength;
206 
207    //clog << "bytes after header = " << size << endl;
208 
209    while ( size > 0 )
210    {
211       // !jf! should check that there are enough bytes left in the buffer
212 
213       StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>(body);
214 
215       unsigned int attrLen = ntohs(attr->length);
216       int atrType = ntohs(attr->type);
217 
218       //if (verbose) clog << "Found attribute type=" << AttrNames[atrType] << " length=" << attrLen << endl;
219       if ( attrLen+4 > size )
220       {
221          clog << "claims attribute is larger than size of message "
222               <<"(attribute type="<<atrType<<")"<< endl;
223          return false;
224       }
225 
226       body += 4; // skip the length and type in attribute header
227       size -= 4;
228 
229       switch ( atrType )
230       {
231          case MappedAddress:
232             msg.hasMappedAddress = true;
233             if ( stunParseAtrAddress(  body,  attrLen,  msg.mappedAddress )== false )
234             {
235                clog << "problem parsing MappedAddress" << endl;
236                return false;
237             }
238             else
239             {
240                if (verbose) clog << "MappedAddress = " << msg.mappedAddress.ipv4 << endl;
241             }
242 
243             break;
244 
245          case ResponseAddress:
246             msg.hasResponseAddress = true;
247             if ( stunParseAtrAddress(  body,  attrLen,  msg.responseAddress )== false )
248             {
249                clog << "problem parsing ResponseAddress" << endl;
250                return false;
251             }
252             else
253             {
254                if (verbose) clog << "ResponseAddress = " << msg.responseAddress.ipv4 << endl;
255             }
256             break;
257 
258          case ChangeRequest:
259             msg.hasChangeRequest = true;
260             if (stunParseAtrChangeRequest( body, attrLen, msg.changeRequest) == false)
261             {
262                clog << "problem parsing ChangeRequest" << endl;
263                return false;
264             }
265             else
266             {
267                if (verbose) clog << "ChangeRequest = " << msg.changeRequest.value << endl;
268             }
269             break;
270 
271          case SourceAddress:
272             msg.hasSourceAddress = true;
273             if ( stunParseAtrAddress(  body,  attrLen,  msg.sourceAddress )== false )
274             {
275                clog << "problem parsing SourceAddress" << endl;
276                return false;
277             }
278             else
279             {
280                if (verbose) clog << "SourceAddress = " << msg.sourceAddress.ipv4 << endl;
281             }
282             break;
283 
284          case ChangedAddress:
285             msg.hasChangedAddress = true;
286             if ( stunParseAtrAddress(  body,  attrLen,  msg.changedAddress )== false )
287             {
288                clog << "problem parsing ChangedAddress" << endl;
289                return false;
290             }
291             else
292             {
293                if (verbose) clog << "ChangedAddress = " << msg.changedAddress.ipv4 << endl;
294             }
295             break;
296 
297          case Username:
298             msg.hasUsername = true;
299             if (stunParseAtrString( body, attrLen, msg.username) == false)
300             {
301                clog << "problem parsing Username" << endl;
302                return false;
303             }
304             else
305             {
306                if (verbose) clog << "Username = " << msg.username.value << endl;
307             }
308 
309             break;
310 
311          case Password:
312             msg.hasPassword = true;
313             if (stunParseAtrString( body, attrLen, msg.password) == false)
314             {
315                clog << "problem parsing Password" << endl;
316                return false;
317             }
318             else
319             {
320                if (verbose) clog << "Password = " << msg.password.value << endl;
321             }
322             break;
323 
324          case MessageIntegrity:
325             msg.hasMessageIntegrity = true;
326             if (stunParseAtrIntegrity( body, attrLen, msg.messageIntegrity) == false)
327             {
328                clog << "problem parsing MessageIntegrity" << endl;
329                return false;
330             }
331             else
332             {
333                //if (verbose) clog << "MessageIntegrity = " << msg.messageIntegrity.hash << endl;
334             }
335 
336             // read the current HMAC
337             // look up the password given the user of given the transaction id
338             // compute the HMAC on the buffer
339             // decide if they match or not
340             break;
341 
342          case ErrorCode:
343             msg.hasErrorCode = true;
344             if (stunParseAtrError(body, attrLen, msg.errorCode) == false)
345             {
346                clog << "problem parsing ErrorCode" << endl;
347                return false;
348             }
349             else
350             {
351                if (verbose) clog << "ErrorCode = " << int(msg.errorCode.errorClass)
352                                  << " " << int(msg.errorCode.number)
353                                  << " " << msg.errorCode.reason << endl;
354             }
355 
356             break;
357 
358          case UnknownAttribute:
359             msg.hasUnknownAttributes = true;
360             if (stunParseAtrUnknown(body, attrLen, msg.unknownAttributes) == false)
361             {
362                clog << "problem parsing UnknownAttribute" << endl;
363                return false;
364             }
365             break;
366 
367          case ReflectedFrom:
368             msg.hasReflectedFrom = true;
369             if ( stunParseAtrAddress(  body,  attrLen,  msg.reflectedFrom ) == false )
370             {
371                clog << "problem parsing ReflectedFrom" << endl;
372                return false;
373             }
374             break;
375 
376          case XorMappedAddress:
377             msg.hasXorMappedAddress = true;
378             if ( stunParseAtrAddress(  body,  attrLen,  msg.xorMappedAddress ) == false )
379             {
380                clog << "problem parsing XorMappedAddress" << endl;
381                return false;
382             }
383             else
384             {
385                if (verbose) clog << "XorMappedAddress = " << msg.mappedAddress.ipv4 << endl;
386             }
387             break;
388 
389          case XorOnly:
390             msg.xorOnly = true;
391             if (verbose)
392             {
393                clog << "xorOnly = true" << endl;
394             }
395             break;
396 
397          case ServerName:
398             msg.hasServerName = true;
399             if (stunParseAtrString( body, attrLen, msg.serverName) == false)
400             {
401                clog << "problem parsing ServerName" << endl;
402                return false;
403             }
404             else
405             {
406                if (verbose) clog << "ServerName = " << msg.serverName.value << endl;
407             }
408             break;
409 
410          case SecondaryAddress:
411             msg.hasSecondaryAddress = true;
412             if ( stunParseAtrAddress(  body,  attrLen,  msg.secondaryAddress ) == false )
413             {
414                clog << "problem parsing secondaryAddress" << endl;
415                return false;
416             }
417             else
418             {
419                if (verbose) clog << "SecondaryAddress = " << msg.secondaryAddress.ipv4 << endl;
420             }
421             break;
422 
423          default:
424             if (verbose) clog << "Unknown attribute: " << atrType << endl;
425             if ( atrType <= 0x7FFF )
426             {
427                return false;
428             }
429       }
430 
431       body += attrLen;
432       size -= attrLen;
433    }
434 
435    return true;
436 }
437 
438 
439 static char*
encode16(char * buf,UInt16 data)440 encode16(char* buf, UInt16 data)
441 {
442    UInt16 ndata = htons(data);
443    memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt16));
444    return buf + sizeof(UInt16);
445 }
446 
447 static char*
encode32(char * buf,UInt32 data)448 encode32(char* buf, UInt32 data)
449 {
450    UInt32 ndata = htonl(data);
451    memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt32));
452    return buf + sizeof(UInt32);
453 }
454 
455 
456 static char*
encode(char * buf,const char * data,unsigned int length)457 encode(char* buf, const char* data, unsigned int length)
458 {
459    memcpy(buf, data, length);
460    return buf + length;
461 }
462 
463 
464 static char*
encodeAtrAddress4(char * ptr,UInt16 type,const StunAtrAddress4 & atr)465 encodeAtrAddress4(char* ptr, UInt16 type, const StunAtrAddress4& atr)
466 {
467    ptr = encode16(ptr, type);
468    ptr = encode16(ptr, 8);
469    *ptr++ = atr.pad;
470    *ptr++ = IPv4Family;
471    ptr = encode16(ptr, atr.ipv4.port);
472    ptr = encode32(ptr, atr.ipv4.addr);
473 
474    return ptr;
475 }
476 
477 static char*
encodeAtrChangeRequest(char * ptr,const StunAtrChangeRequest & atr)478 encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest& atr)
479 {
480    ptr = encode16(ptr, ChangeRequest);
481    ptr = encode16(ptr, 4);
482    ptr = encode32(ptr, atr.value);
483    return ptr;
484 }
485 
486 static char*
encodeAtrError(char * ptr,const StunAtrError & atr)487 encodeAtrError(char* ptr, const StunAtrError& atr)
488 {
489    ptr = encode16(ptr, ErrorCode);
490    ptr = encode16(ptr, 6 + atr.sizeReason);
491    ptr = encode16(ptr, atr.pad);
492    *ptr++ = atr.errorClass;
493    *ptr++ = atr.number;
494    ptr = encode(ptr, atr.reason, atr.sizeReason);
495    return ptr;
496 }
497 
498 
499 static char*
encodeAtrUnknown(char * ptr,const StunAtrUnknown & atr)500 encodeAtrUnknown(char* ptr, const StunAtrUnknown& atr)
501 {
502    ptr = encode16(ptr, UnknownAttribute);
503    ptr = encode16(ptr, 2+2*atr.numAttributes);
504    for (int i=0; i<atr.numAttributes; i++)
505    {
506       ptr = encode16(ptr, atr.attrType[i]);
507    }
508    return ptr;
509 }
510 
511 
512 static char*
encodeXorOnly(char * ptr)513 encodeXorOnly(char* ptr)
514 {
515    ptr = encode16(ptr, XorOnly );
516    return ptr;
517 }
518 
519 
520 static char*
encodeAtrString(char * ptr,UInt16 type,const StunAtrString & atr)521 encodeAtrString(char* ptr, UInt16 type, const StunAtrString& atr)
522 {
523    assert(atr.sizeValue % 4 == 0);
524 
525    ptr = encode16(ptr, type);
526    ptr = encode16(ptr, atr.sizeValue);
527    ptr = encode(ptr, atr.value, atr.sizeValue);
528    return ptr;
529 }
530 
531 
532 static char*
encodeAtrIntegrity(char * ptr,const StunAtrIntegrity & atr)533 encodeAtrIntegrity(char* ptr, const StunAtrIntegrity& atr)
534 {
535    ptr = encode16(ptr, MessageIntegrity);
536    ptr = encode16(ptr, 20);
537    ptr = encode(ptr, atr.hash, sizeof(atr.hash));
538    return ptr;
539 }
540 
541 
542 unsigned int
stunEncodeMessage(const StunMessage & msg,char * buf,unsigned int bufLen,const StunAtrString & password,bool verbose)543 stunEncodeMessage( const StunMessage& msg,
544                    char* buf,
545                    unsigned int bufLen,
546                    const StunAtrString& password,
547                    bool verbose)
548 {
549    assert(bufLen >= sizeof(StunMsgHdr));
550    char* ptr = buf;
551 
552    ptr = encode16(ptr, msg.msgHdr.msgType);
553    char* lengthp = ptr;
554    ptr = encode16(ptr, 0);
555    ptr = encode(ptr, reinterpret_cast<const char*>(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id));
556 
557    if (verbose) clog << "Encoding stun message: " << endl;
558    if (msg.hasMappedAddress)
559    {
560       if (verbose) clog << "Encoding MappedAddress: " << msg.mappedAddress.ipv4 << endl;
561       ptr = encodeAtrAddress4 (ptr, MappedAddress, msg.mappedAddress);
562    }
563    if (msg.hasResponseAddress)
564    {
565       if (verbose) clog << "Encoding ResponseAddress: " << msg.responseAddress.ipv4 << endl;
566       ptr = encodeAtrAddress4(ptr, ResponseAddress, msg.responseAddress);
567    }
568    if (msg.hasChangeRequest)
569    {
570       if (verbose) clog << "Encoding ChangeRequest: " << msg.changeRequest.value << endl;
571       ptr = encodeAtrChangeRequest(ptr, msg.changeRequest);
572    }
573    if (msg.hasSourceAddress)
574    {
575       if (verbose) clog << "Encoding SourceAddress: " << msg.sourceAddress.ipv4 << endl;
576       ptr = encodeAtrAddress4(ptr, SourceAddress, msg.sourceAddress);
577    }
578    if (msg.hasChangedAddress)
579    {
580       if (verbose) clog << "Encoding ChangedAddress: " << msg.changedAddress.ipv4 << endl;
581       ptr = encodeAtrAddress4(ptr, ChangedAddress, msg.changedAddress);
582    }
583    if (msg.hasUsername)
584    {
585       if (verbose) clog << "Encoding Username: " << msg.username.value << endl;
586       ptr = encodeAtrString(ptr, Username, msg.username);
587    }
588    if (msg.hasPassword)
589    {
590       if (verbose) clog << "Encoding Password: " << msg.password.value << endl;
591       ptr = encodeAtrString(ptr, Password, msg.password);
592    }
593    if (msg.hasErrorCode)
594    {
595       if (verbose) clog << "Encoding ErrorCode: class="
596 			<< int(msg.errorCode.errorClass)
597 			<< " number=" << int(msg.errorCode.number)
598 			<< " reason="
599 			<< msg.errorCode.reason
600 			<< endl;
601 
602       ptr = encodeAtrError(ptr, msg.errorCode);
603    }
604    if (msg.hasUnknownAttributes)
605    {
606       if (verbose) clog << "Encoding UnknownAttribute: ???" << endl;
607       ptr = encodeAtrUnknown(ptr, msg.unknownAttributes);
608    }
609    if (msg.hasReflectedFrom)
610    {
611       if (verbose) clog << "Encoding ReflectedFrom: " << msg.reflectedFrom.ipv4 << endl;
612       ptr = encodeAtrAddress4(ptr, ReflectedFrom, msg.reflectedFrom);
613    }
614    if (msg.hasXorMappedAddress)
615    {
616       if (verbose) clog << "Encoding XorMappedAddress: " << msg.xorMappedAddress.ipv4 << endl;
617       ptr = encodeAtrAddress4 (ptr, XorMappedAddress, msg.xorMappedAddress);
618    }
619    if (msg.xorOnly)
620    {
621       if (verbose) clog << "Encoding xorOnly: " << endl;
622       ptr = encodeXorOnly( ptr );
623    }
624    if (msg.hasServerName)
625    {
626       if (verbose) clog << "Encoding ServerName: " << msg.serverName.value << endl;
627       ptr = encodeAtrString(ptr, ServerName, msg.serverName);
628    }
629    if (msg.hasSecondaryAddress)
630    {
631       if (verbose) clog << "Encoding SecondaryAddress: " << msg.secondaryAddress.ipv4 << endl;
632       ptr = encodeAtrAddress4 (ptr, SecondaryAddress, msg.secondaryAddress);
633    }
634 
635    if (password.sizeValue > 0)
636    {
637       if (verbose) clog << "HMAC with password: " << password.value << endl;
638 
639       StunAtrIntegrity integrity;
640       computeHmac(integrity.hash, buf, int(ptr-buf) , password.value, password.sizeValue);
641       ptr = encodeAtrIntegrity(ptr, integrity);
642    }
643    if (verbose) clog << endl;
644 
645    encode16(lengthp, UInt16(ptr - buf - sizeof(StunMsgHdr)));
646    return int(ptr - buf);
647 }
648 
649 int
stunRand()650 stunRand()
651 {
652    // return 32 bits of random stuff
653    static bool init=false;
654    if ( !init ) {
655       srandomdev();
656       init = true;
657    }
658    /* random() is described as returning 0...2**31-1 */
659    return 0xffffffff & ( ( random() << 31 ) | random() );
660 }
661 
662 
663 /// return a random number to use as a port
664 int
stunRandomPort()665 stunRandomPort()
666 {
667    int min=0x4000;
668    int max=0x7FFF;
669 
670    int ret = stunRand();
671    ret = ret|min;
672    ret = ret&max;
673 
674    return ret;
675 }
676 
677 
678 #ifdef NOSSL
679 static void
computeHmac(char * hmac,const char * input,int length,const char * key,int sizeKey)680 computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey)
681 {
682    strncpy(hmac,"hmac-not-implemented",20);
683 }
684 #else
685 #include <openssl/hmac.h>
686 
687 static void
computeHmac(char * hmac,const char * input,int length,const char * key,int sizeKey)688 computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey)
689 {
690    unsigned int resultSize=0;
691    HMAC(EVP_sha1(),
692         key, sizeKey,
693         reinterpret_cast<const unsigned char*>(input), length,
694         reinterpret_cast<unsigned char*>(hmac), &resultSize);
695    assert(resultSize == 20);
696 }
697 #endif
698 
699 
700 static void
toHex(const char * buffer,int bufferSize,char * output)701 toHex(const char* buffer, int bufferSize, char* output)
702 {
703    static char hexmap[] = "0123456789abcdef";
704 
705    const char* p = buffer;
706    char* r = output;
707    for (int i=0; i < bufferSize; i++)
708    {
709       unsigned char temp = *p++;
710 
711       int hi = (temp & 0xf0)>>4;
712       int low = (temp & 0xf);
713 
714       *r++ = hexmap[hi];
715       *r++ = hexmap[low];
716    }
717    *r = 0;
718 }
719 
720 void
stunCreateUserName(const StunAddress4 & source,StunAtrString * username)721 stunCreateUserName(const StunAddress4& source, StunAtrString* username)
722 {
723    UInt64 time = stunGetSystemTimeSecs();
724    time -= (time % 20*60);
725    //UInt64 hitime = time >> 32;
726    UInt64 lotime = time & 0xFFFFFFFF;
727 
728    char buffer[1024];
729    sprintf(buffer,
730            "%08x:%08x:%08x:",
731            UInt32(source.addr),
732            UInt32(stunRand()),
733            UInt32(lotime));
734    assert( strlen(buffer) < 1024 );
735 
736    assert(strlen(buffer) + 41 < STUN_MAX_STRING);
737 
738    char hmac[20];
739    char key[] = "Jason";
740    computeHmac(hmac, buffer, strlen(buffer), key, strlen(key) );
741    char hmacHex[41];
742    toHex(hmac, 20, hmacHex );
743    hmacHex[40] =0;
744 
745    strcat(buffer,hmacHex);
746 
747    int l = strlen(buffer);
748    assert( l+1 < STUN_MAX_STRING );
749    assert( l%4 == 0 );
750 
751    username->sizeValue = l;
752    memcpy(username->value,buffer,l);
753    username->value[l]=0;
754 
755    //if (verbose) clog << "computed username=" << username.value << endl;
756 }
757 
758 void
stunCreatePassword(const StunAtrString & username,StunAtrString * password)759 stunCreatePassword(const StunAtrString& username, StunAtrString* password)
760 {
761    char hmac[20];
762    char key[] = "Fluffy";
763    //char buffer[STUN_MAX_STRING];
764    computeHmac(hmac, username.value, strlen(username.value), key, strlen(key));
765    toHex(hmac, 20, password->value);
766    password->sizeValue = 40;
767    password->value[40]=0;
768 
769    //clog << "password=" << password->value << endl;
770 }
771 
772 
773 UInt64
stunGetSystemTimeSecs()774 stunGetSystemTimeSecs()
775 {
776    UInt64 time=0;
777 #if defined(WIN32)
778    SYSTEMTIME t;
779    // CJ TODO - this probably has bug on wrap around every 24 hours
780    GetSystemTime( &t );
781    time = (t.wHour*60+t.wMinute)*60+t.wSecond;
782 #else
783    struct timeval now;
784    gettimeofday( &now , NULL );
785    //assert( now );
786    time = now.tv_sec;
787 #endif
788    return time;
789 }
790 
791 
operator <<(ostream & strm,const UInt128 & r)792 ostream& operator<< ( ostream& strm, const UInt128& r )
793 {
794    strm << int(r.octet[0]);
795    for ( int i=1; i<16; i++ )
796    {
797       strm << ':' << int(r.octet[i]);
798    }
799 
800    return strm;
801 }
802 
803 ostream&
operator <<(ostream & strm,const StunAddress4 & addr)804 operator<<( ostream& strm, const StunAddress4& addr)
805 {
806    UInt32 ip = addr.addr;
807    strm << ((int)(ip>>24)&0xFF) << ".";
808    strm << ((int)(ip>>16)&0xFF) << ".";
809    strm << ((int)(ip>> 8)&0xFF) << ".";
810    strm << ((int)(ip>> 0)&0xFF) ;
811 
812    strm << ":" << addr.port;
813 
814    return strm;
815 }
816 
817 
818 // returns true if it scucceeded
819 bool
stunParseHostName(char * peerName,UInt32 & ip,UInt16 & portVal,UInt16 defaultPort)820 stunParseHostName( char* peerName,
821                UInt32& ip,
822                UInt16& portVal,
823                UInt16 defaultPort )
824 {
825    in_addr sin_addr;
826 
827    char host[512];
828    strncpy(host,peerName,512);
829    host[512-1]='\0';
830    char* port = NULL;
831 
832    int portNum = defaultPort;
833 
834    // pull out the port part if present.
835    char* sep = strchr(host,':');
836 
837    if ( sep == NULL )
838    {
839       portNum = defaultPort;
840    }
841    else
842    {
843       *sep = '\0';
844       port = sep + 1;
845       // set port part
846 
847       char* endPtr=NULL;
848 
849       portNum = strtol(port,&endPtr,10);
850 
851       if ( endPtr != NULL )
852       {
853          if ( *endPtr != '\0' )
854          {
855             portNum = defaultPort;
856          }
857       }
858    }
859 
860    if ( portNum < 1024 ) return false;
861    if ( portNum >= 0xFFFF ) return false;
862 
863    // figure out the host part
864    struct hostent* h;
865 
866 #ifdef WIN32
867    assert( strlen(host) >= 1 );
868    if ( isdigit( host[0] ) )
869    {
870       // assume it is a ip address
871       unsigned long a = inet_addr(host);
872       //cerr << "a=0x" << hex << a << dec << endl;
873 
874       ip = ntohl( a );
875    }
876    else
877    {
878       // assume it is a host name
879       h = gethostbyname( host );
880 
881       if ( h == NULL )
882       {
883          int err = getErrno();
884          std::cerr << "error was " << err << std::endl;
885          assert( err != WSANOTINITIALISED );
886 
887          ip = ntohl( 0x7F000001L );
888 
889          return false;
890       }
891       else
892       {
893          sin_addr = *(struct in_addr*)h->h_addr;
894          ip = ntohl( sin_addr.s_addr );
895       }
896    }
897 
898 #else
899    h = gethostbyname( host );
900    if ( h == NULL )
901    {
902       int err = getErrno();
903       std::cerr << "error was " << err << std::endl;
904       ip = ntohl( 0x7F000001L );
905       return false;
906    }
907    else
908    {
909       sin_addr = *(struct in_addr*)h->h_addr;
910       ip = ntohl( sin_addr.s_addr );
911    }
912 #endif
913 
914    portVal = portNum;
915 
916    return true;
917 }
918 
919 
920 bool
stunParseServerName(char * name,StunAddress4 & addr)921 stunParseServerName( char* name, StunAddress4& addr)
922 {
923    assert(name);
924 
925    // TODO - put in DNS SRV stuff.
926 
927    bool ret = stunParseHostName( name, addr.addr, addr.port, 3478);
928    if ( ret != true )
929    {
930        addr.port=0xFFFF;
931    }
932    return ret;
933 }
934 
935 
936 static void
stunCreateErrorResponse(StunMessage & response,int cl,int number,const char * msg)937 stunCreateErrorResponse(StunMessage& response, int cl, int number, const char* msg)
938 {
939    response.msgHdr.msgType = BindErrorResponseMsg;
940    response.hasErrorCode = true;
941    response.errorCode.errorClass = cl;
942    response.errorCode.number = number;
943    strcpy(response.errorCode.reason, msg);
944 }
945 
946 #if 0
947 static void
948 stunCreateSharedSecretErrorResponse(StunMessage& response, int cl, int number, const char* msg)
949 {
950    response.msgHdr.msgType = SharedSecretErrorResponseMsg;
951    response.hasErrorCode = true;
952    response.errorCode.errorClass = cl;
953    response.errorCode.number = number;
954    strcpy(response.errorCode.reason, msg);
955 }
956 #endif
957 
958 static void
stunCreateSharedSecretResponse(const StunMessage & request,const StunAddress4 & source,StunMessage & response)959 stunCreateSharedSecretResponse(const StunMessage& request, const StunAddress4& source, StunMessage& response)
960 {
961    response.msgHdr.msgType = SharedSecretResponseMsg;
962    response.msgHdr.id = request.msgHdr.id;
963 
964    response.hasUsername = true;
965    stunCreateUserName( source, &response.username);
966 
967    response.hasPassword = true;
968    stunCreatePassword( response.username, &response.password);
969 }
970 
971 
972 // This funtion takes a single message sent to a stun server, parses
973 // and constructs an apropriate repsonse - returns true if message is
974 // valid
975 bool
stunServerProcessMsg(char * buf,unsigned int bufLen,StunAddress4 & from,StunAddress4 & secondary,StunAddress4 & myAddr,StunAddress4 & altAddr,StunMessage * resp,StunAddress4 * destination,StunAtrString * hmacPassword,bool * changePort,bool * changeIp,bool verbose)976 stunServerProcessMsg( char* buf,
977                       unsigned int bufLen,
978                       StunAddress4& from,
979                       StunAddress4& secondary,
980                       StunAddress4& myAddr,
981                       StunAddress4& altAddr,
982                       StunMessage* resp,
983                       StunAddress4* destination,
984                       StunAtrString* hmacPassword,
985                       bool* changePort,
986                       bool* changeIp,
987                       bool verbose)
988 {
989 
990    // set up information for default response
991 
992    memset( resp, 0 , sizeof(*resp) );
993 
994    *changeIp = false;
995    *changePort = false;
996 
997    StunMessage req;
998    bool ok = stunParseMessage( buf,bufLen, req, verbose);
999 
1000    if (!ok)      // Complete garbage, drop it on the floor
1001    {
1002       if (verbose) clog << "Request did not parse" << endl;
1003       return false;
1004    }
1005    if (verbose) clog << "Request parsed ok" << endl;
1006 
1007    StunAddress4 mapped = req.mappedAddress.ipv4;
1008    StunAddress4 respondTo = req.responseAddress.ipv4;
1009    UInt32 flags = req.changeRequest.value;
1010 
1011    switch (req.msgHdr.msgType)
1012    {
1013       case SharedSecretRequestMsg:
1014          if(verbose) clog << "Received SharedSecretRequestMsg on udp. send error 433." << endl;
1015          // !cj! - should fix so you know if this came over TLS or UDP
1016          stunCreateSharedSecretResponse(req, from, *resp);
1017          //stunCreateSharedSecretErrorResponse(*resp, 4, 33, "this request must be over TLS");
1018          return true;
1019 
1020       case BindRequestMsg:
1021          if (!req.hasMessageIntegrity)
1022          {
1023             if (verbose) clog << "BindRequest does not contain MessageIntegrity" << endl;
1024 
1025             if (0) // !jf! mustAuthenticate
1026             {
1027                if(verbose) clog << "Received BindRequest with no MessageIntegrity. Sending 401." << endl;
1028                stunCreateErrorResponse(*resp, 4, 1, "Missing MessageIntegrity");
1029                return true;
1030             }
1031          }
1032          else
1033          {
1034             if (!req.hasUsername)
1035             {
1036                if (verbose) clog << "No UserName. Send 432." << endl;
1037                stunCreateErrorResponse(*resp, 4, 32, "No UserName and contains MessageIntegrity");
1038                return true;
1039             }
1040             else
1041             {
1042                if (verbose) clog << "Validating username: " << req.username.value << endl;
1043                // !jf! could retrieve associated password from provisioning here
1044                if (strcmp(req.username.value, "test") == 0)
1045                {
1046                   if (0)
1047                   {
1048                      // !jf! if the credentials are stale
1049                      stunCreateErrorResponse(*resp, 4, 30, "Stale credentials on BindRequest");
1050                      return true;
1051                   }
1052                   else
1053                   {
1054                      if (verbose) clog << "Validating MessageIntegrity" << endl;
1055                      // need access to shared secret
1056 
1057                      unsigned char hmac[20];
1058 #ifndef NOSSL
1059                      unsigned int hmacSize=20;
1060 
1061                      HMAC(EVP_sha1(),
1062                           "1234", 4,
1063                           reinterpret_cast<const unsigned char*>(buf), bufLen-20-4,
1064                           hmac, &hmacSize);
1065                      assert(hmacSize == 20);
1066 #endif
1067 
1068                      if (memcmp(buf, hmac, 20) != 0)
1069                      {
1070                         if (verbose) clog << "MessageIntegrity is bad. Sending " << endl;
1071                         stunCreateErrorResponse(*resp, 4, 3, "Unknown username. Try test with password 1234");
1072                         return true;
1073                      }
1074 
1075                      // need to compute this later after message is filled in
1076                      resp->hasMessageIntegrity = true;
1077                      assert(req.hasUsername);
1078                      resp->hasUsername = true;
1079                      resp->username = req.username; // copy username in
1080                   }
1081                }
1082                else
1083                {
1084                   if (verbose) clog << "Invalid username: " << req.username.value << "Send 430." << endl;
1085                }
1086             }
1087          }
1088 
1089          // TODO !jf! should check for unknown attributes here and send 420 listing the
1090          // unknown attributes.
1091 
1092          if ( respondTo.port == 0 ) respondTo = from;
1093          if ( mapped.port == 0 ) mapped = from;
1094 
1095          *changeIp   = ( flags & ChangeIpFlag )?true:false;
1096          *changePort = ( flags & ChangePortFlag )?true:false;
1097 
1098          if (verbose)
1099          {
1100             clog << "Request is valid:" << endl;
1101             clog << "\t flags=" << flags << endl;
1102             clog << "\t changeIp=" << *changeIp << endl;
1103             clog << "\t changePort=" << *changePort << endl;
1104             clog << "\t from = " << from << endl;
1105             clog << "\t respond to = " << respondTo << endl;
1106             clog << "\t mapped = " << mapped << endl;
1107          }
1108 
1109          // form the outgoing message
1110          resp->msgHdr.msgType = BindResponseMsg;
1111          for ( int i=0; i<16; i++ )
1112          {
1113             resp->msgHdr.id.octet[i] = req.msgHdr.id.octet[i];
1114          }
1115 
1116          if ( req.xorOnly == false )
1117          {
1118             resp->hasMappedAddress = true;
1119             resp->mappedAddress.ipv4.port = mapped.port;
1120             resp->mappedAddress.ipv4.addr = mapped.addr;
1121          }
1122 
1123          if (1) // do xorMapped address or not
1124          {
1125             resp->hasXorMappedAddress = true;
1126             UInt16 id16 = req.msgHdr.id.octet[0]<<8
1127                | req.msgHdr.id.octet[1];
1128             UInt32 id32 = req.msgHdr.id.octet[0]<<24
1129                | req.msgHdr.id.octet[1]<<16
1130                | req.msgHdr.id.octet[2]<<8
1131                | req.msgHdr.id.octet[3];
1132             resp->xorMappedAddress.ipv4.port = mapped.port^id16;
1133             resp->xorMappedAddress.ipv4.addr = mapped.addr^id32;
1134          }
1135 
1136          resp->hasSourceAddress = true;
1137          resp->sourceAddress.ipv4.port = (*changePort) ? altAddr.port : myAddr.port;
1138          resp->sourceAddress.ipv4.addr = (*changeIp)   ? altAddr.addr : myAddr.addr;
1139 
1140          resp->hasChangedAddress = true;
1141          resp->changedAddress.ipv4.port = altAddr.port;
1142          resp->changedAddress.ipv4.addr = altAddr.addr;
1143 
1144          if ( secondary.port != 0 )
1145          {
1146             resp->hasSecondaryAddress = true;
1147             resp->secondaryAddress.ipv4.port = secondary.port;
1148             resp->secondaryAddress.ipv4.addr = secondary.addr;
1149          }
1150 
1151          if ( req.hasUsername && req.username.sizeValue > 0 )
1152          {
1153             // copy username in
1154             resp->hasUsername = true;
1155             assert( req.username.sizeValue % 4 == 0 );
1156             assert( req.username.sizeValue < STUN_MAX_STRING );
1157             memcpy( resp->username.value, req.username.value, req.username.sizeValue );
1158             resp->username.sizeValue = req.username.sizeValue;
1159          }
1160 
1161          if (1) // add ServerName
1162          {
1163             resp->hasServerName = true;
1164             const char serverName[] = "Vovida.org " STUN_VERSION; // must pad to mult of 4
1165 
1166             assert( sizeof(serverName) < STUN_MAX_STRING );
1167             //cerr << "sizeof serverName is "  << sizeof(serverName) << endl;
1168             assert( sizeof(serverName)%4 == 0 );
1169             memcpy( resp->serverName.value, serverName, sizeof(serverName));
1170             resp->serverName.sizeValue = sizeof(serverName);
1171          }
1172 
1173          if ( req.hasMessageIntegrity & req.hasUsername )
1174          {
1175             // this creates the password that will be used in the HMAC when then
1176             // messages is sent
1177             stunCreatePassword( req.username, hmacPassword );
1178          }
1179 
1180          if (req.hasUsername && (req.username.sizeValue > 64 ) )
1181          {
1182             UInt32 source;
1183             assert( sizeof(int) == sizeof(UInt32) );
1184 
1185             sscanf(req.username.value, "%x", &source);
1186             resp->hasReflectedFrom = true;
1187             resp->reflectedFrom.ipv4.port = 0;
1188             resp->reflectedFrom.ipv4.addr = source;
1189          }
1190 
1191          destination->port = respondTo.port;
1192          destination->addr = respondTo.addr;
1193 
1194          return true;
1195 
1196       default:
1197          if (verbose) clog << "Unknown or unsupported request " << endl;
1198          return false;
1199    }
1200 
1201    assert(0);
1202    return false;
1203 }
1204 
1205 bool
stunInitServer(StunServerInfo & info,const StunAddress4 & myAddr,const StunAddress4 & altAddr,int startMediaPort,bool verbose)1206 stunInitServer(StunServerInfo& info, const StunAddress4& myAddr,
1207                const StunAddress4& altAddr, int startMediaPort, bool verbose )
1208 {
1209    assert( myAddr.port != 0 );
1210    assert( altAddr.port!= 0 );
1211    assert( myAddr.addr  != 0 );
1212    //assert( altAddr.addr != 0 );
1213 
1214    info.myAddr = myAddr;
1215    info.altAddr = altAddr;
1216 
1217    info.myFd = INVALID_SOCKET;
1218    info.altPortFd = INVALID_SOCKET;
1219    info.altIpFd = INVALID_SOCKET;
1220    info.altIpPortFd = INVALID_SOCKET;
1221 
1222    memset(info.relays, 0, sizeof(info.relays));
1223    if (startMediaPort > 0)
1224    {
1225       info.relay = true;
1226 
1227       for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1228       {
1229          StunMediaRelay* relay = &info.relays[i];
1230          relay->relayPort = startMediaPort+i;
1231          relay->fd = 0;
1232          relay->expireTime = 0;
1233       }
1234    }
1235    else
1236    {
1237       info.relay = false;
1238    }
1239 
1240    if ((info.myFd = openPort(myAddr.port, myAddr.addr,verbose)) == INVALID_SOCKET)
1241    {
1242       clog << "Can't open " << myAddr << endl;
1243       stunStopServer(info);
1244 
1245       return false;
1246    }
1247    //if (verbose) clog << "Opened " << myAddr.addr << ":" << myAddr.port << " --> " << info.myFd << endl;
1248 
1249    if ((info.altPortFd = openPort(altAddr.port,myAddr.addr,verbose)) == INVALID_SOCKET)
1250    {
1251       clog << "Can't open " << myAddr << endl;
1252       stunStopServer(info);
1253       return false;
1254    }
1255    //if (verbose) clog << "Opened " << myAddr.addr << ":" << altAddr.port << " --> " << info.altPortFd << endl;
1256 
1257 
1258    info.altIpFd = INVALID_SOCKET;
1259    if (  altAddr.addr != 0 )
1260    {
1261       if ((info.altIpFd = openPort( myAddr.port, altAddr.addr,verbose)) == INVALID_SOCKET)
1262       {
1263          clog << "Can't open " << altAddr << endl;
1264          stunStopServer(info);
1265          return false;
1266       }
1267       //if (verbose) clog << "Opened " << altAddr.addr << ":" << myAddr.port << " --> " << info.altIpFd << endl;;
1268    }
1269 
1270    info.altIpPortFd = INVALID_SOCKET;
1271    if (  altAddr.addr != 0 )
1272    {  if ((info.altIpPortFd = openPort(altAddr.port, altAddr.addr,verbose)) == INVALID_SOCKET)
1273       {
1274          clog << "Can't open " << altAddr << endl;
1275          stunStopServer(info);
1276          return false;
1277       }
1278       //if (verbose) clog << "Opened " << altAddr.addr << ":" << altAddr.port << " --> " << info.altIpPortFd << endl;;
1279    }
1280 
1281    return true;
1282 }
1283 
1284 void
stunStopServer(StunServerInfo & info)1285 stunStopServer(StunServerInfo& info)
1286 {
1287    if (info.myFd > 0) closesocket(info.myFd);
1288    if (info.altPortFd > 0) closesocket(info.altPortFd);
1289    if (info.altIpFd > 0) closesocket(info.altIpFd);
1290    if (info.altIpPortFd > 0) closesocket(info.altIpPortFd);
1291 
1292    if (info.relay)
1293    {
1294       for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1295       {
1296          StunMediaRelay* relay = &info.relays[i];
1297          if (relay->fd)
1298          {
1299             closesocket(relay->fd);
1300             relay->fd = 0;
1301          }
1302       }
1303    }
1304 }
1305 
1306 
1307 bool
stunServerProcess(StunServerInfo & info,bool verbose)1308 stunServerProcess(StunServerInfo& info, bool verbose)
1309 {
1310    char msg[STUN_MAX_MESSAGE_SIZE];
1311    int msgLen = sizeof(msg);
1312 
1313    bool ok = false;
1314    bool recvAltIp =false;
1315    bool recvAltPort = false;
1316 
1317    fd_set fdSet;
1318    Socket maxFd=0;
1319 
1320    FD_ZERO(&fdSet);
1321    FD_SET(info.myFd,&fdSet);
1322    if ( info.myFd >= maxFd ) maxFd=info.myFd+1;
1323    FD_SET(info.altPortFd,&fdSet);
1324    if ( info.altPortFd >= maxFd ) maxFd=info.altPortFd+1;
1325 
1326    if ( info.altIpFd != INVALID_SOCKET )
1327    {
1328       FD_SET(info.altIpFd,&fdSet);
1329       if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1;
1330    }
1331    if ( info.altIpPortFd != INVALID_SOCKET )
1332    {
1333       FD_SET(info.altIpPortFd,&fdSet);
1334       if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1;
1335    }
1336 
1337    if (info.relay)
1338    {
1339       for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1340       {
1341          StunMediaRelay* relay = &info.relays[i];
1342          if (relay->fd)
1343          {
1344             FD_SET(relay->fd, &fdSet);
1345             if (relay->fd >= maxFd)
1346 			{
1347 				maxFd=relay->fd+1;
1348 			}
1349          }
1350       }
1351    }
1352 
1353    if ( info.altIpFd != INVALID_SOCKET )
1354    {
1355       FD_SET(info.altIpFd,&fdSet);
1356       if (info.altIpFd>=maxFd) maxFd=info.altIpFd+1;
1357    }
1358    if ( info.altIpPortFd != INVALID_SOCKET )
1359    {
1360       FD_SET(info.altIpPortFd,&fdSet);
1361       if (info.altIpPortFd>=maxFd) maxFd=info.altIpPortFd+1;
1362    }
1363 
1364    struct timeval tv;
1365    tv.tv_sec = 0;
1366    tv.tv_usec = 1000;
1367 
1368    int e = select( maxFd, &fdSet, NULL,NULL, &tv );
1369    if (e < 0)
1370    {
1371       int err = getErrno();
1372       clog << "Error on select: " << strerror(err) << endl;
1373    }
1374    else if (e >= 0)
1375    {
1376       StunAddress4 from;
1377 
1378       // do the media relaying
1379       if (info.relay)
1380       {
1381          time_t now = time(0);
1382          for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1383          {
1384             StunMediaRelay* relay = &info.relays[i];
1385             if (relay->fd)
1386             {
1387                if (FD_ISSET(relay->fd, &fdSet))
1388                {
1389                   char msg[MAX_RTP_MSG_SIZE];
1390                   int msgLen = sizeof(msg);
1391 
1392                   StunAddress4 rtpFrom;
1393                   ok = getMessage( relay->fd, msg, &msgLen, &rtpFrom.addr, &rtpFrom.port ,verbose);
1394                   if (ok)
1395                   {
1396                      sendMessage(info.myFd, msg, msgLen, relay->destination.addr, relay->destination.port, verbose);
1397                      relay->expireTime = now + MEDIA_RELAY_TIMEOUT;
1398                      if ( verbose ) clog << "Relay packet on "
1399                                          << relay->fd
1400                                          << " from " << rtpFrom
1401                                          << " -> " << relay->destination
1402                                          << endl;
1403                   }
1404                }
1405                else if (now > relay->expireTime)
1406                {
1407                   closesocket(relay->fd);
1408                   relay->fd = 0;
1409                }
1410             }
1411          }
1412       }
1413 
1414 
1415       if (FD_ISSET(info.myFd,&fdSet))
1416       {
1417          if (verbose) clog << "received on A1:P1" << endl;
1418          recvAltIp = false;
1419          recvAltPort = false;
1420          ok = getMessage( info.myFd, msg, &msgLen, &from.addr, &from.port,verbose );
1421       }
1422       else if (FD_ISSET(info.altPortFd, &fdSet))
1423       {
1424          if (verbose) clog << "received on A1:P2" << endl;
1425          recvAltIp = false;
1426          recvAltPort = true;
1427          ok = getMessage( info.altPortFd, msg, &msgLen, &from.addr, &from.port,verbose );
1428       }
1429       else if ( (info.altIpFd!=INVALID_SOCKET) && FD_ISSET(info.altIpFd,&fdSet))
1430       {
1431          if (verbose) clog << "received on A2:P1" << endl;
1432          recvAltIp = true;
1433          recvAltPort = false;
1434          ok = getMessage( info.altIpFd, msg, &msgLen, &from.addr, &from.port ,verbose);
1435       }
1436       else if ( (info.altIpPortFd!=INVALID_SOCKET) && FD_ISSET(info.altIpPortFd, &fdSet))
1437       {
1438          if (verbose) clog << "received on A2:P2" << endl;
1439          recvAltIp = true;
1440          recvAltPort = true;
1441          ok = getMessage( info.altIpPortFd, msg, &msgLen, &from.addr, &from.port,verbose );
1442       }
1443       else
1444       {
1445          return true;
1446       }
1447 
1448       int relayPort = 0;
1449       if (info.relay)
1450       {
1451          for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1452          {
1453             StunMediaRelay* relay = &info.relays[i];
1454             if (relay->destination.addr == from.addr &&
1455                 relay->destination.port == from.port)
1456             {
1457                relayPort = relay->relayPort;
1458                relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT;
1459                break;
1460             }
1461          }
1462 
1463          if (relayPort == 0)
1464          {
1465             for (int i=0; i<MAX_MEDIA_RELAYS; ++i)
1466             {
1467                StunMediaRelay* relay = &info.relays[i];
1468                if (relay->fd == 0)
1469                {
1470                   if ( verbose ) clog << "Open relay port " << relay->relayPort << endl;
1471 
1472                   relay->fd = openPort(relay->relayPort, info.myAddr.addr, verbose);
1473                   relay->destination.addr = from.addr;
1474                   relay->destination.port = from.port;
1475                   relay->expireTime = time(0) + MEDIA_RELAY_TIMEOUT;
1476                   relayPort = relay->relayPort;
1477                   break;
1478                }
1479             }
1480          }
1481       }
1482 
1483       if ( !ok )
1484       {
1485          if ( verbose ) clog << "Get message did not return a valid message" <<endl;
1486          return true;
1487       }
1488 
1489       if ( verbose ) clog << "Got a request (len=" << msgLen << ") from " << from << endl;
1490 
1491       if ( msgLen <= 0 )
1492       {
1493          return true;
1494       }
1495 
1496       bool changePort = false;
1497       bool changeIp = false;
1498 
1499       StunMessage resp;
1500       StunAddress4 dest;
1501       StunAtrString hmacPassword;
1502       hmacPassword.sizeValue = 0;
1503 
1504       StunAddress4 secondary;
1505       secondary.port = 0;
1506       secondary.addr = 0;
1507 
1508       if (info.relay && relayPort)
1509       {
1510          secondary = from;
1511 
1512          from.addr = info.myAddr.addr;
1513          from.port = relayPort;
1514       }
1515 
1516       ok = stunServerProcessMsg( msg, msgLen, from, secondary,
1517                                  recvAltIp ? info.altAddr : info.myAddr,
1518                                  recvAltIp ? info.myAddr : info.altAddr,
1519                                  &resp,
1520                                  &dest,
1521                                  &hmacPassword,
1522                                  &changePort,
1523                                  &changeIp,
1524                                  verbose );
1525 
1526       if ( !ok )
1527       {
1528          if ( verbose ) clog << "Failed to parse message" << endl;
1529          return true;
1530       }
1531 
1532       char buf[STUN_MAX_MESSAGE_SIZE];
1533       int len = sizeof(buf);
1534 
1535       len = stunEncodeMessage( resp, buf, len, hmacPassword,verbose );
1536 
1537       if ( dest.addr == 0 )  ok=false;
1538       if ( dest.port == 0 ) ok=false;
1539 
1540       if ( ok )
1541       {
1542          assert( dest.addr != 0 );
1543          assert( dest.port != 0 );
1544 
1545          Socket sendFd;
1546 
1547          bool sendAltIp   = recvAltIp;   // send on the received IP address
1548          bool sendAltPort = recvAltPort; // send on the received port
1549 
1550          if ( changeIp )   sendAltIp   = !sendAltIp;   // if need to change IP, then flip logic
1551          if ( changePort ) sendAltPort = !sendAltPort; // if need to change port, then flip logic
1552 
1553          if ( !sendAltPort )
1554          {
1555             if ( !sendAltIp )
1556             {
1557                sendFd = info.myFd;
1558             }
1559             else
1560             {
1561                sendFd = info.altIpFd;
1562             }
1563          }
1564          else
1565          {
1566             if ( !sendAltIp )
1567             {
1568                sendFd = info.altPortFd;
1569             }
1570             else
1571             {
1572                sendFd = info.altIpPortFd;
1573             }
1574          }
1575 
1576          if ( sendFd != INVALID_SOCKET )
1577          {
1578             sendMessage( sendFd, buf, len, dest.addr, dest.port, verbose );
1579          }
1580       }
1581    }
1582 
1583    return true;
1584 }
1585 
1586 int
stunFindLocalInterfaces(UInt32 * addresses,int maxRet)1587 stunFindLocalInterfaces(UInt32* addresses,int maxRet)
1588 {
1589 #if defined(WIN32) || defined(__sparc__)
1590    return 0;
1591 #else
1592    struct ifconf ifc;
1593 
1594    int s = socket( AF_INET, SOCK_DGRAM, 0 );
1595    int len = 100 * sizeof(struct ifreq);
1596 
1597    char buf[ len ];
1598 
1599    ifc.ifc_len = len;
1600    ifc.ifc_buf = buf;
1601 
1602    int e = ioctl(s,SIOCGIFCONF,&ifc);
1603    char *ptr = buf;
1604    int tl = ifc.ifc_len;
1605    int count=0;
1606 
1607    while ( (tl > 0) && ( count < maxRet) )
1608    {
1609       struct ifreq* ifr = (struct ifreq *)ptr;
1610 
1611       int si = sizeof(ifr->ifr_name) + sizeof(struct sockaddr);
1612       tl -= si;
1613       ptr += si;
1614       //char* name = ifr->ifr_ifrn.ifrn_name;
1615       //cerr << "name = " << name << endl;
1616 
1617       struct ifreq ifr2;
1618       ifr2 = *ifr;
1619 
1620       e = ioctl(s,SIOCGIFADDR,&ifr2);
1621       if ( e == -1 )
1622       {
1623          break;
1624       }
1625 
1626       //cerr << "ioctl addr e = " << e << endl;
1627 
1628       struct sockaddr a = ifr2.ifr_addr;
1629       struct sockaddr_in* addr = (struct sockaddr_in*) &a;
1630 
1631       UInt32 ai = ntohl( addr->sin_addr.s_addr );
1632       if (int((ai>>24)&0xFF) != 127)
1633       {
1634          addresses[count++] = ai;
1635       }
1636 
1637 #if 0
1638       cerr << "Detected interface "
1639            << int((ai>>24)&0xFF) << "."
1640            << int((ai>>16)&0xFF) << "."
1641            << int((ai>> 8)&0xFF) << "."
1642            << int((ai    )&0xFF) << endl;
1643 #endif
1644    }
1645 
1646    closesocket(s);
1647 
1648    return count;
1649 #endif
1650 }
1651 
1652 
1653 void
stunBuildReqSimple(StunMessage * msg,const StunAtrString & username,bool changePort,bool changeIp,unsigned int id)1654 stunBuildReqSimple( StunMessage* msg,
1655                     const StunAtrString& username,
1656                     bool changePort, bool changeIp, unsigned int id )
1657 {
1658    assert( msg );
1659    memset( msg , 0 , sizeof(*msg) );
1660 
1661    msg->msgHdr.msgType = BindRequestMsg;
1662 
1663    for ( int i=0; i<16; i=i+4 )
1664    {
1665       assert(i+3<16);
1666       int r = stunRand();
1667       msg->msgHdr.id.octet[i+0]= r>>0;
1668       msg->msgHdr.id.octet[i+1]= r>>8;
1669       msg->msgHdr.id.octet[i+2]= r>>16;
1670       msg->msgHdr.id.octet[i+3]= r>>24;
1671    }
1672 
1673    if ( id != 0 )
1674    {
1675       msg->msgHdr.id.octet[0] = id;
1676    }
1677 
1678    msg->hasChangeRequest = true;
1679    msg->changeRequest.value =(changeIp?ChangeIpFlag:0) |
1680       (changePort?ChangePortFlag:0);
1681 
1682    if ( username.sizeValue > 0 )
1683    {
1684       msg->hasUsername = true;
1685       msg->username = username;
1686    }
1687 }
1688 
1689 
1690 static void
stunSendTest(Socket myFd,StunAddress4 & dest,const StunAtrString & username,const StunAtrString & password,int testNum,bool verbose)1691 stunSendTest( Socket myFd, StunAddress4& dest,
1692               const StunAtrString& username, const StunAtrString& password,
1693               int testNum, bool verbose )
1694 {
1695    assert( dest.addr != 0 );
1696    assert( dest.port != 0 );
1697 
1698    bool changePort=false;
1699    bool changeIP=false;
1700    bool discard=false;
1701 
1702    switch (testNum)
1703    {
1704       case 1:
1705       case 10:
1706       case 11:
1707          break;
1708       case 2:
1709          //changePort=true;
1710          changeIP=true;
1711          break;
1712       case 3:
1713          changePort=true;
1714          break;
1715       case 4:
1716          changeIP=true;
1717          break;
1718       case 5:
1719          discard=true;
1720          break;
1721       default:
1722          cerr << "Test " << testNum <<" is unkown\n";
1723          assert(0);
1724    }
1725 
1726    StunMessage req;
1727    memset(&req, 0, sizeof(StunMessage));
1728 
1729    stunBuildReqSimple( &req, username,
1730                        changePort , changeIP ,
1731                        testNum );
1732 
1733    char buf[STUN_MAX_MESSAGE_SIZE];
1734    int len = STUN_MAX_MESSAGE_SIZE;
1735 
1736    len = stunEncodeMessage( req, buf, len, password,verbose );
1737 
1738    if ( verbose )
1739    {
1740       clog << "About to send msg of len " << len << " to " << dest << endl;
1741    }
1742 
1743    sendMessage( myFd, buf, len, dest.addr, dest.port, verbose );
1744 
1745    // add some delay so the packets don't get sent too quickly
1746 #ifdef WIN32 // !cj! TODO - should fix this up in windows
1747 		 clock_t now = clock();
1748 		 assert( CLOCKS_PER_SEC == 1000 );
1749 		 while ( clock() <= now+10 ) { };
1750 #else
1751 		 usleep(10*1000);
1752 #endif
1753 
1754 }
1755 
1756 
1757 void
stunGetUserNameAndPassword(const StunAddress4 & dest,StunAtrString * username,StunAtrString * password)1758 stunGetUserNameAndPassword(  const StunAddress4& dest,
1759                              StunAtrString* username,
1760                              StunAtrString* password)
1761 {
1762    // !cj! This is totally bogus - need to make TLS connection to dest and get a
1763    // username and password to use
1764    stunCreateUserName(dest, username);
1765    stunCreatePassword(*username, password);
1766 }
1767 
1768 
1769 void
stunTest(StunAddress4 & dest,int testNum,bool verbose,StunAddress4 * sAddr)1770 stunTest( StunAddress4& dest, int testNum, bool verbose, StunAddress4* sAddr )
1771 {
1772    assert( dest.addr != 0 );
1773    assert( dest.port != 0 );
1774 
1775    int port = stunRandomPort();
1776    UInt32 interfaceIp=0;
1777    if (sAddr)
1778    {
1779       interfaceIp = sAddr->addr;
1780       if ( sAddr->port != 0 )
1781       {
1782         port = sAddr->port;
1783       }
1784    }
1785    Socket myFd = openPort(port,interfaceIp,verbose);
1786 
1787    StunAtrString username;
1788    StunAtrString password;
1789 
1790    username.sizeValue = 0;
1791    password.sizeValue = 0;
1792 
1793 #ifdef USE_TLS
1794    stunGetUserNameAndPassword( dest, username, password );
1795 #endif
1796 
1797    stunSendTest( myFd, dest, username, password, testNum, verbose );
1798 
1799    char msg[STUN_MAX_MESSAGE_SIZE];
1800    int msgLen = STUN_MAX_MESSAGE_SIZE;
1801 
1802    StunAddress4 from;
1803    getMessage( myFd,
1804                msg,
1805                &msgLen,
1806                &from.addr,
1807                &from.port,verbose );
1808 
1809    StunMessage resp;
1810    memset(&resp, 0, sizeof(StunMessage));
1811 
1812    if ( verbose ) clog << "Got a response" << endl;
1813    bool ok = stunParseMessage( msg,msgLen, resp,verbose );
1814 
1815    if ( verbose )
1816    {
1817       clog << "\t ok=" << ok << endl;
1818       clog << "\t id=" << resp.msgHdr.id << endl;
1819       clog << "\t mappedAddr=" << resp.mappedAddress.ipv4 << endl;
1820       clog << "\t changedAddr=" << resp.changedAddress.ipv4 << endl;
1821       clog << endl;
1822    }
1823 
1824    if (sAddr)
1825    {
1826       sAddr->port = resp.mappedAddress.ipv4.port;
1827       sAddr->addr = resp.mappedAddress.ipv4.addr;
1828    }
1829 }
1830 
1831 
1832 NatType
stunNatType(StunAddress4 & dest,bool verbose,bool * preservePort,bool * hairpin,int port,StunAddress4 * sAddr)1833 stunNatType( StunAddress4& dest,
1834              bool verbose,
1835              bool* preservePort, // if set, is return for if NAT preservers ports or not
1836              bool* hairpin,  // if set, is the return for if NAT will hairpin packets
1837              int port, // port to use for the test, 0 to choose random port
1838              StunAddress4* sAddr // NIC to use
1839    )
1840 {
1841    assert( dest.addr != 0 );
1842    assert( dest.port != 0 );
1843 
1844    if ( hairpin )
1845    {
1846       *hairpin = false;
1847    }
1848 
1849    if ( port == 0 )
1850    {
1851       port = stunRandomPort();
1852    }
1853    UInt32 interfaceIp=0;
1854    if (sAddr)
1855    {
1856       interfaceIp = sAddr->addr;
1857    }
1858    Socket myFd1 = openPort(port,interfaceIp,verbose);
1859    Socket myFd2 = openPort(port+1,interfaceIp,verbose);
1860 
1861    if ( ( myFd1 == INVALID_SOCKET) || ( myFd2 == INVALID_SOCKET) )
1862    {
1863         cerr << "Some problem opening port/interface to send on" << endl;
1864        return StunTypeFailure;
1865    }
1866 
1867    assert( myFd1 != INVALID_SOCKET );
1868    assert( myFd2 != INVALID_SOCKET );
1869 
1870    bool respTestI=false;
1871    bool isNat=true;
1872    StunAddress4 testIchangedAddr;
1873    StunAddress4 testImappedAddr;
1874    bool respTestI2=false;
1875    bool mappedIpSame = true;
1876    StunAddress4 testI2mappedAddr;
1877    StunAddress4 testI2dest=dest;
1878    bool respTestII=false;
1879    bool respTestIII=false;
1880 
1881    bool respTestHairpin=false;
1882    bool respTestPreservePort=false;
1883 
1884    memset(&testImappedAddr,0,sizeof(testImappedAddr));
1885 
1886    StunAtrString username;
1887    StunAtrString password;
1888 
1889    username.sizeValue = 0;
1890    password.sizeValue = 0;
1891 
1892 #ifdef USE_TLS
1893    stunGetUserNameAndPassword( dest, username, password );
1894 #endif
1895 
1896    int count=0;
1897    while ( count < 7 )
1898    {
1899       struct timeval tv;
1900       fd_set fdSet;
1901 #ifdef WIN32
1902       unsigned int fdSetSize;
1903 #else
1904       int fdSetSize;
1905 #endif
1906       FD_ZERO(&fdSet); fdSetSize=0;
1907       FD_SET(myFd1,&fdSet); fdSetSize = (myFd1+1>fdSetSize) ? myFd1+1 : fdSetSize;
1908       FD_SET(myFd2,&fdSet); fdSetSize = (myFd2+1>fdSetSize) ? myFd2+1 : fdSetSize;
1909       tv.tv_sec=0;
1910       tv.tv_usec=150*1000; // 150 ms
1911       if ( count == 0 ) tv.tv_usec=0;
1912 
1913       int  err = select(fdSetSize, &fdSet, NULL, NULL, &tv);
1914       int e = getErrno();
1915       if ( err == SOCKET_ERROR )
1916       {
1917          // error occured
1918          cerr << "Error " << e << " " << strerror(e) << " in select" << endl;
1919         return StunTypeFailure;
1920      }
1921       else if ( err == 0 )
1922       {
1923          // timeout occured
1924          count++;
1925 
1926          if ( !respTestI )
1927          {
1928             stunSendTest( myFd1, dest, username, password, 1 ,verbose );
1929          }
1930 
1931          if ( (!respTestI2) && respTestI )
1932          {
1933             // check the address to send to if valid
1934             if (  ( testI2dest.addr != 0 ) &&
1935                   ( testI2dest.port != 0 ) )
1936             {
1937                stunSendTest( myFd1, testI2dest, username, password, 10  ,verbose);
1938             }
1939          }
1940 
1941          if ( !respTestII )
1942          {
1943             stunSendTest( myFd2, dest, username, password, 2 ,verbose );
1944          }
1945 
1946          if ( !respTestIII )
1947          {
1948             stunSendTest( myFd2, dest, username, password, 3 ,verbose );
1949          }
1950 
1951          if ( respTestI && (!respTestHairpin) )
1952          {
1953             if (  ( testImappedAddr.addr != 0 ) &&
1954                   ( testImappedAddr.port != 0 ) )
1955             {
1956                stunSendTest( myFd1, testImappedAddr, username, password, 11 ,verbose );
1957             }
1958          }
1959       }
1960       else
1961       {
1962          //if (verbose) clog << "-----------------------------------------" << endl;
1963          assert( err>0 );
1964          // data is avialbe on some fd
1965 
1966          for ( int i=0; i<2; i++)
1967          {
1968             Socket myFd;
1969             if ( i==0 )
1970             {
1971                myFd=myFd1;
1972             }
1973             else
1974             {
1975                myFd=myFd2;
1976             }
1977 
1978             if ( myFd!=INVALID_SOCKET )
1979             {
1980                if ( FD_ISSET(myFd,&fdSet) )
1981                {
1982                   char msg[STUN_MAX_MESSAGE_SIZE];
1983                   int msgLen = sizeof(msg);
1984 
1985                   StunAddress4 from;
1986 
1987                   getMessage( myFd,
1988                               msg,
1989                               &msgLen,
1990                               &from.addr,
1991                               &from.port,verbose );
1992 
1993                   StunMessage resp;
1994                   memset(&resp, 0, sizeof(StunMessage));
1995 
1996                   stunParseMessage( msg,msgLen, resp,verbose );
1997 
1998                   if ( verbose )
1999                   {
2000                      clog << "Received message of type " << resp.msgHdr.msgType
2001                           << "  id=" << (int)(resp.msgHdr.id.octet[0]) << endl;
2002                   }
2003 
2004                   switch( resp.msgHdr.id.octet[0] )
2005                   {
2006                      case 1:
2007                      {
2008                         if ( !respTestI )
2009                         {
2010 
2011                            testIchangedAddr.addr = resp.changedAddress.ipv4.addr;
2012                            testIchangedAddr.port = resp.changedAddress.ipv4.port;
2013                            testImappedAddr.addr = resp.mappedAddress.ipv4.addr;
2014                            testImappedAddr.port = resp.mappedAddress.ipv4.port;
2015 
2016                            respTestPreservePort = ( testImappedAddr.port == port );
2017                            if ( preservePort )
2018                            {
2019                               *preservePort = respTestPreservePort;
2020                            }
2021 
2022                            testI2dest.addr = resp.changedAddress.ipv4.addr;
2023 
2024                            if (sAddr)
2025                            {
2026                               sAddr->port = testImappedAddr.port;
2027                               sAddr->addr = testImappedAddr.addr;
2028                            }
2029 
2030                            count = 0;
2031                         }
2032                         respTestI=true;
2033                      }
2034                      break;
2035                      case 2:
2036                      {
2037                         respTestII=true;
2038                      }
2039                      break;
2040                      case 3:
2041                      {
2042                         respTestIII=true;
2043                      }
2044                      break;
2045                      case 10:
2046                      {
2047                         if ( !respTestI2 )
2048                         {
2049                            testI2mappedAddr.addr = resp.mappedAddress.ipv4.addr;
2050                            testI2mappedAddr.port = resp.mappedAddress.ipv4.port;
2051 
2052                            mappedIpSame = false;
2053                            if ( (testI2mappedAddr.addr  == testImappedAddr.addr ) &&
2054                                 (testI2mappedAddr.port == testImappedAddr.port ))
2055                            {
2056                               mappedIpSame = true;
2057                            }
2058 
2059 
2060                         }
2061                         respTestI2=true;
2062                      }
2063                      break;
2064                      case 11:
2065                      {
2066 
2067                         if ( hairpin )
2068                         {
2069                            *hairpin = true;
2070                         }
2071                         respTestHairpin = true;
2072                      }
2073                      break;
2074                   }
2075                }
2076             }
2077          }
2078       }
2079    }
2080 
2081    // see if we can bind to this address
2082    //cerr << "try binding to " << testImappedAddr << endl;
2083    Socket s = openPort( 0/*use ephemeral*/, testImappedAddr.addr, false );
2084    if ( s != INVALID_SOCKET )
2085    {
2086       closesocket(s);
2087       isNat = false;
2088       //cerr << "binding worked" << endl;
2089    }
2090    else
2091    {
2092       isNat = true;
2093       //cerr << "binding failed" << endl;
2094    }
2095 
2096    if (verbose)
2097    {
2098       clog << "test I = " << respTestI << endl;
2099       clog << "test II = " << respTestII << endl;
2100       clog << "test III = " << respTestIII << endl;
2101       clog << "test I(2) = " << respTestI2 << endl;
2102       clog << "is nat  = " << isNat <<endl;
2103       clog << "mapped IP same = " << mappedIpSame << endl;
2104       clog << "hairpin = " << respTestHairpin << endl;
2105       clog << "preserver port = " << respTestPreservePort << endl;
2106    }
2107 
2108 #if 0
2109    // implement logic flow chart from draft RFC
2110    if ( respTestI )
2111    {
2112       if ( isNat )
2113       {
2114          if (respTestII)
2115          {
2116             return StunTypeConeNat;
2117          }
2118          else
2119          {
2120             if ( mappedIpSame )
2121             {
2122                if ( respTestIII )
2123                {
2124                   return StunTypeRestrictedNat;
2125                }
2126                else
2127                {
2128                   return StunTypePortRestrictedNat;
2129                }
2130             }
2131             else
2132             {
2133                return StunTypeSymNat;
2134             }
2135          }
2136       }
2137       else
2138       {
2139          if (respTestII)
2140          {
2141             return StunTypeOpen;
2142          }
2143          else
2144          {
2145             return StunTypeSymFirewall;
2146          }
2147       }
2148    }
2149    else
2150    {
2151       return StunTypeBlocked;
2152    }
2153 #else
2154    if ( respTestI ) // not blocked
2155    {
2156       if ( isNat )
2157       {
2158          if ( mappedIpSame )
2159          {
2160             if (respTestII)
2161             {
2162                return StunTypeIndependentFilter;
2163             }
2164             else
2165             {
2166                if ( respTestIII )
2167                {
2168                   return StunTypeDependentFilter;
2169                }
2170                else
2171                {
2172                   return StunTypePortDependedFilter;
2173                }
2174             }
2175          }
2176          else // mappedIp is not same
2177          {
2178             return StunTypeDependentMapping;
2179          }
2180       }
2181       else  // isNat is false
2182       {
2183          if (respTestII)
2184          {
2185             return StunTypeOpen;
2186          }
2187          else
2188          {
2189             return StunTypeFirewall;
2190          }
2191       }
2192    }
2193    else
2194    {
2195       return StunTypeBlocked;
2196    }
2197 #endif
2198 
2199    return StunTypeUnknown;
2200 }
2201 
2202 
2203 int
stunOpenSocket(StunAddress4 & dest,StunAddress4 * mapAddr,int port,StunAddress4 * srcAddr,bool verbose)2204 stunOpenSocket( StunAddress4& dest, StunAddress4* mapAddr,
2205                 int port, StunAddress4* srcAddr,
2206                 bool verbose )
2207 {
2208    assert( dest.addr != 0 );
2209    assert( dest.port != 0 );
2210    assert( mapAddr );
2211 
2212    if ( port == 0 )
2213    {
2214       port = stunRandomPort();
2215    }
2216    unsigned int interfaceIp = 0;
2217    if ( srcAddr )
2218    {
2219       interfaceIp = srcAddr->addr;
2220    }
2221 
2222    Socket myFd = openPort(port,interfaceIp,verbose);
2223    if (myFd == INVALID_SOCKET)
2224    {
2225       return myFd;
2226    }
2227 
2228    char msg[STUN_MAX_MESSAGE_SIZE];
2229    int msgLen = sizeof(msg);
2230 
2231    StunAtrString username;
2232    StunAtrString password;
2233 
2234    username.sizeValue = 0;
2235    password.sizeValue = 0;
2236 
2237 #ifdef USE_TLS
2238    stunGetUserNameAndPassword( dest, username, password );
2239 #endif
2240 
2241    stunSendTest(myFd, dest, username, password, 1, 0/*false*/ );
2242 
2243    StunAddress4 from;
2244 
2245    getMessage( myFd, msg, &msgLen, &from.addr, &from.port,verbose );
2246 
2247    StunMessage resp;
2248    memset(&resp, 0, sizeof(StunMessage));
2249 
2250    bool ok = stunParseMessage( msg, msgLen, resp,verbose );
2251    if (!ok)
2252    {
2253       return -1;
2254    }
2255 
2256    StunAddress4 mappedAddr = resp.mappedAddress.ipv4;
2257    StunAddress4 changedAddr = resp.changedAddress.ipv4;
2258 
2259    //clog << "--- stunOpenSocket --- " << endl;
2260    //clog << "\treq  id=" << req.id << endl;
2261    //clog << "\tresp id=" << id << endl;
2262    //clog << "\tmappedAddr=" << mappedAddr << endl;
2263 
2264    *mapAddr = mappedAddr;
2265 
2266    return myFd;
2267 }
2268 
2269 
2270 bool
stunOpenSocketPair(StunAddress4 & dest,StunAddress4 * mapAddr,int * fd1,int * fd2,int port,StunAddress4 * srcAddr,bool verbose)2271 stunOpenSocketPair( StunAddress4& dest, StunAddress4* mapAddr,
2272                     int* fd1, int* fd2,
2273                     int port, StunAddress4* srcAddr,
2274                     bool verbose )
2275 {
2276    assert( dest.addr!= 0 );
2277    assert( dest.port != 0 );
2278    assert( mapAddr );
2279 
2280    const int NUM=3;
2281 
2282    if ( port == 0 )
2283    {
2284       port = stunRandomPort();
2285    }
2286 
2287    *fd1=-1;
2288    *fd2=-1;
2289 
2290    char msg[STUN_MAX_MESSAGE_SIZE];
2291    int msgLen =sizeof(msg);
2292 
2293    StunAddress4 from;
2294    int fd[NUM];
2295    int i;
2296 
2297    unsigned int interfaceIp = 0;
2298    if ( srcAddr )
2299    {
2300       interfaceIp = srcAddr->addr;
2301    }
2302 
2303    for( i=0; i<NUM; i++)
2304    {
2305       fd[i] = openPort( (port == 0) ? 0 : (port + i),
2306                         interfaceIp, verbose);
2307       if (fd[i] < 0)
2308       {
2309          while (i > 0)
2310          {
2311             closesocket(fd[--i]);
2312          }
2313          return false;
2314       }
2315    }
2316 
2317    StunAtrString username;
2318    StunAtrString password;
2319 
2320    username.sizeValue = 0;
2321    password.sizeValue = 0;
2322 
2323 #ifdef USE_TLS
2324    stunGetUserNameAndPassword( dest, username, password );
2325 #endif
2326 
2327    for( i=0; i<NUM; i++)
2328    {
2329       stunSendTest(fd[i], dest, username, password, 1/*testNum*/, verbose );
2330    }
2331 
2332    StunAddress4 mappedAddr[NUM];
2333    for( i=0; i<NUM; i++)
2334    {
2335       msgLen = sizeof(msg)/sizeof(*msg);
2336       getMessage( fd[i],
2337                   msg,
2338                   &msgLen,
2339                   &from.addr,
2340                   &from.port ,verbose);
2341 
2342       StunMessage resp;
2343       memset(&resp, 0, sizeof(StunMessage));
2344 
2345       bool ok = stunParseMessage( msg, msgLen, resp, verbose );
2346       if (!ok)
2347       {
2348          return false;
2349       }
2350 
2351       mappedAddr[i] = resp.mappedAddress.ipv4;
2352       StunAddress4 changedAddr = resp.changedAddress.ipv4;
2353    }
2354 
2355    if (verbose)
2356    {
2357       clog << "--- stunOpenSocketPair --- " << endl;
2358       for( i=0; i<NUM; i++)
2359       {
2360          clog << "\t mappedAddr=" << mappedAddr[i] << endl;
2361       }
2362    }
2363 
2364    if ( mappedAddr[0].port %2 == 0 )
2365    {
2366       if (  mappedAddr[0].port+1 ==  mappedAddr[1].port )
2367       {
2368          *mapAddr = mappedAddr[0];
2369          *fd1 = fd[0];
2370          *fd2 = fd[1];
2371          closesocket( fd[2] );
2372          return true;
2373       }
2374    }
2375    else
2376    {
2377       if (( mappedAddr[1].port %2 == 0 )
2378           && (  mappedAddr[1].port+1 ==  mappedAddr[2].port ))
2379       {
2380          *mapAddr = mappedAddr[1];
2381          *fd1 = fd[1];
2382          *fd2 = fd[2];
2383          closesocket( fd[0] );
2384          return true;
2385       }
2386    }
2387 
2388    // something failed, close all and return error
2389    for( i=0; i<NUM; i++)
2390    {
2391       closesocket( fd[i] );
2392    }
2393 
2394    return false;
2395 }
2396 
2397 /* ====================================================================
2398  * The Vovida Software License, Version 1.0
2399  *
2400  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
2401  *
2402  * Redistribution and use in source and binary forms, with or without
2403  * modification, are permitted provided that the following conditions
2404  * are met:
2405  *
2406  * 1. Redistributions of source code must retain the above copyright
2407  *    notice, this list of conditions and the following disclaimer.
2408  *
2409  * 2. Redistributions in binary form must reproduce the above copyright
2410  *    notice, this list of conditions and the following disclaimer in
2411  *    the documentation and/or other materials provided with the
2412  *    distribution.
2413  *
2414  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
2415  *    and "Vovida Open Communication Application Library (VOCAL)" must
2416  *    not be used to endorse or promote products derived from this
2417  *    software without prior written permission. For written
2418  *    permission, please contact vocal@vovida.org.
2419  *
2420  * 4. Products derived from this software may not be called "VOCAL", nor
2421  *    may "VOCAL" appear in their name, without prior written
2422  *    permission of Vovida Networks, Inc.
2423  *
2424  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
2425  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2426  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
2427  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
2428  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
2429  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
2430  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2431  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2432  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2433  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2434  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2435  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2436  * DAMAGE.
2437  *
2438  * ====================================================================
2439  *
2440  * This software consists of voluntary contributions made by Vovida
2441  * Networks, Inc. and many individuals on behalf of Vovida Networks,
2442  * Inc.  For more information on Vovida Networks, Inc., please see
2443  * <http://www.vovida.org/>.
2444  *
2445  */
2446 
2447 // Local Variables:
2448 // mode:c++
2449 // c-file-style:"ellemtel"
2450 // c-file-offsets:((case-label . +))
2451 // indent-tabs-mode:nil
2452 // End:
2453 
2454 
2455