123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- #include <curl/curl.h>
- #include <time.h>
- #include <string.h>
- #include <stdio.h>
- #if defined(USE_GNUTLS)
- #include <gnutls/gnutls.h>
- #include <gnutls/crypto.h>
- #elif defined(__APPLE__)
- #define USE_CC_CRYPT 1
- #include <CommonCrypto/CommonDigest.h>
- #elif defined(_WIN32)
- #include <windows.h>
- #include <wincrypt.h>
- #else
- #include <openssl/sha.h>
- #endif
- #include <sstream>
- #include <iomanip>
- #include "BBS2chProxyAuth.h"
- #include "DataStorage.h"
- #define SID_UPDATE_INTERVAL (60*60)
- #ifdef USE_CC_CRYPT
- #define SHA256_CTX CC_SHA256_CTX
- #define SHA256_Init CC_SHA256_Init
- #define SHA256_Update CC_SHA256_Update
- #define SHA256_Final CC_SHA256_Final
- #endif
- extern char *proxy_server;
- extern long proxy_port;
- extern long proxy_type;
- extern long timeout;
- extern char *user_agent;
- extern char *appKey;
- extern char *hmacKey;
- extern char *api_ua_auth;
- extern char *x_2ch_ua_auth;
- extern int force_ipv4;
- extern char *api_server;
- extern int force_5chnet_https;
- extern CURLSH *curl_share;
- extern void log_printf(int level, const char *format ...);
- typedef struct
- {
- #ifdef _WIN32
- HCRYPTPROV prov;
- HCRYPTHASH sha;
- #elif defined(USE_GNUTLS)
- gnutls_hmac_hd_t hmac;
- #else
- SHA256_CTX sha;
- #endif
- unsigned char keybuf[64];
- } hmac_sha256_t;
- static void HMAC_SHA256_Init(hmac_sha256_t *hmac, const void *key, int length)
- {
- #ifdef _WIN32
- int i;
- CryptAcquireContext(&hmac->prov,NULL,NULL,PROV_RSA_AES,CRYPT_VERIFYCONTEXT);
- if(length > 64) {
- unsigned char digest[32];
- HCRYPTHASH sha;
- DWORD bufLength = 32;
- CryptCreateHash(hmac->prov,CALG_SHA_256,0,0,&sha);
- CryptHashData(sha,(PBYTE)key,length,0);
- CryptGetHashParam(sha,HP_HASHVAL,hmac->keybuf,&bufLength,0);
- CryptDestroyHash(sha);
- }
- else memcpy(hmac->keybuf,key,length);
- for(i=length;i<64;i++) hmac->keybuf[i] = 0;
- for(i=0;i<64;i++) hmac->keybuf[i] ^= 0x36;
- CryptCreateHash(hmac->prov,CALG_SHA_256,0,0,&hmac->sha);
- CryptHashData(hmac->sha,hmac->keybuf,64,0);
- #elif defined(USE_GNUTLS)
- gnutls_hmac_init(&hmac->hmac, GNUTLS_MAC_SHA256, key, length);
- #else
- int i;
- if(length > 64) {
- unsigned char digest[32];
- SHA256_CTX sha;
- SHA256_Init(&sha);
- SHA256_Update(&sha,key,length);
- SHA256_Final(digest,&sha);
- memcpy(hmac->keybuf,digest,32);
- length = 32;
- }
- else memcpy(hmac->keybuf,key,length);
- for(i=length;i<64;i++) hmac->keybuf[i] = 0;
- for(i=0;i<64;i++) hmac->keybuf[i] ^= 0x36;
- SHA256_Init(&hmac->sha);
- SHA256_Update(&hmac->sha,hmac->keybuf,64);
- #endif
- }
- static void HMAC_SHA256_Update(hmac_sha256_t *hmac, const void *data, int length)
- {
- #ifdef _WIN32
- CryptHashData(hmac->sha,(PBYTE)data,length,0);
- #elif defined(USE_GNUTLS)
- gnutls_hmac(hmac->hmac, data, length);
- #else
- SHA256_Update(&hmac->sha,data,length);
- #endif
- }
- static void HMAC_SHA256_Final(hmac_sha256_t *hmac, unsigned char *md)
- {
- #ifdef _WIN32
- DWORD i, bufLength = 32;
- CryptGetHashParam(hmac->sha,HP_HASHVAL,md,&bufLength,0);
- CryptDestroyHash(hmac->sha);
- HCRYPTHASH sha;
- CryptCreateHash(hmac->prov,CALG_SHA_256,0,0,&sha);
- for(i=0;i<64;i++) hmac->keybuf[i] ^= 0x36 ^ 0x5c;
- CryptHashData(sha,hmac->keybuf,64,0);
- CryptHashData(sha,md,32,0);
- CryptGetHashParam(sha,HP_HASHVAL,md,&bufLength,0);
- CryptDestroyHash(sha);
- CryptReleaseContext(hmac->prov, 0);
- #elif defined(USE_GNUTLS)
- gnutls_hmac_deinit(hmac->hmac, md);
- #else
- int i;
- SHA256_Final(md,&hmac->sha);
- SHA256_CTX sha;
- SHA256_Init(&sha);
- for(i=0;i<64;i++) hmac->keybuf[i] ^= 0x36 ^ 0x5c;
- SHA256_Update(&sha,hmac->keybuf,64);
- SHA256_Update(&sha,md,32);
- SHA256_Final(md,&sha);
- #endif
- }
- static size_t write_callback_download(char *buffer, size_t size, size_t nitems, void *userdata)
- {
- DataStorage *data = reinterpret_cast<DataStorage *>(userdata);
- size_t downloaded = size*nitems;
- data->appendBytes(buffer, downloaded);
- return downloaded;
- }
- bool BBS2chProxyAuth::updateSID(void)
- {
- int ct = time(0);
- bool ret = false;
- CURL *curl;
- pthread_mutex_lock(mutex);
- if(ct < expire) {
- ret = true;
- goto last;
- }
-
- curl = curl_easy_init();
- if(curl) {
- CURLcode res;
- struct curl_slist *headers = NULL;
- DataStorage *dat = new DataStorage();
- char gateway[1024];
- if(force_5chnet_https) sprintf(gateway,"https://%s/v1/auth/",api_server);
- else sprintf(gateway,"http://%s/v1/auth/",api_server);
- if(curl_share) curl_easy_setopt(curl, CURLOPT_SHARE, curl_share);
- curl_easy_setopt(curl, CURLOPT_URL, gateway);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
- curl_easy_setopt(curl, CURLOPT_ENCODING, "");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback_download);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, dat);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
- if(force_ipv4) curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
- if(proxy_server) {
- curl_easy_setopt(curl, CURLOPT_PROXY, proxy_server);
- curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxy_port);
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, proxy_type);
- }
- curl_easy_setopt(curl, CURLOPT_USERAGENT, api_ua_auth?api_ua_auth:"");
- if(x_2ch_ua_auth) headers = curl_slist_append(headers, x_2ch_ua_auth);
- if(headers) curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
- curl_easy_setopt(curl, CURLOPT_POST, 1L);
-
- std::stringstream postData;
- std::stringstream msg;
- postData << "ID=&PW=&KY=" << appKey << "&CT=" << ct << "&HB=";
- msg << appKey << ct;
-
- hmac_sha256_t hmac;
- unsigned char digest[32];
- HMAC_SHA256_Init(&hmac, hmacKey, strlen(hmacKey));
- HMAC_SHA256_Update(&hmac, msg.str().c_str(), msg.str().length());
- HMAC_SHA256_Final(&hmac, digest);
- for(int i=0;i<32;i++) {
- postData << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)digest[i];
- }
- #if LIBCURL_VERSION_NUM >= 0x071101
- curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, postData.str().c_str());
- #else
- std::string postDataStr = postData.str();
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postDataStr.c_str());
- #endif
-
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long statusCode;
- curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE, &statusCode);
- //fprintf(stderr,"%ld\n",statusCode);
- if(statusCode == 200) {
- dat->appendBytes("",1);
- char *ptr = strchr(dat->bytes,':');
- if(ptr && !strncmp(dat->bytes,"SESSION-ID=Monazilla",20)) {
- sid = std::string(ptr+1);
- expire = ct + SID_UPDATE_INTERVAL;
- ret = true;
- log_printf(1,"Updated SID: %s\n",sid.c_str());
- }
- else {
- log_printf(0,"Cannot update SID: %s\n",dat->bytes);
- }
- }
- else {
- log_printf(0,"Cannot update SID: API gateway returned %ld\n",statusCode);
- }
- }
- else log_printf(0,"curl error while updating SID: %s\n",curl_easy_strerror(res));
- curl_slist_free_all(headers);
- curl_easy_cleanup(curl);
- delete dat;
- }
- last:
- pthread_mutex_unlock(mutex);
- return ret;
- }
- const std::string BBS2chProxyAuth::requestBodyForURL(const char *url)
- {
- if(!this->updateSID() || sid.empty()) return "";
- std::stringstream postData;
- std::stringstream msg;
- postData << "sid=" << sid << "&appkey=" << appKey << "&hobo=";
- msg << strstr(url,"/v1/") << sid << appKey;
-
- hmac_sha256_t hmac;
- unsigned char digest[32];
- HMAC_SHA256_Init(&hmac, hmacKey, strlen(hmacKey));
- HMAC_SHA256_Update(&hmac, msg.str().c_str(), msg.str().length());
- HMAC_SHA256_Final(&hmac, digest);
- for(int i=0;i<32;i++) {
- postData << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)digest[i];
- }
-
- return postData.str();
- }
|