Skip to content
This repository has been archived by the owner on May 8, 2022. It is now read-only.

Commit

Permalink
Automatically generate self-signed cert. if not found. Fallback to no…
Browse files Browse the repository at this point in the history
…n-TLS mode. Update TLS article in README.md
  • Loading branch information
SCP002 committed Apr 24, 2022
1 parent d59a3ac commit b80a93c
Show file tree
Hide file tree
Showing 12 changed files with 148 additions and 84 deletions.
42 changes: 20 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ Documentation for setup and configuration is [here](https://github.com/xteve-pro

---

## TLS mode

This mode can be enabled by ticking the checkbox in `Settings -> General`.

Unless the server's certificate and it's private key already exists in xTeVe config directory, xTeVe will generate a self-signed automatically.

Self-signed certificate will only allow TLS mode to start up but not to actually establish a secure connections.
For truly working HTTPS, you should [generate](https://gist.github.com/fntlnz/cf14feb5a46b2eda428e000157447309) a certificate by yourself and **also** add the CA certificate to the client-side certificate storage (where the web browser, Plex etc. is).

Certificate and it's private key should be placed in xTeVe config directory like so:

```text
/home/username/.xteve/certificates/xteve.crt
/home/username/.xteve/certificates/xteve.key
```

If the certificate is signed by a certificate authority (CA), it should be the concatenation of the server's certificate, any intermediates, and the CA's certificate.

---

### xTeVe Beta branch

New features and bug fixes are only available in beta branch. Only after successful testing are they are merged into the master branch.
Expand Down Expand Up @@ -160,28 +180,6 @@ gox -output="./xteve-build/{{.Dir}}_{{.OS}}_{{.Arch}}" ./

---

## TLS mode

Before enabling TLS mode, you should put a self-signed certificate and it's private key into your xTeVe config directory, for example:

```text
/home/username/.xteve/certificates/xteve.crt
/home/username/.xteve/certificates/xteve.key
```

Next, enable this mode by the checkbox in `Settings -> General`.

You can either [generate](https://gist.github.com/fntlnz/cf14feb5a46b2eda428e000157447309) your own or download a 'dummy' certificate and it's key [from this repository](https://github.com/SCP002/xTeVe/tree/master/certeficates).

❗ Certificate from this repository will only allow TLS mode to start up but not to actually establish a secure connections.
For truly working HTTPS, you should generate it by yourself and **also** add self-signed root CA to client-side certificate storage (where the web browser, Plex etc. is).

See also:
* <https://pkg.go.dev/net/http#ListenAndServeTLS>
* <https://github.com/denji/golang-tls>

---

## Fork without pull request :mega:

When creating a fork, the xTeVe GitHub account must be changed from the source code or the update function disabled.
Expand Down
21 changes: 0 additions & 21 deletions certeficates/xteve.crt

This file was deleted.

27 changes: 0 additions & 27 deletions certeficates/xteve.key

This file was deleted.

2 changes: 1 addition & 1 deletion html/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@
},
"tlsMode": {
"title": "TLS (HTTPS) mode",
"description": "Changes web server protocol to HTTPS. Requires xteve.crt and xteve.key in xTeVe config /certificates directory."
"description": "Changes web server protocol to HTTPS.<br>For details, see <a>https://github.com/SCP002/xTeVe#tls-mode</a>"
},
"filesUpdate":
{
Expand Down
79 changes: 79 additions & 0 deletions src/cert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package src

import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"net"
"os"
"time"
)

// genCertFiles creates a self-signed certificate and it's private key in config/certificates directory.
//
// Inspired by https://gist.github.com/shaneutt/5e1995295cff6721c89a71d13a71c251
func genCertFiles() (err error) {
showInfo("Web server:" + "Generating certificate")

subject := pkix.Name{
CommonName: "xTeVe",
Country: []string{"US"},
Locality: []string{"San Francisco"},
Organization: []string{"xTeVe, Inc."},
PostalCode: []string{"94016"},
Province: []string{""},
StreetAddress: []string{"Golden Gate Bridge"},
}

serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return
}

certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return
}

certPrivKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey),
})

cert := &x509.Certificate{
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
IPAddresses: append(System.IPAddressesV4Raw, net.IPv6loopback),
KeyUsage: x509.KeyUsageDigitalSignature,
NotAfter: time.Now().AddDate(10, 0, 0),
NotBefore: time.Now(),
SerialNumber: serialNumber,
Subject: subject,
SubjectKeyId: []byte{1, 2, 3, 4, 6},
}

certBytes, err := x509.CreateCertificate(rand.Reader, cert, cert, &certPrivKey.PublicKey, certPrivKey)
if err != nil {
return
}

certPEM := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
})

err = os.WriteFile(System.File.ServerCertPrivKey, certPrivKeyPEM, 0644)
if err != nil {
return
}

err = os.WriteFile(System.File.ServerCert, certPEM, 0644)
if err != nil {
return
}

return
}
2 changes: 2 additions & 0 deletions src/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ func Init() (err error) {
return
}

System.File.ServerCert = getPlatformFile(fmt.Sprintf("%sxteve.crt", System.Folder.Certificates))
System.File.ServerCertPrivKey = getPlatformFile(fmt.Sprintf("%sxteve.key", System.Folder.Certificates))
System.File.XML = getPlatformFile(fmt.Sprintf("%s%s.xml", System.Folder.Data, System.AppName))
System.File.M3U = getPlatformFile(fmt.Sprintf("%s%s.m3u", System.Folder.Data, System.AppName))

Expand Down
6 changes: 6 additions & 0 deletions src/screen.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ func getErrMsg(errCode int) (errMsg string) {
errMsg = fmt.Sprintf("Specified temp folder path is invalid, fallback to %s", os.TempDir())
case 1016:
errMsg = fmt.Sprintf("Web server could not be stopped.")
case 1017:
errMsg = fmt.Sprintf("Web server could not be started in TLS mode, fallback to default.")

case 1020:
errMsg = fmt.Sprintf("Data could not be saved, invalid keyword")
Expand Down Expand Up @@ -397,6 +399,10 @@ func getErrMsg(errCode int) (errMsg string) {
case 6004:
errMsg = fmt.Sprintf("xTeVe update available")

// Certificates
case 7000:
errMsg = fmt.Sprintf("Can not generate a certificate")

default:
errMsg = fmt.Sprintf("Unknown error / warning (%d)", errCode)
}
Expand Down
22 changes: 14 additions & 8 deletions src/struct-system.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package src

import "xteve/src/internal/imgcache"
import (
"net"
"xteve/src/internal/imgcache"
)

// SystemStruct : Contains all System Information
type SystemStruct struct {
Expand Down Expand Up @@ -35,13 +38,15 @@ type SystemStruct struct {
}

File struct {
Authentication string
M3U string
PMS string
Settings string
URLS string
XEPG string
XML string
Authentication string
M3U string
PMS string
ServerCert string
ServerCertPrivKey string
Settings string
URLS string
XEPG string
XML string
}

Compressed struct {
Expand Down Expand Up @@ -73,6 +78,7 @@ type SystemStruct struct {
IPAddress string
IPAddressesList []string
IPAddressesV4 []string
IPAddressesV4Raw []net.IP
IPAddressesV6 []string
Name string
OS string
Expand Down
10 changes: 10 additions & 0 deletions src/toolchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ func checkFile(filename string) (err error) {
return
}

func allFilesExist(list ...string) bool {
for _, f := range list {
if err := checkFile(f); err != nil {
return false
}
}
return true
}

// GetUserHomeDirectory : User Home Directory
func GetUserHomeDirectory() (userHomeDirectory string) {

Expand Down Expand Up @@ -327,6 +336,7 @@ func resolveHostIP() (err error) {
if networkIP.IP.To4() != nil {

System.IPAddressesV4 = append(System.IPAddressesV4, ip)
System.IPAddressesV4Raw = append(System.IPAddressesV4Raw, networkIP.IP)

if !networkIP.IP.IsLoopback() && ip[0:7] != "169.254" {
System.IPAddress = ip
Expand Down
2 changes: 1 addition & 1 deletion src/webUI.go

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions src/webserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,24 @@ func StartWebserver() (err error) {
server := http.Server{Addr: ":" + port}

go func() {
var err error

if Settings.TLSMode {
certFile := System.Folder.Certificates + "xteve.crt"
keyFile := System.Folder.Certificates + "xteve.key"
err = server.ListenAndServeTLS(certFile, keyFile)
if allFilesExist(System.File.ServerCertPrivKey, System.File.ServerCert) == false {
if err = genCertFiles(); err != nil {
ShowError(err, 7000)
}
}

err = server.ListenAndServeTLS(System.File.ServerCert, System.File.ServerCertPrivKey)
if err != nil && err != http.ErrServerClosed {
ShowError(err, 1017)
err = server.ListenAndServe()
}
} else {
err = server.ListenAndServe()
}

if err != nil && err != http.ErrServerClosed {
ShowError(err, 1001)
return
Expand Down
2 changes: 1 addition & 1 deletion xteve.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var GitHub = GitHubStruct{Branch: "master", User: "SCP002", Repo: "xTeVe", Updat
const Name = "xTeVe"

// Version : Version, the Build Number is parsed in the main func
const Version = "2.3.0.0000"
const Version = "2.3.1.0000"

// DBVersion : Database Version
const DBVersion = "2.2.2"
Expand Down

0 comments on commit b80a93c

Please sign in to comment.