Based on Nekogram. Key additions: - Rebrand to FoxiGram (app name, APK name, applicationId com.foxigram.app) - Embedded Xray (VLESS+Reality) proxy client via JNI libxray.so - Bundled hidden one-tap proxies (LTE + WiFi), read-only in UI - Auto-restore proxy on restart, rebind to active network (LTE/WiFi) - Server credentials externalized to git-ignored XrayServers.java (+ template) - libxray Go source included; compiled .so, keystore, google-services.json ignored
245 lines
6.7 KiB
C++
245 lines
6.7 KiB
C++
// Copyright 2016 The Chromium Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "cert_errors.h"
|
|
|
|
#include "cert_error_params.h"
|
|
#include "parse_name.h"
|
|
#include "parsed_certificate.h"
|
|
|
|
#include <sstream>
|
|
|
|
BSSL_NAMESPACE_BEGIN
|
|
|
|
namespace {
|
|
|
|
void AppendLinesWithIndentation(const std::string &text,
|
|
const std::string &indentation,
|
|
std::string *out) {
|
|
std::istringstream stream(text);
|
|
for (std::string line; std::getline(stream, line, '\n');) {
|
|
out->append(indentation);
|
|
out->append(line);
|
|
out->append("\n");
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
CertError::CertError() = default;
|
|
|
|
CertError::CertError(Severity in_severity, CertErrorId in_id,
|
|
std::unique_ptr<CertErrorParams> in_params)
|
|
: severity(in_severity), id(in_id), params(std::move(in_params)) {}
|
|
|
|
CertError::CertError(CertError &&other) = default;
|
|
|
|
CertError &CertError::operator=(CertError &&) = default;
|
|
|
|
CertError::~CertError() = default;
|
|
|
|
std::string CertError::ToDebugString() const {
|
|
std::string result;
|
|
switch (severity) {
|
|
case SEVERITY_WARNING:
|
|
result += "WARNING: ";
|
|
break;
|
|
case SEVERITY_HIGH:
|
|
result += "ERROR: ";
|
|
break;
|
|
}
|
|
result += CertErrorIdToDebugString(id);
|
|
result += +"\n";
|
|
|
|
if (params) {
|
|
AppendLinesWithIndentation(params->ToDebugString(), " ", &result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
CertErrors::CertErrors() = default;
|
|
CertErrors::CertErrors(CertErrors &&other) = default;
|
|
CertErrors &CertErrors::operator=(CertErrors &&) = default;
|
|
CertErrors::~CertErrors() = default;
|
|
|
|
void CertErrors::Add(CertError::Severity severity, CertErrorId id,
|
|
std::unique_ptr<CertErrorParams> params) {
|
|
nodes_.emplace_back(severity, id, std::move(params));
|
|
}
|
|
|
|
void CertErrors::AddError(CertErrorId id,
|
|
std::unique_ptr<CertErrorParams> params) {
|
|
Add(CertError::SEVERITY_HIGH, id, std::move(params));
|
|
}
|
|
|
|
void CertErrors::AddError(CertErrorId id) { AddError(id, nullptr); }
|
|
|
|
void CertErrors::AddWarning(CertErrorId id,
|
|
std::unique_ptr<CertErrorParams> params) {
|
|
Add(CertError::SEVERITY_WARNING, id, std::move(params));
|
|
}
|
|
|
|
void CertErrors::AddWarning(CertErrorId id) { AddWarning(id, nullptr); }
|
|
|
|
std::string CertErrors::ToDebugString() const {
|
|
std::string result;
|
|
for (const CertError &node : nodes_) {
|
|
result += node.ToDebugString();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool CertErrors::ContainsErrorWithSeverity(CertErrorId id,
|
|
CertError::Severity severity) const {
|
|
for (const CertError &node : nodes_) {
|
|
if (node.id == id && node.severity == severity) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CertErrors::ContainsError(CertErrorId id) const {
|
|
return ContainsErrorWithSeverity(id, CertError::SEVERITY_HIGH);
|
|
}
|
|
|
|
bool CertErrors::ContainsAnyErrorWithSeverity(
|
|
CertError::Severity severity) const {
|
|
for (const CertError &node : nodes_) {
|
|
if (node.severity == severity) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
CertPathErrors::CertPathErrors() = default;
|
|
|
|
CertPathErrors::CertPathErrors(CertPathErrors &&other) = default;
|
|
CertPathErrors &CertPathErrors::operator=(CertPathErrors &&) = default;
|
|
|
|
CertPathErrors::~CertPathErrors() = default;
|
|
|
|
CertErrors *CertPathErrors::GetErrorsForCert(size_t cert_index) {
|
|
if (cert_index >= cert_errors_.size()) {
|
|
cert_errors_.resize(cert_index + 1);
|
|
}
|
|
return &cert_errors_[cert_index];
|
|
}
|
|
|
|
const CertErrors *CertPathErrors::GetErrorsForCert(size_t cert_index) const {
|
|
if (cert_index >= cert_errors_.size()) {
|
|
return nullptr;
|
|
}
|
|
return &cert_errors_[cert_index];
|
|
}
|
|
|
|
CertErrors *CertPathErrors::GetOtherErrors() { return &other_errors_; }
|
|
|
|
const CertErrors *CertPathErrors::GetOtherErrors() const {
|
|
return &other_errors_;
|
|
}
|
|
|
|
bool CertPathErrors::ContainsError(CertErrorId id) const {
|
|
for (const CertErrors &errors : cert_errors_) {
|
|
if (errors.ContainsError(id)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (other_errors_.ContainsError(id)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CertPathErrors::ContainsAnyErrorWithSeverity(
|
|
CertError::Severity severity) const {
|
|
for (const CertErrors &errors : cert_errors_) {
|
|
if (errors.ContainsAnyErrorWithSeverity(severity)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (other_errors_.ContainsAnyErrorWithSeverity(severity)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
std::optional<CertErrorId> CertPathErrors::FindSingleHighSeverityError(
|
|
ptrdiff_t &out_depth) const {
|
|
std::optional<CertErrorId> id_seen;
|
|
for (ptrdiff_t i = -1; i < (ptrdiff_t)cert_errors_.size(); ++i) {
|
|
const CertErrors *errors =
|
|
(i < 0) ? GetOtherErrors() : GetErrorsForCert(i);
|
|
for (const CertError &node : errors->nodes_) {
|
|
if (node.severity == CertError::SEVERITY_HIGH) {
|
|
if (!id_seen.has_value()) {
|
|
id_seen = node.id;
|
|
out_depth = i;
|
|
} else {
|
|
if (id_seen.value() != node.id) {
|
|
return {};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return id_seen;
|
|
}
|
|
|
|
std::string CertPathErrors::ToDebugString(
|
|
const ParsedCertificateList &certs) const {
|
|
std::ostringstream result;
|
|
|
|
for (size_t i = 0; i < cert_errors_.size(); ++i) {
|
|
// Pretty print the current CertErrors. If there were no errors/warnings,
|
|
// then continue.
|
|
const CertErrors &errors = cert_errors_[i];
|
|
std::string cert_errors_string = errors.ToDebugString();
|
|
if (cert_errors_string.empty()) {
|
|
continue;
|
|
}
|
|
|
|
// Add a header that identifies which certificate this CertErrors pertains
|
|
// to.
|
|
std::string cert_name_debug_str;
|
|
if (i < certs.size() && certs[i]) {
|
|
RDNSequence subject;
|
|
if (ParseName(certs[i]->tbs().subject_tlv, &subject) &&
|
|
ConvertToRFC2253(subject, &cert_name_debug_str)) {
|
|
cert_name_debug_str = " (" + cert_name_debug_str + ")";
|
|
}
|
|
}
|
|
result << "----- Certificate i=" << i << cert_name_debug_str << " -----\n";
|
|
result << cert_errors_string << "\n";
|
|
}
|
|
|
|
// Print any other errors that aren't associated with a particular certificate
|
|
// in the chain.
|
|
std::string other_errors = other_errors_.ToDebugString();
|
|
if (!other_errors.empty()) {
|
|
result << "----- Other errors (not certificate specific) -----\n";
|
|
result << other_errors << "\n";
|
|
}
|
|
|
|
return result.str();
|
|
}
|
|
|
|
BSSL_NAMESPACE_END
|