⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpcommon.cc

📁 本人收集整理的一份c/c++跨平台网络库
💻 CC
📖 第 1 页 / 共 2 页
字号:
    version = HVER_1_1;  } else {    return HE_PROTOCOL;  }  std::string sverb(line, vend);  if (!FromString(verb, sverb.c_str())) {    return HE_PROTOCOL; // !?! HC_METHOD_NOT_SUPPORTED?  }  path.assign(line + dstart, line + dend);  return HE_NONE;}//// HttpResponseData//voidHttpResponseData::clear(bool release_document) {  HttpData::clear(release_document);  scode = HC_INTERNAL_SERVER_ERROR;  message.clear();}voidHttpResponseData::set_success(uint32 scode) {  this->scode = scode;  message.clear();  setHeader(HH_CONTENT_LENGTH, "0");}voidHttpResponseData::set_success(const std::string& content_type,                              StreamInterface* document,                              uint32 scode) {  this->scode = scode;  message.erase(message.begin(), message.end());  setContent(content_type, document);}voidHttpResponseData::set_redirect(const std::string& location, uint32 scode) {  this->scode = scode;  message.clear();  setHeader(HH_LOCATION, location);  setHeader(HH_CONTENT_LENGTH, "0");}voidHttpResponseData::set_error(uint32 scode) {  this->scode = scode;  message.clear();  setHeader(HH_CONTENT_LENGTH, "0");}size_tHttpResponseData::formatLeader(char* buffer, size_t size) {  size_t len = sprintfn(buffer, size, "HTTP/%s %lu", ToString(version), scode);  if (!message.empty()) {    len += sprintfn(buffer + len, size - len, " %.*s",                    message.size(), message.data());  }  return len;}HttpErrorHttpResponseData::parseLeader(const char* line, size_t len) {  size_t pos = 0;  uint32 vmajor, vminor;  if ((sscanf(line, "HTTP/%lu.%lu %lu%n", &vmajor, &vminor, &scode, &pos) != 3)      || (vmajor != 1)) {    return HE_PROTOCOL;  }  if (vminor == 0) {    version = HVER_1_0;  } else if (vminor == 1) {    version = HVER_1_1;  } else {    return HE_PROTOCOL;  }  while ((pos < len) && isspace(static_cast<unsigned char>(line[pos]))) ++pos;  message.assign(line + pos, len - pos);  return HE_NONE;}//////////////////////////////////////////////////////////////////////// Http Authentication//////////////////////////////////////////////////////////////////////#define TEST_DIGEST 0#if TEST_DIGEST/*const char * const DIGEST_CHALLENGE =  "Digest realm=\"testrealm@host.com\","  " qop=\"auth,auth-int\","  " nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\","  " opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";const char * const DIGEST_METHOD = "GET";const char * const DIGEST_URI =  "/dir/index.html";;const char * const DIGEST_CNONCE =  "0a4f113b";const char * const DIGEST_RESPONSE =  "6629fae49393a05397450978507c4ef1";//user_ = "Mufasa";//pass_ = "Circle Of Life";*/const char * const DIGEST_CHALLENGE =  "Digest realm=\"Squid proxy-caching web server\","  " nonce=\"Nny4QuC5PwiSDixJ\","  " qop=\"auth\","  " stale=false";const char * const DIGEST_URI =  "/";const char * const DIGEST_CNONCE =  "6501d58e9a21cee1e7b5fec894ded024";const char * const DIGEST_RESPONSE =  "edffcb0829e755838b073a4a42de06bc";#endifstatic std::string quote(const std::string& str) {  std::string result;  result.push_back('"');  for (size_t i=0; i<str.size(); ++i) {    if ((str[i] == '"') || (str[i] == '\\'))      result.push_back('\\');    result.push_back(str[i]);  }  result.push_back('"');  return result;}#ifdef WIN32struct NegotiateAuthContext : public HttpAuthContext {  CredHandle cred;  CtxtHandle ctx;  size_t steps;  bool specified_credentials;  NegotiateAuthContext(const std::string& auth, CredHandle c1, CtxtHandle c2)  : HttpAuthContext(auth), cred(c1), ctx(c2), steps(0),    specified_credentials(false)  { }  virtual ~NegotiateAuthContext() {    DeleteSecurityContext(&ctx);    FreeCredentialsHandle(&cred);  }};#endif // WIN32HttpAuthResult HttpAuthenticate(  const char * challenge, size_t len,  const SocketAddress& server,  const std::string& method, const std::string& uri,  const std::string& username, const CryptString& password,  HttpAuthContext *& context, std::string& response, std::string& auth_method){#if TEST_DIGEST  challenge = DIGEST_CHALLENGE;  len = strlen(challenge);#endif  HttpAttributeList args;  HttpParseAttributes(challenge, len, args);  HttpHasNthAttribute(args, 0, &auth_method, NULL);  if (context && (context->auth_method != auth_method))    return HAR_IGNORE;  // BASIC  if (_stricmp(auth_method.c_str(), "basic") == 0) {    if (context)      return HAR_CREDENTIALS; // Bad credentials    if (username.empty())      return HAR_CREDENTIALS; // Missing credentials    context = new HttpAuthContext(auth_method);    // TODO: convert sensitive to a secure buffer that gets securely deleted    //std::string decoded = username + ":" + password;    size_t len = username.size() + password.GetLength() + 2;    char * sensitive = new char[len];    size_t pos = strcpyn(sensitive, len, username.data(), username.size());    pos += strcpyn(sensitive + pos, len - pos, ":");    password.CopyTo(sensitive + pos, true);    response = auth_method;    response.append(" ");    // TODO: create a sensitive-source version of Base64::encode    response.append(Base64::encode(sensitive));    memset(sensitive, 0, len);    delete [] sensitive;    return HAR_RESPONSE;  }  // DIGEST  if (_stricmp(auth_method.c_str(), "digest") == 0) {    if (context)      return HAR_CREDENTIALS; // Bad credentials    if (username.empty())      return HAR_CREDENTIALS; // Missing credentials    context = new HttpAuthContext(auth_method);    std::string cnonce, ncount;#if TEST_DIGEST    method = DIGEST_METHOD;    uri    = DIGEST_URI;    cnonce = DIGEST_CNONCE;#else    char buffer[256];    sprintf(buffer, "%d", time(0));    cnonce = MD5(buffer);#endif    ncount = "00000001";    std::string realm, nonce, qop, opaque;    HttpHasAttribute(args, "realm", &realm);    HttpHasAttribute(args, "nonce", &nonce);    bool has_qop = HttpHasAttribute(args, "qop", &qop);    bool has_opaque = HttpHasAttribute(args, "opaque", &opaque);    // TODO: convert sensitive to be secure buffer    //std::string A1 = username + ":" + realm + ":" + password;    size_t len = username.size() + realm.size() + password.GetLength() + 3;    char * sensitive = new char[len];  // A1    size_t pos = strcpyn(sensitive, len, username.data(), username.size());    pos += strcpyn(sensitive + pos, len - pos, ":");    pos += strcpyn(sensitive + pos, len - pos, realm.c_str());    pos += strcpyn(sensitive + pos, len - pos, ":");    password.CopyTo(sensitive + pos, true);    std::string A2 = method + ":" + uri;    std::string middle;    if (has_qop) {      qop = "auth";      middle = nonce + ":" + ncount + ":" + cnonce + ":" + qop;    } else {      middle = nonce;    }    std::string HA1 = MD5(sensitive);    memset(sensitive, 0, len);    delete [] sensitive;    std::string HA2 = MD5(A2);    std::string dig_response = MD5(HA1 + ":" + middle + ":" + HA2);#if TEST_DIGEST    assert(strcmp(dig_response.c_str(), DIGEST_RESPONSE) == 0);#endif    std::stringstream ss;    ss << auth_method;    ss << " username=" << quote(username);    ss << ", realm=" << quote(realm);    ss << ", nonce=" << quote(nonce);    ss << ", uri=" << quote(uri);    if (has_qop) {      ss << ", qop=" << qop;      ss << ", nc="  << ncount;      ss << ", cnonce=" << quote(cnonce);    }    ss << ", response=\"" << dig_response << "\"";    if (has_opaque) {      ss << ", opaque=" << quote(opaque);    }    response = ss.str();    return HAR_RESPONSE;  }#ifdef WIN32#if 1  bool want_negotiate = (_stricmp(auth_method.c_str(), "negotiate") == 0);  bool want_ntlm = (_stricmp(auth_method.c_str(), "ntlm") == 0);  // SPNEGO & NTLM  if (want_negotiate || want_ntlm) {    const size_t MAX_MESSAGE = 12000, MAX_SPN = 256;    char out_buf[MAX_MESSAGE], spn[MAX_SPN];#if 0 // Requires funky windows versions    DWORD len = MAX_SPN;    if (DsMakeSpn("HTTP", server.IPAsString().c_str(), NULL, server.port(),                  0, &len, spn) != ERROR_SUCCESS) {      LOG_F(WARNING) << "(Negotiate) - DsMakeSpn failed";      return HAR_IGNORE;    }#else    sprintfn(spn, MAX_SPN, "HTTP/%s", server.ToString().c_str());#endif    SecBuffer out_sec;    out_sec.pvBuffer   = out_buf;    out_sec.cbBuffer   = sizeof(out_buf);    out_sec.BufferType = SECBUFFER_TOKEN;    SecBufferDesc out_buf_desc;    out_buf_desc.ulVersion = 0;    out_buf_desc.cBuffers  = 1;    out_buf_desc.pBuffers  = &out_sec;    const ULONG NEG_FLAGS_DEFAULT =      //ISC_REQ_ALLOCATE_MEMORY      ISC_REQ_CONFIDENTIALITY      //| ISC_REQ_EXTENDED_ERROR      //| ISC_REQ_INTEGRITY      | ISC_REQ_REPLAY_DETECT      | ISC_REQ_SEQUENCE_DETECT      //| ISC_REQ_STREAM      //| ISC_REQ_USE_SUPPLIED_CREDS      ;    TimeStamp lifetime;    SECURITY_STATUS ret = S_OK;    ULONG ret_flags = 0, flags = NEG_FLAGS_DEFAULT;    bool specify_credentials = !username.empty();    size_t steps = 0;    //uint32 now = Time();    NegotiateAuthContext * neg = static_cast<NegotiateAuthContext *>(context);    if (neg) {      const size_t max_steps = 10;      if (++neg->steps >= max_steps) {        LOG(WARNING) << "AsyncHttpsProxySocket::Authenticate(Negotiate) too many retries";        return HAR_ERROR;      }      steps = neg->steps;      std::string decoded_challenge;      HttpHasNthAttribute(args, 1, &decoded_challenge, NULL);      decoded_challenge = Base64::decode(decoded_challenge);      if (!decoded_challenge.empty()) {        SecBuffer in_sec;        in_sec.pvBuffer   = const_cast<char *>(decoded_challenge.data());        in_sec.cbBuffer   = static_cast<unsigned long>(decoded_challenge.size());        in_sec.BufferType = SECBUFFER_TOKEN;        SecBufferDesc in_buf_desc;        in_buf_desc.ulVersion = 0;        in_buf_desc.cBuffers  = 1;        in_buf_desc.pBuffers  = &in_sec;        ret = InitializeSecurityContextA(&neg->cred, &neg->ctx, spn, flags, 0, SECURITY_NATIVE_DREP, &in_buf_desc, 0, &neg->ctx, &out_buf_desc, &ret_flags, &lifetime);        //LOG(INFO) << "$$$ InitializeSecurityContext @ " << TimeDiff(talk_base::Time(), now);        if (FAILED(ret)) {          LOG(LS_ERROR) << "InitializeSecurityContext returned: "                      << ErrorName(ret, SECURITY_ERRORS);          return HAR_ERROR;        }      } else if (neg->specified_credentials) {        // Try again with default credentials        specify_credentials = false;        delete context;        context = neg = 0;      } else {        return HAR_CREDENTIALS;      }    }    if (!neg) {      unsigned char userbuf[256], passbuf[256], domainbuf[16];      SEC_WINNT_AUTH_IDENTITY_A auth_id, * pauth_id = 0;      if (specify_credentials) {        memset(&auth_id, 0, sizeof(auth_id));        size_t len = password.GetLength()+1;        char * sensitive = new char[len];        password.CopyTo(sensitive, true);        std::string::size_type pos = username.find('\\');        if (pos == std::string::npos) {          auth_id.UserLength = static_cast<unsigned long>(            _min((unsigned int)sizeof(userbuf) - 1, (unsigned int)username.size()));          memcpy(userbuf, username.c_str(), auth_id.UserLength);          userbuf[auth_id.UserLength] = 0;          auth_id.DomainLength = 0;          domainbuf[auth_id.DomainLength] = 0;          auth_id.PasswordLength = static_cast<unsigned long>(            _min((unsigned int)sizeof(passbuf) - 1, (unsigned int)password.GetLength()));          memcpy(passbuf, sensitive, auth_id.PasswordLength);          passbuf[auth_id.PasswordLength] = 0;        } else {          auth_id.UserLength = static_cast<unsigned long>(            _min((unsigned int)sizeof(userbuf) - 1, (unsigned int)username.size() - pos - 1));          memcpy(userbuf, username.c_str() + pos + 1, auth_id.UserLength);          userbuf[auth_id.UserLength] = 0;          auth_id.DomainLength = static_cast<unsigned long>(            _min((unsigned int)sizeof(domainbuf) - 1, (unsigned int)pos));          memcpy(domainbuf, username.c_str(), auth_id.DomainLength);          domainbuf[auth_id.DomainLength] = 0;          auth_id.PasswordLength = static_cast<unsigned long>(            _min((unsigned int)sizeof(passbuf) - 1, (unsigned int)password.GetLength()));          memcpy(passbuf, sensitive, auth_id.PasswordLength);          passbuf[auth_id.PasswordLength] = 0;        }        memset(sensitive, 0, len);        delete [] sensitive;        auth_id.User = userbuf;        auth_id.Domain = domainbuf;        auth_id.Password = passbuf;        auth_id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;        pauth_id = &auth_id;        LOG(LS_VERBOSE) << "Negotiate protocol: Using specified credentials";      } else {        LOG(LS_VERBOSE) << "Negotiate protocol: Using default credentials";      }      CredHandle cred;      ret = AcquireCredentialsHandleA(0, want_negotiate ? NEGOSSP_NAME_A : NTLMSP_NAME_A, SECPKG_CRED_OUTBOUND, 0, pauth_id, 0, 0, &cred, &lifetime);      //LOG(INFO) << "$$$ AcquireCredentialsHandle @ " << TimeDiff(talk_base::Time(), now);      if (ret != SEC_E_OK) {        LOG(LS_ERROR) << "AcquireCredentialsHandle error: "                    << ErrorName(ret, SECURITY_ERRORS);        return HAR_IGNORE;      }      //CSecBufferBundle<5, CSecBufferBase::FreeSSPI> sb_out;      CtxtHandle ctx;      ret = InitializeSecurityContextA(&cred, 0, spn, flags, 0, SECURITY_NATIVE_DREP, 0, 0, &ctx, &out_buf_desc, &ret_flags, &lifetime);      //LOG(INFO) << "$$$ InitializeSecurityContext @ " << TimeDiff(talk_base::Time(), now);      if (FAILED(ret)) {        LOG(LS_ERROR) << "InitializeSecurityContext returned: "                    << ErrorName(ret, SECURITY_ERRORS);        FreeCredentialsHandle(&cred);        return HAR_IGNORE;      }      assert(!context);      context = neg = new NegotiateAuthContext(auth_method, cred, ctx);      neg->specified_credentials = specify_credentials;      neg->steps = steps;    }    if ((ret == SEC_I_COMPLETE_NEEDED) || (ret == SEC_I_COMPLETE_AND_CONTINUE)) {      ret = CompleteAuthToken(&neg->ctx, &out_buf_desc);      //LOG(INFO) << "$$$ CompleteAuthToken @ " << TimeDiff(talk_base::Time(), now);      LOG(LS_VERBOSE) << "CompleteAuthToken returned: "                      << ErrorName(ret, SECURITY_ERRORS);      if (FAILED(ret)) {        return HAR_ERROR;      }    }    //LOG(INFO) << "$$$ NEGOTIATE took " << TimeDiff(talk_base::Time(), now) << "ms";    std::string decoded(out_buf, out_buf + out_sec.cbBuffer);    response = auth_method;    response.append(" ");    response.append(Base64::encode(decoded));    return HAR_RESPONSE;  }#endif#endif // WIN32  return HAR_IGNORE;}//////////////////////////////////////////////////////////////////////} // namespace talk_base

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -