util.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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 "sslconnection.h"
  13. #ifdef _WIN32
  14. #include <wincrypt.h>
  15. #endif
  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
  79. #ifdef USE_SSL
  80. if (!open_ssl_initted)
  81. {
  82. InitSSL();
  83. open_ssl_initted=1;
  84. }
  85. #endif
  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
  99. #endif
  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. {
  106. return 0;
  107. }
  108. strncpy(o, str, n);
  109. o[n]=0;
  110. return o;
  111. }
  112. int JNL::parse_url(const char *url, char **prot, char **host, unsigned short *port, char **req, char **lp)
  113. {
  114. free(*prot); *prot=0;
  115. free(*host); *host = 0;
  116. free(*req); *req = 0;
  117. free(*lp); *lp = 0;
  118. *port = 0;
  119. const char *p;
  120. const char *protocol = strstr(url, "://");
  121. if (protocol)
  122. {
  123. *prot = jnl_strndup(url, protocol-url);
  124. p = protocol + 3;
  125. }
  126. else
  127. {
  128. p = url;
  129. }
  130. while (p && *p && *p == '/') p++; // skip extra /
  131. size_t end = strcspn(p, "@/");
  132. // check for username
  133. if (p[end] == '@')
  134. {
  135. *lp = jnl_strndup(p, end);
  136. p = p+end+1;
  137. end = strcspn(p, "[:/");
  138. }
  139. if (p[0] == '[') // IPv6 style address
  140. {
  141. p++;
  142. const char *ipv6_end = strchr(p, ']');
  143. if (!ipv6_end)
  144. return NErr_Malformed;
  145. *host = jnl_strndup(p, ipv6_end-p);
  146. p = ipv6_end+1;
  147. }
  148. else
  149. {
  150. end = strcspn(p, ":/");
  151. *host = jnl_strndup(p, end);
  152. p += end;
  153. }
  154. // is there a port number?
  155. if (p[0] == ':')
  156. {
  157. char *new_end;
  158. *port = (unsigned short)strtoul(p+1, &new_end, 10);
  159. p = new_end;
  160. }
  161. if (p[0])
  162. {
  163. *req = _strdup(p);
  164. }
  165. return NErr_Success;
  166. }