util.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. ** JNetLib
  3. ** Copyright (C) 2000-2007 Nullsoft, Inc.
  4. ** Author: Justin Frankel
  5. ** File: util.cpp - JNL implementation of basic network utilities
  6. ** License: see jnetlib.h
  7. */
  8. #include "netinc.h"
  9. #include "util.h"
  10. #include "foundation\error.h"
  11. #ifdef USE_SSL
  12. #include "wac_network_ssl_connection.h"
  13. #ifdef _WIN32
  14. #include <wincrypt.h>
  15. #endif // !_WIN32
  16. #include <openssl/rand.h>
  17. #ifdef _WIN32
  18. static HCRYPTPROV GetKeySet()
  19. {
  20. HCRYPTPROV hCryptProv;
  21. LPCWSTR UserName = L"WinampKeyContainer"; // name of the key container
  22. if ( CryptAcquireContext(
  23. &hCryptProv, // handle to the CSP
  24. UserName, // container name
  25. NULL, // use the default provider
  26. PROV_RSA_FULL, // provider type
  27. 0 ) ) // flag values
  28. {
  29. return hCryptProv;
  30. }
  31. else if ( CryptAcquireContext(
  32. &hCryptProv,
  33. UserName,
  34. NULL,
  35. PROV_RSA_FULL,
  36. CRYPT_NEWKEYSET ) )
  37. {
  38. return hCryptProv;
  39. }
  40. else
  41. return 0;
  42. }
  43. #endif
  44. static void InitSSL()
  45. {
  46. SSL_load_error_strings();
  47. SSL_library_init();
  48. #ifdef _WIN32
  49. HCRYPTPROV hCryptProv = GetKeySet();
  50. if ( hCryptProv )
  51. {
  52. BYTE pbData[ 8 * sizeof( unsigned long ) ] = { 0 };
  53. if ( CryptGenRandom( hCryptProv, 8 * sizeof( unsigned long ), pbData ) )
  54. {
  55. RAND_seed( pbData, 16 );
  56. }
  57. CryptReleaseContext( hCryptProv, 0 );
  58. }
  59. #endif
  60. // sslContext = SSL_CTX_new(SSLv23_client_method());
  61. // SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
  62. // SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
  63. }
  64. static int open_ssl_initted = 0;
  65. #endif
  66. static int was_initted = 0;
  67. int JNL::open_socketlib()
  68. {
  69. #ifdef _WIN32
  70. if ( !was_initted )
  71. {
  72. WSADATA wsaData = { 0 };
  73. if ( WSAStartup( MAKEWORD( 1, 1 ), &wsaData ) )
  74. {
  75. return NErr_Error;
  76. }
  77. }
  78. #endif // !_WIN32
  79. #ifdef USE_SSL
  80. if ( !open_ssl_initted )
  81. {
  82. InitSSL();
  83. open_ssl_initted = 1;
  84. }
  85. #endif // !USE_SSL
  86. return NErr_Success;
  87. }
  88. void JNL::close_socketlib()
  89. {
  90. #ifdef _WIN32
  91. if ( was_initted )
  92. {
  93. WSACleanup();
  94. }
  95. #ifdef USE_SSL
  96. // TODO need to do some reference counting to free this correctly
  97. //SSL_CTX_free(sslContext);
  98. #endif // !USE_SSL
  99. #endif // !_WIN32
  100. }
  101. static char *jnl_strndup( const char *str, size_t n )
  102. {
  103. char *o = (char *)calloc( n + 1, sizeof( char ) );
  104. if ( !o )
  105. return 0;
  106. strncpy( o, str, n );
  107. o[ n ] = 0;
  108. return o;
  109. }
  110. int JNL::parse_url( const char *url, char **prot, char **host, unsigned short *port, char **req, char **lp )
  111. {
  112. free( *prot ); *prot = 0;
  113. free( *host ); *host = 0;
  114. free( *req ); *req = 0;
  115. free( *lp ); *lp = 0;
  116. *port = 0;
  117. const char *p;
  118. const char *protocol = strstr( url, "://" );
  119. if ( protocol )
  120. {
  121. *prot = jnl_strndup( url, protocol - url );
  122. p = protocol + 3;
  123. }
  124. else
  125. {
  126. p = url;
  127. }
  128. while ( p && *p && *p == '/' ) p++; // skip extra /
  129. size_t end = strcspn( p, "@/" );
  130. // check for username
  131. if ( p[ end ] == '@' )
  132. {
  133. *lp = jnl_strndup( p, end );
  134. p = p + end + 1;
  135. end = strcspn( p, "[:/" );
  136. }
  137. if ( p[ 0 ] == '[' ) // IPv6 style address
  138. {
  139. p++;
  140. const char *ipv6_end = strchr( p, ']' );
  141. if ( !ipv6_end )
  142. return NErr_Malformed;
  143. *host = jnl_strndup( p, ipv6_end - p );
  144. p = ipv6_end + 1;
  145. }
  146. else
  147. {
  148. end = strcspn( p, ":/" );
  149. *host = jnl_strndup( p, end );
  150. p += end;
  151. }
  152. // is there a port number?
  153. if ( p[ 0 ] == ':' )
  154. {
  155. char *new_end;
  156. *port = (unsigned short)strtoul( p + 1, &new_end, 10 );
  157. p = new_end;
  158. }
  159. if ( p[ 0 ] )
  160. {
  161. // benski> this is here to workaround a bug with YP and NSV streams
  162. if ( !strcmp( p, ";stream.nsv" ) )
  163. return NErr_Success;
  164. *req = _strdup( p );
  165. }
  166. return NErr_Success;
  167. }
  168. #if 0
  169. unsigned long JNL::ipstr_to_addr( const char *cp )
  170. {
  171. return inet_addr( cp );
  172. }
  173. void JNL::addr_to_ipstr( unsigned long addr, char *host, int maxhostlen )
  174. {
  175. in_addr a; a.s_addr = addr;
  176. sprintf( host, /*maxhostlen,*/ "%u.%u.%u.%u", a.S_un.S_un_b.s_b1, a.S_un.S_un_b.s_b2, a.S_un.S_un_b.s_b3, a.S_un.S_un_b.s_b4 );
  177. //char *p=::inet_ntoa(a); strncpy(host,p?p:"",maxhostlen);
  178. }
  179. #endif