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
260 lines
6.4 KiB
Go
260 lines
6.4 KiB
Go
// Copyright 2015 The BoringSSL 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.
|
|
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path"
|
|
"sort"
|
|
"strconv"
|
|
)
|
|
|
|
// libraryNames must be kept in sync with the enum in err.h. The generated code
|
|
// will contain static assertions to enforce this.
|
|
var libraryNames = []string{
|
|
"NONE",
|
|
"SYS",
|
|
"BN",
|
|
"RSA",
|
|
"DH",
|
|
"EVP",
|
|
"BUF",
|
|
"OBJ",
|
|
"PEM",
|
|
"DSA",
|
|
"X509",
|
|
"ASN1",
|
|
"CONF",
|
|
"CRYPTO",
|
|
"EC",
|
|
"SSL",
|
|
"BIO",
|
|
"PKCS7",
|
|
"PKCS8",
|
|
"X509V3",
|
|
"RAND",
|
|
"ENGINE",
|
|
"OCSP",
|
|
"UI",
|
|
"COMP",
|
|
"ECDSA",
|
|
"ECDH",
|
|
"HMAC",
|
|
"DIGEST",
|
|
"CIPHER",
|
|
"HKDF",
|
|
"TRUST_TOKEN",
|
|
"USER",
|
|
}
|
|
|
|
// stringList is a map from uint32 -> string which can output data for a sorted
|
|
// list as C literals.
|
|
type stringList struct {
|
|
// entries is an array of keys and offsets into |stringData|. The
|
|
// offsets are in the bottom 15 bits of each uint32 and the key is the
|
|
// top 17 bits.
|
|
entries []uint32
|
|
// internedStrings contains the same strings as are in |stringData|,
|
|
// but allows for easy deduplication. It maps a string to its offset in
|
|
// |stringData|.
|
|
internedStrings map[string]uint32
|
|
stringData []byte
|
|
}
|
|
|
|
func newStringList() *stringList {
|
|
return &stringList{
|
|
internedStrings: make(map[string]uint32),
|
|
}
|
|
}
|
|
|
|
// offsetMask is the bottom 15 bits. It's a mask that selects the offset from a
|
|
// uint32 in entries.
|
|
const offsetMask = 0x7fff
|
|
|
|
func (st *stringList) Add(key uint32, value string) error {
|
|
if key&offsetMask != 0 {
|
|
return errors.New("need bottom 15 bits of the key for the offset")
|
|
}
|
|
offset, ok := st.internedStrings[value]
|
|
if !ok {
|
|
offset = uint32(len(st.stringData))
|
|
if offset&offsetMask != offset {
|
|
return errors.New("stringList overflow")
|
|
}
|
|
st.stringData = append(st.stringData, []byte(value)...)
|
|
st.stringData = append(st.stringData, 0)
|
|
st.internedStrings[value] = offset
|
|
}
|
|
|
|
for _, existing := range st.entries {
|
|
if existing>>15 == key>>15 {
|
|
panic("duplicate entry")
|
|
}
|
|
}
|
|
st.entries = append(st.entries, key|offset)
|
|
return nil
|
|
}
|
|
|
|
func (st *stringList) buildList() []uint32 {
|
|
sort.Slice(st.entries, func(i, j int) bool { return (st.entries[i] >> 15) < (st.entries[j] >> 15) })
|
|
return st.entries
|
|
}
|
|
|
|
type stringWriter interface {
|
|
io.Writer
|
|
WriteString(string) (int, error)
|
|
}
|
|
|
|
func (st *stringList) WriteTo(out stringWriter, name string) {
|
|
list := st.buildList()
|
|
values := "kOpenSSL" + name + "Values"
|
|
out.WriteString("extern const uint32_t " + values + "[];\n")
|
|
out.WriteString("const uint32_t " + values + "[] = {\n")
|
|
for _, v := range list {
|
|
fmt.Fprintf(out, " 0x%x,\n", v)
|
|
}
|
|
out.WriteString("};\n\n")
|
|
out.WriteString("extern const size_t " + values + "Len;\n")
|
|
out.WriteString("const size_t " + values + "Len = sizeof(" + values + ") / sizeof(" + values + "[0]);\n\n")
|
|
|
|
stringData := "kOpenSSL" + name + "StringData"
|
|
out.WriteString("extern const char " + stringData + "[];\n")
|
|
out.WriteString("const char " + stringData + "[] =\n \"")
|
|
for i, c := range st.stringData {
|
|
if c == 0 {
|
|
out.WriteString("\\0\"\n \"")
|
|
continue
|
|
}
|
|
out.Write(st.stringData[i : i+1])
|
|
}
|
|
out.WriteString("\";\n\n")
|
|
}
|
|
|
|
type errorData struct {
|
|
reasons *stringList
|
|
libraryMap map[string]uint32
|
|
}
|
|
|
|
func (e *errorData) readErrorDataFile(filename string) error {
|
|
inFile, err := os.Open(filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer inFile.Close()
|
|
|
|
scanner := bufio.NewScanner(inFile)
|
|
comma := []byte(",")
|
|
|
|
lineNo := 0
|
|
for scanner.Scan() {
|
|
lineNo++
|
|
|
|
line := scanner.Bytes()
|
|
if len(line) == 0 {
|
|
continue
|
|
}
|
|
parts := bytes.Split(line, comma)
|
|
if len(parts) != 3 {
|
|
return fmt.Errorf("bad line %d in %s: found %d values but want 3", lineNo, filename, len(parts))
|
|
}
|
|
libNum, ok := e.libraryMap[string(parts[0])]
|
|
if !ok {
|
|
return fmt.Errorf("bad line %d in %s: unknown library", lineNo, filename)
|
|
}
|
|
if libNum >= 64 {
|
|
return fmt.Errorf("bad line %d in %s: library value too large", lineNo, filename)
|
|
}
|
|
key, err := strconv.ParseUint(string(parts[1]), 10 /* base */, 32 /* bit size */)
|
|
if err != nil {
|
|
return fmt.Errorf("bad line %d in %s: %s", lineNo, filename, err)
|
|
}
|
|
if key >= 2048 {
|
|
return fmt.Errorf("bad line %d in %s: key too large", lineNo, filename)
|
|
}
|
|
value := string(parts[2])
|
|
|
|
listKey := libNum<<26 | uint32(key)<<15
|
|
|
|
err = e.reasons.Add(listKey, value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return scanner.Err()
|
|
}
|
|
|
|
type ErrDataTask struct {
|
|
TargetName string
|
|
Inputs []string
|
|
}
|
|
|
|
func (t *ErrDataTask) Destination() string {
|
|
return path.Join("gen", t.TargetName, "err_data.cc")
|
|
}
|
|
|
|
func (t *ErrDataTask) Run() ([]byte, error) {
|
|
e := &errorData{
|
|
reasons: newStringList(),
|
|
libraryMap: make(map[string]uint32),
|
|
}
|
|
for i, name := range libraryNames {
|
|
e.libraryMap[name] = uint32(i) + 1
|
|
}
|
|
|
|
for _, input := range t.Inputs {
|
|
if err := e.readErrorDataFile(input); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
var out bytes.Buffer
|
|
out.WriteString(`// Copyright 2015 The BoringSSL 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.
|
|
|
|
// This file was generated by go run ./util/pregenerate.
|
|
|
|
#include <openssl/base.h>
|
|
#include <openssl/err.h>
|
|
|
|
#include <assert.h>
|
|
|
|
`)
|
|
|
|
for i, name := range libraryNames {
|
|
fmt.Fprintf(&out, "static_assert(ERR_LIB_%s == %d, \"library value changed\");\n", name, i+1)
|
|
}
|
|
fmt.Fprintf(&out, "static_assert(ERR_NUM_LIBS == %d, \"number of libraries changed\");\n", len(libraryNames)+1)
|
|
out.WriteString("\n")
|
|
|
|
e.reasons.WriteTo(&out, "Reason")
|
|
return out.Bytes(), nil
|
|
}
|