mirror of
https://wiilab.wiimart.org/wiimart/WiiMart-Patcher
synced 2025-09-03 20:11:19 +02:00

This should be refined in some way going forward, but will work for now. We rewrite the default API (i.e. https://api.oscwii.org) to be http. None of this is covered by the Wii Shop Channel's specified subdomain, so we explicitly state it.
131 lines
3.8 KiB
Go
131 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/x509"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io/ioutil"
|
|
)
|
|
|
|
// modifyAllowList patches the Opera filter to include our custom base domain.
|
|
func modifyAllowList() {
|
|
file, err := mainArc.OpenFile("arc/opera/myfilter.ini")
|
|
check(err)
|
|
|
|
// TODO(spotlightishere): Find an INI parser that handles reading an array from a section
|
|
// As I could not - and I spent a good while looking - and do not want to implement my own parser,
|
|
// no matter how rudimentary - I've copied the original file as a template verbatim. We only make one edit,
|
|
// adding the base domain.
|
|
filter := fmt.Sprintf(`[prefs]
|
|
prioritize excludelist=0
|
|
|
|
[include]
|
|
file:/cnt/*
|
|
https://*.%s/*
|
|
http://*.oscwii.org/*
|
|
https://*.oscwii.org/*
|
|
miip:*
|
|
|
|
[exclude]
|
|
*`, baseDomain)
|
|
|
|
// Replace UNIX line (LR) returns with that of Windows (CRLF).
|
|
output := bytes.ReplaceAll([]byte(filter), []byte("\n"), []byte("\r\n"))
|
|
file.Write(output)
|
|
}
|
|
|
|
// Tag represents a single byte representing a tag's ID.
|
|
type Tag byte
|
|
|
|
const (
|
|
TagSSLCertType = 0x20
|
|
TagSSLCertName = 0x21
|
|
TagSSLCertSubject = 0x22
|
|
TagSSLCertContents = 0x23
|
|
|
|
TagCACertificate = 0x02
|
|
TagUserCertificate = 0x03
|
|
TagUserPassword = 0x04
|
|
)
|
|
|
|
// generateTag generates a byte representation of a tag and contents.
|
|
func generateTag(tag Tag, tagContents []byte) []byte {
|
|
// Tag ID
|
|
contents := []byte{
|
|
byte(tag),
|
|
}
|
|
// Tag length
|
|
contents = append(contents, fourByte(uint32(len(tagContents)))...)
|
|
// Tag contents
|
|
contents = append(contents, tagContents...)
|
|
|
|
return contents
|
|
}
|
|
|
|
// generateOperaCertStore creates our own custom Opera cert store for the given certificate.
|
|
func generateOperaCertStore() {
|
|
file, err := mainArc.OpenFile("arc/opera/opcacrt6.dat")
|
|
check(err)
|
|
|
|
// Load our existing root certificate in DER form.
|
|
rootCertContents, err := ioutil.ReadFile("./output/root.cer")
|
|
check(err)
|
|
rootCert, err := x509.ParseCertificate(rootCertContents)
|
|
check(err)
|
|
|
|
// The following array was done manually after several hours of tinkering.
|
|
// Please refer to docs/opcacrt6.yml for more about the structure of this file.
|
|
// TODO(spotlightishere): Is it possible to somehow generate a structure for easier access?
|
|
header := []byte{
|
|
// File version number
|
|
0x00, 0x00, 0x10, 0x00,
|
|
// App version number
|
|
0x05, 0x05, 0x00, 0x23,
|
|
// ID tag "length" - always one byte
|
|
0x00, 0x01,
|
|
// Length field byte length - always four bytes
|
|
0x00, 0x04,
|
|
}
|
|
|
|
// It's unclear on what 0x01 is supposed to represent,
|
|
// but it must be a CA certificate.
|
|
certTypeTag := generateTag(TagSSLCertType, []byte{
|
|
0x0, 0x0, 0x0, 0x1,
|
|
})
|
|
|
|
// We can obtain the name and subject from the root certificate.
|
|
certNameTag := generateTag(TagSSLCertName, []byte(rootCert.Subject.CommonName))
|
|
certSubjectTag := generateTag(TagSSLCertSubject, rootCert.RawSubject)
|
|
|
|
// Finally, our actual certificate.
|
|
certContentsTag := generateTag(TagSSLCertContents, rootCertContents)
|
|
|
|
// We must enclose our type, name, subject and contents tag in a CA certificate tag.
|
|
bundledContents := append(certTypeTag, certNameTag...)
|
|
bundledContents = append(bundledContents, certSubjectTag...)
|
|
bundledContents = append(bundledContents, certContentsTag...)
|
|
|
|
caCertTag := generateTag(TagCACertificate, bundledContents)
|
|
|
|
// Thankfully, that is all.
|
|
// In the end, we have a structure similar to the following:
|
|
// - header (file/app version, id/length byte length)
|
|
// - ca certificate
|
|
// - id
|
|
// - length
|
|
// - value:
|
|
// - type tag (id, length, value)
|
|
// - type name (id, length, value)
|
|
// - type subject (id, length, value)
|
|
// - type contents (id, length, value)
|
|
file.Write(append(header, caCertTag...))
|
|
}
|
|
|
|
// fourByte returns 4 bytes, suitable for the given length.
|
|
func fourByte(value uint32) []byte {
|
|
holder := make([]byte, 4)
|
|
binary.BigEndian.PutUint32(holder, value)
|
|
return holder
|
|
}
|