BBS2chProxyAuth.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #include <time.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <sstream>
  5. #include <iomanip>
  6. #include "BBS2chProxyAuth.h"
  7. #include "DataStorage.h"
  8. #include "hmac.h"
  9. #define SID_UPDATE_INTERVAL (60*60)
  10. extern char *proxy_server;
  11. extern long proxy_port;
  12. extern long proxy_type;
  13. extern long timeout;
  14. extern char *user_agent;
  15. extern char *appKey;
  16. extern char *hmacKey;
  17. extern char *api_ua_auth;
  18. extern char *x_2ch_ua_auth;
  19. extern int force_ipv4;
  20. extern char *api_server;
  21. extern CURLSH *curl_share;
  22. extern void log_printf(int level, const char *format ...);
  23. static size_t write_callback_download(char *buffer, size_t size, size_t nitems, void *userdata)
  24. {
  25. DataStorage *data = reinterpret_cast<DataStorage *>(userdata);
  26. size_t downloaded = size*nitems;
  27. data->appendBytes(buffer, downloaded);
  28. return downloaded;
  29. }
  30. bool BBS2chProxyAuth::updateSID(CURL *curl)
  31. {
  32. int ct = time(0);
  33. bool ret = false;
  34. pthread_mutex_lock(mutex);
  35. if(ct < expire) {
  36. ret = true;
  37. goto last;
  38. }
  39. if(curl) {
  40. CURLcode res;
  41. struct curl_slist *headers = NULL;
  42. DataStorage *dat = new DataStorage();
  43. char gateway[1024];
  44. snprintf(gateway,1024,"https://%s/v1/auth/",api_server);
  45. if(curl_share) curl_easy_setopt(curl, CURLOPT_SHARE, curl_share);
  46. curl_easy_setopt(curl, CURLOPT_URL, gateway);
  47. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
  48. curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
  49. curl_easy_setopt(curl, CURLOPT_ENCODING, "");
  50. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback_download);
  51. curl_easy_setopt(curl, CURLOPT_WRITEDATA, dat);
  52. curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
  53. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
  54. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
  55. if(force_ipv4) curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
  56. if(proxy_server) {
  57. curl_easy_setopt(curl, CURLOPT_PROXY, proxy_server);
  58. curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxy_port);
  59. curl_easy_setopt(curl, CURLOPT_PROXYTYPE, proxy_type);
  60. }
  61. if (api_ua_auth) {
  62. curl_easy_setopt(curl, CURLOPT_USERAGENT, api_ua_auth);
  63. }
  64. else {
  65. if (user_agent && !strncmp(user_agent, "Monazilla/", strlen("Monazilla/")))
  66. curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent);
  67. else
  68. curl_easy_setopt(curl, CURLOPT_USERAGENT, "");
  69. }
  70. if(x_2ch_ua_auth) headers = curl_slist_append(headers, x_2ch_ua_auth);
  71. if(headers) curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  72. curl_easy_setopt(curl, CURLOPT_POST, 1L);
  73. std::stringstream postData;
  74. std::stringstream msg;
  75. postData << "ID=&PW=&KY=" << appKey << "&CT=" << ct << "&HB=";
  76. msg << appKey << ct;
  77. unsigned char digest[32];
  78. proxy2ch_HMAC_SHA256(hmacKey, strlen(hmacKey), msg.str().c_str(), msg.str().length(), digest);
  79. for(int i=0;i<32;i++) {
  80. postData << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)digest[i];
  81. }
  82. #if LIBCURL_VERSION_NUM >= 0x071101
  83. curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, postData.str().c_str());
  84. #else
  85. std::string postDataStr = postData.str();
  86. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postDataStr.c_str());
  87. #endif
  88. res = curl_easy_perform(curl);
  89. if(res == CURLE_OK) {
  90. long statusCode;
  91. curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE, &statusCode);
  92. //fprintf(stderr,"%ld\n",statusCode);
  93. if(statusCode == 200) {
  94. dat->appendBytes("",1);
  95. char *ptr = strchr(dat->bytes,':');
  96. if(ptr && !strncmp(dat->bytes,"SESSION-ID=Monazilla",20)) {
  97. sid = std::string(ptr+1);
  98. expire = ct + SID_UPDATE_INTERVAL;
  99. ret = true;
  100. log_printf(1,"Updated SID: %s\n",sid.c_str());
  101. }
  102. else {
  103. log_printf(0,"Cannot update SID: %s\n",dat->bytes);
  104. }
  105. }
  106. else {
  107. log_printf(0,"Cannot update SID: API gateway returned %ld\n",statusCode);
  108. }
  109. }
  110. else log_printf(0,"curl error while updating SID: %s\n",curl_easy_strerror(res));
  111. curl_slist_free_all(headers);
  112. curl_easy_reset(curl);
  113. delete dat;
  114. }
  115. last:
  116. pthread_mutex_unlock(mutex);
  117. return ret;
  118. }
  119. std::string BBS2chProxyAuth::requestBodyForURL(const char *url, CURL *curl)
  120. {
  121. if (!updateSID(curl) || sid.empty()) return "";
  122. std::stringstream postData;
  123. std::stringstream msg;
  124. postData << "sid=" << sid << "&appkey=" << appKey << "&hobo=";
  125. msg << strstr(url,"/v1/") << sid << appKey;
  126. unsigned char digest[32];
  127. proxy2ch_HMAC_SHA256(hmacKey, strlen(hmacKey), msg.str().c_str(), msg.str().length(), digest);
  128. for(int i=0;i<32;i++) {
  129. postData << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)digest[i];
  130. }
  131. return postData.str();
  132. }